4、MFC:菜单栏、工具栏与状态栏

菜单栏、工具栏与状态栏

1、菜单栏

1.1 简介

菜单在界面设计中是经常使用的一种元素,包括Windows系统中的窗口、智能终端设备的应用界面等都会经常见到菜单的身影。我们在对可视化窗口操作时,菜单确实提供了很大方便。

菜单分为:

  1. 下拉式菜单:下拉式菜单一般在窗口标题栏下面显示,下拉式菜单通常是由主菜单栏、子菜单及子菜单中的菜单项和分隔条所组成的。
  2. 弹出式菜单:弹出式菜单一般可以通过单击鼠标右键等操作显示。它的主菜单不可见,只显示子菜单。

1.2 创建

属性设置

  1. 菜单项中含有"..."则表示点击后会弹出对话框。
  2. 热键:菜单项的标题文本中都有一个字母带下划线,带下划线的字母为热键。中文则为括号中的字母。

主菜单栏上的"File"中字母"F"带下划线,F就是热键,程序运行并显示窗口时,在键盘上点击Alt+F就等同于直接点菜单项File,弹出File下的子菜单后,点击"Open"的热键O就可以实现与直接点菜单项Open相同的功能。

热键的定义:可在属性中直接设置。Caption为"&File",很明显,只要在要定义为热键的字母前加&就可以了。

  1. 快捷键:用这些组合键就能实现与相应菜单项一样的功能。
    定义:"Open"菜单项的Caption属性,为"&Open...\tCtrl+O",这里的\t表示在显示前面的文本后跳格再显示快捷键Ctrl+O,但这样设置其Caption属性只是能显示出快捷键,要实现快捷键的功能还需要在Accelerator资源中设定。
  • Accelerator中有四列,分别为:ID、Modifier、Key和Type。ID就是菜单项的ID,Modifer和Key就代表了组合键。例如,Open菜单项的ID为ID_FILE_OPEN,Modifer为"Ctrl",Key为"O"。
  1. 创建:右键插入新列、分隔符、菜单项等;也可以直接输入。
    需要为菜单项设置ID、热键和快捷键(Accelerator)。

菜单消息

菜单主要能发送两种消息:COMMAND消息和UPDATE_COMMAND_UI消息。

  1. COMMAND消息:在菜单项被点击时发送该消息。
  2. UPDATE_COMMAND_UI消息:用来维护菜单项的各项状态,包括激活、禁用、变灰、选中、未选中等。在下拉菜单每次打开的时候,所有菜单项的此消息都会被发送出去。如果所属类中为菜单项的该消息添加了处理函数,则执行相应函数更新菜单状态,如果菜单项没有此消息处理函数,也没有COMMAND消息的处理函数,那么它就会变灰。

成员函数

