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

📄 9.5状态栏编程.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
9.5状态栏编程
应用程序窗口的最下方就是状态栏,如图9.30所示。 
图 9.30状态栏

状态栏可以分为两部分,其中左边最长的那部分称为提示行,当我们把鼠标移动到某个菜单项或工
具按钮上时,该部分将显示相应的提示信息。例如当鼠标移动到 Style程序中【文件】子菜单下的
【保存】菜单项时,状态栏最左边的窗格将显示该菜单项的提示信息:"保存活动文档",如图9.31
所示。

图 9.31状态栏上的提示信息状态栏的第二部分是其右边的三个窗格,主要用来显示Caps Lock, Num 
Lock和 Scroll 
Lock键的状态,称为状态栏指示器。当在程序运行后按下CapsLock键,程序状态栏上这三个窗格中
左边第一个窗格将显示:"大写",如图9.32所示:当再次按下CapsLock键,该窗格上的字符串就消失
了。 
图 9.32 Caps Lock键按下后的状态栏

在 Style程序中,状态栏对象也是在 CMainFrame类中定义的,在该类的头文件中有下面这行代码,
其中CStatusBar类就是与状态栏相关的MFC类: 
CStatusBar m_wndStatusBar; 
在CMainFrame类的OnCreate函数中可以看到如例9-18所示的这段代码。 
例9-18 

