MFC 状态栏梳理

MFC状态栏梳理

MFC状态栏,觉得挺简单的,但是用的时候总是不得劲,梳理了一下代码。理解通透些。
MFC 状态栏梳理_第1张图片

先说状态栏窗口怎么来的

在MainFrame里面会有一个成员变量,状态栏 m_wndStatusBar

protected:  // 控件条嵌入成员
	CMFCMenuBar       m_wndMenuBar;
	CMFCToolBar       m_wndToolBar;
	CMFCStatusBar     m_wndStatusBar; //状态栏窗口
	CMFCToolBarImages m_UserImages;
	CFileView         m_wndFileView;
	CClassView        m_wndClassView;
	COutputWnd        m_wndOutput;
	CPropertiesWnd    m_wndProperties;

在创建的时候,好好仔细的创建出来,大意是根据数组指示器,将状态栏分为指示器数组个数窗口,每一个窗口的含义由指示器指定,可以自己分状态栏。

static UINT indicators[] =
{
	ID_SEPARATOR,           // 状态行指示器
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

创建的时候其实很关键,在create函数里面有一个资源的id,状态栏运行机制其实全靠这个资源id来实现,而由于create函数资源id又是默认参数,导致看代码的时候死活有转不过弯,信息是如何发送到状态栏的。

	if (!m_wndStatusBar.Create(this))
	{
		TRACE0("未能创建状态栏\n");
		return -1;      // 未能创建
	}
	m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

关键的最后一个参数,函数声明太长,还显示不出来,我调整一下

BOOL Create(CWnd* pParentWnd, 
DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
UINT nID = AFX_IDW_STATUS_BAR);

BOOL CreateEx(CWnd* pParentWnd,
 DWORD dwCtrlStyle = 0, 
 DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
 UINT nID = AFX_IDW_STATUS_BAR);

MFC运行通过资源ID AFX_IDW_STATUS_BAR 来操作状态栏
典型的函数就是

CWnd* CFrameWnd::GetMessageBar()
{
	return GetDescendantWindow(AFX_IDW_STATUS_BAR, TRUE);
}

就是如此,通过在子孙窗口里面一通乱找,反正有资源ID就能找到对应的创建的窗口,最后就能设置信息了。

说一下这个就绪怎么来的

如果你在多文档程序里面想在程序搞定以后设置一个准备好了,你会发现非常诡异的总是显示就绪,好坑爹。

比如你在mainframe的创建函数里面,不管你是直接设置
SetMessageText 还是POSTMessage 还是SendMessage都不好使
这里面有一个设置时机的问题。

int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	if (CWnd::OnCreate(lpcs) == -1)
		return -1;

	// create special children first
	if (!OnCreateClient(lpcs, pContext))
	{
		TRACE(traceAppMsg, 0, "Failed to create client pane/view for frame.\n");
		return -1;
	}

	// post message for initial message string
	PostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);

	// make sure the child windows have been properly sized
	RecalcLayout();

	return 0;   // create ok
}

AFX_IDS_IDLEMESSAGE就是 【就绪字符串】
通过梳理代码我们可以知道,在CFrameWnd::OnCreateHelper每次都会发送设置状态信息,就绪。那就可以知道了。
由于子框架也是继承CFrameWnd,那么他也会发送设置状态信息。
所以时机应该在子框架设置完以后再设置就可以实现。
不能改MFC的原代码吧,可以改字符串,但是得知道怎么回事。

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMDIChildWndEx::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	PostMessage(WM_SETMESSAGESTRING, 0, (LPARAM)"准备好了");
	return 0;
}

MFC 状态栏梳理_第2张图片

这里面还有一个坑爹的是需要发送消息来设置

由于在MFC框架源代码里面是发送消息,而且是POST,那么我们也只能POST,不然你搞定以后,MFC框架代码在处理的时候又来设置一顿,是不是白搞了。
哈,那就是这样子了。

主要就是解决两个疑惑:
1 问:MFC如何通过SetMessageText之类的函数来设置状态信息的?
答:通过一个叫AFX_IDW_STATUS_BAR 的标准资源ID来找到状态栏窗口再操纵他设置信息。

2 问 多文档程序中在MainFrame的Create函数里面设置状态信息,为什么不起作用。
答:因为子框架的create函数里面会重新设置一番,覆盖了。如果程序启动没有子框架是不会覆盖的。

你可能感兴趣的:(mfc,c++,状态栏)