⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 9.6.2 在状态栏的窗格中创建.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
📖 第 1 页 / 共 2 页
字号:
9.6.2 在状态栏的窗格中创建进度栏
下面,我们要实现在程序状态栏的窗格中显示进度栏。这时,首先需要获得该窗格的区域,然后将
这个区域的大小作为进度栏的大小。为了获得窗格的区域,可以利用 CStatusBar类的 GetPaneInfo
成员函数来完成。该函数的原型声明如下所示 : 
void GetltemRect(int nindex, LPRECT lpRect ) const ; 
其中,第一个参数( nlndex )指定窗格索引:第二个参数 OpRect)指定用来接收指定索引的窗格的矩
形区域。
因此,在 Style程序的 CMainFrame类的 OnCreate函数中,对上面。和 @符号所示的创建进度栏的
代码进行修改,以实现在状态栏的第三个窗格 ( Il. P IDS_PROGRESS资源 D指定的窗格,其索引为 
2)上显示进度栏,此时,状态栏对象将作为进度栏的父窗口。修改后的代码如例如25所示。
例9-25 
1. CRect rect ; 
2. m_wndStatusBar.GetItemRect(2 , &rect); 

3. m-progress . Create(WS_CHILD | WS_VISIBLE , rect , &m_wndStatusBar , 123) ; 


4. m-progress . SetPos(50) ; 


Build并运行Style程序,读者将会发现在状态栏上并未创建进度栏。为了找到原因,我们在上述例
如21所示代码段的第三行代码处设置一个断点,并调试运行Style程序。当程序执行到这个断点时,
利用VC++提供的Watch窗口(在调试状态下可利用【View\Debug Windows\Watch】菜单命令打开此窗
口)查看rect变量的当前值,如图9.41所示。可以看到,这时, rect对象的left和right值都是-17。
这明显不是一个正常的矩形区域,说明我们没有得到状态栏上指定窗格的区域。因此,随后创建进
度栏的操作自然也就失败了。
这里之所以没有得到状态栏上指定窗格的矩形区域,是因为此时状态栏的初始化工作,即对窗格的
摆放操作还没有完成。我们知道, CMainFrame类的OnCreate函数是在响应框架窗口的WM CREATE消
息时调用的,只有在这个函数执行完成之后,才能够获得窗口状态栏上窗格的矩形区域。遵照这种
思路,我们可以试试这种方法是否可行:自定义一个消息,然后在CMainFrame类的OnCreate函数中在
其返回之前发送这条消息,最后在这个自定义消息的响应函数中获得状态栏上窗格的矩形区域。 
我们知道,在Windows中,所有的消息都是用一个特定的整数值来表示的,为了避免我们自定义的这
条消息与其他己有消息值发生冲突,应该利用Windows提供的一个常量: WM USERo小于这个常量的值
都是Windows系统保留的,我们自定义的消息只需要大于这个常量就可以了。于是,在定义自定义消
息时,通常都是用WM USER加上一个数值,这个值可由编程人员自行决定,但是要注意最后表示消息
的数值不要超过Ox7FFFF(关于消息数值的范围和它们表示的含义,读者可以在MSDN的索引页面中查
看WM USER的帮助文档)。本例中,加上值1就可以了。因此,在Style程序中,在CMainFrame类的头
文件中定义一条自定义的消息,定义代码如下所示: 
#define UM_PROGRESS WM_USER+l 
目标: Windows消息用 WM_为前缀表示,我们自定义的消息最好用 UM_

