📄 ch13.htm
字号:
Editor and return to the Form Designer.</P><BLOCKQUOTE> <P><HR><strong>NOTE:</strong> When you modify the Panels property of a StatusBar component, the Form Designer automatically sets the SimplePanel property to False. The assumption is that if you are using multiple panels, you don't want to have a simple status bar. <HR></BLOCKQUOTE><H4>Changing Text in the Status Bar</H4><P>There are two ways to change text in a status bar:</P><UL> <LI>Manually modify the SimpleText property of the status bar (for simple status bars) or the Text property of an individual panel (for complex status bars). <P> <LI>Let VCL automatically supply the status bar text by setting the AutoHint property to True.</UL><P>Manually changing the text in the status bar is simple, particularly if you havea simple status bar. When the SimplePanel property is True, you can set the SimpleTextproperty to the text you want displayed in the status bar:</P><P><PRE>StatusBar.SimpleText := `This shows up in the status bar.';</PRE><P>In the case of complex status bars, changing the text is only slightly more complicated.If you want to change the text for the first panel of a complex status bar, you woulduse something like this:</P><P><PRE>StatusBar.Panels[0].Text := `Status Bar Text';</PRE><P>The Panels property of the StatusBar component has a property called Items thatis an array of panels in the status bar. Setting the Text property for an elementin the Items array changes the text for that panel (because Items is the defaultarray property for the Panels object, you don't have to specifically reference Items).As you can see, the array is 0-based. The first panel in the status bar is arrayelement 0.</P><P>Automatic status bar hint text doesn't require much in the way of explanation.All you have to do is set the AutoHint property to True. The rest is, as the propertyname implies, automatic.</P><BLOCKQUOTE> <P><HR><strong>NOTE:</strong> You can still modify the status bar's text manually even when using AutoHint. There's nothing to stop you from changing the text manually, but remember that the text will be replaced the next time the mouse passes over a component with hint text. <HR></BLOCKQUOTE><H4>Owner-Drawn Status Bar Panels</H4><P>Earlier I said that a panel's Style property can be either psText or psOwnerDraw.When you set a panel's style to psOwnerDraw, you must take the responsibility ofdrawing anything in the panel that needs to be displayed there. It is unlikely thatyou are going to go to the trouble of using an owner-drawn panel just to displaytext. Usually it means you are going to display some sort of icon or bitmap in thestatus bar. Regardless of what is being drawn on the panel, the steps are the same:</P><DL> <DD><B>1. </B>Set the panel's Style property to psOwnerDraw (usually via the StatusBar Panels Editor). <DT></DT> <DD><B>2. </B>Respond to the OnDrawPanel event. <P></DL><P>Obviously, the real work here is going to take place in the event handler forthe OnDrawPanel event. The declaration for the OnDrawPanel event handler looks likethis:</P><P><PRE>procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar; Panel: TStatusPanel; const Rect: TRect);</PRE><P>The StatusBar parameter is a pointer to the status bar. Usually you have a pointerto the status bar anyway (the Name property of the StatusBar component), so thisparameter is not all that useful unless you are using multiple owner-drawn statusbars. The Panel property is a pointer to the particular panel that currently needsdrawing. You can use this parameter to determine which panel needs drawing if youhave more than one owner-drawn panel in your status bar. The Rect parameter containsthe panel's size and position. The Rect parameter is important because it tells youthe exact dimensions of the drawing area.</P><P>The OnDrawPanel event handler is called once for each panel that has its Styleproperty set to psOwnerDraw. If you have only one panel to draw, you don't have toworry about much except the Rect parameter. If you have multiple panels to draw,you must first determine which panel to draw and then do your drawing. An illustrationmight help to explain this. The book's code includes a program called StatBar thatillustrates some of the things you can do with status bars. Run the program and examineits source for tips on implementing status bars in your applications. Figure 13.6shows the StatBar program running.</P><P><A HREF="javascript:popUp('28671306.gif')"><B>FIGURE 13.6.</B></A><B> </B><I>TheStatBar program with owner-drawn status bar panels.</I></P><P>As you can see, the status bar in this program has multiple panels. The middlethree panels are owner-drawn. The panels marked OVR and EXT simulate the status baron a word processing program or code editor. In those types of programs, the Overtypeor Extended Selection modes might be on or off. If the mode is on, the text in thestatus bar panel shows in black. If the mode is off, the text has a 3D disabled-textappearance. The third owner-drawn panel displays a stock Windows icon to illustratethe use of a graphic on a status bar. Run the program and experiment with it to learnhow it works.</P><P>Listing 13.1 shows the OnDrawPanel event handler from the StatBar program. Examineit and read the comments to understand what is going on in the code.</P><P><H4>LISTING 13.1. THE StatusBarDrawPanel METHOD OF THE StatBar PROGRAM.</H4><PRE>procedure TMainForm.StatusBarDrawPanel(StatusBar: TStatusBar; Panel: TStatusPanel; const Rect: TRect);var R : TRect; Icon : HIcon;begin with StatusBar.Canvas do begin { Create a temporary TRect object. The Rect parameter { is const so we can't change it. } R := Rect; { Check to see if panel 3 is the panel which needs { to be drawn. If so, draw an icon in the panel. } if Panel.Index = 3 then begin { Load one of the stock Windows icons. This time { using the API is easier than using VCL. } Icon := LoadIcon(0, IDI_HAND); { Draw the icon and shrink it down to 15 x 15 pixels. } { Center it in the panel, too. } DrawIconEx(Handle, Rect.Left + 6, 3, Icon, 15, 15, 0, 0, DI_NORMAL); { Nothing more to do. } Exit; end; { This rather lengthy if statement checks to see if { either the Overtype Mode or Extended Selection { check boxes are checked. If so, then what we need { to do is to draw the text twice. First, we draw it { in white. Then we draw it again, offset by 1 pixel, { in gray. The effect is a 3D disabled-text look. } if ((Panel.Index = 1) and (OvrMode.Checked = False)) or ((Panel.Index = 2) and (ExtendedSel.Checked = False)) then begin { Move over and down one pixel for the offset. } Inc(R.Left); Inc(R.Top, 2); { Change the text color to white. } Font.Color := clWhite; { Set the backround mode to transparent so the { text appears hollow and so that the white { text can be seen under the gray. } Brush.Style := bsClear; { Draw the text using the API function DrawText. } { I use DrawText because it allows me to center { the text both horizontally and vertically within { the given rectangle. } DrawText(Handle, PChar(Panel.Text), -1, R, DT_CENTER or DT_VCENTER or DT_SINGLELINE); { Set the color to gray because we're going to { draw the text in gray in a moment. } Font.Color := clGray;</PRE><PRE> { Set the rect back to the original size. }</PRE><PRE> Dec(R.Left); Dec(R.Top, 2); end; { Display the text. If the item is not disabled then { the default color (black) is used to draw the text. } { If the item is disabled, then the text color has { been set to gray by the code above. } DrawText(Handle, PChar(Panel.Text), -1, R, DT_CENTER or DT_VCENTER or DT_SINGLELINE); end;end;</PRE><P>This code might seem intimidating, but most of it is comment lines. The code itselfis relatively simple. The comment lines explain what is happening at each step: The3D appearance for the disabled text is accomplished by drawing the text once in whiteand then drawing it again in gray with a slight offset. The result is that the textlooks recessed. The icon is displayed using the Windows API functions LoadIcon andDrawIconEx.</P><P>Owner drawing of status bar panels is daunting at first, but you'll soon findout that it's not all that bad. You might write Windows applications for a long timeand never need owner-drawn panels in your status bar. If you ever need them, however,you'll know that's not impossible to accomplish.</P><P><H2><A NAME="Heading7"></A>Adding Functionality with Command Enabling</H2><P><I>Command enabling</I> is the process of enabling or disabling buttons dependingon current conditions. For example, there's not much point of having the Cut or Copybutton or menu item enabled for a text editor when no text is currently selected.Likewise, if there is no text in the Clipboard, the Paste button should be disabled.</P><P>Command enabling isn't difficult, especially with Delphi's new TActionList component.Still, it takes time to get right. It takes time because you have to pay attentionto detail. (Sometimes it is attention to detail that separates the great applicationsfrom the mediocre applications.)</P><P><H3><A NAME="Heading8"></A>Command Enabling with TActionList and TAction</H3><P>The TAction class provides a convenient way of performing command enabling. TActionList,the nonvisual component that manages actions, is found on the Additional tab of theComponent palette. TActionList, as its name implies, contains a list of TAction objects.You create an action and then assign that action to any controls that need to beenabled or disabled based on that action. By controls I mean menu items, toolbarbuttons, context menu items, and so on.</P><P>Let's take the Edit|Cut menu item, for example. You could have at least threeobjects associated with this particular task:</P><UL> <LI>A main menu item <P> <LI>A toolbar button <P> <LI>A pop-up menu item</UL><P>You create actions with the ActionList Editor. Given the Edit|Cut example, youwould create an action for Cut called, say, CutAction. Then, using the Object Inspector,you assign CutAction to the Action property of each of the objects that correspondto the cut operation (toolbar buttons and menus, for example). At runtime, when youneed to enable the Cut option, you can do so with just one line of code:</P><P><PRE>CutAction.Enabled := True;</PRE><P>This will enable all components with their Action properties set to CutAction.Disabling the Cut items is as simple as assigning False to the Enabled property ofthe action. The OnUpdate event of TAction and TActionList provides a convenient placeto put your command-enabling code.</P><P>Command enabling with TAction is something that you have to experience to fullyappreciate. You add command enabling to ScratchPad in the next section.</P><P><H3><A NAME="Heading9"></A>Implementing Command Enabling</H3><P>In this section you implement command enabling for the ScratchPad program. Firstyou set up the ActionList component, and then you hook up the various componentsto the action list.</P><P><H4>Creating an ActionList</H4><P>It all starts with the ActionList component, which is the heart of the command-enablingsystem in VCL. First you add the actions for the Edit menu items. After that, youadd an action for the File menu's Save and Save As menu items. The following stepswill take you through the ActionList setup process.</P><P><B>Creating the Edit Menu Actions</B></P><P>The following steps show you how to create actions for the Edit menu's Cut, Copy,and Paste items. Perform these steps:</P><DL> <DT></DT> <DD><B>1. </B>Place an ActionList component on the form and change the Name property to ActionList. <P> <DT></DT> <DD><B>2. </B>Double-click the ActionList icon to invoke the ActionList Editor. <P> <DT></DT> <DD><B>3. </B>Right-click on the ActionList Editor and choose New Standard Action from the context menu. Choose the TEditCopy action and click OK. Notice that the Object Inspector changes to show the properties of the TEditCopy action class. <P> <DT></DT> <DD>I want to pause for a moment here and explain more about how actions work. Examine the Object Inspector at this point. Notice that the TEditCopy action has several familiar properties and that those properties all have values. In particular, notice that the Caption, Hint, ImageIndex, and ShortCut properties already have values that correspond to an Edit menu's Copy item. These properties will be transferred to any control that you assign this action to, which means that you must set any properties of the action to the values that you want the corresponding components to acquire. That won't make much sense until you attach the action to components in the next section, but it will be clear at that time. Let's continue with the action creation process. <P> <DT></DT> <DD><B>4. </B>Change the new action's Name property to CopyAction, the Hint property to Copy|Copy to Clipboard, and the ImageIndex property to 3. <P> <DT></DT> <DD><B>5. </B>Create another standard action, this time a TEditCut action. Change the Name to CutAction, the Hint property to Cut|Cut to Clipboard, and the ImageIndex property to 4. <P> <DT></DT> <DD><B>6. </B>Create a third action, a TEditPaste action. Change the Name property to PasteAction, the Hint property to Paste|Paste from Clipboard, and the ImageIndex property to 5. <P></DL><P>You have now created the actions for the primary Edit menu items.</P><P><B>Creating the File Menu Actions</B></P><P>Next you need to create the actions for the File menu's Save and Save As menu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -