Status Bars

原创 2001年05月28日 19:52:00

Status Bars

It has become common, even expected, for Windows applications to include status bars that display context-sensitive help for toolbar buttons and menu items. SDK-style Windows applications customarily display descriptive help text for menu items by trapping WM_MENUSELECT messages and updating the status bar. MFC provides an easier way. When a CStatusBar is connected to a frame window, it automatically displays a string of help text when a menu item is highlighted. If the application includes a toolbar, and if the toolbar style includes a CBRS_FLYBY flag, the status bar also displays flyby text for toolbar buttons. The best part is that all you're responsible for besides creating and initializing the status bar (something that requires just a few lines of code) is providing the help text in the form of string resources in your application's RC file. The framework does the rest.

Status bars can do much more than just display help text, of course. A status bar can be divided into one or more areas that are variously referred to as panes, panels, or indicators. The text of each pane can be set individually, so one pane can display the current line number or page number in a document while another displays menu and toolbar help and still others display the current Caps Lock and Num Lock states. Some status bars even contain progress controls that report percentage-complete figures for potentially lengthy operations such as document saving and loading.

Creating and Initializing a Status Bar

In MFC, a status bar is an instance of CStatusBar. An application that uses a status bar typically declares a CStatusBar object as a member of the frame window class. Then the frame window's OnCreate handler creates the status bar with a statement like this one:

m_wndStatusBar.Create (this);

The lone argument passed to Create identifies the status bar's parent window. Passing a this pointer referring to a frame window makes the status bar a child of the frame window. A status bar created in this way doesn't need to be destroyed before the application terminates because it's destroyed automatically when its parent is destroyed. CStatusBar::Create also accepts parameters specifying the status bar's style and child window ID, but the default values MFC provides for these parameters do quite nicely for most applications.

After it's created, a status bar is initialized by calling CStatusBar::SetIndicators. SetIndicators specifies the number of panes the status bar will contain and optionally assigns string resources to individual panes. The statements

UINT nIndicator = ID_SEPARATOR;
m_wndStatusBar.Create (this);
m_wndStatusBar.SetIndicators (&nIndicator, 1);

create a simple status bar containing just one pane. ID_SEPARATOR is a generic ID that says no string resource is associated with this pane. You can create a simple "binary" pane that indicates whether a particular feature of your application is on or off by specifying a string resource ID instead of ID_SEPARATOR and connecting the pane to an update handler that uses CCmdUI::Enable to enable and disable the pane. An enabled pane displays the string resource assigned to it, but a disabled pane is blank. The status bar created by the following code sample includes a pane that displays the text string "INS" when the application is in insert mode and nothing when it's in overstrike mode. This example assumes that insert mode is on when m_bInsert is nonzero and off when m_bInsert is 0:

// In the RC file
STRINGTABLE
BEGIN
    ID_INDICATOR_INS "INS"
END

// In CMainFrame's message map
ON_UPDATE_COMMAND_UI (ID_INDICATOR_INS, OnUpdateIndicator)

// In CMainFrame::OnCreate
static UINT nIndicators[] = {
    ID_SEPARATOR,
    ID_INDICATOR_INS
};

m_wndStatusBar.Create (this);
m_wndStatusBar.SetIndicators (nIndicators, 2);

// Elsewhere in CMainFrame
void CMainFrame::OnUpdateIndicator (CCmdUI* pCmdUI)
{
    pCmdUI->Enable (m_bInsert);
}

In this example, the frame window handles the UI update commands. In a real application, it might be more appropriate to make OnUpdateIndicator a member of the document or the view class. ID_INDICATOR_INS is a symbolic constant defined elsewhere in the application; MFC doesn't define it for you.

MFC defines four special indicator IDs for status bar panes that display keyboard states and maps them to a common update handler in the CFrameWnd class:

ID_INDICATOR_CAPS, which corresponds to the Caps Lock key

ID_INDICATOR_NUM, which corresponds to the Num Lock key

ID_INDICATOR_SCRL, which corresponds to the Scroll Lock key

