使用CreateWindowEx()创建两个Windows

时间:2010-04-05 22:37:02

标签: c winapi forms

我有一个窗体,有一个简单的菜单,并执行一个简单的操作,我希望能够创建另一个窗口表单,具有菜单栏,消息泵等的所有功能..作为一个单独的线程,所以我可以然后将操作结果分享到第二个窗口。

1)表格A打开表格B作为单独的帖子打开

2)表格A执行操作

3)表格A通过记忆将结果传递给表格B

4)表格B显示结果

我很困惑如何去做,主应用程序运行良好,但我不知道如果第一个窗口已经存在,如何添加第二个窗口。我认为使用CreateWindow将允许我创建另一个窗口但是我不知道如何访问消息泵,所以我可以在第二个窗口响应某些事件,如WM_CREATE。

我希望这是有道理的。

谢谢!

修改

我试图制作第二个窗口,虽然这确实可以编译,但是在构建时没有窗口显示。

//////////////////////
// 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 个答案:

答案 0 :(得分:4)

您应该能够使用CreateWindow()创建另一个辅助窗口,标准GetMessage()DispatchMessage()循环应该实际将窗口事件提供给两个窗口。 Windows将以某种方式将在CreateWindow上进行调用的线程与这些窗口上的窗口事件相关联,并通过调用GetMessage()将它们的事件提供给它。您不必创建第二个线程来处理第二个窗口的事件。

现在,如果将相同的窗口类名传递给两个对CreateWindow()的调用,则应该有两个相同窗口类的实例,并且区分它们的方式是,在wndproc中,DispatchMessage将为您提供窗口句柄到相关窗口。如果这样做,请注意任何对应用程序静态的数据实际上将成为这两个窗口之间的共享资源。例如,如果您静态声明一个屏幕外位图/设备上下文来支持WM_PAINT,您可能会突然发现两个窗口都显示为响应事件上的事件而绘制。获得这种纠缠的可能性是为了在线程之间轻松共享数据而付出的代价。

您可以通过仅使用一个线程来获得,前提是您打算使用它完成的工作不会将消息队列的处理限制在用户遇到滞后控制的位置。

答案 1 :(得分:2)

在您的CreateWindow()调用中,您将0传递给位置和大小参数 尝试修改你的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.

发表第二回复的道歉。我的另一个是一个非常普遍的回应,现在OP可能只是OBE提供了更多细节。