Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CallWindowProc для диалогов? 
:(
    Опции темы
Alca
Дата 18.6.2009, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



CallWindowProc для диалогов? Как можно заменить процедуру диалога?


--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 18.6.2009, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Alca @  18.6.2009,  14:24 Найти цитируемый пост)
Как можно заменить процедуру диалога?

в рантайме - как и для всех остальных окон, через SetWindowLong и GWL_WNDPROC

а вот кгда ты сам управляешь ресурсом, то можно диалог просто наследовать (суперклассить)
для этого нужно: зарегистрировать класс-потомок от диалога, а в ресурсах самого диалога заполнить свойство "Class"
тут нужно указать имя этого зарегистрированного класса

в программе все аналогично, как с обычным диалогом, за исключением последнего параметра (lpDialogFunc),
в него можно передать NULL:
Код

DialogBox(hInstance, lpTemplate, hWndParent, NULL);


Добавлено через 1 минуту и 39 секунд
да, вместо DefWindowProc, в перекрытой процедуре окна нужно уже вызывать DefDlgProc 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Alca
Дата 19.6.2009, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

да, вместо DefWindowProc, в перекрытой процедуре окна нужно уже вызывать DefDlgProc 

Я создаю главное окно через CreateDialog. Использовать DefWindowProc или DefDlgProc?

Добавлено через 1 минуту и 14 секунд
Чета у меня не получается CreateDialog и DefWindowProc в класс завернуть...


--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 19.6.2009, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



без разницы, какой функцией создавать диалог,
при перекрытии, в любом случае нужно уже вызывать DefDlgProc,
напоминаю условия суперклассинга диалогов: http://msdn.microsoft.com/en-us/library/ms...px#custom_boxes


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Alca
Дата 19.6.2009, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Для начала, сдесь все правильно?
Код

#include "Test.h"

#include <windows.h>
#include <assert.h>
#include <iostream>
#include <stdlib.h>
#include <commctrl.h>
//---------------------------------------------------------------------------
HINSTANCE        g_hInstance  = NULL; 
HWND             g_hMainWnd   = NULL; 

int     WINAPI   WinMain     (HINSTANCE hInstance,    HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); 
LRESULT CALLBACK lpMainProc  (HWND hWnd, UINT message, UINT wParam, LONG lParam);
BOOL             bRegWndClass(HINSTANCE hInstance);
//---------------------------------------------------------------------------
BOOL bRegWndClass(HINSTANCE hInstance) {
    BOOL bRes = FALSE;

    //-------------------------------------
    //The Window structure
    WNDCLASSEX wcex = {0};

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = lpMainProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = NULL;
    wcex.hCursor        = ::LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = "TestWindowClass";
    wcex.hIconSm        = NULL;

    //-------------------------------------
    //Register the window class
    bRes = ::RegisterClassEx(&wcex);
    assert(FALSE != bRes);

    return TRUE;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK lpMainProc(HWND hWnd, UINT uiMsg, UINT wParam, LONG lParam) {
    INT wmId    = - 1;
    INT wmEvent = - 1;

    switch (uiMsg) {
        case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            switch (wmId) 
            {
                case IDC_btnTest:
                    ::MessageBox(0, "Test", "ID_btnTest", MB_OK);
                    break;

                case IDC_btnExit:
                    ::DestroyWindow(hWnd);
                    break;
            }
            break;

        case WM_CLOSE: 
            ::DestroyWindow(hWnd); 
            break;

        case WM_DESTROY:
            ::PostQuitMessage(0);
            break;

        default:
            ////    return ::DefWindowProc(hWnd, uiMsg, wParam, lParam);      /*>>Так нормально<<*/
            return ::DefDlgProc(hWnd, uiMsg, wParam, lParam);     /*>>Валиться здесь<<*/
            /*Unhandled exception at 0x004116e6 in Test.exe: 0xC00000FD: Stack overflow.*/
    }

    return 0;
}
//---------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance,    HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nCmdShow);

    INT  iRes = - 1;
    BOOL bRes = FALSE;
    MSG  msg  = {0};

    g_hInstance = hInstance;
    assert(0 != g_hInstance);

    bRes = bRegWndClass(g_hInstance);
    assert(FALSE != bRes);

    //-------------------------------------
    //Создаем диалог
    g_hMainWnd = ::CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_dlgMain), NULL, (DLGPROC)lpMainProc);
    assert(NULL != g_hMainWnd);

    bRes = ::ShowWindow(g_hMainWnd, SW_SHOW);
    assert(FALSE == bRes);

    bRes = ::UpdateWindow(g_hMainWnd);
    assert(FALSE != bRes);

    //-------------------------------------
    //Вертушка
    while (iRes = ::GetMessage(&msg, NULL, 0, 0 )) {
        if (- 1 == iRes) {
            assert(false);
        } else {
            ::TranslateMessage(&msg);
            ::DispatchMessage (&msg);
        }
    }

    return (INT)msg.wParam;;
}
//---------------------------------------------------------------------------


Это сообщение отредактировал(а) Alca - 19.6.2009, 11:18


--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 19.6.2009, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



нет,
поправка 1:
Код

