C++ WM#u EX#u透明不';t重新绘制子窗口
我在一些窗口上使用了C++ WM#u EX#u透明不';t重新绘制子窗口,c++,winapi,user-interface,ws-ex-transparent,C++,Winapi,User Interface,Ws Ex Transparent,我在一些窗口上使用了WM_EX_TRANSPARENT窗口样式,试图利用透明度进行双缓冲。但是,我遇到了一个问题,因为当我在父窗口上执行invalidate操作时,子窗口不会被重新绘制 父窗口的责任是迭代子窗口并让它们自己重新绘制,还是我做错了?如果这是父窗口的责任,那么如何获取父窗口无效矩形内的所有子窗口 下面是一个完全可编译的示例,它演示了我所说的行为。当您将鼠标移到父窗口上时,可以看到该按钮消失。如果单击该按钮,该按钮会自动重画,但当您将鼠标移离该按钮并返回到父窗口时,该按钮会再次消失 #
WM_EX_TRANSPARENT
窗口样式,试图利用透明度进行双缓冲。但是,我遇到了一个问题,因为当我在父窗口上执行invalidate
操作时,子窗口不会被重新绘制
父窗口的责任是迭代子窗口并让它们自己重新绘制,还是我做错了?如果这是父窗口的责任,那么如何获取父窗口无效矩形内的所有子窗口
下面是一个完全可编译的示例,它演示了我所说的行为。当您将鼠标移到父窗口上时,可以看到该按钮消失。如果单击该按钮,该按钮会自动重画,但当您将鼠标移离该按钮并返回到父窗口时,该按钮会再次消失
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND window, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
return 0;
case WM_MOUSEMOVE:
InvalidateRect(window, NULL, true);
return 0;
case WM_NCDESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(window, uMsg, wParam, lParam);
}
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd) {
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "test_window";
RegisterClass(&wc);
HWND wnd = CreateWindowEx(WS_EX_TRANSPARENT, "test_window", "test", WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, 50, 50, 400, 400, NULL, NULL, hinst, NULL);
ShowWindow(wnd, SW_SHOW);
HWND btn = CreateWindowEx(WS_EX_TRANSPARENT, "BUTTON", "button 1", WS_CHILD, 50, 50, 100, 50, wnd, NULL, hinst, NULL);
ShowWindow(btn, SW_SHOW);
MSG m;
while (GetMessage(&m, NULL, 0, 0)) {
TranslateMessage(&m);
DispatchMessage(&m);
}
return 0;
}
再次感谢johnathon花了这么多时间帮助我解决这个问题。从父窗口样式中删除WS_CLIPCHILDREN。这将允许父窗口在子窗口的不动产上绘制,然后子窗口将在其绘制调用期间有效地在该不动产上绘制。首先调用父窗口的绘制,然后调用所有子窗口的绘制。祝赛斯好运 @Flot2011
WS_EX_COMPOSITED
有自己的双缓冲,我想自己做。使用它可以防止儿童窗口消失,但它们闪烁得非常厉害。你可以用我的示例程序试试,它也能做同样的事情。可惜你的解决方案在标准控件上不起作用。我忍不住觉得有更好的解决方案,但我没有提供。@Markransem是的,我觉得有更好的解决方案,但我找不到。而且我认为你可以通过某种方式让它在标准控件上工作,但我和你一样,没有提供它。@Markransem也许是WM_PRINT
什么的?再次感谢,我已经在这个愚蠢的问题上工作了好几天了。这不是问题Seth。很高兴我能帮助你。
#include <Windows.h>
// the handle to the single child window
HWND child;
// parent's backbuffer so we can use it in the child
HDC bbuf = 0;
LRESULT CALLBACK WndProc(HWND window, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
return 0;
case WM_MOUSEMOVE:
InvalidateRect(window, NULL, true);
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
POINT mpos;
GetCursorPos(&mpos);
ScreenToClient(window, &mpos);
BeginPaint(window, &ps);
// create the backbuffer once
bbuf = bbuf ? bbuf : CreateCompatibleDC(ps.hdc);
// hardcoded size is the same in the CreateWindowEx call
static auto backbmp = CreateCompatibleBitmap(ps.hdc, 400, 400);
static auto unused = SelectObject(bbuf, backbmp);
POINT points[2] = {
{ 0, 0 },
{ mpos.x, mpos.y }
};
// painting into bbuf
// give ourselves a white background so we can see the wblack line
SelectObject(bbuf, (HBRUSH)GetStockObject(WHITE_BRUSH));
Rectangle(bbuf, 0, 0, 400, 400);
SelectObject(bbuf, (HBRUSH)GetStockObject(BLACK_BRUSH));
Polyline(bbuf, points, 2);
// get the child to paint itself into our bbuf
SendMessage(child, WM_PAINT, 0, 0);
// and after the child has drawn, bitblt everything onto the screen
BitBlt(ps.hdc, 0, 0, 400, 400, bbuf, 0, 0, SRCCOPY);
EndPaint(window, &ps);
return 0;
}
case WM_ERASEBKGND:
return 0;
case WM_NCDESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(window, uMsg, wParam, lParam);
}
LRESULT CALLBACK ChildWndProc(HWND window, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(window, &ps);
static auto backbuffer = CreateCompatibleDC(ps.hdc);
static auto backbmp = CreateCompatibleBitmap(ps.hdc, 100, 50);
static auto unused = SelectObject(backbuffer, backbmp);
// copy the parent's stuff into our backbuffer (the parent has already drawn)
BitBlt(backbuffer, 0, 0, 100, 50, bbuf, 50, 150, SRCCOPY);
RECT r = { 0, 0, 50, 100 };
// draw into our backbuffer
SetBkMode(backbuffer, TRANSPARENT);
SetTextColor(backbuffer, RGB(255, 0, 0));
DrawText(backbuffer, "hello", 5, &r, DT_NOCLIP | DT_TABSTOP | DT_EXPANDTABS | DT_NOPREFIX);
// bitblt our stuff into the parent's backbuffer
BitBlt(bbuf, 50, 150, 100, 50, backbuffer, 0, 0, SRCCOPY);
EndPaint(window, &ps);
return 0;
}
case WM_ERASEBKGND:
return 0;
}
return DefWindowProc(window, uMsg, wParam, lParam);
}
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd) {
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "test_window";
RegisterClass(&wc);
wc.style = 0;
wc.lpfnWndProc = ChildWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "transparent_window";
RegisterClass(&wc);
HWND wnd = CreateWindowEx(NULL, "test_window", "test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 50, 50, 400, 400, NULL, NULL, hinst, NULL);
child = CreateWindowEx(NULL, "transparent_window", "", WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILD, 50, 150, 100, 50, wnd, NULL, hinst, NULL);
MSG m;
while (GetMessage(&m, NULL, 0, 0)) {
TranslateMessage(&m);
DispatchMessage(&m);
}
return 0;
}