点击透明 window,不允许拖动 [C++]
Click-through Transparent window, no dragging allowed [C++]
有多种方法可以使用 .NET 执行此操作(以 this 为例),但我无法仅使用 C++ win32 重现相同的内容。
我的方法是使用 WS_EX_LAYERED
,然后使用 SetLayeredWindowAttributes
来控制不透明度,但我阅读更多,发现 WS_EX_TRANSPARENT
是 'better' - 它允许点击。
但是,使用
hWnd = CreateWindowEx(WS_EX_TRANSPARENT, fooName, fooName, WS_OVERLAPPEDWINDOW | WS_POPUP | WS_CLIPSIBLINGS, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
似乎并不能解决问题。还有一件事:一旦我的点击率 window 正常工作,我可以使用
PostMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(GET_X_LPARAM(lParam) ,GET_Y_LPARAM(lParam)));
阻止拖动状态通过?
注意:拖动状态是使用触摸板设备产生的。
click-through部分:
的确,WS_EX_TRANSPARENT
本身就是一个弥天大谎;所以我改用 WS_EX_COMPOSITED | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST
。
我使用 SetLayeredWindowAttributes(hWnd, 0, (255 * opacity) / 100, LWA_ALPHA);
控制不透明度(非常不正统,但它有效)并且我还使用
SetCapture(hWnd);
ShowCursor(false);
作为顶层抓住鼠标焦点window不松手隐藏光标
我还试图将焦点集中在 window 添加 WM_NCACTIVATE
和 WM_ACTIVEAPP
:
case WM_MOUSEMOVE:
fprintf(stdout, "Mouse move [%d][%d]\n", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
SetForegroundWindow(hWnd);
break;
case WM_LBUTTONDOWN:
printf("Mouse click\n");
SetForegroundWindow(hWnd);
break;
case WM_NCACTIVATE:
return false;
case WM_ACTIVATEAPP:
wActive = (bool)wParam;
if(wActive == false)
return 0;
else
return DefWindowProc(hWnd, message, wParam, lParam);
拖动部分:
在我的特殊情况下,我想 'poke' 下面的 window (child window) 而不会失去焦点;不幸的是,任何鼠标单击事件都会将焦点更改为 child window - 解决方案是:
- 设置一个计时器(
SetTimer
、WM_TIMER
)并检查您的应用程序是否失去焦点
- 设置一个挂钩到您的 window 并使用
WM_SETFOCUS
消息回复 WM_KILLFOCUS
消息
我最近一直致力于创建具有透明度和点击属性的 windows,我刚刚尝试了这个:
HWND hWnd = CreateWindowEx(WS_EX_LAYERED|WS_EX_TRANSPARENT, cName, wTitle, NULL, 0, 0, 640, 480, NULL, 0, GetModuleHandle(NULL), 0);
您不能关闭它、最小化它、拖动它等等 - 您所做的每一次点击都会直接通过,就好像它不存在一样。
然后只需使用以下方法更改透明度:
SetLayeredWindowAttributes(hWnd, 0, 100, LWA_ALPHA);
如果我理解正确的话,它实现了你问题中的所有内容。
您的方法可能无效,因为如果您使用 WS_EX_TRANSPARENT
,则必须定义 WS_EX_LAYERED
。
有多种方法可以使用 .NET 执行此操作(以 this 为例),但我无法仅使用 C++ win32 重现相同的内容。
我的方法是使用 WS_EX_LAYERED
,然后使用 SetLayeredWindowAttributes
来控制不透明度,但我阅读更多,发现 WS_EX_TRANSPARENT
是 'better' - 它允许点击。
但是,使用
hWnd = CreateWindowEx(WS_EX_TRANSPARENT, fooName, fooName, WS_OVERLAPPEDWINDOW | WS_POPUP | WS_CLIPSIBLINGS, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
似乎并不能解决问题。还有一件事:一旦我的点击率 window 正常工作,我可以使用
PostMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(GET_X_LPARAM(lParam) ,GET_Y_LPARAM(lParam)));
阻止拖动状态通过?
注意:拖动状态是使用触摸板设备产生的。
click-through部分:
的确,WS_EX_TRANSPARENT
本身就是一个弥天大谎;所以我改用 WS_EX_COMPOSITED | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST
。
我使用 SetLayeredWindowAttributes(hWnd, 0, (255 * opacity) / 100, LWA_ALPHA);
控制不透明度(非常不正统,但它有效)并且我还使用
SetCapture(hWnd);
ShowCursor(false);
作为顶层抓住鼠标焦点window不松手隐藏光标
我还试图将焦点集中在 window 添加 WM_NCACTIVATE
和 WM_ACTIVEAPP
:
case WM_MOUSEMOVE:
fprintf(stdout, "Mouse move [%d][%d]\n", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
SetForegroundWindow(hWnd);
break;
case WM_LBUTTONDOWN:
printf("Mouse click\n");
SetForegroundWindow(hWnd);
break;
case WM_NCACTIVATE:
return false;
case WM_ACTIVATEAPP:
wActive = (bool)wParam;
if(wActive == false)
return 0;
else
return DefWindowProc(hWnd, message, wParam, lParam);
拖动部分:
在我的特殊情况下,我想 'poke' 下面的 window (child window) 而不会失去焦点;不幸的是,任何鼠标单击事件都会将焦点更改为 child window - 解决方案是:
- 设置一个计时器(
SetTimer
、WM_TIMER
)并检查您的应用程序是否失去焦点 - 设置一个挂钩到您的 window 并使用
WM_SETFOCUS
消息回复WM_KILLFOCUS
消息
我最近一直致力于创建具有透明度和点击属性的 windows,我刚刚尝试了这个:
HWND hWnd = CreateWindowEx(WS_EX_LAYERED|WS_EX_TRANSPARENT, cName, wTitle, NULL, 0, 0, 640, 480, NULL, 0, GetModuleHandle(NULL), 0);
您不能关闭它、最小化它、拖动它等等 - 您所做的每一次点击都会直接通过,就好像它不存在一样。 然后只需使用以下方法更改透明度:
SetLayeredWindowAttributes(hWnd, 0, 100, LWA_ALPHA);
如果我理解正确的话,它实现了你问题中的所有内容。
您的方法可能无效,因为如果您使用 WS_EX_TRANSPARENT
,则必须定义 WS_EX_LAYERED
。