【问题标题】:Border size of a fixed window固定窗口的边框大小
【发布时间】:2017-05-21 18:09:31
【问题描述】:

我需要以某种方式获取(固定)窗口边框大小(垂直边框)的宽度。默认情况下,在 WinXP 上它非常薄,但在开启 Aero 的 Win7 上,它要厚得多。

我认为 GetSystemMetrics 可以解决问题,但它似乎为 XP 和 Win7 系统返回相同的值,我检查了以下参数:

SM_CXBORDER
SM_CXEDGE
SM_CYFIXEDFRAME
SM_CYBORDER
SM_CXFIXEDFRAME

但正如我所写,无论垂直窗口边框实际有多厚,它们都会为两个操作系统返回相同的值。该窗口是使用标志 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX 创建的(如果有任何帮助)(它不是很大)。

感谢您的任何想法。

克拉

【问题讨论】:

    标签: winapi


    【解决方案1】:

    好吧,在花了一些时间之后,这是一个似乎返回真实边框宽度的代码(如果有人需要它):

    NONCLIENTMETRICS ncm;
    OSVERSIONINFO OS;
    
    OS.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
    
    GetVersionEx (&OS);
    
    if (OS.dwMajorVersion < 6)
    {
        ncm.cbSize = sizeof (ncm) - sizeof(ncm.iPaddedBorderWidth);
        SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
        BorderWidth = ncm.iBorderWidth;
    }
    else
    {
        ncm.cbSize = sizeof (ncm);
        SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
        BorderWidth = ncm.iBorderWidth + ncm.iPaddedBorderWidth;
    }
    

    我想它仍然存在一些故障,但它对我来说可以接受:)) 我知道的故障是,它确实计算了一个相当大的窗口的边框宽度,如果你有一个弹出窗口,它的边框略有不同大小(但例如在 XP 上,您似乎无法设置弹出窗口边框大小,您只能为相当大的窗口设置)。

    【讨论】:

    • 好的。多年来,我一直在使用给出的“其他”信息计算边界。但如果这有效,那也很酷。 :-)
    【解决方案2】:

    如果根本问题是,您需要计算“窗口”大小以实现期望的客户端矩形,然后跳过数学。

    AdjustWindowRectEx 更具未来性。即使是 AdjustWindowRect 也需要进行一些猜测,因为没有真正的窗口它不知道滚动条或包装菜单:向现有窗口发送WM_NCCALCSIZE 消息,DefWindowProc 将计算并返回结果的客户区。通过计算的客户区和所需的客户区之间的差异来膨胀窗口矩形。

    【讨论】:

      【解决方案3】:

      Kra,关键词是 DwmApi(Vista 及更新版本):

      1. DwmIsCompositionEnabled
      2. DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS)

      【讨论】:

        【解决方案4】:

        可能GetClientRect 是您所需要的。无论如何,您可以根据GetClientRectGetWindowRect 返回的维度计算它们

        伪代码:

        wr = GetWindowRect()
        cr = GetClientRect()
        
        left_border_width = cr.left
        right_border_width = wr.right - wr.left - cr.right
        

        【讨论】:

        • 不幸的是,这也不起作用。我得到两个操作系统的结果 6。我实际上不需要计算客户的面积或类似的东西。我需要将另一个窗口与这个窗口对齐,并且我需要考虑正确的垂直边框厚度来做到这一点(我知道 CreateWindowEx 中使用的窗口宽度,但不包含边框)。根据您的想法,我还尝试使用 GetWindowRect(hwnd,&rect) 并将另一个窗口与 rect.right 对齐,但这也离边框很远。
        • 那一定是6。你能举个例子说明这个值是错误的吗(截图)?请记住,阴影不是窗口边框的一部分。
        • 这是 Win7 中的样子,注意第二个窗口与边框重叠:img17.imageshack.us/img17/9882/win7i.png 这是 XP 中的样子,正确对齐:img838.imageshack.us/img838/3656/85193079.png 消息框中的值是这个:GetClientRect (hMainWnd, &smaller); GetWindowRect (hMainWnd, &bigger); MsgBox val = large.right - large.left -smaller.right);请注意,我的第二个窗口左角与固定值对齐,它尚未计算.. 尚未.. 在我知道如何计算边框之后,我将实现它:)
        • 那么看起来边框的外部部分根本不被视为边框,而是像阴影一样的图形效果。如果您最大化窗口,这部分可能会超出屏幕。我认为你不应该打扰那个。你能做的最好的就是坚持GetWindowRect/GetClientect返回的值。 SceenToClientClientToScreen 也可能对你有用。
        • 你可以做一个实验——自己画(用Rectangle函数)窗口边框和客户区边框,你会看到什么是什么。
        【解决方案5】:

        GetWindowRect() 从桌面返回坐标作为原点。屏幕左上角。

        GetClientRect() 从您调用它的窗口客户端区域返回坐标。

        您必须将坐标从一个转换为另一个。

        正如 adf88 所说,这是通过 ScreenToClient 和 ClientToScreen 完成的。 “屏幕”是桌面。

        查找 GetWindowRect()、GetClientRect()、ScreenToClient() 和 ClientToScreen()。

        HTH

        【讨论】:

        • 感谢您的评论,但这仍然不能解决问题。即使边框粗细不同,两个相同窗口的窗口区域宽度和客户区域宽度也相同。这让我觉得窗口区域根本不包含(整个)边框。
        • 然后查看所有“NC”类型的函数。 NC 表示非客户端。例如:WM_NCHITTEST、WM_NCLBUTTONDBLCLK、WM_NCLBUTTONUP、WM_NCPAINT 等
        【解决方案6】:

        我能得到的最接近的是:-
        顶部:GetSystemMetrics(SM_CXPADDEDBORDER) + GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYCAPTION)
        底部:GetSystemMetrics(SM_CXPADDEDBORDER) + GetSystemMetrics(SM_CYDLGFRAME)
        左或右:GetSystemMetrics(SM_CXPADDEDBORDER) + GetSystemMetrics(SM_CXDLGFRAME)

        将这些值添加到窗口大小以获得所需的客户端大小。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-02
          • 1970-01-01
          • 2016-09-06
          • 1970-01-01
          • 2012-09-13
          • 2013-07-12
          • 1970-01-01
          • 2011-09-22
          相关资源
          最近更新 更多