Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

WM_CREATE и 2 WINDOW в одной нити

287
18 сентября 2009 года
Shiizoo
958 / / 14.03.2004
Привет. Такой вопрос от CPP/WINAPI/ETC rookie: возможно ли в оконном приложении, крутящемся на одной нити, создать второе окно с отдельной WndProc (WndProc2, скажем), и обработать в этой WndProc2 сообщение WM_CREATE. Я не очень понимаю, как win там внутри с этим работает, но полагаю, что пока WndProc (первая, первого окна) не вернет что-либо, WndProc2 не сработает. А если так, то WndProc2 может сработать только после вызова CreateWindow(Ex) (для создания этого второго окна), а тогда WM_CREATE уже морально устареет. Собственно, в такой ситуации я и не могу получить этот самый WM_CREATE для второго окна. Аналогично еще с некоторыми сообщениями, который тоже обещают появиться как раз перед чем-то, что обуславливает та или иная API функция.
Как я уже написал, опыта/знаний в этом деле с гулькин нос, а вот Рихтер (в книге) советует UI обрабатывать в одной нити. Как быть? Создавать все таки еще одну нить, или же просто я что-то не так делаю. Может, кто-нибудь каркас кода для правильной работы в такой ситуации даст? Спасибо.
399
18 сентября 2009 года
KIV
432 / / 20.01.2009
Окно обрабатывает ВСЕ сообщения, которые ему адресованны. Окно Windows не может обычными способами (я не знаю, может вообще не может) перехватить сообщения для других окон. КАЖДОМУ окну при создании посылается сообщение WM_CREATE. А разделение UI между нитями вообще не рекомендуется т. к. возникнут проблемы с синхранизацией. Если это вообще возможно. Ведь может так получится, что все сообщения пойдут на первую нить с GetMessage. А код приблизительно такой:
 
Код:
<Подготовка структур WNDCLASS и их регистрация с помощью RegisterClass>
<Создание окон с помощью CreateWindowEx>
<Цикл GetMessage, TranslateMessage, DispatchMessage>
<Завершение приложния>
287
19 сентября 2009 года
Shiizoo
958 / / 14.03.2004
Не очень понял терминологию. Окно вообще ничего не обрабатывает. Вроде. =) Обрабатывает функция. Функция в нити. Так что скорее нить может или не может. Впрочем, детали это. Приведенный каркас понятен, знаком, используется и тут вопросов вообще нет. Собственно, проблема поменялась. WM_CREATE теперь получается, но неясно, почему получается. =) См. код ниже.

Код:
#include "smm.h"

int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE, //legacy parameter
                       LPTSTR   lpCmdLine,
                       int      nCmdShow)
{
    MSG msg;

    if (0 == MyRegisterClass(
        CS_HREDRAW | CS_VREDRAW,
        WndProc,
        0,
        0,
        hInstance,
        NULL,
        NULL,
        (HBRUSH)(COLOR_WINDOW + 1),
        NULL,
        "APP1_MAIN",
        NULL))
    {
        return 1;
    }

    if (0 == MyRegisterClass(
        CS_HREDRAW | CS_VREDRAW,
        WndProc2,
        0,
        0,
        hInstance,
        NULL,
        NULL,
        (HBRUSH)(COLOR_WINDOW + 1),
        NULL,
        "APP1_CHILD",
        NULL))
    {
        return 1;
    }
   
    hInst = hInstance;

    hwndMain = CreateWindowEx(0, "APP1_MAIN", "APP1_MAIN", WS_OVERLAPPEDWINDOW,
        15, 15, 200, 200, NULL, NULL, hInst, NULL);

    if (!hwndMain)
    {
        return 1;
    }
   
    ShowWindow(hwndMain, nCmdShow);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(UINT style, WNDPROC lpfnWndProc,
                     int cbClsExtra, int cbWndExtra,
                     HINSTANCE hInstance, HICON hIcon,
                     HCURSOR hCursor, HBRUSH hbrBackground,
                     LPCSTR lpszMenuName,
                     LPCSTR lpszClassName, HICON hIconSm)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = style;
    wcex.lpfnWndProc    = lpfnWndProc;
    wcex.cbClsExtra     = cbClsExtra;
    wcex.cbWndExtra     = cbWndExtra;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = hIcon;
    wcex.hCursor        = hCursor;
    wcex.hbrBackground  = hbrBackground;
    wcex.lpszMenuName   = lpszMenuName;
    wcex.lpszClassName  = lpszClassName;
    wcex.hIconSm        = hIconSm;

    return RegisterClassEx(&wcex);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static bool click = false;

    switch (message)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONUP:
            if (!click)
            {
                hwndChild = CreateWindowEx(0, "APP1_CHILD", "APP1_CHILD", WS_OVERLAPPEDWINDOW,
                    40, 40, 200, 200, hwndMain, NULL, hInst, NULL);

                while(true);

                if (!hwndChild)
                {
                    PostQuitMessage(0);
                }
               
                UpdateWindow(hwndChild);

                ShowWindow(hwndChild, SW_SHOW);

                click = true;
            }
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (WM_CREATE == message)
    {
        MessageBox(hwndMain, "WM_CREATE received", "NOTICE", MB_OK | MB_TOPMOST);
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}


Прога регистрирует два класса для окон, создает окно для первого класса и по клику в этом окне создает второе окно. Причем сразу после создания второго окна отправляется в бесконечный цикл. Только перед этим циклом успевает выдать месджбокс, а ведь он вызывается по событию WM_CREATE для второго окна. Каким образом нить умудряется перескочить из бесконечного цикла в WndProc2, а затем обратно? Далее оба окна намертво висят, т. е. больше таких скачков из wndProc в WndProc2 не случается. Я полагал, что пока WndProc (любая) не вернет значение, никакие другие сообщения обработаны не будут. Однако получается что нет. Поделитесь мыслями, знаниями, ссылками на источники, где этот вопрос разъясняется. У меня только догадки.

---

Нашел ответ дебаггером. CreateWindow перед возвратом вызывает _InternalCallWinProc@20, которая передает управление WndProc создаваемого окна. Теперь стало яснее. =)
399
19 сентября 2009 года
KIV
432 / / 20.01.2009
Конечно же. При создании окна ему сразу же посылается WM_CREATE, WM_SIZE, WM_PAINT и многое другое. А зачем бесконечный цикл? Ты его для проверки вставил? Модальные окна иначе создаются.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог