лист свойств в диалоге с использованием примера WINAPI (без использования MFC) - PullRequest
2 голосов
/ 11 июля 2011

Может кто-нибудь указать мне на пример WINAPI для встраивания листа свойств в диалоговое окно с использованием WINAPI (не MFC)?

Ответы [ 2 ]

2 голосов
/ 24 июля 2011

Для справки, вот некоторые из вещей, которые я узнал во время исследуя этот вопрос. Я получил большинство / все это от задавать вопросы здесь или с помощью поиска в Интернете. Спасибо всем за ваша помощь!

Я написал класс для инкапсуляции всего, что обнаружил; если вы заинтересованы в получении копии, отправьте мне письмо по электронной почте mdorl@wisc.edu.

Передайте HWND родительского окна для вашего листа свойств в .hwndParent из PROPSHEETHEADER при создании листа свойств с функцией страницы PropertySheet.

Я использовал элемент управления рисунком в диалоговом окне в качестве родителя свойства лист, так что это HWND я использовал в качестве hwndParent.

Изменить стиль листа свойств с помощью обратного вызова Поле pfnCallback в заголовке, не забудьте включить PSH_USECALLBACK в dwFlags. Смотрите функцию PropSheetProc в MSDN. В обработчике PSCB_PRECREATE обратного вызова настроить стиль окна листа свойств, удалив WS_POPUP и добавление WS_CHILD. Я не хотел границы или заголовка панель на листе свойств, поэтому я также удалил WS_CAPTION, WS_SYSEMNU, & DS_MODALFRAME

LONG L = ((LPDLGTEMPLATE)lParam)->style;
L &= ~WS_POPUP; 
L &= ~WS_CAPTION;       // gets rid of title bar
L &= ~WS_SYSMENU;       
L &= ~DS_MODALFRAME;        // gets rid of border
L |=  WS_CHILD;         // 40000000
((LPDLGTEMPLATE)lParam)->style = L;

Использование дочернего окна вместо всплывающего окна аккуратно решает некоторые проблемы, такие как перемещение листа свойств, когда родитель перемещается, правильно сохраняя сине-серое состояние родительского окна цветные и проблемы с отсечкой. То есть вам не нужно беспокоиться об этих вещах.

Если вы остановитесь здесь, вы столкнетесь с другой проблемой. Поддержка диалога код в WIN32 попадет в цикл процессора, пытаясь найти страницу свойств и контролирует в своей винде. Смотри

Для чего нужны WS_EX_CONTROLPARENT и DS_CONTROL?

за довольно хорошее объяснение Эта проблема. Решение состоит в том, чтобы добавить расширенный WS_EX_CONTROLPARENT стиль на листе недвижимости. Вы можете найти информацию об этом в Интернете с помощью поиска WS_EX_CONTROLPARENT. Чего вы не найдете причинил мне много горя. Если вы используете элемент управления в диалоговом окне в качестве parent, вы также должны установить его WS_EX_CONTROLPARENT.

Я не знаю, в чем разница между WS_EX_CONTROLPARENT и DS_CONTROL, и я не знаю, можно ли заменить DS_CONTROL на WS_EX_CONTROLPARENT. Из Интернета я понимаю, что DS_CONTROL как-то связан с вкладками. Мое тестовое приложение работает одинаково с вкладками с DS_CONTROL или без него.

Я позаботился о бизнесе WS_EX_CONTROLPARENT после вызова Функция PropertySheet для создания листа свойств. я не знаю если вы могли бы сделать это в процедуре обратного вызова или нет. Я полагаю вы можете использовать GetParent при обратном вызове, чтобы получить HWND управление.

LONG S;

S = GetWindowLong (hwndPS, GWL_EXSTYLE) | WS_EX_CONTROLPARENT;
SetWindowLong (hwndPS, GWL_EXSTYLE, S);

S = GetWindowLong (hwndPS_Area, GWL_EXSTYLE) | WS_EX_CONTROLPARENT;
SetWindowLong (hwndPS_Area, GWL_EXSTYLE, S);

После создания листа свойств с помощью функции PropertySheet, Вы должны правильно расположить его:

SetWindowPos(hwndPS, HWND_TOP, 2, 2, -1, -1,
             SWP_NOSIZE | SWP_NOACTIVATE); 

Я позволил пару пикселей для границы.

Если вы хотите избавиться от всех кнопок листа свойств и занимаемого ими пространства:

RECT rectWnd;
RECT rectButton;

GetWindowRect(hwndPS, &rectWnd);
HWND hWnd = ::GetDlgItem(hwndPS, IDOK);

if(!hWnd)
{
    DebugBreak();
}

GetWindowRect(hWnd, &rectButton);

SetWindowPos (hwndPS, NULL, 0, 0,
          rectWnd.right - rectWnd.left, rectButton.top - rectWnd.top,
          SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);

Отдельные кнопки могут быть исключены:

hwndOk = GetDlgItem (hwndPS,IDOK);              // Hide the OK button
ShowWindow (hwndOk, SW_HIDE);
EnableWindow (hwndOk, FALSE);

Вы можете избавиться от кнопки APPLY, используя PSH_NOAPPLYNOW dwFlags в PROPERTYSHEETHEADER при создании листа свойств.

Страницы листа свойств НЕ будут создаваться до тех пор, пока пользователь не будет первым активирует их. Я хотел, чтобы они все были созданы, когда собственность лист был создан.

unsigned int iP;
for (iP=0; iP<Header.nPages; iP++)
{
    if (iP != Header.nStartPage)
        SendMessage (hwndPS, PSM_SETCURSEL,iP,NULL);
}
SendMessage (hwndPS, PSM_SETCURSEL,Header.nStartPage,NULL);

Есть флаг PROPSHEETPAGE, который делает то же самое (из MSDN)

PSP_PREMATURE Версия 4.71. Вызывает создание страницы, когда список свойств создан. Если этот флаг не указан, страница не будет создан, пока не будет выбран в первый раз.

Но меня беспокоило дело с версией 4.71, поэтому я сделал это сам.

Вы можете изменить текст на любой из кнопок:

SetDlgItemText (hwndPS,ButtonID,Text);

, где ButtonID является одним из IDOK IDCANCEL IDHELP IDAPPLYNOW

IDAPPLYNOW в моей системе не определено, поэтому

#define IDAPPLYNOW     0x3021   

Вот как я собираюсь использовать свой список свойств. Я собираюсь поставить всю инициализацию и код завершения в диалоговом окне, содержащем лист свойств, и исключите все кнопки листа свойств. Я могу установить все начальные значения там и получить все конечные значения там, когда пользователь нажимает какую-либо кнопку DO IT. Я замечаю, что в результате установки, например, текстового поля, диалоговое окно содержащей страницы получает WM_COMMAND / EN_CHANGE. Если вы используете это сообщение для включения кнопки ПРИМЕНИТЬ, вам может потребоваться отключить флаг изменения страницы после установки любых списков. Я решил эту проблему, очистив все измененные флаги после установки начального значения. (Я подозреваю, что лист свойств очищает измененный флаг после того, как все сообщения INITDIALOG были отправлены. В любом случае APPLY не включается, если текстовые поля установлены на обработчиках страницы INITDIALOG.) Если я обнаружу ошибку, я выберу этот лист свойств страницы и поместите красный текст в родительский диалог, описывающий ошибку. Единственное, что нужно сделать диалоговым процедурам листа свойств, - это управлять их элементами управления.

Одна из вещей, которая озадачивает меня, - это как определить, все ли страницы вернули PSNRET_NOERROR из своих сообщений WS_NOTIFY / PSN_APPLY. Я имел некоторый успех, считая число последовательных ответов PSNRET_NOERROR, устанавливающих счетчик равным нулю, когда сообщается PSNRET_INVALID или получен PSN_KILLACTIVE. Если число достигает количества страниц в заголовке листа свойств, я предполагаю, что все страницы вернули PSNRET_NOERROR. Но я беспокоюсь о таких вещах, как отключенные и невидимые страницы.

2 голосов
/ 11 июля 2011

Как насчет MSDN пример .

...