Win32 API 打开新窗口

Posted

技术标签:

【中文标题】Win32 API 打开新窗口【英文标题】:Win32 API open new window 【发布时间】:2020-07-24 13:20:29 【问题描述】:

我正在学习 Win32 API。在我的主/第一个窗口中,我想要一个打开窗口 2 按钮,然后打开一个新窗口。 所以想法是,当按下按钮时,会调用一个函数来打开窗口 2。 但是我不确定如何在这里调用这个函数:

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

     switch (message)
    
        case WM_COMMAND:
        
            switch(wParam) 
            case OPEN_WINDOW2_BUTTON:
                                      // <------------------------- what do I put here?
            
        
        case WM_CREATE:
            AddControls1(hwnd);
            break;
        
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:

            return DefWindowProc (hwnd, message, wParam, lParam);
        
        return 0;

这是我的全部代码:

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#include <tchar.h>
#include <iostream>
#include <tchar.h>
#include <windows.h>


#define OPEN_WINDOW2_BUTTON 1

using namespace std;

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow2,UINT message,WPARAM wParam,LPARAM lParam);

void AddControls1(HWND);
void createwindow2 (WNDCLASSEX wincl_2, HWND& hwnd, HINSTANCE hThisInstance, int nCmdShow);

HWND hMainWindow, hwnd, hHeader;

TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain(HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)

    bool endprogram=false;

    //create window 1

    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl_1;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl_1.hInstance = hThisInstance;
    wincl_1.lpszClassName = szClassName;
    wincl_1.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl_1.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl_1.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl_1.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl_1.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl_1.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl_1.lpszMenuName = NULL;                 /* No menu */
    wincl_1.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl_1.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl_1.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 //----

    if (!RegisterClassEx (&wincl_1))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           1800,                 /* The programs width */
           920,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
    /* Make the window visible on the screen */
    ShowWindow(hwnd,nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;


void createwindow2 (WNDCLASSEX wincl_2, HWND& hwnd, HINSTANCE hThisInstance, int nCmdShow)

    if (!RegisterClassEx (&wincl_2))
    wincl_2.hInstance = hThisInstance;
    wincl_2.lpszClassName = szClassName;
    wincl_2.lpfnWndProc = (WNDPROC)windowprocessforwindow2;      /* This function is called by windows */
    wincl_2.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl_2.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl_2.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl_2.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl_2.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl_2.lpszMenuName = NULL;                 /* No menu */
    wincl_2.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl_2.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl_2.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    HWND handleforwindow2 = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           330,                 /* The programs width */
           320,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
    /* Make the window visible on the screen */
    ShowWindow(handleforwindow2,nCmdShow);


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

     switch (message)
    
        case WM_COMMAND:
        
            switch(wParam) 
            case OPEN_WINDOW2_BUTTON:
                                      // <------------------------- what do I put here?
            
        
        case WM_CREATE:
            AddControls1(hwnd);
            break;
        
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:

            return DefWindowProc (hwnd, message, wParam, lParam);
        
        return 0;


LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow2,UINT msg,WPARAM wParam,LPARAM lParam)

    switch(msg)
    
         case WM_COMMAND:
        
            switch(wParam) 

            
        
        case WM_CREATE:
            AddControls1(hwnd);
            break;
        
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:

    return DefWindowProc(handleforwindow2,msg,wParam,lParam);
    
    return 0;


void AddControls1(HWND hwnd)

    CreateWindowW(L"Button",L" Open Window 2", WS_VISIBLE | WS_CHILD, 215,285,300,30,hwnd, (HMENU)OPEN_WINDOW2_BUTTON,NULL,NULL);



任何帮助将不胜感激。谢谢!

【问题讨论】:

如果你有第二个窗口,那么你必须像第一个窗口一样。创建它,然后显示它。 修复 AddControls1 以创建类似于您最初所做的子窗口并在您的按钮处理程序中调用 AddControls1。看起来您已经在 WM_CREATE 中调用它但没有显示它(ShowWindow)。 您还需要指定新窗口的行为,我的意思是您希望新窗口替换旧窗口还是像弹出窗口一样 【参考方案1】:

首先,可以通过GetWindowLong函数获取应用的实例句柄。

然后创建一个WNDCLASSEX 结构并将其传递给您的createwindow2 函数。

最后在OPEN_WINDOW2_BUTTON消息中调用(原createwindow2函数中的hwnd参数不需要了)。

修改后的代码如下:

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include <tchar.h>
#include <iostream>
#include <tchar.h>
#include <windows.h>


#define OPEN_WINDOW2_BUTTON 1

using namespace std;

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow2, UINT message, WPARAM wParam, LPARAM lParam);

void AddControls1(HWND);
void createwindow2(WNDCLASSEX& wincl_2, HINSTANCE& hThisInstance, int nCmdShow);
void AddControls2(HWND hwnd);
HWND hMainWindow, hwnd, hHeader;

TCHAR szClassName[] = _T("CodeBlocksWindowsApp");
TCHAR szClassName2[] = _T("CodeBlocksWindowsApp2");

