多次显示同一窗口

时间:2019-12-15 19:14:49

标签: c++ winapi visual-c++

我需要多次显示相同的窗口。但是,第二次显示该窗口时,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;
}

1 个答案:

答案 0 :(得分: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;
}