You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SetLayeredWindowAttributes导致窗口最小化后鼠标点击异常求助

问题描述

窗口最小化恢复后,除单个像素区域外,无法点击窗口上的任何内容。使用MinGW编译,通过清单文件启用子窗口透明效果;移除清单文件则问题消失,但子窗口无法实现透明效果。

相关WM_CREATE代码片段:

case WM_CREATE:
        SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED);
        SetLayeredWindowAttributes(hwnd, RGB(255, 0, 0), 0 /*doesn't matter*/, LWA_COLORKEY);
        hbackground = CreateWindowExA(0,
                                      "STATIC",
                                      NULL,
                                      WS_CHILD | WS_VISIBLE | SS_BITMAP,
                                      0,
                                      0,
                                      window_width,
                                      window_height,
                                      hwnd,
                                      NULL,
                                      NULL,
                                      (LPVOID)NULL);
        setImage(hbackground, background_image_name, monitor_dimension.width, monitor_dimension.height);
        SetWindowLongA(hbackground, GWL_EXSTYLE, GetWindowLongA(hbackground, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED);
        SetLayeredWindowAttributes(hbackground, 0, (255 * 50) / 100, LWA_ALPHA);
        SetLayeredWindowAttributes(hbackground, 0, (255 * 50) / 100, LWA_ALPHA);
        break;
解决方法

1. 修正清单文件的兼容性配置

清单文件中的旧系统兼容或DPI设置可能导致窗口区域计算错误,建议调整为以下内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
        </dependentAssembly>
    </dependency>
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
            <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
        </windowsSettings>
    </application>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>
  • 启用每监视器DPI感知,避免窗口缩放导致的区域偏移
  • 移除不必要的旧Windows版本兼容节点,减少兼容性冲突

2. 在窗口恢复时重置分层属性

窗口最小化后,分层窗口的区域或属性信息可能丢失,需在WM_SIZE或WM_RESTORE消息中重新初始化:

case WM_SIZE:
    if (wParam != SIZE_MINIMIZED) {
        // 重置父窗口分层属性与尺寸
        SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetWindowPos(hwnd, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_FRAMECHANGED | SWP_NOMOVE);
        SetLayeredWindowAttributes(hwnd, RGB(255, 0, 0), 0, LWA_COLORKEY);
        
        // 重置子窗口尺寸与透明属性
        SetWindowPos(hbackground, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER);
        SetWindowLongA(hbackground, GWL_EXSTYLE, GetWindowLongA(hbackground, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetLayeredWindowAttributes(hbackground, 0, (255 * 50) / 100, LWA_ALPHA);
    }
    break;

case WM_RESTORE:
    // 强制触发WM_SIZE逻辑,确保窗口属性正确重置
    RECT rc;
    GetWindowRect(hwnd, &rc);
    SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
    break;

3. 清理冗余代码

原WM_CREATE中重复调用了SetLayeredWindowAttributes(hbackground, ...),移除其中一次即可,避免不必要的属性覆盖。

4. 改用UpdateLayeredWindow(可选)

若SetLayeredWindowAttributes仍存在问题,可改用UpdateLayeredWindow精确控制窗口透明度与区域:

// 示例:在初始化或WM_PAINT中调用
HDC hdcScreen = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, window_width, window_height);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmp);

// 绘制内容到hdcMem(此处替换为你的绘图逻辑)
// ...

BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = (255 * 50)/100;
blend.AlphaFormat = AC_SRC_ALPHA;

POINT ptWinPos = {0, 0};
SIZE szWin = {window_width, window_height};
POINT ptSrc = {0, 0};

UpdateLayeredWindow(hbackground, hdcScreen, &ptWinPos, &szWin, hdcMem, &ptSrc, 0, &blend, ULW_ALPHA);

// 清理资源
SelectObject(hdcMem, hbmpOld);
DeleteObject(hbmp);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);

内容的提问来源于stack exchange,提问作者SKNG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:45:37