开发者

Making two Windows using CreateWindowsEx()

开发者 https://www.devze.com 2022-12-25 23:23 出处:网络
I have a windows form that has a simple menu and performs a simple operation, I want to be able to create another windows form with all the functionality of a menu bar, message pump etc.. as a separat

I have a windows form that has a simple menu and performs a simple operation, I want to be able to create another windows form with all the functionality of a menu bar, message pump etc.. as a separate thread so I can then share the results of the operation to the second window.

I.E.

1) Form A opens Form B opens as a separate thread

2)Form A performs operation

3)Form A passes results via memory to Form B

4)Form B display results

I'm confused as to how to go about it, the main app runs fine but i'm not sure how to add a second window if the first one already exists. I think that using CreateWindow will allow me to make another window but again i'm not sure how to access the message pump so I can respond to certain events like WM_CREATE on the second window.

I hope it makes sense.

Thanks!

Edit:

I've attempted to make a second window and although this does compile, no windows show atall on build.

//////////////////////
// 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;

Any suggestions as to why this happens?

Edit 2:

This is everything there is, I've no idea if I'm implementing this right but I've tried to be consistent with the other window creation.

//////////////////
// 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;
  开发者_Python百科  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;


You should be able to create another, secondary window using CreateWindow(), and the standard GetMessage() DispatchMessage() loop should actually feed window events to both of the windows. Windows will somehow associate the thread that makes the calls on CreateWindow with the window events on those windows, and feed the events for both of them to it through its calls to GetMessage(). You shouldn't have to make a second thread to process the events for the second window.

Now, if you pass the same window class name to both calls to CreateWindow(), you should have two instances of the same window class, and the way you distinguish them is that, in the wndproc, DispatchMessage will give you the window handle to the relevant window. If you do that, be aware that any data that is static to the application will in effect become a shared resource between both of those windows. For example, if you statically declare an offscreen bitmap/device context to back your WM_PAINTs, you might suddenly find both your windows apparently painting in response to events on the one. The possibilities for getting this kind of entanglement are the price you pay for the benefit of easily sharing data between threads.

You might be able to get by using just the one thread, provided that the work you intend to do with it doesn't tie up processing of the message queue to the point where the user experiences laggy controls.


In your CreateWindow() call you are passing 0's into the location and size parameters.
Try revising your WM_CREATE case like so..

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;

Here's an interpretation of what I think you're trying to do, at least w/regard to the child window. (I still don't see why a second thread is needed, but one problem at a time..)

#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;
}

I have that exact code in a file called demo.c, and use MS visual studio express 2005 to compile it using the line

cl demo.c user32.lib gdi32.lib

.. and I get two windows. Just to distinguish the fact I have two window classes, one of them quits via pressing ESC and the other upper case X.

Apologies for posting a 2nd response. My other one was a very generalized response and may just be OBE now that the OP has supplied more detail.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号