if ( !m_wndStatusBar .Create(this) || !m_wndStatusBar.Setlndicators(indicators , 
. 
sizeof(indicatorsl /sizeof(UINT) || 
TRACEO("Failed to create status bar\n" ) ; 
return -1; // fail to create 

这段代码首先调用状态栏对象的Create函数创建状态栏对象,这个函数的原型声明如下所示: 
BOOL Create ( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD 1 WS_VISIBLE 1 CBRS_ BOTTOM, U
工NT nID = AFX_IDW_STATUS_BAR ) ; 
其中,该函数的各个参数的意义如下所述: 
. pParent飞νnd
指定状态栏的父窗口指针,通常都是指向程序的框架窗口对象。 


. dwStyle 


第二个参数指定状态栏的风格,除了标准的Windows窗口风格外,该参数还可以取表 
9.3中所列的值。
表9.3状态栏风格 

dwStyle    取值   说明
CBRS_TOP   控制条位于框架窗口的顶部
CBRS BOTTOM  控制条位于框架窗口的底部
CBRS NOALIGN    当父窗口大小发生改变时,控制条的位置不变 

. nID 
指定状态栏这个子窗口的ID,默认值是AFX_IDW_STATUS_BAR。
上述代码在创建状态栏之后,接着调用 SetInd i cators函数设置状态栏指示器,其中用到一个数
组参数: indicators,这个数组是在CMainFrame类源文件的前部定义的,定义代码如例9-19所示。
{例 9-19 
static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};
可以看到,这个数组是一个静态的变量,数组元素是一些,第一个ID表示的是刚才看到的状态栏
最左边最长的那个窗格,即提示行,后面三个m分别是Caps Lock, Num Lock和ScrollLock键的状态
指示器。 
SetIndicators函数的第二个参数用来设定indicators数组中元素的个数。
实际上, indicators数组中后三个E都是 MFC预先为我们定义好的字符串资源ID,读者可以在VC++
开发环境中打开Style工程的ResourceView选项卡,双击StringTable文件夹下的 String Table J
页,即可打开Style程序的字符串资源,在其中可以找到这三个ID的定义,如图9.33所示。 
图 9.33状态栏使用的字符串资源D的定义

如果想要修改状态栏的外观,例如添加或减少状态栏上的窗格,则只需要在indicators数组中添加
或减少相应的字符串资源ID即可。本例想在Style程序的状态栏上显示当前系统的时间和一个进度条
控件,因此,首先需要为 Style程序增加两个新的字符串资源,其 B及Caption如表9.4所示。
表9.4新增的字符串资源 

IDS_TIMER 时钟
IDS PROGRESS  进度栏 
然后将这两个新的字符串资源ID添加到indicators数组中,结果如例9-20所示。 
static UINT indicators[) 
ID_SEPARATOR,
IDS_ TIMER , 
IDS_PROGRESS , 
ID_ INDICATOR_CAPS , 
ID_INDICATOR_NUM , 

ID_INDICATOR_SCRL, 
Build井运行Style程序,结果如图9.34所示,可以看到程序的状态栏上多了两个窗格,其中一个显
示的是"时钟",另一个显示的是"进度栏",也就是刚才我们定义的字符串资源所表示的文本内容。 . 
图 9.34新添两个窗格后的状态栏显示效果

接下来,我们希望在状态栏上显示"时钟"字符串的那个窗格上显示系统当前的时间,那么首先就需
要获取到系统当前时间,这需要用到一个新的MFC类: CTime,该类有一个静态的成员函数: 
GetCurrentTime。该函数返回一个CTime类型的对象,表示系统当前的时间。然后,可以调用CTime
类的另一个成员函数: Format,对得到的CTime类型的时间对象进行格式化,得到一个包含格式化时
间的字符串。该函数常用的格式如表9.5所示(关于其他格式读者可查看MSDN中相关信息)。
表9.5 CTime类的Format函数常用的格式

%y   不带世纪的年号 00-99
%m  月份 1-12
%d     日期, 1-31 
%H     以24小时制表示的时间,   0-23
%1 ,  以 12小时制表示的时间, 1-12  


为了将字符串显示到状态栏的窗格上,可以调用 CStatusBar类的 SetPaneText函数, 该函数的原
型声明如下所示:
BOOL SetPaneText(int nIndex, LPCTSTR lpszNewText , BOOL bUpdate = TRUE ); 
可以看到,这个函数有三个参数,其中,第一个参数是窗格在指示器数组 ( indicators ) 中的索
引,这里,根据前面 indi ca tor s数组的定义,可以知道 IDS TIMER表示的窗格在 indicators
数组中的索引是 1 ;
第二个参数就是在窗格上显示的文本 ;
第三个参数是 BOOL类型,如果其值为 
TRUE,那么在设置窗格的文本之后,该窗格变成是无效的,当下次 WM PAINT消息发送后,该窗格将
发生重绘,该参数的默认值是 TRUE。
因此,为了在状态栏上显示"时钟"字符串的那个窗格上显示系统当前的时间,我们在 Style程序的 
CMainFrame类的 OnCreate函数的后部,但要在其 return语句之前添加例如2 1这段代码。
例 9-21 

CTime t=CTime : :GetCurrentTime() ; 
CString str=t .Format( "%H :%M :%S " ) ; 
m_wndStatusBar .SetPaneText(1 , str) ; 

上述如例如2 1所示代码中,首先定义了一个 CTime类型的对象:t,接着调用 CTime类的静态函数 
GetC Ul 11 entTime,运回一个表本系统当前时间的 CTime类型的对象。接下来,调用 CTime类的 
Format函数得到一个表示时间的格式化字符串,其中 "%H ", "%D " 都是格式化符号,而" :"字符
将原样输出。然后,调用 CStatusBar对象的 SetPaneText函数把得到的时间字符串显示到状态栏的
相应窗格上。 
Build并运行 Style程序,结果如图 9.35所示,可以看到这时在程序状态栏上显示了系统当前的时
图 9 .35状态栏上显不系统当前时间

如果在设置窗格的文本时不知道窗格的索引,此时可以利用 CStatusBar类的另一个成员函数 : 
CommandToIndex,通过指定资源 E来得到相应的索引。这种情况下,上述如例如2 1所示代码应该变
成如例如22所示的这样。 
i91J 9-22 
CTime t=CTime : : GetCurrentTime ( ) ; 
CString str=t . Format( "%H :%M :%S " ) ; 
i ntindex=0 ; 
index=m_wndStatusBar.CommandTolndex(IDS_TIMER) ; 
m_wndStatusBar . SetPaneText(index,str) ; 

读者可以测试一下这段代码,将会发现它与前面的代码实现的结果是一样的。但是,
读者可能已经注意到,由于这个窗格的宽度太小,因此未能将时间字符串显示完整,图 9.35只显示
了小时和分钟,没有秒数。为了把时间字符串显示完整,需要把这个窗格的宽度再加大些。这可以
利用 CStatusBar类的另一个成员函数: SetPaneInfo来实现。该函数可以为指定的窗格设置新的 B、
样式和宽度。它的原型声明如下所示: 
void SetPaneInfo(int nindex, UINT nID , UINT nStyle , int cxWidth ); 
可以看到,这个函数有四个参数,其意义分别如下所述: 
. nIndex 
指定将要设置其样式的窗格索引。 
.nID 
为指定窗格重新设置的新 ID。 
. nStyle 
指示窗格的样式,表 9.6中列出了这个参数能够取的值及其意义。
表 9.6 SetPanelnfo函数的 nStyle参数取值

样式 意义  
SBPS NOBORDERS  窗格周围没有 3维边框  
SBPS_POPOUT  边框下陷,文本突出  
SBPS DlSABLED  不绘制文本  
SBPS STRETCH  伸展窗格以填充未用空间。一个控制栏只能有一个窗格具有这种样式  
SBPS NORMAL  不伸展,周围有边框,但不下陷,文本也不突出  

, 
. cxWidth 
指定窗格新的宽度。
如果想让窗格把时间文本显示完整,那么首先就要获得这个文本在显示时占据的宽度,然后直接用
这个宽度去修改窗格的宽度。根据前面的知识,我们知道这里应该调用 GetTextExtent函数来获得
时间文本的宽度。因此,对如例 9-22所示代码修改后的结果如例 9-23所示。 
19IJ9-23 

CTime t=CTime : :GetCurrentTime() ; 
CString str=t .Format("% H:%M :% S" ) ; 
CClientDC dc (this); 
CSize sz=dc . GetTextExtent(str) ; 
int index=. ; 
index=m_wndStatusBar.CommandTolndex(IDS_TIMER) ; 
m_wndStatusBar.SetPaneInfo(index , IDS_TIMER , SBPS_NORMAL , sz.cx); 
m_wndStatusBar.SetPaneText (index, str) ; 

Build并运行 Style程序,结果如图 9.36所示。这时,可以看到程序状态栏上将当前时间完整地显
示出来了。
图 9.36显示完整的时间字符串

但是,这个时间是一个静止的时间,我们希望能够实时地显示系统当前时间。也就是说,让这个时
间"动起来"。前面我们己经为Style程序设置了一个定时器,该定时器每隔 1秒钟发送一次WM TIMER
定时器消息,那么我们就可以在该定时器消息响应函数中再次获得系统当前时间,井设置状态栏窗
格的文本。因此,应在OnTimer函数中添加如例如24所示代码中加灰显示的代码。 
19IJ 9-24 

void CMainFrame: :OnTimer(UINT nIDEvent) 
// TODO: Add your message handler code here and/or call default 
static int index=0 ; 
SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hlcons[index]) ; 
index=++index%3 ; 
+ . 	CTime t=CTime::GetCurrentTime(); 
CString str=t.Format("%H:%M:%S" ) ; 
CClientDC 
dc(this); CSize sz=dc.GetTextExtent(str); 
. 	m_wndStatusBar.SetPaneInfo(1 , IDS_TIMER, SBPS_NORMAL , sz.cx); 
m_wndStatusBar.SetPaneText(1 , str) ; 
CFrameWnd : :OnTimer(nIDEvent) ; 
Build井运行Style,这时会看到状态栏上显示的时间实时地反映了系统当前时间,这个时间"动起来
"了。 

⌨️ 快捷键说明

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