如何“清除”WinAPI透明窗口

8

我已经在Win32 C++中创建了一个透明的复选框。我这样做是因为据我所知,你不能在本机win32中拥有透明的复选框,而我需要在NSIS安装程序中使用此复选框。

我的问题: 当重新绘制时,我不知道如何擦除我的透明背景,以便我可以在“清空画布”上绘制。当用户更改复选框内的文本并且我需要重新绘制它时,这很重要。我想我遇到了每个人都必须遇到的透明窗口问题。

有什么方法可以清除我的透明窗口,请注意,我熟悉WinAPI,据我所知,你实际上无法清除窗口,因为你只是在窗口上重绘。因此,我正在寻求关于我可以使用哪些技术重新绘制窗口的建议,例如:

  • 向父窗口发送重绘消息,希望它会重绘父窗口(即位于复选框下方的窗口),而不向其子窗口(即复选框)发送消息。我尝试过这样做,但会使复选框闪烁很多。
  • 也许有一个我不知道的透明画刷/绘图函数,我可以用它来绘制整个复选框窗口,从而清除窗口?我尝试过这样做,但会使复选框窗口变为黑色。

我的代码:

case WM_SET_TEXT:
{
        // set checkbox text
        // Technique 1: update parent window to clear this window
        RECT thisRect = {thisX, thisY, thisW, thisH};
        InvalidateRect(parentHwnd, &thisRect, TRUE);
}
break;
case WM_PAINT:
{
     PAINTSTRUCT ps;
     HDC hdc = BeginPaint(hwnd, &ps);
     // Technique 2:
     SetBkMode(hdc, TRANSPARENT);
     Rectangle(hdc, thisX, thisY, thisW, thisH); // doesn't work just makes the window a big black rectangle?
     EndPaint(hwnd, &ps);
}
break;  

3
一般来说,您不应该向另一个窗口发送绘制消息,如果您想要重绘它,请使其矩形区域无效。 - Larry Osterman
你的 WM_ERASEBKGND 消息处理程序中做了什么? - Larry Osterman
@LarryOsterman 嗯,我以前从未处理过这个消息?现在什么都没有,我该怎么办? - sazr
你可能想添加一个什么都不做的处理程序。这将防止系统使用背景颜色绘制窗口背景。另外,尝试一下 clipsiblings 的建议,那也可能有所帮助。 - Larry Osterman
2个回答

1

您需要处理 WM_ERASEBKGND 消息。以下类似的代码应该有效!

case WM_ERASEBKGND:
{
    RECT rcWin;
    RECT rcWnd;
    HWND parWnd = GetParent( hwnd ); // Get the parent window.
    HDC parDc = GetDC( parWnd ); // Get its DC.

    GetWindowRect( hwnd, &rcWnd );
    ScreenToClient( parWnd, &rcWnd ); // Convert to the parent's co-ordinates

    GetClipBox(hdc, &rcWin );
    // Copy from parent DC.
    BitBlt( hdc, rcWin.left, rcWin.top, rcWin.right - rcWin.left,
        rcWin.bottom - rcWin.top, parDC, rcWnd.left, rcWnd.top, SRC_COPY );

    ReleaseDC( parWnd, parDC );
}
break;

这会绘制一个透明的“颜色”还是标准按钮灰色?请记住,复选框具有透明背景,其父hwnd可能没有标准的灰色背景,它可能是一张图片等。 - sazr
@JakeM 请查看更新后的答案。我假设你正在处理复选框的绘制部分。 - Ragesh Chakkadath

0
尝试移除窗口样式WS_CLIPCHILDREN。

你的意思是要移除复选框的样式还是其父元素的样式? - sazr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接