Winapi CStatusBarCtrl自动调整大小

Winapi CStatusBarCtrl自动调整大小,winapi,mfc,Winapi,Mfc,在MFC中,当父窗口更新时,状态栏不应该自动调整大小吗?是否需要使用缺少的设置来实现这一点 class Mainwindow { public: MainWindow() { Create(NULL, _T("Main Window")); } afx_msg int OnCreate(LPCREATESTRUCT lp) { // Status bar CRect rc; this->GetClientRect(&a

在MFC中,当父窗口更新时,状态栏不应该自动调整大小吗?是否需要使用缺少的设置来实现这一点

class Mainwindow {
public:
    MainWindow() {
        Create(NULL, _T("Main Window"));
}
afx_msg int OnCreate(LPCREATESTRUCT lp) {
        // Status bar
        CRect rc;
        this->GetClientRect(&rc);
        std::array<int, 3> sb = { rc.right / 3,rc.right / 3 * 2,-1 };
        status_bar.Create(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, CRect(0, 0, 0, 0), this, IDS_STATUSBARCTRL);
        status_bar.SetParts(3, sb.data());
        status_bar.SetTipText(1, _T("Tooltip text"));
        status_bar.SetText(_T("Left"), 0, SBT_POPOUT);
        status_bar.SetText(_T("Middle"), 1, 0);
        status_bar.SetText(_T("Right"), 2, 0);
        return TRUE;
    }

// This resizes the status bar fine, but shouldn't MFC handle it?
       afx_msg void OnSize(UINT, int cx, int cy) {
        status_bar.SendMessage(WM_SIZE, 0, 0);
    }

    DECLARE_MESSAGE_MAP()

private:
    CStatusBarCtrl status_bar;
};


BEGIN_MESSAGE_MAP(MainWindow,CFrameWnd)
    ON_WM_CREATE()
    ON_WM_SIZE()
END_MESSAGE_MAP()
class主窗口{
公众:
主窗口(){
创建(空,_T(“主窗口”);
}
afx_msg int OnCreate(LPCREATESTRUCT lp){
//状态栏
正确的rc;
此->GetClientRect(&rc);
数组sb={rc.right/3,rc.right/3*2,-1};
状态栏。创建(WS|u CHILD | WS|u VISIBLE | CCS|u BOTTOM | SBARS|u SIZEGRIP,正确(0,0,0),this,id_STATUSBARCTRL);
状态栏设置部件(3,sb数据());
状态栏.setTiptText(1,_T(“工具提示文本”);
状态栏设置文本(_T(“左”),0,SBT_弹出);
status_bar.SetText(_T(“中间”),1,0;
状态栏SetText(_T(“右”),2,0;
返回TRUE;
}
//这会很好地调整状态栏的大小,但MFC不应该处理它吗?
afx\U消息无效大小(UINT、int cx、int cy){
状态栏SendMessage(WM_大小,0,0);
}
声明消息映射()
私人:
CStatusBarCtrl状态_栏;
};
开始消息映射(主窗口,CFrameWnd)
关于\u WM\u CREATE()
关于_WM_SIZE()
结束消息映射()

只需扫描MFC代码。。。(目前无法让我的调试器单步执行,啊)

在CFrameWnd类中,有一个名为RecalcLayout的函数。MSDN说:

当打开或关闭标准控制栏或调整框架窗口的大小时,框架调用

RecalcLayout调用CWnd::RespositionBars。函数中有一条注释:

// walk kids in order, control bars get the resize notification
//   which allow them to shrink the client area
通知似乎是通过WM_SIZEPARENT消息完成的:

a) CControlBar类具有WM_SIZEPARENT的消息处理程序

b) CStatusBarCtrl是从CWnd派生的,而不是从CControlBar派生的,因此不会获取消息

解决方案:我会像应用程序向导那样做——将您的状态栏成员变量设置为CStatusBar。(从CControlBar派生)从那里可以调用GetStatusBarCtrl()


我这里有一个替代解决方案,它不会避免使用
CStatusBarCtrl
。这是一个老问题,但如果您感兴趣,请继续阅读:

如果仔细观察,每当创建
CStatusBarCtrl
时,它总是知道它在父窗口中的确切位置,并忽略
cost RECT&RECT
参数。因此,它具有调整自身大小的能力。您只需在父窗口调整大小时唤醒它,方法是调用
CStatusBarCtrl
中的
CWnd::SetWindowPos
方法。参数可以全部为零,因为
CStatusBarCtrl
无论如何都会忽略它,只需提醒它需要重新定位

这是您实现它的方式:

步骤1:在父窗口的OnCreate()方法中,创建
CStatusBarCtrl

int MainFrmWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    
    m_infoBar = new CStatusBar;
    m_infoBar->Create(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, 
                      CRect(), 0x1234);
    int partWidths[] = { 100, 200, -1 };
    m_infoBar->SetParts(3, partWidths);
    m_infoBar->SetText(_T("Pane 1..."), 0, NULL);
    m_infoBar->SetText(_T("Pane 2..."), 1, NULL);
    m_infoBar->SetText(_T("Pane 3..."), 2, NULL);
    return 0;
}
步骤2:在父窗口的WM_大小中,用
SetWindowPos
戳出
CStatusBarCtrl

void MainFrmWnd::OnSize(UINT nType, int cx, int cy) {
    CFrameWnd::OnSize(nType, cx, cy);

    // Parameter values don't matter,
    // This is just to remind CStatusBarCtrl it needs repositioning
    m_infoBar->SetWindowPos(&wndTop, 0, 0, 0, 0, NULL);
}
使用VS2019测试


这是可行的,但仅供参考,您必须完全删除
WM_SIZE
处理程序,让MFC自己执行所有更新,或者在任何自定义大小调整后调用
CFrameWnd::OnSize()
void MainFrmWnd::OnSize(UINT nType, int cx, int cy) {
    CFrameWnd::OnSize(nType, cx, cy);

    // Parameter values don't matter,
    // This is just to remind CStatusBarCtrl it needs repositioning
    m_infoBar->SetWindowPos(&wndTop, 0, 0, 0, 0, NULL);
}