首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当style为WS_CHILD时,通过ps.rcPaint查找脏区域不起作用

当style为WS_CHILD时,通过ps.rcPaint查找脏区域不起作用
EN

Stack Overflow用户
提问于 2015-11-29 04:27:39
回答 3查看 192关注 0票数 0

我已经用C++写了用WinApi绘制的程序。我的回调函数:

代码语言:javascript
复制
/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_DESTROY:
            PostQuitMessage(0);       /* send a WM_QUIT to the message queue */
            break;
        case WM_ERASEBKGND:
            {
                elWidget *widget = (elWidget *)GetWindowLong(hwnd, GWL_USERDATA);
                if (widget)
                {
                    PAINTSTRUCT ps;
                    HDC hdc = BeginPaint(hwnd, &ps);
                    HBRUSH hBrush = CreateSolidBrush(widget->color.ColorRef());
                    FillRect((HDC)wParam, &ps.rcPaint, hBrush);
                    DeleteObject(hBrush);
                    EndPaint(hwnd, &ps);
                }
            }
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

它适用于独立窗口(样式为WS_OVERLAPPED),但当样式为WS_CHILDWS_CHILD | WS_VISIBLE时,始终ps.rcPaint为(0,0,0,0)。我不知道该怎么解决。

代码语言:javascript
复制
elButton::elButton(elWidget *owner)
        : elWidget(owner)
{
    WNDCLASSEX winclChild;        /* Data structure for the windowclass */
    /* The Window structure */
    winclChild.hInstance = gThisInstance; //global variable instance
    winclChild.lpszClassName = L"Child";
    winclChild.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    winclChild.style = CS_DBLCLKS;                 /* Catch double-clicks */
    winclChild.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    winclChild.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    winclChild.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    winclChild.hCursor = LoadCursor (NULL, IDC_ARROW);
    winclChild.lpszMenuName = NULL;                 /* No menu */
    winclChild.cbClsExtra = 0;                      /* No extra bytes after the window class */
    winclChild.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    winclChild.hbrBackground = 0;// CreateSolidBrush(RGB(255, 200, 200));//(HBRUSH)COLOR_WINDOW;//COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx(&winclChild))
        return;
    hwnd = CreateWindowEx(
        0,                   /* Extended possibilites for variation */
        L"Child",         /* Classname */
        L"Title",       /* Title Text */
        WS_CHILD | WS_VISIBLE,
        100,
        100,
        40,
        40,
        owner->getHwnd(),        /* The window is a child-window to desktop */
        NULL,                /* No menu */
        gThisInstance,       /* Program Instance handler */
        this                 /* to lParam */
       );
    SetWindowLong(hwnd, GWL_USERDATA, (long)this);
}

我可以添加到谷歌磁盘上的整个项目的链接,但我不能保证它将是永久的多年。

EN

回答 3

Stack Overflow用户

发布于 2015-11-29 16:16:21

只能在WM_PAINT上调用BeginPaint,

要获取WM_ERASEBKGND上的剪贴框,请调用GetClipBox((HDC)wParam,&rect);

票数 3
EN

Stack Overflow用户

发布于 2015-11-29 05:26:04

仅对WM_PAINT使用BeginPaint/EndPaint

来自:的Windows文档

除非响应WM_PAINT消息,否则

应用程序不应该调用BeginPaint。每个对BeginPaint的调用都必须有一个对EndPaint函数的对应调用。

虽然您的代码看起来似乎可以工作,但它很可能会在其他地方造成问题,例如在WM_PAINT

要从WM_PAINT外部获取更新区域,请使用GetUpdateRect。但是,不能在WM_ERASEBKGND中使用GetUpdateRect。另请参阅

一个简单的解决方案是强制WM_ERASEBKGND什么都不做,然后在WM_PAINT中处理所有事情

代码语言:javascript
复制
switch(msg)
{
case WM_ERASEBKGND:
    return TRUE;
case WM_PAINT:
    ...
}
票数 2
EN

Stack Overflow用户

发布于 2015-11-29 06:10:55

这段代码非常适合我。答案是我们必须分别为父窗口和子窗口定义单独的窗口类。我看到SetWindowLong在所有情况下都能正常工作。但是如果你想立即用新数据重绘新窗口,你必须删除WS_VISIBLE作为你的创建风格,并且在ShowWindow之前使用SetWindowLongShowWindow函数使您的窗口可见,并使用新参数重新绘制窗口。

代码语言:javascript
复制
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam);

int RegClass(HINSTANCE hInstance,LPCTSTR lpszClassName)
{
    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = (LPCTSTR)lpszClassName;
    wc.lpszMenuName = (LPCTSTR)NULL;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wc.hCursor = (HCURSOR)LoadCursor(NULL,IDC_CROSS);
    wc.hIcon = (HICON)LoadIcon(NULL,IDI_APPLICATION);
    return RegisterClass(&wc);
}

HWND hWnd0, hWnd1;

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nShowCmd)
{
    MSG message;

    static LPCTSTR lpszClName = L"Wnd Class";
    static LPCTSTR lpszCl0Name = L"Child Class";
    if(!RegClass(hInstance,lpszClName))
        exit(0);
    if(!RegClass(hInstance,lpszCl0Name))
        exit(0);

    hWnd0 = CreateWindow(
        lpszClName,
        L"Привіт!",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        800,
        600,
        0,
        0,
        hInstance,
        NULL
        );

    hWnd1 = CreateWindow(
        lpszCl0Name,
        L"Привіт!",
        WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        40,
        40,
        400,
        300,
        hWnd0,
        0,
        hInstance,
        NULL
        );

    ShowWindow(hWnd0,SW_SHOWNORMAL);
    UpdateWindow(hWnd0);

    RECT WndRect;

    // For parent redraw
    GetWindowRect(hWnd0, &WndRect);
    MoveWindow(hWnd0, WndRect.left, WndRect.top, 801, 601, TRUE);

    SetWindowLong(hWnd0, GWL_USERDATA, RGB(0, 255, 0));

    ShowWindow(hWnd1,SW_SHOWNORMAL);
    UpdateWindow(hWnd1);

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

    return message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            InvalidateRect(hWnd, NULL, TRUE);
            break;

        case WM_DESTROY:
            PostQuitMessage(0);       /* send a WM_QUIT to the message queue */
            break;
        case WM_ERASEBKGND:
            {
                if (true)
                {
                    PAINTSTRUCT ps;
                    HDC hdc = BeginPaint(hWnd, &ps);

                    COLORREF color = (hWnd == hWnd0) ? RGB(255, 0, 0) : GetWindowLong(hWnd0, GWL_USERDATA);

                    HBRUSH hBrush = CreateSolidBrush(color);
                    FillRect((HDC)wParam, &ps.rcPaint, hBrush);
                    DeleteObject(hBrush);
                    EndPaint(hWnd, &ps);

                    ValidateRect(hWnd, NULL);
                }
            }
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

结果将会是。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33976115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档