多次显示同一个窗口

Posted

技术标签:

【中文标题】多次显示同一个窗口【英文标题】:show the same window several times 【发布时间】:2019-12-15 19:14:49 【问题描述】:

我需要。但是,第二次显示窗口时,调用 RegisterClassEx 时出现错误,即 ERROR_CLASS_ALREADY_EXISTS,这似乎是合理的。如果我要,是否可以忽略此错误并继续执行程序?

#include <Windows.h>
#include <tchar.h>
#include <WinUser.h>
#include <sstream>
#include <Commctrl.h>

#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "comctl32.lib")

#define WIDTH_WINDOW 378
#define HEIGHT_WINDOW 171

#define LEFT_BUTTON_YES 170
#define TOP_BUTTON_YES 96
#define WIDTH_BUTTON_YES 88
#define HEIGHT_BUTTON_YES 26


void test();
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void show_message(HWND parent,int wndState);

WORD result;
HWND YesButton;

void show_message(HWND parent,int wndState) 
    MSG messages;
    WNDCLASSEX wincl;
    ZeroMemory(&wincl, sizeof(wincl));
    wincl.hInstance = GetModuleHandle(NULL);
    HINSTANCE instance = wincl.hInstance;
    wincl.lpszClassName = L"WindowsApp";
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof(wincl);
    wincl.hCursor = LoadCursor(NULL, IDC_ARROW);

    if (!RegisterClassEx (&wincl)) 

        auto err = GetLastError();
        std::wostringstream ss;
        wchar_t *text = L"error: ";
        ss << text << err;
        MessageBox(NULL,ss.str().c_str(),L"RegisterClassEx",0);
        return;

    

    HWND hwnd = CreateWindow(L"WindowsApp", L"Some Error", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |WS_POPUP|WS_CLIPSIBLINGS,CW_USEDEFAULT, CW_USEDEFAULT,  WIDTH_WINDOW, HEIGHT_WINDOW, parent,  NULL,  instance,NULL 
    );
    YesButton = CreateWindow(L"BUTTON",L"&Yes",BS_DEFPUSHBUTTON |WS_TABSTOP | WS_VISIBLE | WS_CHILD,LEFT_BUTTON_YES,TOP_BUTTON_YES,WIDTH_BUTTON_YES,HEIGHT_BUTTON_YES, hwnd, NULL, instance,NULL);

    ShowWindow(hwnd, wndState);
    UpdateWindow(hwnd);

    while (GetMessage(&messages, NULL, 0, 0) >0)
    
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    


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

    HDC hdcStatic = (HDC)wParam;
    switch (message)
    
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_COMMAND:
            switch(HIWORD(wParam)) 
                case BN_CLICKED:
                    if((HWND)lParam == YesButton) 
                        result = IDYES;
                    
                    break;
            
            DestroyWindow(hwnd);
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    

    return 0;


void test() 

    size_t times = 2;
    do 
        show_message(NULL,1);
        if(result == IDYES) 
            result = 0;
            MessageBox(NULL,L"yes",L"button",0);
        
        Sleep(2000);
    while(--times);


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

    test();

    return 0;

【问题讨论】:

您只需拨打RegisterClassEx一次(同一班) 为什么投反对票? Get Started with Win32 and C++. 第二次调用RegisterClassEx 失败,因为该类已经注册。因此,只需在程序开始时调用一次RegisterClassEx 【参考方案1】:

提取RegisterClassEx的函数,放在应用程序的开头。正如评论所说,您只需执行一次,应用程序终止时将被取消注册。

#include <Windows.h>
#include <tchar.h>
#include <WinUser.h>
#include <sstream>
#include <Commctrl.h>

#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "comctl32.lib")

#define WIDTH_WINDOW 378
#define HEIGHT_WINDOW 171

#define LEFT_BUTTON_YES 170
#define TOP_BUTTON_YES 96
#define WIDTH_BUTTON_YES 88
#define HEIGHT_BUTTON_YES 26


void test();
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void show_message(HWND parent, int wndState);

WORD result;
HWND YesButton;
void MyRegisterClass()


    WNDCLASSEX wincl;
    ZeroMemory(&wincl, sizeof(wincl));
    wincl.hInstance = GetModuleHandle(NULL);
    HINSTANCE instance = wincl.hInstance;
    wincl.lpszClassName = L"WindowsApp";
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof(wincl);
    wincl.hCursor = LoadCursor(NULL, IDC_ARROW);

    if (!RegisterClassEx(&wincl)) 

        auto err = GetLastError();
        std::wostringstream ss;
        wchar_t text[] = L"error: ";
        ss << text << err;
        MessageBox(NULL, ss.str().c_str(), L"RegisterClassEx", 0);
    
    return;

void show_message(HWND parent, int wndState) 

    MSG messages;
    HWND hwnd = CreateWindow(L"WindowsApp", L"Some Error", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_POPUP | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH_WINDOW, HEIGHT_WINDOW, parent, NULL, GetModuleHandle(NULL), NULL);
    YesButton = CreateWindow(L"BUTTON", L"&Yes", BS_DEFPUSHBUTTON | WS_TABSTOP | WS_VISIBLE | WS_CHILD, LEFT_BUTTON_YES, TOP_BUTTON_YES, WIDTH_BUTTON_YES, HEIGHT_BUTTON_YES, hwnd, NULL, GetModuleHandle(NULL), NULL);

    ShowWindow(hwnd, wndState);
    UpdateWindow(hwnd);

    while (GetMessage(&messages, NULL, 0, 0) > 0)
    
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    


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

    HDC hdcStatic = (HDC)wParam;
    switch (message)
    
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_COMMAND:
        switch (HIWORD(wParam)) 
        case BN_CLICKED:
            if ((HWND)lParam == YesButton) 
                result = IDYES;
            
            break;
        
        DestroyWindow(hwnd);
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    

    return 0;


void test() 

    size_t times = 2;
    do 
        show_message(NULL, 1);
        if (result == IDYES) 
            result = 0;
            MessageBox(NULL, L"yes", L"button", 0);
        
        Sleep(2000);
     while (--times);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

    MyRegisterClass();
    test();

    return 0;

【讨论】:

以上是关于多次显示同一个窗口的主要内容,如果未能解决你的问题,请参考以下文章

在窗口中显示任何内容之前和窗口抛光后无法进行介绍

#JS 窗口resize避免触发多次

qt多次调用函数显示多张图片

ubuntu上的窗口出现在屏幕外[关闭]

面试基础知识准备,博客汇总

想让JS弹出窗口显示在第二个(辅助)显示器上?