ID_INDICATOR_KANA, which corresponds to the Kana key on Japanese keyboards

A status bar pane assigned the ID value ID_INDICATOR_CAPS displays the word "CAP" when Caps Lock is on. Similarly, an ID_INDICATOR_NUM pane displays "NUM" when Num Lock is on, an ID_INDICATOR_SCRL pane displays "SCRL" when Scroll Lock is on, and an ID_INDICATOR_KANA pane displays "KANA" when Kana mode is enabled on Japanese keyboards. The framework (in reality, CFrameWnd::OnUpdateKeyIndicator) keeps these indicators in sync with the keyboard. Consequently, you can create a status bar with Caps Lock, Num Lock, and Scroll Lock indicators simply by adding the magic ID values to the array passed to SetIndicators:

static UINT nIndicators[] = {
    ID_SEPARATOR,
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL
};

m_wndStatusBar.Create (this);
m_wndStatusBar.SetIndicators (nIndicators, 4);

The resulting status bar is shown in Figure 12-6. The blank pane indicates that Scroll Lock is inactive. CStatusBar automatically positions all panes after the first at the far right end of the status bar and stretches the leftmost pane to fill the remaining space. It sizes the other panes so that they're just wide enough to display the text strings assigned to them. Panes other than the first are also drawn "indented" so that they're visible even when they're blank.

Figure 12-6. Status bar with Caps Lock, Num Lock, and Scroll Lock indicators.

Providing Context-Sensitive Help for Menu Items

When you assign the first (leftmost) pane in a status bar the value ID_SEPARATOR, you enable a special feature of MFC that is elegant in both design and simplicity. When the user highlights a menu item, the framework checks to see whether the application's EXE file contains a string resource whose ID equals the menu item ID. If the search turns up a match, the string resource is loaded and displayed in the status bar pane. As a result, you can provide context-sensitive help for your application's menus by providing string resources whose IDs match the menu item IDs. If a menu item and a toolbar button share the same ID, the same string resource doubles as help text for the menu item and as flyby text for the toolbar.

As it does for toolbar buttons, the framework provides default help strings for ID_FILE_NEW, ID_FILE_OPEN, and other common command IDs. It also provides default help strings for commands found in the system menu. (For a complete list of predefined IDs and the help text and ToolTip text associated with them, look in the MFC source code file Prompts.rc.) Simply include the header file Afxres.h in your application's RC file, and the framework's predefined string resources will be included, too. If you use AppWizard to create the application, Afxres.h is included for you. Rather than add string resources for other menu items by hand, you can double-click a menu item in the menu editor and enter a string in the Menu Item Properties window's Prompt box.

You can override the help text for predefined menu item IDs by defining your own string resources with identical ID values. For a nice touch, include an

AFX_IDS_IDLEMESSAGE "Ready"

statement in your application's string table, and the framework will display the word "Ready" in the status bar when no menu is pulled down or no item is selected. As usual, this is done for you if you use AppWizard to add a status bar to your application.

Creating Custom Status Bar Panes

Now you know how to display help text in a status bar, add Caps Lock, Num Lock, and Scroll Lock indicators, and create simple on/off indicators by combining string resources and update handlers. But what about more complex status bars like the ones featured in Microsoft Word, Microsoft Excel, Microsoft PowerPoint, and other Windows applications? How, for example, would you create a status bar pane that displays the time of day or the current page number?

For starters, you can add panes to a status bar and size them any way you want using CStatusBar's SetPaneInfo function. SetPaneInfo accepts four parameters: the 0-based index of the pane whose attributes you want to modify and the pane's ID, style, and width, in that order. The pane style specifies whether the pane will be drawn indented, protruding, or flush with the face of the status bar. It also determines whether the pane is currently enabled or disabled and identifies variable-width panes that expand and contract with the status bar. The style is a combination of one or more of the following values:

Style Description
SBPS_NOBORDERS Draws the pane flush with the surface of the status bar.
SBPS_POPOUT Draws the pane so that it protrudes from the status bar.
SBPS_NORMAL Draws the pane so that it is indented into the status bar.
SBPS_DISABLED Disables the pane. Disabled panes don't display text.
SBPS_STRETCH Stretches the pane to fill unused space when the status bar is resized. Only one pane per status bar can have this style.
SBPS_OWNERDRAW Creates an owner-draw pane.

The following code creates a status bar with three custom panes. The first pane is 64 pixels wide and is drawn flush with the surface of the status bar. The second is also 64 pixels wide, but it protrudes from the status bar. The third is a variable-width pane whose right edge follows the right edge of the status bar. It's drawn with an indented border.

static UINT nIndicators[] = {
    ID_SEPARATOR,
    ID_SEPARATOR,
    ID_SEPARATOR
};

m_wndStatusBar.Create (this);
m_wndStatusBar.SetIndicators (nIndicators, 3);

m_wndStatusBar.SetPaneInfo (0, ID_SEPARATOR, SBPS_NOBORDERS, 64);
m_wndStatusBar.SetPaneInfo (1, ID_SEPARATOR, SBPS_POPOUT, 64);
m_wndStatusBar.SetPaneInfo (2, ID_SEPARATOR, SBPS_NORMAL ¦
    SBPS_STRETCH, 0);

In a real application, you'll probably want to avoid hard pixel counts and, instead, base pane widths on a scalable screen metric such as the average width of a character in the status bar font. You can get a CFont pointer for the default status bar font by calling the GetFont function a CStatusBar inherits from CWnd.

Once a custom pane is created, it's your job to tell the status bar what to display inside the pane. You can add text to a pane in two ways. You can call CStatusBar::SetPaneText to set the text directly, or you can assign the pane an update handler and let the update handler set the text with CCmdUI::SetText. Which method you use depends on how you want the pane to be updated. The following code fragment sets a timer to fire every 200 milliseconds and uses SetPaneText to update an hours:minutes:seconds display in pane 2. (Windows timers are discussed in Chapter 14.) In this case, the ID assigned to the pane in the call to SetIndicators or SetPaneInfo is irrelevant because SetPaneText identifies panes by index.

// In CMainFrame::OnCreate
SetTimer (ID_TIMER, 200, NULL);
    
void CMainFrame::OnTimer (UINT nTimerID)
{
    CTime time = CTime::GetCurrentTime ();
    int nSecond = time.GetSecond ();
    int nMinute = time.GetMinute ();
    int nHour = time.GetHour () % 12;

    CString string;
    string.Format (_T ("%0.2d:%0.2d:%0.2d"), nHour, nMinute, nSecond);
    m_wndStatusBar.SetPaneText (2, string);
}

An alternative approach is to assign the pane a unique ID such as ID_INDICATOR_TIME and connect it to an update handler with a message-map entry. Now the time-of-day display in the status bar will be continually updated by the framework.

// In the message map
ON_UPDATE_COMMAND_UI (ID_INDICATOR_TIME, OnUpdateTime)
    
void CMainFrame::OnUpdateTime (CCmdUI* pCmdUI)
{
    CTime time = CTime::GetCurrentTime ();
    int nSecond = time.GetSecond ();
    int nMinute = time.GetMinute ();
    int nHour = time.GetHour () % 12;

    CString string;
    string.Format (_T ("%0.2d:%0.2d:%0.2d"), nHour, nMinute, nSecond);
    pCmdUI->SetText (string);
}

The best way to define ID_INDICATOR_TIME is to add a string resource with that ID to your application. Assign the string a dummy value such as "MMMMM," and MFC will use the width of the string to size the status bar pane. Incidentally, you can include a leading tab character ("/t") in text written to a status bar to center the text in the pane or two leading tab characters ("/t/t") to right-align the text.

Status Bar Support in AppWizard

You can use AppWizard to add a status bar to an MFC application by checking the Initial Status Bar box in AppWizard's Step 4 dialog box, as shown in Figure 12-7. AppWizard responds by adding a CStatusBar member variable to the main frame window class and hooking it up with an OnCreate handler that creates a four-pane status bar: an ID_SEPARATOR pane in which help text appears and indicator panes for the Caps Lock, Num Lock, and Scroll Lock keys.