MFC为菜单的操作提供了CMenu类。

  1. BOOL LoadMenu(UINT nIDResource);
    加载菜单资源,并将其附加到CMenu对象上。参数nIDResource指定了要加载的菜单资源的ID。如果菜单加载成功则返回TRUE,否则返回FALSE。
  2. BOOL DeleteMenu(UINT nPosition,UINT nFlags);
    在菜单中删除一个菜单项。参数nPosition指定要删除的菜单项。参数nFlags就用来解释nPosition的意义,为MF_BYCOMMAND时说明nPosition表示菜单项的ID,为MF_BYPOSITION时说明nPosition表示菜单项的位置,第一个菜单项的位置为0。如果删除菜单项成功则返回TRUE,否则返回FALSE。
  3. BOOL TrackPopupMenu(UINT nFlags,int x,int y,CWnd* pWnd,LPCRECT lpRect = 0);
    用来在指定位置显示一个浮动的弹出式菜单。参数nFlags指定屏幕坐标和鼠标位置的标志,可以是以下取值:
    TPM_CENTERALIGN:菜单在水平方向上相对于参数x指定的坐标值居中显示
    TPM_LEFTALIGN:菜单的左侧与参数x指定的坐标值对齐
    TPM_RIGHTALIGN:菜单的右侧与参数x指定的坐标值对齐
    TPM_BOTTOMALIGN:菜单的底部与参数y指定的坐标值对齐
    TPM_TOPALIGN:菜单项的顶部与参数y指定的坐标值对齐
    TPM_VCENTERALIGN:菜单在垂直方向上相对于参数y指定的坐标值居中显示
    参数x指定弹出式菜单的水平方向的屏幕坐标,参数y指定菜单顶部垂直方向上的屏幕坐标,参数pWnd指明哪个窗口拥有此弹出式菜单,不能为NULL,参数lpRect忽略。
  4. UINT CheckMenuItem(UINT nIDCheckItem,UINT nCheck);
    在弹出菜单中为菜单项增加选中标记或移除选中标记。参数nIDCheckItem指定要选中或取消选中的菜单项。参数nCheck指定菜单项的选中状态和如何根据nIDCheckItem确定菜单项的位置,可以是MF_CHECKED或MF_UNCHECKED与MF_BYPOSITION或MF_BYCOMMAND的组合,这几个标志的含义如下:
    MF_BYCOMMAND:为默认值。说明参数nIDCheckItem表示菜单项的ID
    MF_BYPOSITION:说明参数nIDCheckItem表示菜单项的位置,第一个菜单项的位置是0
    MF_CHECKED:为菜单项添加选中标记
    MF_UNCHECKED:为菜单项移除选中标记
    该函数返回菜单项之前的状态:MF_CHECKED或MF_UNCHECKED, 如果菜单项不存在则返回0xFFFFFFFF。
  5. UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);
    激活、禁用菜单项或使其变灰。参数nIDEnableItem指定要激活、禁用或变灰的菜单项。参数nEnable指定操作的类型,可以是MF_DISABLED、MF_ENABLED或MF_GRAYED与MF_BYCOMMAND或MF_BYPOSITION的组合,这些值的含义如下:
    MF_BYCOMMAND:同CheckMenuItem
    MF_BYPOSITION:同CheckMenuItem
    MF_DISABLED:禁用菜单项,使其不能被选择但不变灰
    MF_ENABLED:激活菜单项,使其能够被选择并由变灰状态恢复
    MF_GRAYED:禁用菜单项,使其不能被选择并变灰
    该函数返回菜单项之前的状态:MF_DISABLED、MF_ENABLED或MF_GRAYED
  6. CMenu* GetSubMenu(int nPos) const;
    获取弹出菜单的CMenu对象。参数nPos指定弹出菜单在菜单中的位置,不能使用ID。返回值是CMenu对象的指针,该CMenu对象的m_hMenu成员为由nPos指定的弹出菜单的句柄,如果不存在这样的CMenu对象则返回NULL,然后创建一个临时弹出菜单。

1.3 实例

  • 下拉式菜单实现
  1. 创建菜单项:设置ID,名称,热键,快捷键等;
  2. 创建消息相应函数(消息响应函数应该创建在CMainFrame类中);
cpp 复制代码
ON_COMMAND(IDM_TOOLSDRAW, &CMainFrame::OnToolsdraw)
ON_UPDATE_COMMAND_UI(IDM_TOOLSDRAW, &CMainFrame::OnUpdateToolsdraw)

void CMainFrame::OnToolsdraw()
{
	// TODO: 在此添加命令处理程序代码
}


void CMainFrame::OnUpdateToolsdraw(CCmdUI* pCmdUI)
{
	// TODO: 在此添加命令更新用户界面处理程序代码
}
  1. 编写函数体中处理代码;数据成员和函数成员实现
  • 弹出式菜单实现
    鼠标右键的点击为消息响应函数操作。
  1. 创建弹出菜单资源;
  2. 通过消息响应函数来弹出菜单项,有两种实现方式:
cpp 复制代码
void CSingleDocAppView::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CMenu menu;       // 菜单(包含主菜单栏和子菜单)   
	CMenu* pSubMenu;  // 右键菜单   

	// 加载菜单资源到menu对象   
	menu.LoadMenu(IDR_POPUP_EDIT);
	// 因为右键菜单是弹出式菜单,不包含主菜单栏,所以取子菜单   
	pSubMenu = menu.GetSubMenu(0);
	// 将坐标值由客户坐标转换为屏幕坐标   
	ClientToScreen(&point);
	// 弹出右键菜单,菜单左侧与point.x坐标值对齐   
	pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);

	CView::OnRButtonDown(nFlags, point);
}
cpp 复制代码
void CSingleDocAppView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CSingleDocAppView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
  1. 在弹出式菜单弹出的相关类中对菜单项的消息响应函数进行实现。

