首页 > 解决方案 > Winapi:已注册但未创建的子窗口为父窗口提供背景色

问题描述

我正在尝试使用 winapi 创建一个 Windows 应用程序。所以我想要一个父窗口和一个子窗口。这是我的代码:

#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);

const char szChildName[] = "Child window title";
const UINT PM_COLORCHANGED = WM_APP + 1;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    MSG        msg;
    HWND       hWnd;
    WNDCLASS   wc;

    char       szAppName[] = "title";

    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = NULL;
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = (LPCWSTR)szAppName;
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClass(&wc);
    wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
    wc.hIcon = NULL;
    wc.lpfnWndProc = ChildProc;
    wc.lpszClassName = (LPCWSTR)szChildName;

    RegisterClass(&wc);

    hWnd = CreateWindow((LPCWSTR)szAppName,
        (LPCWSTR)szAppName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND    hChild;
    static RECT    rect;

    switch (message)
    {
    case WM_CREATE:
    {
        GetClientRect(hWnd, &rect);
        hChild = CreateWindow((LPCWSTR)szChildName,
            NULL,
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME,
            5,
            rect.bottom - 35,
            rect.right - 10,
            30,
            hWnd,
            NULL,
            ((LPCREATESTRUCT)lParam)->hInstance,
            NULL);
        return 0;
    }
    case WM_SIZE:
    {
        return 0;
    }
    case PM_COLORCHANGED:
    {
        return 0;
    }
    case WM_PAINT:
    {
        return 0;
    }
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_SIZE:
    {
        
        return 0;
    }
    case WM_LBUTTONDOWN:
    {
        
        return 0;
    }
    case WM_PAINT:
    {
        
        return 0;
    }
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

这很完美,所以我在应用程序底部看到了子窗口。但是,而不是WNDCLASS我想使用WNDCLASSEX,这迫使我使用RegisterClassEx()来注册窗口。我也想使用CreateWindowEx,我的代码如下所示:

#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);

const char szChildName[] = "Child name";
const UINT PM_COLORCHANGED = WM_APP + 1;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    MSG        msg;
    HWND       hWnd;
    WNDCLASSEX   wc;

    char       szAppName[] = "The Child Window";

    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbClsExtra = 0;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = NULL;
    wc.hIconSm = NULL;
    wc.hInstance = hInstance;
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.lpszClassName = (LPCWSTR)szAppName;
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClassEx(&wc);

    wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
    wc.hIcon = NULL;
    wc.lpfnWndProc = (WNDPROC)ChildProc;
    wc.lpszClassName = (LPCWSTR)szChildName;

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL,
        wc.lpszClassName,
        L"parent window",
        (WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU),
        200,
        150,
        1000,
        1000,
        NULL,
        NULL,
        hInstance,
        NULL               
    );

    

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND    hChild;
    static RECT    rect;

    switch (message)
    {
    case WM_CREATE:
    {
        GetClientRect(hWnd, &rect);
        hChild = CreateWindowEx(NULL,
           (LPCWSTR)szChildName,
            L"child window",
            (WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
            200,
            150,
            200,
            200,
            hWnd,
            NULL,
            ((LPCREATESTRUCT)lParam)->hInstance,
            NULL
        );

        return 0;
    }
    case WM_SIZE:
    {
        return 0;
    }
    case PM_COLORCHANGED:
    {
        return 0;
    }
    case WM_PAINT:
    {
        return 0;
    }
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    

    switch (message)
    {
    case WM_SIZE:
    {
        
        return 0;
    }
    case WM_LBUTTONDOWN:
    {
        
        return 0;
    }
    case WM_PAINT:
    {
        
        return 0;
    }
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

问题:现在我只看到子窗口的颜色,所以整个应用程序都有子窗口的背景颜色,所以电脑以某种方式重新绘制了子窗口颜色的所有内容。(甚至没有子窗口可见,我看到的只是子窗口的这个 LTGRAY_Brush。

奇怪的是:如果我删除创建子窗口的行,那么这一行:

hChild = CreateWindowEx(NULL,
           (LPCWSTR)szChildName,
            L"child window",
            (WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
            200,
            150,
            200,
            200,
            hWnd,
            NULL,
            ((LPCREATESTRUCT)lParam)->hInstance,
            NULL 

然后即使是现在,背景颜色也与我注册子类的颜色相同。尽管尚未创建子类。谢谢你的帮助。

标签: c++winapi

解决方案


推荐阅读