Figure 12-7. Using AppWizard to add a status bar.

One of the first questions new MFC programmers ask about AppWizard-generated status bars is, "How do I get rid of the keyboard indicator panes?" The answer is simple. Begin by finding the following statements in the CPP file for the AppWizard-generated main frame window class:

static UINT indicators[] =
{
    ID_SEPARATOR,           // status line indicator
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
};

Then remove the final three entries so that the array looks like this:

static UINT indicators[] =
{
    ID_SEPARATOR            // status line indicator
};

That's all there is to it. Rebuild the application and the indicator panes will be no more.

jquery 绘图工具 flot 使用

今天想做一个统计图表,像163博客的流量统计一样的,借助 flot 实现了,而且很简单。 flot网址:http://code.google.com/p/flot/ 下载 JS 文件,使用方法和 ...
  • liu_yanna
  • liu_yanna
  • 2016年01月25日 10:36
  • 292

三十而立,从零开始学ios开发(十一):Tab Bars和Pickers - minglz - 博客

不好意思各位,本人休息了一个礼拜,所以这次的进度延后了,而且这次的学习的内容比较多,时间用的也比较长,文章发布的时间间隔有些长了,望各位谅解,下面继续我们的ios之旅。 这次我们主要学习的内容有2个...
  • billhepeng
  • billhepeng
  • 2015年07月27日 00:04
  • 605

PCIe to AXI Translation——PCIe 内存空间到AXI内存空间的转换

PCIe to AXI Translation——PCIe 内存空间到AXI内存空间的转换UltraScale系列芯片包含PCIe的Gen3 Integrated Block IP核在内的多种不同功能...
  • qq_20748649
  • qq_20748649
  • 2016年12月05日 19:16
  • 879

status函数(自学数据结构第一天)

个人认为今天学到的是status函数类型的意义: #define TRUE  1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEAS...
  • qwezhaohaihong
  • qwezhaohaihong
  • 2016年01月28日 18:24
  • 773

英语单词state和status的区别

今天在数据库表添加状态字段时改用state还是Status起名时发愁了,百度了一下还真长知识 state:比较常用,各种状态都可以用它,但是它更着重于一种心理状态或者物理状态。 Statu...
  • yinyichao0107
  • yinyichao0107
  • 2015年10月29日 20:26
  • 376

git status简单用法

git status可以用来查看仓库的状态,这个命令是一个很有用的命令,在用GIT的过程中,会出现各种意想不到的情况,原因是我们反复提交和修改。git status可以帮助我们快速的知道当前的GIT状...
  • lv_xinmy
  • lv_xinmy
  • 2013年02月21日 12:08
  • 15374

http status 状态码汇总

常见HTTP状态码 200 OK301 Moved Permanently302 Found304 Not Modified307 Temporary Redirect400 Bad Reque...
  • leo115
  • leo115
  • 2013年04月26日 15:48
  • 4164

mysql之status和variables区别及用法详解

一、mysql之status和variables区别 首先可以通过下属两个命令来查看mysql的相应的系统参数 show status like '%abc%'; show variables ...
  • andyzhaojianhui
  • andyzhaojianhui
  • 2015年11月26日 11:51
  • 4254

通过show status 来优化MySQL数据库

通过show status 来优化MySQL数据库 http://lxneng.iteye.com/blog/451985 1, 查看MySQL服务器配置信息 Java代码 mysql> sh...
  • kash_chen007
  • kash_chen007
  • 2014年02月23日 14:17
  • 3775

Log4j2介绍和特性实例(二)--一个实例和初学注意事项(configuration标签中的 status 和 monitorInterval)

Log4j2完整实例,初学注意事项(configuration标签中的 status 和 monitorInterval)
  • chenhaotong
  • chenhaotong
  • 2015年12月13日 11:15
  • 6366
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Status Bars
举报原因:
原因补充:

(最多只允许输入30个字)