2、工具栏

2.1 简介

工具栏一般位于主框架窗口的上部,菜单栏的下方,由一些带图片的按钮组成。当用户用鼠标单击工具栏上某个按钮时,程序会执行相应的操作,如果鼠标没有点击,只是停留在某个按钮上一会后,会弹出一个小窗口显示提示信息。

工具栏一般位于主框架窗口的上部,菜单栏的下方,由一些带图片的按钮组成。当用户用鼠标单击工具栏上某个按钮时,程序会执行相应的操作,如果鼠标没有点击,只是停留在某个按钮上一会后,会弹出一个小窗口显示提示信息。

工具栏属性

资源位置:在资源视图的Toolbar栏下

以IDR_MAINFRAME工具栏的第一个按钮为例说明工具栏按钮的各项属性。用鼠标单击工具栏资源上的第一个按钮,属性页中就会显示其属性。下面分别讲解各项属性。

  1. ID属性:ID_FILE_NEW。不知大家是否还记得,菜单IDR_MAINFRAME的菜单项File->New的ID也是ID_FILE_NEW,两者ID相同,正是如此才使得工具栏第一个按钮与菜单项File->New能实现相同的功能。如果想让工具栏某个按钮与菜单栏某个菜单项点击后执行的操作相同,就要为两者设置相同的ID。
  2. Prompt属性:Create a new document\nNew。此属性为工具栏按钮的提示文本。在鼠标指向此按钮时,状态栏中会显示"Create a new document",当弹出提示信息窗口时会显示包含"New"的提示信息。"\n"是两者的分隔转义符。
  3. Height属性:15。此属性为工具栏按钮的像素高度。
  4. Width属性:16。此属性为工具栏按钮的像素宽度。
  • 工具栏资源的最右边总是会有一个待编辑的按钮,我们对其进行编辑后,工具栏资源会自动增加一个新的空白按钮,这也实现了按钮的添加操作。如果我们想要删除某个按钮,就可以用鼠标左键点住它,拖出工具栏资源的范围即可。
  • 另外,我们看到,第三个按钮(保存按钮)和第四个按钮(剪切按钮)之间有一些间隙,在运行程序后会出现一个竖的分隔线,所以想要在两个按钮之间添加分隔线的话,可以用鼠标左键拖住右边的按钮往右稍移动一些就可以了。

2.2 创建

消息

一般情况下工具栏中的按钮在菜单栏中都有对应的菜单项,两者实现的功能相同,要想实现这种效果,只需要将工具栏按钮的ID与对应的菜单栏中菜单项的ID设置为相同值即可。

在实际使用工具栏时,除了前面讲的资源编辑外,其他使用与菜单类似。例如,对COMMAND消息和UPDATE_COMMAND_UI消息,可像菜单应用实例那样为工具栏按钮添加消息处理函数。

  • 如果工具栏按钮对应的菜单项已经添加了消息处理函数,那么就不必再为它添加了,因为它的ID与菜单项相同,所以会调用同样的消息处理函数。这样点击工具栏按钮与点击相应菜单项执行相同的功能,在菜单项为选中、激活或禁用等状态时,工具栏按钮会有一样的状态。

CToolBar类的主要成员函数

MFC为工具栏的操作提供了CToolBar类。

  1. virtual BOOL CreateEx(
    CWnd* pParentWnd,
    DWORD dwCtrlStyle = TBSTYLE_FLAT,
    DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP,
    CRect rcBorders = CRect(0, 0, 0, 0),
    UINT nID = AFX_IDW_TOOLBAR
    );
    创建工具栏对象。参数pParentWnd为工具栏父窗口的指针。参数dwCtrlStyle为工具栏按钮的风格,默认为TBSTYLE_FLAT,即"平面的"。参数dwStyle为工具栏的风格,默认取值WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP,由于是主框架窗口的子窗口,所以要有WS_CHILD和WS_VISIBLE风格,CBRS_ALIGN_TOP风格表示工具栏位于父窗口的顶部, 各种风格可以参见MSDN的Toolbar Control and Button Styles中的定义。参数rcBorders为工具栏边框各个方向的宽度,默认为CRect(0, 0, 0, 0),即没有边框。参数nID为工具栏子窗口的ID,默认为AFX_IDW_TOOLBAR。
  2. BOOL LoadBitmap(UINT nIDResource);
    为工具栏加载位图。参数nIDResource为位图资源的ID。成功则返回TRUE,否则返回FALSE。注意,这里的位图资源应当为每个工具栏按钮都提供位图,如果图片不是标准大小(16像素宽,15像素高),则需要调用SetSizes成员函数调整按钮大小和图片大小。
  3. BOOL LoadToolBar(UINT nIDResource);
    加载由nIDResource指定的工具栏。参数nIDResource为要加载的工具栏的资源ID。成功则返回TRUE,否则返回FALSE。
  4. void SetSizes(SIZE sizeButton,SIZE sizeImage);
    设置工具栏按钮的大小和图片的大小。参数sizeButton为工具栏按钮的像素大小。参数sizeImage为图片的像素大小。
  5. void SetButtonStyle(int nIndex,UINT nStyle);
    设置工具栏按钮或分隔线的风格,或者为按钮分组。参数nIndex为将要进行设置的按钮或分隔线的索引。参数nStyle为按钮风格,可以是以下取值:
    TBBS_BUTTON 标准按钮(默认)
    TBBS_SEPARATOR 分隔条
    TBBS_CHECKBOX 复选框
    TBBS_GROUP 标记一组按钮的开始
    TBBS_CHECKGROUP 标记一组复选框的开始
    TBBS_DROPDOWN 创建下拉列表按钮
    TBBS_AUTOSIZE 按钮的宽度根据按钮文本计算,而不基于图片大小
    TBBS_NOPREFIX 按钮的文本没有快捷键前缀
  6. UINT GetButtonStyle(int nIndex) const;
    获取工具栏按钮或分隔条的风格。风格可参考SetButtonStyle。参数nIndex为按钮或分隔条的索引。
  7. BOOL SetButtonText(int nIndex,LPCTSTR lpszText);
    设置工具栏按钮的文本。参数nIndex为工具栏按钮的索引。参数lpszText为指向要设置的文本字符串的指针。设置成功则返回TRUE,否则返回FALSE。
  8. CString GetButtonText(int nIndex) const;
    获取工具栏按钮上显示的文本。参数nIndex为工具栏按钮的索引。

2.3 实例

CMainFrame类中看到,它创建工具栏所使用的类并不是常用的CToolBar类,而是CMFCToolBar类。CMFCToolBar类是自VS2008以来MFC提供的类,它与CToolBar类有些类似,但功能更丰富。这里要注意,CMFCToolBar类与CToolBar类并没有任何派生关系。

以CMFCToolBar类讲解工具栏的创建步骤:

  1. 创建工具栏资源。
  2. 构造CMFCToolBar类的对象。
  3. 调用CMFCToolBar类的Create或CreateEx成员函数创建工具栏。
  4. 调用LoadToolBar成员函数加载工具栏资源。
cpp 复制代码
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
	{
		TRACE0("未能创建工具栏\n");
		return -1;      // 未能创建
	}

	CString strToolBarName;
	bNameValid = strToolBarName.LoadString(IDS_TOOLBAR_STANDARD);
	ASSERT(bNameValid);
	m_wndToolBar.SetWindowText(strToolBarName);

	CString strCustomize;
	bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE);
	ASSERT(bNameValid);
	m_wndToolBar.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);
}

因为创建框架窗口时需要调OnCreate函数,所以工具栏的创建也是在OnCreate中完成的。

  • 工具栏的停靠
    创建好工具栏后,如果想要停靠工具栏,也需要添加相应的停靠代码。工具栏停靠的步骤及需要调用的函数如下(前两个步骤可以颠倒顺序):
  1. 在框架窗口中启用停靠
    若要将工具栏停靠到某个框架窗口,则必须启用该框架窗口(或目标)以允许停靠。可以在CFrameWndEx类中调用下面的成员函数来实现:
cpp 复制代码
BOOL EnableDocking(DWORD dwDockStyle);

该函数采用一个DWORD参数,用来指定框架窗口的哪个边可以接受停靠,可以有四种取值:CBRS_ALIGN_TOP(顶部)、CBRS_ALIGN_BOTTOM(底部)、CBRS_ALIGN_LEFT(左侧)、CBRS_ALIGN_RIGHT(右侧)。如果希望能够将控制条停靠在任意位置,将CBRS_ALIGN_ANY作为参数传递给EnableDocking。

  1. 工具栏启用停靠
    框架窗口启用停靠准备好后,必须以相似的方式准备工具栏。为想要停靠的每一个工具栏CMFCToolBar对象调用下面的函数:
