0

长话短说,我正在构建一个 i3 风格的平铺窗口管理器,并且需要覆盖任意窗口的镶边以强制删除边框、标题栏和相关按钮。

在尝试了几乎所有与镀铬相关的 WS_STYLE 和 WS_EX 样式的逻辑组合后,我对大多数应用程序一无所获。简单的本机程序(终端按预期工作)没问题,但对于绝大多数其他应用程序,也会出现同样的问题;

边界问题

大多数情况下都会出现上述结果。有一个大小相同的周围边框,但每个应用程序的行为不同。据我所知,这是用于鼠标拖动命中测试的“透明”(在这种情况下显然不是)边框(尽管在样式中禁用了框架,但这不应该存在)。似乎该区域中的帧缓冲区没有被清除(即,如果将窗口调整为自身大小,则边框将被该位置的先前像素填充)。

这是一个快速的周末项目——我的工作与 WinAPI 编程无关,所以这对我来说是全新的,但如果我假设正确,那么这个边界实际上是非客户区吗?换句话说,非客户区必须归零,以便客户区占据整个窗口矩形。我试图通过使用 GWL_WNDPROC 对所有目标窗口进行子类化并将 WM_NCCALCSIZE 归零来处理这个问题,但我得到了相同的结果。

如何强制任意窗口(不是我自己创建的)完全删除它的整个非客户区?

4

1 回答 1

0

我使用以下函数来删除/恢复窗口的边框:

void WndSetFrame(HWND hWnd, int bSmall)
{
    static int wwStyle=0;       // remember initial style
    int ww= GetWindowLong(hWnd, GWL_STYLE);

    if (bSmall) {
        wwStyle= ww;
        ww &= ~(WS_OVERLAPPED|WS_CAPTION|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_SIZEBOX|WS_SYSMENU);
        ww |=  (WS_POPUP /*|WS_DLGFRAME*/);
        if (ww==wwStyle) return;
        SetWindowLong(hWnd, GWL_STYLE, ww);
    }
    else {
        if (!wwStyle || ww==wwStyle) return;
        SetWindowLong(hWnd, GWL_STYLE, wwStyle);
    }
    SetWindowPos (hWnd,0,0,0,0,0,SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);

}
于 2020-01-21T10:36:44.490 回答