在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()
答案 0 :(得分:1)
只是扫描MFC代码......(目前无法让我的调试器逐步完成,等等)
在CFrameWnd类中,有一个名为RecalcLayout的函数。 MSDN说:
在打开或关闭标准控制条或调整框架窗口大小时由框架调用。
RecalcLayout调用CWnd :: RepositionBars。函数内部是注释:
// 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()。
// .h
CStatusBar status_bar;
// .cpp
if (!status_bar.Create(this))
{
TRACE0("Failed to create status bar\n");
return -1;
}
auto& statusBarCtrl = status_bar.GetStatusBarCtrl();
statusBarCtrl.SetParts(3, sb);
// etc.
答案 1 :(得分:0)
我在这里确实有一个不避免使用 CStatusBarCtrl
的替代解决方案。这是一个老问题,但如果您有兴趣,请继续阅读:
如果你仔细观察,无论何时创建 CStatusBarCtrl
,它总是知道它在父窗口上的确切位置,而忽略 cost RECT& rect
参数。所以它有能力调整自己的大小。您只需在父窗口调整大小时通过调用 CWnd::SetWindowPos
中的 CStatusBarCtrl
方法将其唤醒。参数可以全为零,因为 CStatusBarCtrl
无论如何都会忽略它,只需要提醒它需要重新定位。
这是你实现它的方式:
第一步:在父窗口的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_SIZE中,用CStatusBarCtrl
戳SetWindowPos
:
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 测试