我正在尝试使用Win32 API创建一个透明窗口,该窗口可以在屏幕上拖动,窗口的背景将保持透明并显示其背后的窗口。
我通过执行以下操作来执行此操作:
ATOM MyRegisterClass(HINSTANCE hInstance){
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);}
: wcex.hbrBackground = NULL; 行负责在初始化时使窗口透明。
在以下位置创建窗口:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;}
窗口在拖动时保持透明的方式是:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MOVING:
InvalidateRect(hWnd, NULL, TRUE);
break;
default:
return = DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;}
其中: InvalidateRect(hWnd,NULL,TRUE); line会导致在移动事件时重绘窗口。
问题是窗口的背景不会在不是" new"的区域中重新渲染。
单词示例,
假设我打开一个应用程序(word,chrome等 - 我们称之为WindowB),而不是我运行我的应用程序打开覆盖WindowB的WindowA,但我可以在后台看到WindowB的内容(因为WindowA是透明窗口) )。如果我在屏幕上拖动WindowA,我仍然会在后台看到WindowB,这很棒。
如果我最小化WindowB,我仍然会看到与WindowA区域相交的WindowB部分(这里没问题,因为我没有重绘WindowA)。
如果我开始拖动WindowA,我认为WindowA中显示的WindowB部分将消失,我将看到当前桌面中最顶层的窗口是WindowA的背景,因为我调用 InvalidateRect(hWnd,NULL,TRUE); 移动事件。
实际发生的是我仍然在所有不是"新区域"的区域中看到WindowB。 - 按照新区域,我指的是WindowA移动到的屏幕中的区域,并且在移动之前不是WindowA区域的一部分。
似乎调用 InvalidateRect(hWnd,NULL,TRUE); 是不够的,因为它只渲染"新区域"。
可以在以下链接中找到说明问题的快照: http://imgur.com/gallery/2uVX4yj/new
我非常感谢在此问题上给予的任何帮助。
我的应用程序的主要功能是Visual Studio 2010为Win32应用程序项目创建的默认函数:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow){
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST2));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;}