子窗口上的RedrawWindow()问题

时间:2011-04-20 20:48:35

标签: winapi

在我的win32应用程序中,我创建了一个弹出窗口,我用它来显示其他窗口的内容。

例如,我正在运行一个Photoshop应用程序。我抓住它的主窗口的句柄,使其样式成为子窗口,并将其父窗口设置为我自己的窗口。这将Photoshop放在我的应用程序中。

之后,我隐藏了photoshop窗口(将不透明度设置为0),而是将其设备上下文内容抓取到我创建的位图中,然后在窗口上绘制这个位图。为此,我设置了一个每16毫秒(60赫兹)滴答的计时器。这是计时器:

void CALLBACK drawProc( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
{
    updateFrames();

    RECT r;
    GetClientRect( hwnd, &r );

    //Erase background
    HBRUSH eraseBrush = CreateSolidBrush( RGB( 255, 255, 255 ) );
    FillRect( bbHDC, &r, eraseBrush );
    DeleteObject( eraseBrush );

    //Draw frames
    drawFrames( bbHDC );    

    RedrawWindow( hwnd, 0, 0, RDW_INVALIDATE | RDW_NOCHILDREN );
}

问题是,这会降低photoshop(以及其他一些应用程序的速度)。通过评论行我发现redrawWindow导致了这一点。我认为重绘主窗口可能会导致photoshop重绘其内容,所以我添加了RDW_NOCHILDREN但仍然缓慢。

如果有人可以帮我解决这个问题,我会很高兴。

感谢。

1 个答案:

答案 0 :(得分:3)

我甚至不会评论为什么这是一件奇怪的事情:)

为什么这么慢:

每次调用它时,

RedrawWindow可能会强制完全重画。毕竟,你使整个窗口无效。这将是一个昂贵的操作 - 通常在Windows应用程序中,您只在您知道需要时绘制(通过使矩形或区域无效,这是一个非常便宜的操作,并在某些时候处理WM_PAINT消息,并且在处理该绘画时仅使用无效区域,这是可能的最小工作。)

值得阅读painting and drawing in Windows,尤其是when to draw in a window

现在,尝试回答您的问题:

大多数情况下,嵌入式Photoshop窗口不会发生变化。换句话说,你的程序正在做的大量的浩瀚的大部分绘画工作是完全没必要的。当Photoshop窗口发生变化并且需要重新绘制自己时,你应该做的只是绘制到你的窗口 - 理想情况下,即使这样,也只重绘需要重新绘制的部分。 (一个示例是对鼠标悬停做出反应的按钮:您只需重新绘制按钮,或按钮所在的矩形,而不是整个窗口。)

您正在做的是polling的一般情况。这是非常低效的,因为你做了很多工作,即使不需要做任何事情。您希望在需要工作时收到通知,这样效率会更高。

以下是一个建议,我没有尝试过,但它应该工作。 Windows已经有一个内置框架,因此应用程序知道何时需要绘制:消息队列中将出现WM_PAINT消息。您可以使用PeekMessage查看窗口的消息队列并查看其中的消息,而不删除任何消息。这将告诉你窗口何时需要绘制:然后重新绘制。或者,hook the message functionsubclass the window,当收到WM_PAINT消息时,将其传递给原始消息函数,然后重新绘制。您可以使用GetUpdateRect查看要绘制的区域,然后在WM_PAINT处理完成后,将该区域仅复制到您自己的窗口。等

这是一般答案:尝试其中一些事情,看看会发生什么。请记住,如果您对特定部件有疑问,可以发布另一个问题!