Создание двух Windows с помощью CreateWindowsEx () - PullRequest
2 голосов
/ 06 апреля 2010

У меня есть форма окна, которая имеет простое меню и выполняет простую операцию, я хочу иметь возможность создать другую форму окна со всеми функциями строки меню, сообщения и т. Д. Как отдельную ветку, чтобы я могла затем поделитесь результатами операции во втором окне.

И.Е.

1) Открывается форма A Открывается форма B как отдельная тема

2) Форма А выполняет операцию

3) Форма A передает результаты по памяти в форму B

4) Результаты отображения формы B

Я не совсем понимаю, как это сделать, главное приложение работает нормально, но я не уверен, как добавить второе окно, если первое уже существует. Я думаю, что использование CreateWindow позволит мне создать другое окно, но опять же я не уверен, как получить доступ к насосу сообщений, чтобы я мог отвечать на определенные события, такие как WM_CREATE во втором окне.

Надеюсь, это имеет смысл.

Спасибо!

Edit:

Я попытался создать второе окно, и хотя это компилируется, окна не отображаются при сборке.

//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
    //Fields
    WCHAR buffer[256];
    struct DiceData storage;
    HWND hwnd;

    // Act on current message
    switch(message)    
    {
    case WM_CREATE:
        AddMenus(hMainWindow);

        hwnd = CreateWindowEx(
            0,
            "ChildWClass",
            (LPCTSTR) NULL,
            WS_CHILD | WS_BORDER | WS_VISIBLE,
            0,
            0,
            0,
            0,
            hMainWindow,
            NULL,
            NULL,
            NULL);

        ShowWindow(hwnd, SW_SHOW);

        break;

Любые предложения относительно того, почему это происходит?

Редактировать 2:

Это все, что есть, я понятия не имею, реализую ли я это право, но я пытался быть совместимым с созданием другого окна.

//////////////////
// WINDOWS MAIN //
//////////////////
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, 
                   LPSTR lpszArgs, int nWinMode)
{
    // Declaration of window class (used to register program), 
    // handle to window (returned by CreateWindow)
    // and windows message (holds messages received from windows)
    WNDCLASS wcl;
    WNDCLASS scl;
    HWND hwnd;
    MSG msg;

    // Name of window and window class
    LPCWSTR szWinName   = L"DiceRoller - Producer";
    LPCWSTR szClassName = L"DiceRollProd";

    LPCWSTR szCWinName = L"Dice - Consumer";
    LPCWSTR szCClassName = L"DiceRollCon";

    // Set up the windows class struct
    wcl.hInstance = hThisInst;
    wcl.lpszClassName = szClassName;
    wcl.lpfnWndProc = WindowFunc;
    wcl.style = 0;
    wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcl.lpszMenuName = NULL;
    wcl.cbClsExtra = 0;
    wcl.cbWndExtra = 0;
    wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    // Set up the windows class struct
    scl.hInstance = hThisInst;
    scl.lpszClassName = szCClassName;
    scl.lpfnWndProc = WindowFunc;
    scl.style = 0;
    scl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    scl.hCursor = LoadCursor(NULL, IDC_ARROW);
    scl.lpszMenuName = NULL;
    scl.cbClsExtra = 0;
    scl.cbWndExtra = 0;
    scl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    // Register the windows class
    if(!RegisterClass(&wcl))
    {
        return 0;
    }

    if(!RegisterClass(&scl))
    {
        return 0;
    }

    // Create the main window
    hwnd = CreateWindowEx(0,
        szClassName,
        szWinName,
        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
        100,
        100,
        400,
        400,
        HWND_DESKTOP,
        NULL,
        hThisInst,
        NULL );


    // Show the main window
    ShowWindow(hwnd, nWinMode);
    UpdateWindow(hwnd);

    // Main message processing loop
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}



//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
    //Fields
    WCHAR buffer[256];
    struct DiceData storage;
    HWND hwnd;

    // Act on current message
    switch(message)    
    {
    case WM_CREATE:
        AddMenus(hMainWindow);

        hwnd = CreateWindowEx(
        0,
        "ChildWClass",
        (LPCTSTR) NULL,
        WS_CHILD | WS_BORDER | WS_VISIBLE,
        CW_USEDEFAULT,  // x location
        CW_USEDEFAULT,  // y location
        400,  // width
        300,  // height
        hMainWindow,
        NULL,
        NULL,
        NULL);

        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);

        break;

Ответы [ 2 ]

4 голосов
/ 06 апреля 2010

Вы должны иметь возможность создать другое, вторичное окно, используя CreateWindow (), и стандартный цикл DispatchMessage () GetMessage () должен фактически передавать события окна обоим окнам. Windows каким-то образом связывает поток, который делает вызовы CreateWindow с событиями окна в этих окнах, и передает события для них обоих через свои вызовы GetMessage (). Вам не нужно создавать второй поток для обработки событий для второго окна.

Теперь, если вы передаете одно и то же имя класса окна обоим вызовам CreateWindow (), у вас должно быть два экземпляра одного и того же класса окна, и способ их различения заключается в том, что в wndproc DispatchMessage даст вам дескриптор окна к соответствующему окну. Если вы сделаете это, имейте в виду, что любые данные, которые являются статическими для приложения, в действительности станут общим ресурсом между обоими этими окнами. Например, если вы статически объявляете закадровый контекст растрового изображения / устройства для поддержки своих WM_PAINT, вы можете внезапно обнаружить, что оба ваших окна, по-видимому, рисуют в ответ на события на одном из них. Возможности получения такого рода путаницы - это цена, которую вы платите за удобство обмена данными между потоками.

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

2 голосов
/ 08 апреля 2010

При вызове CreateWindow () вы передаете 0 в параметры location и size.
Попробуйте изменить ваш случай WM_CREATE следующим образом ..

case WM_CREATE:
    AddMenus(hMainWindow);

    hwnd = CreateWindowEx(
        0,
        "ChildWClass",
        (LPCTSTR) NULL,
        WS_CHILD | WS_BORDER | WS_VISIBLE,
        CW_USEDEFAULT,  // x location
        CW_USEDEFAULT,  // y location
        400,  // width
        300,  // height
        hMainWindow,
        NULL,
        NULL,
        NULL);

    ShowWindow(hwnd, SW_SHOW);

    break;

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

#include <windows.h>
LRESULT CALLBACK TheWndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    HDC hdc;
    HWND hwother;

    switch( msg ) {
    case WM_CREATE:
        hwother =
        CreateWindowEx(0, "TerribleClassName100405", "child title",
            WS_OVERLAPPEDWINDOW,
            100, 100, // location
            200, 160,  // size
            (HWND)hwnd,  // parent
            (HMENU)NULL,
            NULL,
            NULL);
        ShowWindow(hwother, SW_SHOW);

        break;

    case WM_CHAR: // quit app using escape key
        switch( LOWORD(wP) ) {
        case 27:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd, msg, wP, lP);
}

LRESULT CALLBACK AltWndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    HDC hdc;

    switch( msg ) {
    case WM_CREATE:
        break;

    case WM_CHAR: // quit app using X
        switch( LOWORD(wP) ) {
        case 'X':
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd, msg, wP, lP);
}

void registerCustomWindows(HINSTANCE hInst) {
    WNDCLASSEX wc1;
    WNDCLASSEX wc2;

    wc1.lpszClassName = "TerribleClassName040914";
    wc1.hInstance = hInst;
    wc1.lpfnWndProc = TheWndProc;
    wc1.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc1.cbSize = sizeof(wc1);
    wc1.cbClsExtra = 0;
    wc1.cbWndExtra = 0;
    wc1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc1.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc1.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc1.hbrBackground = GetStockObject(WHITE_BRUSH);
    wc1.lpszMenuName = NULL;
    RegisterClassEx(&wc1);

    wc2.lpszClassName = "TerribleClassName100405";
    wc2.hInstance = hInst;
    wc2.lpfnWndProc = AltWndProc;
    wc2.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc2.cbSize = sizeof(wc2);
    wc2.cbClsExtra = 0;
    wc2.cbWndExtra = 0;
    wc2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc2.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc2.hbrBackground = GetStockObject(WHITE_BRUSH);
    wc2.lpszMenuName = NULL;
    RegisterClassEx(&wc2);
}

int WINAPI WinMain(HINSTANCE hThis, HINSTANCE hPrev, LPSTR cml, int iCS) {
    MSG msg;
    HWND hwnd;

    registerCustomWindows(hThis);

    hwnd = CreateWindowEx(0, "TerribleClassName040914", "two windows skeleton",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,   // location
        640, 480,   // size
        (HWND)NULL, // parent
        (HMENU)NULL,
        hThis,
        NULL);

    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);

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

У меня есть этот точный код в файле с именем demo.c, и я использую MS visual studio express 2005 для его компиляции с использованием строки

cl demo.c user32.lib gdi32.lib

.. и у меня два окна. Просто чтобы различить тот факт, что у меня есть два оконных класса, один из которых закрывается нажатием ESC, а другой - в верхнем регистре X.

Извинения за публикацию второго ответа. Мой другой был очень обобщенным ответом и может быть просто ОБЕ, теперь, когда ОП предоставил больше деталей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...