Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Как убить не модальный property sheet? |
Автор: Royan 24.8.2004, 21:55 |
Создал modeless PropertySheet: PROPSHEETHEADER psh = {0}; // psh.dwFlags = PSH_USECALLBACK | PSH_MODELESS; Но нажимая на славную кнопку с крестиком или на кнопку OK или на Cancel не могу отловить ни одного сообщения, то есть фактически у меня нет шансов определить нажал ли пользователь на какую-нибудь из этих кнопок или нет. Кто-нибудь знает как с этим сладить? |
Автор: Royan 26.8.2004, 17:31 | ||||
Оказывается способ совсем не тривиальный. И варианта на самом деле два. Первый весьма ограничен в силу того, что приходится всегда держать информацию о HWND вашего PropertySheet в месте доступном из WinMain(). Вот его применение:
Весь код разумеется распологается внутри WinMain, что неудобно Поэтому вот другой подход. Внедрить отдельную функцию обработки сообщений от вашего немодального PropertySheet: код функции может варироваться от навороченности вашей реализации, но вот примелемый пример:
|
Автор: AndyY 26.8.2004, 20:58 |
Royan что-то нифига не понял, зачем такие сложности. Не проще ли отсубклассить окно propertysheet, обработать IDOK и IDCANCEL и вызвать DEstroyWindow из функции окна. Субклассить propertysheet легко через callback Добавлено @ 20:58 вложенных циклов сообщений по возможности лучше избегать. Уж слишком часто они являются причиной ошибки. |
Автор: stab 26.8.2004, 22:30 |
AndyY, "отсубклассить" тут не поможет, т.к. до окна не доходят сообщения, для этого все эти навороты и нужны... |
Автор: Royan 30.8.2004, 15:00 |
2AndyY, проблема еще не только в том, что IDOK и IDCANCEL не передадутся через WM_COMMAND, а еще и в том что ID кнопок OK Cancel и Apply тривиально выяснить нельзя, так как они создаются автоматически после вызова PropertySheet(&ps). 2cully, а ты пробовал сабклассировать окошко propertysheet хотя бы из любопытства не проходит ли туда WM_COMMAND с ID остальных элементов? |
Автор: AndyY 30.8.2004, 15:23 |
cully WM_COMMAND до окна PropertySheet доходит. Естественно, до "внешнего" а не до tabctrl. Да и как может не доходить, если кнопка там самая обычная на окне. Чудес не бывает. Royan ID кнопки OK - IDOK ID кнопки Сancel - IDCANCEL id остальных кнопок: #define IDD_APPLYNOW 0x3021 #define IDD_DLGFRAME 0x3022 #define IDD_BACK 0x3023 #define IDD_NEXT 0x3024 #define IDD_FINISH 0x3025 #define IDD_DIVIDER 0x3026 #define IDD_TOPDIVIDER 0x3027 зашиты жестко и никогда не меняются. Добавлено @ 15:25 единственная сложность в субклассе - то, что в callback функцию нельзя передать параметр (обычно туда складывают указатель на класс). Поэтому приходится либо делать callback-thunk, либо временно сохранять указатель в глобальной переменной. |
Автор: Royan 30.8.2004, 17:07 | ||
AndyY А что такое callback-thunk?
Собственно я пользуюсь ::SetWindowLongPtr() и никгода проблем не было. |
Автор: AndyY 30.8.2004, 17:50 |
суть конечно в этом. но callback для PSH_USECALLBACK не поддерживает передачу параметра. это важно, если нужно ассоциировать HWND с экземпляром класса. поэтому указатель на объект можно сохранять в глобальной переменной, откуда читать из callback. другой путь - сделать callback в виде участка памяти содержащего инструкции: { call realHookProc ret HWND hwdn; } в realHookProc можно получить значение HWND (через SP на старте функции - offset от адреса возврата известен) эдакий кривой способ передачи параметров |
Автор: Royan 30.8.2004, 18:10 |
Я не понял при зачем так извращаться, когда я всегда могу сделать так: hwndMain = (HWND)PropertySheet(&ps); wndprcPointer = ::GetWindowLongPtr(hwndMail, GWLP_WNDPROC); а wndprcPointer уже будет отрабатывать уже в твоей процедуре обработки сообещиний, которую ты же забъешь через SetWindowLongPtr() ![]() |
Автор: AndyY 30.8.2004, 20:34 |
Royan согласен. Для немодального окна - вполне вариант. Хотя в некоторых случаях это позновато - окно например может быть уже показано в момент когда функция возвратит управление. Я просто делал универсальный класс для модального и немодального окна. Идея, почему могут не доходить IDOK и IDCANCEL: их кушает обработчик сообщения PSM_ISDIALOGMESSAGE. Я использовал просто IsDialogMessage. |