【问题标题】:Click-through Transparent window, no dragging allowed [C++]点击透明窗口,不允许拖动 [C++]
【发布时间】:2015-09-27 14:24:50
【问题描述】:

使用 .NET 有几种方法可以做到这一点(以 this 为例),但我无法仅使用 C++ win32 重现相同的内容。

我的方法是使用WS_EX_LAYERED,然后使用SetLayeredWindowAttributes 对不透明度进行一些控制,但我阅读了更多内容,发现WS_EX_TRANSPARENT '更好'——它允许点击。

但是,使用

hWnd = CreateWindowEx(WS_EX_TRANSPARENT, fooName, fooName, WS_OVERLAPPEDWINDOW | WS_POPUP | WS_CLIPSIBLINGS, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

似乎没有办法。还有一件事:一旦我让点击窗口工作,我可以使用

PostMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(GET_X_LPARAM(lParam) ,GET_Y_LPARAM(lParam)));

阻止拖动状态通过?

注意:拖动状态是使用触摸板设备产生的。

【问题讨论】:

  • Like the cake, WS_EX_TRANSPARENT is a lie, or at least not the entire truth。伪造WM_LBUTTONUP 消息将无法更新对输入处理至关重要的内部状态。根据您询问的对象是否按下鼠标左键,您会得到不同的答案。
  • 您是否注意到 STATIC 窗口不接收点击消息? WM_LBUTTONDOWN 和/UP 转到父窗口。这似乎不依赖于创建标志,而是依赖于 Window 类。

标签: c++ user-interface winapi click window


【解决方案1】:

点击部分:

确实,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);

在顶层窗口不松开并隐藏光标时抓住鼠标焦点。

我还尝试强制将焦点放在添加WM_NCACTIVATEWM_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);

拖动部分:

在我的特殊情况下,我想在不失去焦点的情况下“戳”下面的窗口(子窗口);不幸的是,任何鼠标单击事件都会将焦点更改为该子窗口 - 解决方案是:

  1. 设置一个计时器(SetTimerWM_TIMER)并检查您的应用程序是否失去焦点
  2. 为您的窗口设置一个钩子并使用WM_SETFOCUS 消息回复WM_KILLFOCUS 消息

【讨论】:

  • 你使用了什么创建命令?我尝试m_overlay.CreateEx(WS_EX_COMPOSITED | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST, _T("Static"), _T(""), 0, CRect(), this, -1) 没有成功,其中m_overlayCWnd 派生对象(返回FALSE 并且没有创建HWND)。
【解决方案2】:

我最近一直致力于创建具有透明度和点击属性的窗口,我刚刚尝试过:

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

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多