wcex.cbWndExtra        = DLGWINDOWEXTRA;

поправка 2:
Цитата(Alca @  19.6.2009,  13:12 Найти цитируемый пост)

default:
  return::DefDlgProc(hWnd, uiMsg, wParam, lParam);

сколько раз повторять, не используйте условную посылку системных функций типа DefWindowProc, это источник массы неявных ошибок
поправка 3:
Цитата(Alca @  19.6.2009,  13:12 Найти цитируемый пост)
Stack overflow

неудивительно, тут же рекурсия
Цитата

::CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_dlgMain), NULL, NULL);

а в остальном, как я понимаю, раз идет рекурсия, значит свойство Class выставлено правильно, т.е. в TestWindowClass
после поправок 1 и 3, все должно работать


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Alca
Дата 19.6.2009, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



::DefDlgProc действительно был лишний и 
если диалог создается с ресурсов, то:
Код

wcex.cbWndExtra        = DLGWINDOWEXTRA;

GremlinProg, спасибо! Буду дальше разбираться.

Добавлено через 9 минут и 3 секунды
Хочу вступить в клуб волшебников!!!!  smile 


--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 19.6.2009, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Alca @  19.6.2009,  14:03 Найти цитируемый пост)
::DefDlgProc действительно был лишний

нет, Alca, ты не понял
DefDlgProc тут не лишний,
просто, когда в последний параметр CreateDialog ты ставишь lpMainProc,
то, тем самым, из lpMainProc делаешь обычную диалоговую процедуру (при этом, обычно компилятор ругается на несоответствие типов, там у колбэков типы обратных результатов разные),
а раз эта процедура является и процедурой окна,
то DefDlgProc, на всякий нулевой возврат из контекста диалоговой функции, будет вызывать его вновь и вновь, т.е. зациклится
можешь это проверить простым статическим счетчиком на любом единичном сообщении, типа WM_LBUTTONDOWN или WM_SHOWWINDOW

а про default, я все подробно объяснил тут: http://forum.vingrad.ru/forum/topic-260881...size/index.html
неочевидно, но, как видишь, есть очевидные прецеденты


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Alca
Дата 19.6.2009, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

просто, когда в последний параметр CreateDialog ты ставишь lpMainProc,
то, тем самым, из lpMainProc делаешь обычную диалоговую процедуру 
(при этом, обычно компилятор ругается на несоответствие типов, там у колбэков типы обратных результатов разные)

Так а чего туда писать надо?

Добавлено через 43 секунды
Цитата

там у колбэков типы обратных результатов разные

Видел WINPROC и DLGPROC.

Добавлено через 2 минуты и 59 секунд
Я просто убрал:
Код

        default:
            return ::DefDlgProc(hWnd, uiMsg, wParam, lParam);



--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 19.6.2009, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Alca @  19.6.2009,  14:54 Найти цитируемый пост)
Так а чего туда писать надо?

NULL
Цитата(Alca @  19.6.2009,  14:54 Найти цитируемый пост)
Я просто убрал:

это означает лишь то, что диалоговая процедура не будет вызвана, но и стандартный DefWindowProc - тоже

поясняю: из DefDlgProc вызывается DefWindowProc, это цепочка наследования диалога, а когда ты не вызываешь DefDlgProc, ты обрываешь эту цепочку, окно перестает нормально работать, т.е. лишается всего функционала, который давали ей эти процедуры


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Alca
Дата 19.6.2009, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

Цитата

Так а чего туда писать надо?

NULL

Так что ли? А как я буду обрабатывать сообщния? 
Код

g_hMainWnd = ::CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_dlgMain), NULL, (DLGPROC)NULL);


Это сообщение отредактировал(а) Alca - 19.6.2009, 15:45


--------------------
PM WWW ICQ Skype Jabber   Вверх
Alca
Дата 19.6.2009, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 5
Всего: 50



Цитата

Функция DefDlgProc не должна вызваться процедурой диалогового окна; поступив так, вы приведете ее к рекурсивному выполнению. (Примечание переводчика: то есть «подвесите» систему.)



--------------------
PM WWW ICQ Skype Jabber   Вверх
GremlinProg
Дата 21.6.2009, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Alca @  19.6.2009,  17:10 Найти цитируемый пост)
Так что ли?

да, именно так

Цитата(Alca @  19.6.2009,  17:10 Найти цитируемый пост)
А как я буду обрабатывать сообщния?

сообщения здесь обрабатывает уже процедура окна класса TestWindowClass
Цитата

Функция DefDlgProc не должна вызваться процедурой диалогового окна; поступив так, вы приведете ее к рекурсивному выполнению. (Примечание переводчика: то есть «подвесите» систему.)

когда ты передал в последний параметр NULL, ты тем самым сказал: "мне не нужна процедура диалогового окна, вместо этого у меня есть полноценная процедура окна для моего диалога, которая обрабатывает все что мне нужно", т.е. зацикливания тут не будет

Добавлено через 12 минут и 28 секунд
давай лучше так, чтобы не путаться:
есть процедура диалога,
а есть процедура окна диалога

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

понимаешь разницу между этими двумя процедурами?

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


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0811 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.