1

我在 MFC C++ 中有一个附加了 CButton 的对话框。我想修改 OnSize() 以便按钮锚定到左下角。

if (btn.m_hWnd) {
        CRect winRect;
        GetWindowRect(&winRect);

        int width = winRect.right - winRect.left;
        int height = winRect.bottom - winRect.top;

        int x = width - wndWidth;
        int y = height - wndHeight;


        CRect rect;
        btn.GetWindowRect(&rect);
        rect.left += x;
        rect.top += y;
        btn.MoveWindow(&rect);
        ScreenToClient(&rect);
        btn.ShowWindow(SW_SHOW);
    }

x 和 y 是窗口已更改多少并将添加到按钮的开始坐标的差异。

我不确定最后两个命令(我不妨删除它们),但随后我运行程序按钮消失了。

我需要知道一种将按钮移动 x 和 y 的方法。

4

2 回答 2

2

原始代码为父对话框和按钮使用了错误的坐标系。

停靠到左下角的正确方法是这样的:

if (btn.m_hWnd) { 
    CRect winRect; 
    GetClientRect(&winRect); 

    CRect rect; 
    btn.GetWindowRect(&rect); 
    ScreenToClient(&rect); 

    int btnWidth = rect.Width();
    int btnHeight = rect.Width();
    rect.left = winRect.right-btnWidth; 
    rect.top  = winRect.bottom-btnHeight;
    rect.right = winRect.right;
    rect.bottom = winRect.bottom; 
    btn.MoveWindow(&rect); 
}

或者

if (btn.m_hWnd) { 
    CRect winRect; 
    GetClientRect(&winRect); 

    CRect rect; 
    btn.GetWindowRect(&rect); 
    ScreenToClient(&rect); 

    int btnWidth = rect.Width();
    int btnHeight = rect.Width();
    btn.SetWindowPos(NULL,winRect.right-btnWidth,winRect.bottom-btnHeight,0,0,SWP_NOSIZE|SWP_NOZORDER);
}
于 2012-09-12T00:56:58.457 回答
1

基本上,答案应该是在 MoveWindow 之前做 ScreenToClient!

更多细节:您需要熟悉哪些函数返回或使用客户端坐标(以及相对于这些客户端坐标是什么)以及哪些屏幕坐标;这是 MFC 中真正令人困惑的部分之一。至于你的问题:

CWnd::GetWindowRect返回屏幕坐标;CWnd::MoveWindow需要相对于父 CWnd 的坐标(或者如果它是顶级窗口,则相对于屏幕)。所以在调用 MoveWindow 之前,您必须将 GetWindowRect 返回的 rect 转换为父窗口的客户端坐标;假设 pParent 是CWnd *的父窗口btn,那么您的移动代码应如下所示:

CRect rect;
btn.GetWindowRect(&rect);
pParent->ScreenToClient(&rect);  // this line and it's position is important
rect.left += x;
rect.top += y;
btn.MoveWindow(&rect);

如果您在父窗口的方法中(我认为您是,因为您提到了对话框的 OnSize),那么只需省略pParent->. 你现在做 ScreenToClient 的方式,它对 MoveWindow 没有影响,因为它是在它之后执行的!

于 2012-09-11T12:23:41.293 回答