为前缀表示,表示用户消息 ( User Message )。但这并不是必须要这样做。下面,为这条自定义消
息添加消息响应函数原型的声明,方法是在 CMainFrame类的头文件中,在两个 AFx_MSG注释宏的
外面添加这条声明语句,结果如例如26所示。例 9-26 
// Generated message map functions 
protected : 
// {{AFX_MSG(CMainFrame) 
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct) ; 
afx_msg void OnTimer(UINT nIDEvent) ; 
afx_ msg void OnTest() ; 
afx_msg void OnViewNewtoolbar(); 
afx_msg void OnUpdateViewNewtoolbar( C CmdUI* pCmdUI) ; 
// }}
AFX_MSG 
afx_msg void OnProgress(); 
DECLARE_ MESSAGE_MAP() 
这个消息响应函数 C OnProgress )的定义与前面介绍的命令消息的响应函数是相同的,如果在发送
该消息时,还需要附带发送一些数据,在声明这个响应函数时,就应该让其带有与消息相关的两个
附加参数 C wParam和 lParam ) ;否则,这个响应函数可以没有参数。
接下来就是为这条自定义消息添加消息映射,前面介绍的命令消息是用 ON-COMMAND宏将消息与消息
响应函数关联起来,而对于自定义消息来说,使用的是 ON_ MESSGE宏来实现这一功能。因此,在 
CMainFrame类的源文件中,在消息映射表的两个注释宏之外,添加 UM一PROGRESS这一自定义消息的
消息映射,结果如例 9 -27所示。
例 9-27 


BEGIN_MESSAGE_MAP(CMainFrame , CFrameWnd) 11 {{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE () 
ON_WM_TIMER ( ) 
ON_COMMAND(IDM_TEST, OnTest) 
ON_COMMAND(IDM_VIEW_NEWTOOL , OnViewNewtool) 
ON_UPDATE_COMMAND_UI(IDM_VIEW_NEWTOOL, OnUpdateViewNewtool) 
ON_WM_PAINT ( ) 
// }}AFX_ MSG_MAP 
ON_MESSAGE (UM_PROGRESS, OnProgress) 
 END_MESSAGE_MAP() 
最后,当然就是添加这个消息响应函数的实现,具体代码如例 9 -28所示。 例 9-28 
void CMainFrame : : OnProgress() 
{ 
CRect rect ; 
m_wndStatusBar .GetltemRect(2 , &rect) ; 
m-progress .Create(WS_CHILD | WS_VISIBLE , rect , &m_wndStatusBar , 123) ; 
m_progress .SetPos(50) ; 
然后在CMainFrame类的 OnCreate函数中将先前创建进度栏的代码(即上述例 9-25所示代码段)注释
起来,然后在其后添加下面这条语句,即利用 SendMessage函数发送 UM PROGRESS这个自定义的消
息: 
SendMessage(UM_PROGRESS) ; 
Build并运行Style程序,结果,发现在状态栏上仍没有看到进度栏控件。为了了解程序的运行过程,
我们可以在Style程序中设置三个断点,一个是在CMainFrame类的OnCreate函数中刚刚添加的
SendMessage函数处,一个是位于这条代码下面的retum语句,第三个断点设置在OnProgress函数的
定义处。然后调试运行Style程序,程序首先会暂停在SendMessage函数处:继续执行,程序将会暂停
在 OnProgress函数的定义处:再继续执行,程序将会暂停在OnCreate函数的retum语句处。也就是说,
在OnCreate中调用SendMessage函数发送 UM_PROGRESS后,程序就会调用这个消息的响应函数来处
理。在这个响应函数执行完成之后,又返回到OnCreate函数中执行SendMessage函数的下一条语句,
即 retum语句。我们可以发现,实际上,这时就相当于把创建进度栏的代码直接放在 OnCreate函数
中,与上面的实现方式是相同的,因此这时也不能获得窗格的矩形区域,所以,进度栏没有创建成
功。造成这种情况的主要原因是SendMessage函数发送消息的机制,它是直接把消息发送给消息响应
函数,由消息响应函数处理完成之后, SendMessage函数才返回。这就造成了当消息发送之后,程
序流程跳转到相应的消息响应函数中,执行完成之后再返回到 SendMessage函数的下一条语句继续
执行。因此这里不能使用 SendMessage这个函数,应该使用PostMessage函数。 PostMessage函数是
把消息放到消息队列中,然后立即返回,之后程序通过 GetMessage函数按顺序把消息一条一条地取
出来。对于本例来说, OnCreate 
是WM CREATE消息的响应函数,在对这个消息处理完毕后(即OnCreate函数执行完毕), MFC底层代码
调用 GetMessage函数才从消息队列中取出UM PROGRESS这条自定义消息,此时才轮到 OnProgress
函数去执行,这时因为 OnCreate函数已经执行完成,因此状态栏的初始工作也己经全部完成,就可
以得到状态栏窗格的矩形区域,从而就可以创建进度栏了。读者可以把刚才那条SendMessage函数换

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -