gpt4 book ai didi

c++ - WINapi。无法用椭圆删除窗口背景

转载 作者:太空狗 更新时间:2023-10-29 20:35:12 24 4
gpt4 key购买 nike

我只是想画一个椭圆:

case WM_PAINT:
hdc = BeginPaint(parentWindow, &ps);
Ellipse(hdc, x, y, width, height);
EndPaint(parentWindow, &ps);

,然后使用计时器每秒绘制一个带有一些新参数的新椭圆来删除它:

case WM_CREATE:
SetTimer(hWnd, 1, 1000, NULL);
break;
case WM_TIMER:
x += 5;
InvalidateRect(hWnd, NULL, TRUE);
break;

但是椭圆并没有被删除和分层:

Ellipses

但是,我试图跟踪 WM_ERASEBKGND,它确实是在每个 InvalidateRect 中发送的。

完整代码:

#include <Windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <iostream>


TCHAR szWindowClass[] = TEXT("CreateThreadWindow");
TCHAR szAppName[] = TEXT("CreateThreadExample");

BOOL InitWindow(HINSTANCE, int);
ATOM MyRegisterClass(HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND parentWindow;
MSG msg;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MyRegisterClass(hInstance);
if (!InitWindow(hInstance, nCmdShow))
return FALSE;
BOOL bRet;
while ((bRet = GetMessage(&msg, (HWND)NULL, 0, 0)) != 0)
{
if (bRet == -1)
return FALSE;
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wndClass;
memset(&wndClass, 0, sizeof(wndClass));
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = szWindowClass;
return RegisterClass(&wndClass);
}

BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
parentWindow = CreateWindow(szWindowClass, szAppName, WS_OVERLAPPEDWINDOW,
300, 0, 600, 600, NULL, NULL, hInstance, NULL);
ShowWindow(parentWindow, nCmdShow);
return TRUE;
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc;
static int x = 0, y = 0, width = 200, height = 100;
switch (message) {
case WM_ERASEBKGND:
_RPT1(0, "%s\n", "erase");
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
Ellipse(hdc, x, y, width, height);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
SetTimer(hWnd, 1, 1000, NULL);
break;
case WM_TIMER:
x += 5;
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wparam, lparam);
}
}

最佳答案

您的代码没有删除任何内容。它只是在指定坐标处绘制一个椭圆。之前画的椭圆还在。

您提到了 WM_ERASEBKGND 消息,但它对您不起作用的原因有两个:

  1. 在您的窗口过程 (WndProc) 中,您显式处理 WM_ERASEBKGND 消息,这意味着它不会传递给默认窗口过程 ( DefWindowProc)。编写窗口过程的更好方法如下:

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
    {
    static int x = 0, y = 0, width = 200, height = 100;
    switch (message) {
    case WM_ERASEBKGND:
    {
    _RPT1(0, "%s\n", "erase");
    break;
    }
    case WM_PAINT:
    {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);
    Ellipse(hdc, x, y, width, height);
    EndPaint(hWnd, &ps);
    return 0;
    }
    case WM_CREATE:
    {
    SetTimer(hWnd, 1, 1000, NULL);
    break;
    }
    case WM_TIMER:
    {
    x += 5;
    InvalidateRect(hWnd, NULL, TRUE);
    return 0;
    }
    case WM_DESTROY:
    {
    PostQuitMessage(0);
    return 0;
    }
    default:
    break;
    }

    return DefWindowProc(hWnd, message, wparam, lparam);
    }

    现在,默认窗口过程每次都会被调用,除非您明确地从 case 标签内部return

  2. 当您注册您的窗口类时(在 MyRegisterClass 内),您将 WNDCLASS structure 的所有字段清零然后明确地初始化其中的几个。您没有显式初始化 hbrBackground 字段,因此它被设置为 0。当 hbrBackground 为 0 时,

    When this member is NULL, an application must paint its own background whenever it is requested to paint in its client area. To determine whether the background must be painted, an application can either process the WM_ERASEBKGND message or test the fErase member of the PAINTSTRUCT structure filled by the BeginPaint function.

    这意味着默认窗口过程不会对 WM_ERASEBKGND 消息做任何响应,因为您没有为窗口提供背景画笔。

    您需要将 hbrBackground 设置为类似 COLOR_WINDOW + 1 的值,或者您需要将代码添加到您的 WM_ERASEBKGND 消息处理程序自己删除窗口的背景。

或者,也许更好的选择是完全忘记 WM_ERASEBKGND 消息,就像许多 Windows 程序员所做的那样,因为这种两步删除和绘制方法往往会导致闪烁。将 hbrBackground 字段设置为 NULL,不要对 WM_ERASEBKGND 消息做任何响应,并在 WM_PAINT 的顶部进行删除> 处理程序:

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

// Erase background of entire client area.
RECT rcClient;
GetClientRect(hWnd, &rcClient);
FillRect(hdc, &rcClient, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));

// Do normal drawing.
Ellipse(hdc, x, y, width, height);

EndPaint(hWnd, &ps);
return 0;
}

关于c++ - WINapi。无法用椭圆删除窗口背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44066436/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com