int WINAPI WinMain(HINSTANCE hThisInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpszArgument,
    int nCmdShow)

    bool endprogram = false;

    //create window 1

    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl_1;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl_1.hInstance = hThisInstance;
    wincl_1.lpszClassName = szClassName;
    wincl_1.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl_1.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl_1.cbSize = sizeof(WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl_1.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl_1.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl_1.hCursor = LoadCursor(NULL, IDC_ARROW);
    wincl_1.lpszMenuName = NULL;                 /* No menu */
    wincl_1.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl_1.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl_1.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    //----

    if (!RegisterClassEx(&wincl_1))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx(
        0,                   /* Extended possibilites for variation */
        szClassName,         /* Classname */
        _T("Code::Blocks Template Windows App"),       /* Title Text */
        WS_OVERLAPPEDWINDOW, /* default window */
        CW_USEDEFAULT,       /* Windows decides the position */
        CW_USEDEFAULT,       /* where the window ends up on the screen */
        1800,                 /* The programs width */
        920,                 /* and height in pixels */
        HWND_DESKTOP,        /* The window is a child-window to desktop */
        NULL,                /* No menu */
        hThisInstance,       /* Program Instance handler */
        NULL                 /* No Window Creation data */
    );
    /* Make the window visible on the screen */
    ShowWindow(hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage(&messages, NULL, 0, 0))
    
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;


void createwindow2(WNDCLASSEX &wincl_2,HINSTANCE &hThisInstance, int nCmdShow)

    wincl_2.hInstance = hThisInstance;
    wincl_2.lpszClassName = szClassName2;
    wincl_2.lpfnWndProc = (WNDPROC)windowprocessforwindow2;      /* This function is called by windows */
    wincl_2.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl_2.cbSize = sizeof(WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl_2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl_2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl_2.hCursor = LoadCursor(NULL, IDC_ARROW);
    wincl_2.lpszMenuName = NULL;                 /* No menu */
    wincl_2.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl_2.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl_2.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    if (!RegisterClassEx(&wincl_2))
        return;
    HWND handleforwindow2 = CreateWindowEx(
        0,                   /* Extended possibilites for variation */
        szClassName2,         /* Classname */
        _T("Code::Blocks Template Windows App"),       /* Title Text */
        WS_OVERLAPPEDWINDOW, /* default window */
        CW_USEDEFAULT,       /* Windows decides the position */
        CW_USEDEFAULT,       /* where the window ends up on the screen */
        330,                 /* The programs width */
        320,                 /* and height in pixels */
        HWND_DESKTOP,        /* The window is a child-window to desktop */
        NULL,                /* No menu */
        hThisInstance,       /* Program Instance handler */
        NULL                 /* No Window Creation data */
    );
    /* Make the window visible on the screen */
    ShowWindow(handleforwindow2, nCmdShow);


LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

    switch (message)
    
        static HINSTANCE hInstance;
    case WM_COMMAND:
    
        switch (wParam) 
        case OPEN_WINDOW2_BUTTON:
        
            WNDCLASSEX w2;
            hInstance = (HINSTANCE)::GetWindowLong(hwnd, GWL_HINSTANCE);
            createwindow2(w2, hInstance,SW_SHOW);
                                      // <------------------------- what do I put here?
        
    
    case WM_CREATE: 
        AddControls1(hwnd);
        break;
    
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:

        return DefWindowProc(hwnd, message, wParam, lParam);
    
    return 0;


LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow2, UINT msg, WPARAM wParam, LPARAM lParam)

    switch (msg)
    
    case WM_COMMAND:
    
        switch (wParam) 

        
    
    return 0;
    case WM_CREATE: 
        AddControls2(handleforwindow2);
        break;
    
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:

        return DefWindowProc(handleforwindow2, msg, wParam, lParam);
    
    return 0;


void AddControls1(HWND hwnd)

    CreateWindowW(L"Button", L" Open Window 2", WS_VISIBLE | WS_CHILD, 215, 285, 300, 30, hwnd, (HMENU)OPEN_WINDOW2_BUTTON, NULL, NULL);


void AddControls2(HWND hwnd)

    CreateWindowW(L"Button", L" A NEW WINDOW", WS_VISIBLE | WS_CHILD, 215, 285, 300, 30, hwnd, (HMENU)2, NULL, NULL);

【讨论】:

非常感谢 :) 它现在有效,我明白了。 是的,我做到了。所以我现在测试你的代码。打开的第二个窗口与第一个窗口具有相同的按钮。第二个窗口怎么会有不同的按钮? windowprocessforwindow2函数中,您可以将AddControls1函数更改为其他创建函数来创建您需要的按钮或其他窗口。 所以在 LRESULT CALLBACK windowprocessforwindow2 中,在 WM_CREATE 的情况下,我添加了一个新的 AddControls2 函数。但是窗口 2 仍然只显示 Addcontrols1 按钮。在调试器中,我看到这个 LRESULT CALLBACK windowprocessforwindow2 从未被执行。 你应该在wincl_2的定义之后调用RegisterClassEx函数,记住AddControl传入的参数应该是handleforwindow2

以上是关于Win32 API 打开新窗口的主要内容,如果未能解决你的问题,请参考以下文章

widnows 使用WIN32 APi 实现修改另一打开程序的窗口显示方式

WPF点击按钮怎样打开新窗口?

包装 Win32 的库不会在 Visual Studio 中打开窗口

opengl窗口中,拾取物体后,如何弹出新窗口,并在新窗口里显示所拾取物体

ie8浏览器打开网页自动弹出新窗口问题如何解决、

使用 TCP 套接字 (WIN32 API) 创建的两个窗口之间的通信