分享
 
 
 

Status Bars

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

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.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有