C语言创建两个窗口为什么第二个窗口背景颜色跟第一个一样?

今天写了这样一段代码:
#include "windows.h"
#include "pthread.h"

HWND hWnd;
char check = FALSE;

typedef struct{
    int width;
    int height;
    COLORREF bkcolor;
}WINSTRUCT;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

void CreateDrawHWND(void* arg) {
    WINSTRUCT* argptr = arg;

    char szClassName[] = "MyClass";
    char szTitle[] = "EasyX-like";

    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = szClassName;
    wcex.hbrBackground = CreateSolidBrush(argptr -> bkcolor);
    RegisterClassEx(&wcex);

    hWnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW, 50, 50, 50 + argptr -> width, 50 + argptr -> height, NULL, NULL, hInstance, NULL);
    HWND hwnd = hWnd;

    ShowWindow(hwnd, SW_SHOWDEFAULT);
    UpdateWindow(hwnd);

    check = TRUE;

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

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_PAINT: {
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

HWND initgraph(int width, int height, COLORREF bkcolor){
    WINSTRUCT windat = {width, height, bkcolor};
    pthread_t win;
    pthread_create(&win, NULL, (void*)CreateDrawHWND, (void*)&windat);
    pthread_detach(win);
    while(1){
        if(check == TRUE){
            check = FALSE;
            break;
        }
    }
    return hWnd;
}

int main(){
    HWND fir = initgraph(800, 600, RGB(0, 0, 0));
    HWND sce = initgraph(400, 300, RGB(255, 255, 255));

    system("pause");
}


这段代码的功能是利用多线程创建两个窗口,一大一小,其中大窗口为黑色,小窗口为白色,但是运行后,两窗口的背景色都是黑色,如下图:

img

我检查了很多遍代码,但是没有发现问题。为什么这两个窗口背景颜色全是黑色而不是一黑一白呢?求解答,感谢。

问题在于在创建窗口时使用了同样的类名,导致了不同的窗口实际上使用了同一个类,从而导致了两个窗口背景颜色都是黑色。可以通过给不同的窗口使用不同的类名来解决这个问题。
修改后的代码:

#include "windows.h"
#include "pthread.h"

HWND hWnd1, hWnd2;
char check1 = FALSE, check2 = FALSE;

typedef struct{
    int width;
    int height;
    COLORREF bkcolor;
}WINSTRUCT;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

void CreateDrawHWND(void* arg) {
    WINSTRUCT* argptr = arg;

    char szClassName[50];
    sprintf_s(szClassName, "MyClass%d", (int)argptr->bkcolor);
    char szTitle[] = "EasyX-like";

    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = szClassName;
    wcex.hbrBackground = CreateSolidBrush(argptr -> bkcolor);
    RegisterClassEx(&wcex);

    HWND hWnd;
    if (argptr -> bkcolor == RGB(0, 0, 0))
        hWnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW, 50, 50, 50 + argptr -> width, 50 + argptr -> height, NULL, NULL, hInstance, NULL);
    else
        hWnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW, 500, 50, 50 + argptr -> width, 50 + argptr -> height, NULL, NULL, hInstance, NULL);

    if (argptr -> bkcolor == RGB(0, 0, 0))
        hWnd1 = hWnd;
    else
        hWnd2 = hWnd;

    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);

    if (argptr -> bkcolor == RGB(0, 0, 0))
        check1 = TRUE;
    else
        check2 = TRUE;

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

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_PAINT: {
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

HWND initgraph(int width, int height, COLORREF bkcolor){
    WINSTRUCT windat = {width, height, bkcolor};
    pthread_t win;
    pthread_create(&win, NULL, (void*)CreateDrawHWND, (void*)&windat);
    pthread_detach(win);
    while(1){
        if(bkcolor == RGB(0, 0, 0)){
            if(check1 == TRUE){
                check1 = FALSE;
                break;
            }
        }
        else{
            if(check2 == TRUE){
                check2 = FALSE;
                break;
            }
        }
    }
    if (bkcolor == RGB(0, 0, 0))
        return hWnd1;
    else
        return hWnd2;
}

int main(){
    HWND fir = initgraph(800, 600, RGB(0, 0, 0));
    HWND sce = initgraph(400, 300, RGB(255, 255, 255));

    system("pause");
}



在CreateDrawHWND函数中使用CreateSolidBrush函数创建背景画刷时,无论传入参数是什么颜色,都会创建一个黑色画刷。造成这个问题的原因是只设置了画刷的背景颜色属性(lbColor),没有设置颜色类型属性(lbStyle)。

为了解决这个问题,您可以在CreateDrawHWND函数中修改如下行:

wcex.hbrBackground = CreateSolidBrush(argptr -> bkcolor);

改成:

wcex.hbrBackground = (HBRUSH)GetStockObject(DC_BRUSH);
SetDCBrushColor(GetWindowDC(hwnd), argptr->bkcolor);

同时,在WinProc函数中添加了重新画背景的代码:

case WM_PAINT: {
HDC hdc;
PAINTSTRUCT ps;

    hdc = BeginPaint(hwnd, &ps);
    // re-draw the background
    RECT rect;
    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect, wcex.hbrBackground);

    EndPaint(hwnd, &ps);
    break;
}

经过这些修改后,程序应该可以正确地按照参数传递的颜色类型创建对应的窗口了。

窗口类名设置同一个造成的颜色一致,把CreateDrawHWND函数改一下,参考如下代码:

void PTW32_CDECL CreateDrawHWND(void* arg) {
    WINSTRUCT* argptr = (WINSTRUCT*)arg;

    char szClassName[] = "MyClass";
    char* pszClassName = new char[strlen(szClassName) + 2];
    memset(pszClassName, 0, strlen(szClassName) + 2);
    strcpy(pszClassName, szClassName);
    static int a = 0;
    char buf[10] = { 0 };
    _itoa(a++, buf, 10);
    strcat(pszClassName, buf);
    char szTitle[] = "EasyX-like";

    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = pszClassName;// szClassName;
    wcex.hbrBackground = CreateSolidBrush(argptr->bkcolor);
    RegisterClassEx(&wcex);
    hWnd = CreateWindow(pszClassName, szTitle, WS_OVERLAPPEDWINDOW, 50, 50, 50 + argptr->width, 50 + argptr->height, NULL, NULL, hInstance, NULL);
    delete[] pszClassName;
    HWND hwnd = hWnd;

    ShowWindow(hwnd, SW_SHOWDEFAULT);
    UpdateWindow(hwnd);

    check = TRUE;

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



可以自己修改

#include <stdio.h>
#include <windows.h>
 
enum Color
{
      black, blue, green, lakeBlue, red, purple, yellow, white, gray,
      lightBlue, lightGreen, lightSimpleGreen, lightRed, lightPurple, lightYellow, brightWhite  
};
 
void setColor(unsigned short textColor=0, unsigned short backColor=7){
    char command[9]="color 07";        //默认颜色    
    command[6]='0'+backColor;        //将backColor变量改为字符型 
    command[7]='0'+textColor;        //将textColor变量改为字符型 
    system(command);                //调用系统函数 
}
 
int main(){    
    setColor(1,2);
    //setColor(blue,green);
    
    printf("蓝色背景,绿色字体\n\n");
}

可以自己修改背景颜色

#include <stdio.h>
#include <windows.h>
 
enum Color
{
      black, blue, green, lakeBlue, red, purple, yellow, white, gray,
      lightBlue, lightGreen, lightSimpleGreen, lightRed, lightPurple, lightYellow, brightWhite  
};
 
void setColor(unsigned short textColor=0, unsigned short backColor=7){
    char command[9]="color 07";        //默认颜色    
    command[6]='0'+backColor;        //将backColor变量改为字符型 
    command[7]='0'+textColor;        //将textColor变量改为字符型 
    system(command);                //调用系统函数 
}
 
int main(){    
    setColor(1,2);
    //setColor(blue,green);
    
    printf("蓝色背景,绿色字体\n\n");
}

1.你可以在窗口的 WM_PAINT 消息处理函数中进行绘图操作。例如,使用 GDI 来绘制一个矩形:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static HBRUSH hBrush;
    switch (msg) {
        case WM_CREATE:
            hBrush = CreateSolidBrush(RGB(50, 50, 50)); //创建一个画刷
            break;
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            RECT rect;
            GetClientRect(hwnd, &rect); //获取窗口客户区域大小
            FillRect(hdc, &rect, hBrush); //使用画刷填充整个客户区
            Rectangle(hdc, rect.left + 50, rect.top + 50, rect.right - 50, rect.bottom - 50); //绘制一个矩形
            EndPaint(hwnd, &ps);
            break;
        }
        case WM_DESTROY:
            DeleteObject(hBrush); //删除画刷
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

@终泪

先在 WM_CREATE 消息处理函数中创建了一个画刷,然后在 WM_PAINT 消息处理函数中使用 FillRect 函数填充整个窗口客户区,并使用 Rectangle 函数绘制一个矩形。最后在 WM_DESTROY 消息处理函数中删除画刷。

根据提供的代码,发现原因是在调用 CreateSolidBrush 时,将 argptr->bkcolor 直接传递给了函数,而 CreateSolidBrush 函数所接收的是 32 位颜色值,而不是 COLORREF 类型的颜色值。

在 Win32 编程中,颜色值通常是由红、绿、蓝三种颜色的 8 位值(即 0~255 的整数)组成的 24 位颜色值,也可以在 32 位颜色值的最高 8 位中指定 alpha 通道透明度信息,从而实现半透明效果。RGB(r,g,b) 属于一种便捷的宏定义方式,返回的是 COLORREF 类型的颜色值。

因此,需要将 COLORREF 类型的颜色值转换为 32 位颜色值才能正确设置窗口背景颜色。

int color = argptr->bkcolor;
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
DWORD bgcolor = RGB(r, g, b);

然后使用 bgcolor 作为参数创建背景画刷即可。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
问题出在了创建窗口时,使用了同样的类名。因为窗口类名不能重复,所以这两个窗口实际上是同一个类的两个实例,它们共享同一个类样式。

解决方法是为每个窗口创建不同的类名,修改代码如下:

void CreateDrawHWND(void* arg) {
    WINSTRUCT* argptr = arg;

    char szClassName[20];
    char szTitle[] = "EasyX-like";

    sprintf(szClassName, "MyClass%d", argptr->width); // 为每个窗口创建不同的类名

    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = szClassName;
    wcex.hbrBackground = CreateSolidBrush(argptr->bkcolor);
    RegisterClassEx(&wcex);

    HWND hwnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW, 50, 50, 50 + argptr->width, 50 + argptr->height, NULL, NULL, hInstance, NULL);
    hWnd = hwnd;

    ShowWindow(hwnd, SW_SHOWDEFAULT);
    UpdateWindow(hwnd);

    check = TRUE;

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

int main() {
    HWND fir = initgraph(800, 600, RGB(0, 0, 0));
    HWND sce = initgraph(400, 300, RGB(255, 255, 255));

    system("pause");
    return 0;
}

这样就可以创建两个不同的窗口了,大窗口为黑色,小窗口为白色。
如果我的回答解决了您的问题,请采纳!