cpp 复制代码
virtual void EnableDocking(DWORD dwAlignment);

允许工具栏停靠到框架窗口,并指定工具栏应停靠的目标边。此函数指定的目标边必须与框架窗口中启用停靠的边匹配,否则工具栏无法停靠,为浮动状态。

  1. 停靠工具栏
    当用户试图将工具栏放置在允许停靠的框架窗口某一边时,需要框架CFrameWndEx类调用以下函数:
cpp 复制代码
void DockPane(CBasePane* pBar,UINT nDockBarID=0,LPCRECT lpRect=NULL);
  • 参数pBar为要停靠的控制条的指针,参数nDockBarID为要停靠的框架窗口某条边的ID,可以是以下四种取值:AFX_IDW_DOCKBAR_TOP、AFX_IDW_DOCKBAR_BOTTOM、AFX_IDW_DOCKBAR_LEFT、AFX_IDW_DOCKBAR_RIGHT

CMainFrame类的OnCreate函数实现中,工具栏的停靠过程:

cpp 复制代码
// TODO: 如果您不希望工具栏和菜单栏可停靠,请删除这五行
	m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockPane(&m_wndMenuBar);
	DockPane(&m_wndToolBar);

3、状态栏

3.1 简介

状态栏相信大家在很多窗口中都能见到,它总是用来显示各种状态。状态栏实际上也是一个窗口,一般分为几个窗格,每个窗格分别用来显示不同的信息和状态等,如菜单项和工具栏按钮的提示信息。

用MFC向导生成的单文档或多文档程序都会自动创建状态栏,该状态栏被分为了几个窗格,分别用来显示菜单项和工具栏按钮的提示信息及Caps Lock、Num Lock、Scroll Lock键的状态。

3.2 创建

CStatusBar类

  1. virtual BOOL Create(CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR);
    创建一个状态栏。参数pParentWnd为状态栏父窗口的指针,参数dwStyle为状态栏的风格,除了标准的Windows风格外,它还支持:
    CBRS_TOP:位于框架窗口的顶部。
    CBRS_BOTTOM:位于框架窗口的底部。
    CBRS_NOALIGN:父窗口大小改变时状态栏不会被重新定位。
    参数nID指定状态栏的ID。
  2. BOOL SetIndicators(const UINT* lpIDArray, int nIDCount);
    为每个指示器设置显示文本,具体来说,就是用lpIDArray数组中的对应元素为每个指示器设置一个ID,然后加载每个ID代表的字符串,设置为这些指示器的显示文本。参数lpIDArray为指向一个ID数组的指针,参数nIDCount为lpIDArray数组的元素个数。
  3. UINT GetItemID(int nIndex) const;
    获取由nIndex指定的指示器的ID。参数nIndex为要获取ID的指示器索引。
  4. CString GetPaneText(int nIndex) const;
    获取状态栏窗格中显示的文本。参数nIndex为要获取文本的窗格的索引。返回值为包含窗格文本的CString对象。
  5. BOOL SetPaneText(int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE);
    设置状态栏窗格的显示文本。参数nIndex为要设置文本的窗格的索引,参数lpszNewText为指向新的窗格文本的指针,参数bUpdate表示是否设置后立即更新显示。如果设置成功则返回TRUE,否则返回FALSE。

状态栏创建

在CMainFrame类中看到,创建状态栏时使用的是CMFCStatusBar类对象。CMFCStatusBar类是自VS2008以来提供的状态栏类,用法与CStatusBar类相似,甚至很多成员函数也类似,但它的功能更加丰富。

创建步骤:

  1. 构造一个CMFCStatusBar类的对象。
    在MainFrm.h文件中,为CMainFrame类定义了一个成员对象:CMFCStatusBar m_wndStatusBar;。
  2. 调用CMFCStatusBar::Create函数来创建状态栏窗口。
    在CMainFrame::OnCreate函数的实现中,我们可以找到CMFCStatusBar::Create函数的调用:
cpp 复制代码
if (!m_wndStatusBar.Create(this))   
{   
    TRACE0("Failed to create status bar\n");   
    return -1;      // fail to create   
}
  1. 调用CMFCStatusBar::SetIndicators函数为状态栏划分窗格,并为每个指示器设置显示文本。
    CMFCStatusBar::SetIndicators函数需要一个ID数组的参数,在MainFrm.cpp中,如下定义了一个窗格ID的数组:
cpp 复制代码
static UINT indicators[] =   
{   
    ID_SEPARATOR,           // status line indicator   
    ID_INDICATOR_CAPS,   
    ID_INDICATOR_NUM,   
    ID_INDICATOR_SCRL,   
};
  • indicators数组定义了状态栏窗格的划分信息。第一个元素一般为ID_SEPARATOR,对应的窗格用来显示命令提示信息,上面数组中的后三项为指示器文本的字符串ID,可以根据这些ID在String Table字符串资源中找到相应的字符串,查找方法是,在Resource View资源视图中,打开String Table字符串资源,可以看到有ID、Value和Caption三列,在ID列中找到需要的ID,对应的Caption列文本就是要查找的字符串。ID_INDICATOR_CAPS、ID_INDICATOR_NUM和ID_INDICATOR_SCRL对应的字符串分别是CAP、NUM、SCRL,对应的三个窗格分别为Caps Lock指示器、Num Lock指示器和Scroll Lock指示器。

在CMainFrame::OnCreate函数中调用:

cpp 复制代码
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

状态栏就创建完成了,之后我们可以通过CMFCStatusBar::SetPaneText设置窗格的文本。

3.3 实例

在状态栏添加一个事件窗格,用来显示系统时间。

  1. 在Resource View资源视图中打开String Table字符串资源,然后在最后一行的下一个空白行中,或者任意处点右键选择"New String",添加一个新的字符串资源.
  2. 在indicators数组的第一个元素ID_INDICATOR_SCRL后插入IDS_INDICATOR_TIME。
cpp 复制代码
static UINT indicators[] =
{
	ID_SEPARATOR,           // 状态行指示器
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
	IDS_INDICATOR_TIME
};
  1. 要实时显示系统时间,就需要使用一个定时器,每秒钟更新一次时间显示。在CMainFrame::OnCreate函数中开启定时器.
cpp 复制代码
// 启动定时器,定时器ID为1,定时时间为1000ms,即1s   
    SetTimer(1, 1000, NULL);  
  1. 在Class View类视图中找到CMainFrame类,右键选择"Properties",然后在显示出来的属性页中,点工具栏上的Messages按钮,即显示出消息列表,找到WM_TIMER消息,添加其消息处理函数void CMainFrame::OnTimer(UINT_PTR nIDEvent),并修改此函数实现如下:
cpp 复制代码
void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CString strTime;
	// 获取系统当前时间,并保存到curTime   
	CTime curTime = CTime::GetCurrentTime();

	// 格式化curTime,将字符串保存到strTime   
	strTime = curTime.Format(_T("%H:%M:%S"));
	// 在状态栏的时间窗格中显示系统时间字符串   
	m_wndStatusBar.SetPaneText(4, strTime);

	CFrameWndEx::OnTimer(nIDEvent);
}
相关推荐
DY009J20 分钟前
如何搭建C++环境--1.下载安装并调试Microsoft Visual Studio Previerw(Windows)
c++·microsoft·visual studio
nuo53420229 分钟前
The 2024 ICPC Kunming Invitational Contest
c语言·数据结构·c++·算法
小王同学的C++34 分钟前
移动语义和拷贝语义有什么区别?
c++
霁月风44 分钟前
设计模式——装饰器模式
c++·设计模式·装饰器模式
叫我龙翔1 小时前
【项目日记】仿mudou的高并发服务器 --- 实现缓冲区模块,通用类型Any模块,套接字模块
linux·运维·服务器·网络·c++
誓约酱1 小时前
(动画)Qt控件 QLCDNumer
开发语言·c++·git·qt·编辑器
@小博的博客2 小时前
C++初阶学习第十三弹——容器适配器和优先级队列的概念
开发语言·数据结构·c++·学习
离歌漠2 小时前
C#调用C++ DLL方法之P/Invoke
c++·c#·p/invoke
xiaowu0802 小时前
MFC线程-通过CWinThread派生类实现
c++·mfc
LaoWaiHang2 小时前
MFC图形函数学习10——画颜色填充矩形函数
mfc