Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 61 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
61
Dung lượng
256,03 KB
Nội dung
of the control. Setting a Single Property for Multiple Controls You can select more than one type of control and specify the same value for all the controls. This technique can be useful, for example, if you add several Button controls to a form and you want to make sure they are all the same size, or all aligned left or right, and so on. You can select multiple controls of different types, but the Properties window displays only the properties that are common to all the selected controls, such as Width and Height. To select all the controls at the same time, hold down the CTRL key and click each control once. You can also click the left mouse button and drag it over the group of controls, as you do when selecting files in an Explorer window. Complex Property Pages Some controls, like HTML tables, are complex and require the services of advanced property pages for interactive manipulation. Some maintain collections of objects, such as ListBoxes. The property pages are represented in custom dialog boxes. To access the property page for a control, select the control whose property page you want to access. Then, in the Properties window, click the button of the Property that indicates a Property Pages button. The Property Pages dialog box for the control is displayed. You can, however, still provide the data in code, and for complex property pages, I prefer to set my own properties in code. For example, providing a large collection of values for a DropDown list is much easier and quicker to do in code. Setting up an HTML table, for the most part, is far too complex and buggy to set up via its property pages. The following code shows how to generate a search results HTML table in code, a task that is very frustrating to do interactively. (Frankly, the property pages for HTML controls are nearly useless in my opinion, and you need to just get down to typing it all out, as the following example demonstrates.) Public Sub CreateTable(ByVal cursor As Integer, _ ByVal rows As Integer) Dim numCells As Integer Dim rowNum As Integer Try While rowNum <= rows 1 Dim newRow As New HtmlTableRow() While numCells <= maxCells 1 Dim newCell As New HtmlTableCell() newRow.Cells.Add(newCell) numCells += 1 End While TABLE1.Rows.Add(newRow) numCells = 0 rowNum += 1 End While AddData(cursor, rows) Catch Except As Exception exceptInfo = Except.Message End Try End Sub Setting a Single Property for Multiple Controls 589 Using The Property Grid The property grid that is shown in the Properties window is itself an object of the type PropertyGrid, and you can create a new instance of it at will. It can be placed on the parent control, and you set its SelectedObject to the object to display the properties for. The information displayed in the grid is a once−only retrieval of the properties at the time the object is assigned to the grid. So, if a property value of the object specified by the SelectedObject is changed in code at run time, the new value is not displayed in the grid until it is refreshed, which can be done by reselecting the object to reference or by simply dereferencing the grid and instantiating a new one. The property tabs within the property grid appear as buttons on the toolbar at the top of the PropertyGrid. They vary in scope, as defined in the PropertyTabScope enumeration. To use the PropertyGrid, you need to add it to the Toolbox in the IDE because it is not one of the default controls. Once you add a PropertyGrid to the Toolbox, you can drag and drop it onto the form like any other control. Of course, you can bypass the Toolbox work and declare an instance of the PropertyGrid class in your code. The following example illustrates creating a PropertyGrid and setting its location on a form. This example assumes a form with a TextBox on it. Public Sub New() Dim propGrid As New PropertyGrid() propGrid.CommandsVisibleIfAvailable = True propGrid.Location = New Point(10, 20) propGrid.Size = New System.Drawing.Size(400, 300) propGrid.TabIndex = 1 propGrid.Text = "Property Grid" Me.Controls.Add(propGrid) propGrid.SelectedObject = seachEdit End Sub Note Refer to Chapter 3 for specific information about the Toolbox window. Menus and Toolbars Adding and working with shortcut menus, status bars, and toolbars, either interactively or programmatically, is not difficult at all. Menus typically provide commands, grouped by a common theme such as file operations, to your users. Toolbars use buttons to expose the same functionality in the menus or any frequently required operations. Context menus "pop up" in response to a right−click of a mouse and present options in the context in which they were requested. Status bars are used to indicate the application state or to provide information about processing in the application, such as a document that is printing or data that is being transmitted or received. Adding Menus and Menu Items Programmatically To add a menu to a Windows Form programmatically, define a method that includes the code to add the menu to your form: Public Sub AddMenu() Dim mnuFile As New MainMenu() Me.Menu = mnuFile End Sub Once you have added the code for the menu to your form, you need to add child or submenu items to it. Menu Using The Property Grid 590 contents are kept within a collection, so you can add menu items to a menu at run time by simply adding MenuItem objects to the collection. Within the method, you create the child menus to the MainMenu object's collection as follows: Dim menuItemFile As New MenuItem("&File") Dim menuItemNew As New MenuItem("&New") A MainMenu object contains no menu items, so once you add the first menu item to the object, it becomes the menu's heading. This is why the Text property of menuItemFile in the example is set to &File. Within the method, assign the top−level menu item and add subsequent menu items to it as shown here: menuItemFile.MenuItems.Add(menuItemNew) menuItemNew.MenuItems.Add(menuItemProject) To create submenus, you can simply add MenuItem objects to the MenuItems collection of the parent MenuItem. So, to add a third menu item (menuItemOpen) as a submenu of the second menu item (menuItemNew) shown here, just add the following line of code: menuItemNew.MenuItems.Add(menuItemOpen) Menu items can also be dynamically added to the collection in the same code that creates them. The following example shows you how to add another menu item to the preceding collection: menuItemFile.MenuItems.Add("Save &As") As demonstrated earlier in this chapter, in the section "MDI Applications," you provide functionality for the menu items through an event handler that is provided under the MenuItem's.Click event. Context−Changing Menus The following example shows how to create a menu arrangement that changes state according to the activities of the user. When the application starts, it will have only a traditional File menu with New, Open, and Exit commands. But as soon as the user selects either the New or Open menu item, the application state changes and the menu items change accordingly. To do this for your application, create a multicast event handler called GetMenu for the New and Open menu items. This is a multicast delegate that will respond to the Click events of both menu items. Enter the following code in the GetMenu event handler: Private Sub GetMenu(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MenuItem1.Click LoadAlternateMenu() End Sub Now we can switch focus to the second menu on the response of the click handler with the following code: Private Sub LoadAlternateMenu() Me.Menu = MainMenu1 End Sub You can make a copy of the top−level menu item and all of its submenu items by simply dragging another MainMenu component from the Toolbox to the form. Then, in the Menu Designer, right−click the "Type Context−Changing Menus 591 Here" area and choose Paste. The menu items you previously selected from the first MainMenu component are pasted into the second. To test the application, run the debugger. The form first shows a menu that contains File, New, Open, and Exit menu items. But as soon as you click New or Open, an event is raised by which the GetMenu event handler (among others) processes the code related to the event. The application state changes and the new menus are swapped in. Moving menu items between menus or within menus is made possible because the item objects are maintained in a collection. At design time, you can move entire menu structures around within the Menu Designer. But at run time, menu items can be moved between MainMenu objects or MenuItem objects, which allows for some measure of customization. To move a menu item programmatically, at run time, simply change the index position of the MenuIitem object as shown here: Public Sub ChangeMenuItem () Me.Menu.MenuItems(0).MenuItems(0).Index += 1 End Sub Menus can also be copied, cut, and pasted from the designer, which automatically takes care of referencing issues for you. In code, however, it can get a bit tricky because the menu operations are often duplicated in context menus, or toolbar buttons and shortcuts. You can, however, use the CloneMenu method of the MenuItem class to make a copy of the menu in code, and then work with its members as a separate class. Copying menu items preserves property settings and event handlers you have established with the original menu items, so that the new menu items you have created use these same event handlers. This occurs because the entire MenuItem object is cloned, along with everything connected to it. You can also enable and disable menu items to channel a user's activities or limit and broaden them as they progress with the application. All menu items are enabled by default when created, but you can disable them by setting the Enabled property to False. You can also access the property interactively in the Properties window. To disable a menu item programmatically in code, the following line is all you need: MenuItem1.Enabled = False However, if you disable the first or top−level menu item in a menu (for example, the File menu item in a traditional File menu), you end up disabling all the menu items contained within the menu because you are in effect disabling the collection. This is the proper behavior, and disabling a submenu item that has sub−submenu items disables all the sub−submenu items as well. But rather than hiding menu commands that are unavailable to the user by setting the Visible property to False, you can hide the entire menu tree by setting the topmost menu item Visible property to False. This not only obviates the need to enable and disable menu items, and the effort involved in tracking the state, but it is better to hide and disable the entire menu because this keeps the UI clean and free of clutter. Besides, users often click a disabled menu item; I have seen this done numerous times. If you decide to hide a menu chain, you must also disable the menu, because hiding does not prevent access to a menu command via other routes, such as a shortcut key. Context−Changing Menus 592 To hide a menu item programmatically, you can use the following line of code: MenuItem1.Visible = False You can also merge menu items programmatically, which is common in MDI applications where the menus of the children are merged with the parent form's menus. The following example shows how this is done in code: Public Sub MergeMenus() childMenu.MergeMenu(parentMenu) End Sub As mentioned earlier in the section "MDI Applications," two properties, MergeType and MergeOrder, are used to determine how individual menu items are handled during the merge and the order of their placement relative to the other MenuItem in the newly merged menu. You can set these properties on MenuItems individually or collectively to determine the items' presence and location within a menu merge. The following example sets these two properties for a menu item, MenuItemMain: Public Sub MainMenuMergeProperties() MenuItemMain.MergeType = MenuMerge.Add MenuItemMain.MergeOrder = 1 End Sub Enhancing Menus There are four built−in enhancements that can dress up menus in a way that conveys more information to users: Check marks These can be used to designate whether a feature on a menu is turned on or off, such as whether certain toolbars in an application are visible, or to indicate which of a list of files or windows is visible to the user or available. • Shortcut keys These are keyboard commands that let you access menu items within an application. The access keys allow direct access to keyboard commands usually by way of combining the ALT key and the underlined access key that is hooked to the desired menu or menu item. A good example is the ALT−F4 combination used to close the window or application. • Separator bars These are used to group related commands within a menu, which makes the menus easier to follow. • RadioChecks When a property of a menu item is set to True, it displays a small dot (•) next to the itemwhich indicates that the item is selected. • To add a check mark to a menu item programmatically, reference the menu item in code and set the Checked property to True as follows: MenuItemMain.Checked = True To add a shortcut key to a menu item programmatically, add the following code to set the Shortcut property to one of the values of the Shortcut enumeration: MenuItemMain.Shortcut = System.Windows.Forms.Shortcut.F4 Adding an access key is done when you set the Text property (in the Properties window, in the Menu Designer, or in code), by prefixing the letter that will stand as the key with an ampersand (&). This underlines the letter to signify that it is the key. For example, typing F&ile as the Text property of a menu item causes Enhancing Menus 593 the text label to be written as File. To navigate to this menu item, press ALT−I. Alternatively, you can also provide an access key to the superior level, which would obviate the need to press ALT in the sublevel. For example, if under the File menu we provided a Close label on a menu item (Cl&ose), all the user would need to do is press ALT−I−O to select the Close menu item. This is standard Windows navigation stuff that has been around since the 16−bit era. To add a separator bar as a menu item, right−click the location where you want a separator bar, and choose New Separator. Or when setting the Text property interactively or in code, providing a dash () makes the menu item a separator bar. Besides the preceding four enhancements, you can also designate one of the items as the default item. This is done by simply setting its DefaultItem property to True. The default item then appears in bold text. A menu item's Checked property can also be set to either True or False, which indicates whether or not the menu item is selected. If its RadioCheck property is set to True, a radio button appears next to the item. Adding a check mark to a menu item at design time involves nothing more than clicking the area to the left of the menu item. This sets the Checked property to True without the need to select the property in the Properties window. Naturally, all of these properties can be set in code. Finally, just as with earlier versions of Visual Studio and Visual Basic, you can indicate to the compiler that your code will undertake to draw the menu item. This is done by setting the OwnerDraw property to True. Use OwnerDraw to provide your own code to render the menu item. With some time and dedication, you can perform some magic with the menus, such as adding icons, changing colors and fonts, and more. Note To set these dynamic properties interactively, navigate to the DynamicProperties option on the menu's items properties and click the Property Pages button to open the Dynamic Properties dialog box. The Menu Class This class is the base class for the MainMenu, MenuItem, and ContextMenu classes. You cannot create an instance of this class, but you can extend it as in the preceding classes. The menus for an application are comprised of aggregated or composite MenuItem objects. The MenuItem objects are contained in the MainMenu and presented as an entire menu structure for a form or a ContextMenu that is used to list shortcuts and context−sensitive options. Unlike many base classes, the Menu base class delegates to its derived classes to define its properties. In addition to the properties that are provided for all of the derived menu classes, the Menu class also provides methods, such as CloneMenu and MergeMenu, that provide the implementation to create new menus from existing menus, or to merge two menu structures together, and the like. The Menu class also exposes the composite class Menu.MenuItemCollection. This class defines the collection of MenuItem objects used by the MenuItems property. You can use the methods of the Menu.MenuItemCollection class to add and remove menu items from a MainMenu, ContextMenu, or MenuItem, as shown earlier. Responding to User Input As we learned in Chapter 14, an event handler is a method that is bound to an event. When the event is triggered, usually in response to a message from the Windows subsystem, such as a keypress or a mouse click, The Menu Class 594 the code within the event handler is executed. Each event handler lists two parameters that are used in the handle of the event. The following example shows an event handler for a Button control's Click event: Private Sub button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles button1.Click 'And . . . End Sub The first parameter expects an argument that passes a reference to the object that raised the event. The second parameter (e in the preceding example) passes an object specific to the event that is being handled, which connects the event to information relative to the event. By obtaining a reference to the sender in this fashion, you can provide the facility to gain access to the sender's properties and public methods. This can be used to obtain information such as the location of the mouse for mouse events or data being transferred in drag−and−drop events. UI events comprise the bulk of your interface logic and are thus the most complex code constructs you will need to concern yourself with in the UI. Everything else involves little more than setting and getting properties. To create a UI event handler, switch to View Code mode and from the Class Name drop−down box (refer to Chapter 3) above your code to the left (under the Editor tab), select the control that you want to add a specific event handler to (remember, controls are classes). From the Method Name drop−down box on the right, select the event for which you want to add a specific handler (when you select the control's class in the left drop−down box, all events in that class, if any, are listed in the Method Name drop−down box to the right). Choose the event, and the Code Editor automatically inserts the appropriate event handler into your code and positions the insertion point within the method. The following example provides the Click event for the Button control: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'Add Event Handler Code Here End Sub You can also generate the handler by double−clicking the control on the form. There will come a time when you have done this enough times to know how to wire up the event code manually. I find that I can wire up events faster in the Code Editor than by switching between windows, modes, and drop−down list boxes. Binding Events Dynamically In line with what I just said about wiring up an application manually, you can provide code to create event handlers at run time. This practice serves to wire up the events at run time, which lets you control which event handlers are activated depending on the condition or state of the application at a certain time. Similar to late binding, you can think of this as "late wiring." Hot Spots Hot spots are regions in your application that can be referenced by a cursor's tracking position. By default, the hot spot is set to the upper−left corner of the cursor (coordinates 0,0). So, as soon as the cursor hits the coordinates specified in the hot spot, an event can be raised. To set a cursor's hot spot you use Visual Studio's Image Editor toolbar, which is accessed from the Tools, Customize menu. Select the Set Hotspot tool and then Binding Events Dynamically 595 click the pixels you want to designate as the cursor's hot spot. The Hotspot property in the Properties window displays the new coordinates. Tip Tooltips can be made to appear when you hover your cursor over a toolbar button. These tips can help you identify the function of each button. Mouse and Keyboard Events Mice can do a lot more than nibble cheese. In a Windows UI, they can let you know when one of their buttons has been clicked or released, or when the mouse pointer leaves or enters some part of the application. This information is provided in the form of MouseDown, MouseUp, MouseMove, MouseEnter, MouseLeave, and MouseHover events. KeyPress events also bubble up from the OS and are made available to you in KeyPress, KeyDown, and KeyUp events. Mouse event handlers receive an argument of type EventArgs containing data related to their events; however, key−press event handlers receive an argument of type KeyEventArgs (a derivative of EventArgs) containing data specific to the keypress or key release events. When wiring up mouse events, you can also change the mouse cursor. You typically marry the ability to change the cursor to the MouseEnter and MouseLeave events. These are used to provide feedback to the user that something is happening, not happening, or that certain areas are offlimits or welcome to the explorative nature of your cursor. The event is exposed in the following code example: Public Event MouseDown As MouseEventHandler Table 16−3 lists the MouseEventArgs properties to provide information specific to the mouse event. Mouse events occur in the following order: MouseEnter1. MouseMove2. MouseHover/MouseDown/MouseWheel3. MouseUp4. MouseLeave5. Table 16−3: MouseEventArgs Properties Property Purpose Button Tells you which mouse button was pressed Clicks Tells you how many times the mouse button was pressed and released Delta Retrieves a signed count of the number of detents the mouse wheel has rotated. A detent is one notch of the mouse wheel. X Retrieves the X coordinate of a mouse click Y Retrieves the Y coordinate of a mouse click Mouse and Keyboard Events 596 Keyboard Events Keyboard events are fired when a key is pressed in a control that has the focus. The code for a keyboard event looks like this: Public Event KeyPress As KeyPressEventHandler The key event handler receives an argument of type KeyPressEventArgs containing data related to this keypress event. Table 16−4 lists the KeyPressEventArgs properties that provide information related to the event received. Table 16−4: KeyPressEvenArgs Properties Property Purpose Handled Retrieves or returns a value to the property indicating whether the KeyPress event was handled KeyChar Retrieves the KeyChar (character pressed) value corresponding to the key pressed Key events occur in the following order: KeyDown1. KeyPress2. KeyUp3. Using a Timer to Fire Events A timer can also be used to raise events at regular intervals. The component discussed here is designed for UIs, but the server−based timer is also available in the .NET Framework (see the SDK documentation). The timer is switched on when you set its Enabled property to True, and the default interval of 100 milliseconds can be changed in the Interval property. Each Tick event is raised at every interval, which is where you add the code you want executed. A Timer control is started and stopped by calling its Start and Stop methods, respectively. Stopping a timer has the effect of pausing it. Timers on forms are typically used for single−threaded algorithms, where the UI threads are used to perform some processing. The timer thus requires that you maintain the UI message pump and always operate from the same thread, or marshal the call onto another thread. Collecting User Input Many controls and components are designed to collect information from the user or to prompt the user to generate actions and events in the UI. These include the controls listed in Table 16−5. Buttons The most common control used to elicit a user response is a Button control. Button press events let you place code in the Click event handler to perform any action defined in the button event. The following example instantiates a Button, sets its DialogResult property to DialogResult.OK, and adds it to a Form: Keyboard Events 597 Private Sub AddAButton() Dim button1 As New Button() button1.DialogResult = DialogResult.OK Me.Controls.Add(button1) End Sub Table 16−5: User Interface Controls for Soliciting and Obtaining Input Control Purpose Buttons Button press events let you place code in the Click event handler to perform any action defined in the button event. The analogy is clicking a physical VCR button. Text Edit boxes Lets the user enter text in a field−like container Check boxes Lets the user choose items on a check list Radio buttons Provide a toggle facility (only one may be on at any time) Combo boxes Provide a list of items to choose from DomainUpDownBox A combination of a text box and a pair of buttons for moving up or down through a list without having to expand it NumericUpDownBox A combination of a text box and a pair of buttons for moving up or down through a list of numbers DateAndTimePicker A control for interactively selecting a single item from a list of dates or times Calendar A control of some graphical proportions that allows a user to view and set date information. The analogy is a calendar hanging on the wall. Palette A preconfigured dialog box that allows the user to select a color from a palette and to add custom colors to that palette List Box A control that displays a list of items from which the user can choose CheckedListBox A control that displays a list of items the user can check to signify a selection ListView A list of items in a container, such as the list of files in a folder TreeView A collection of items organized in a hierarchical fashion, with roots, branches, and leaf nodes TrackBar A control that lets you set positions on a notched scale ToolBar A form−like object that contains and enumerates buttons representing menu options and events Edit Text Boxes The TextBox control lets your user provide text input to an application. The control provided by .NET includes additional functionality not found in the standard Windows TextBox control. For example, it provides multiline editing and password character masking combined into a single control. In other words, the framework has combined the functions of a classic edit box with a text box (which is why you will not find a TextBox control in the Toolbox). However, the TextBox is mainly used to display, or accept, a single line of text. The Multiline and ScrollBars properties are used to enable multiple lines of text to be displayed or entered. Setting the AcceptsTab and AcceptsReturn properties to True allows enhanced text manipulation and turns the control into a multiline TextBox, as shown in Figure 16−11. Edit Text Boxes 598 [...]... text, with 0 being the leftmost position, and the length of the string after the last character being the rightmost position If the SelectionStart property is set to a value equal to or greater than the number of characters in the text box, the insertion point is placed after the last character You can also set the SelectionLength property to the length of the text to be selected The SelectionLength... text in the TextBox control You write code that searches the text value for a particular String, or use a string−manipulation method to alert the user to the string's position in the box Then, you can write code to select the text by setting the SelectionStart property to the beginning of the text string found The SelectionStart property is an ordinal value that indicates the insertion point in the text,... information The control displays a calendar that contains the numbered days of the month, arranged in columns underneath the days of the week, with the selected range of dates highlighted The control is illustrated in Figure 16−13 Figure 16−13: The MonthCalendar control The user can select a different month by clicking the arrow buttons that appear on either side of the month caption This control lets the. .. setting the AllowDrop property You then handle DragEnter and DragDrop events on the destination Adding drop support to the target begins with setting the AllowDrop property to True To do this, access the DragEnter event for the control where the drop will occur, and use an If statement to do type−checking to ensure the data being dragged is of an acceptable data type for the target The code then sets the. .. specifying your own object as the Object parameter of the SetData method The object must be specified as serializable, which you can do with Serializable attributes The DragDrop event also lets you access the data dragged using the GetData method In the following example, the target of the drag is a TextBox control The code sets the Text property of the TextBox control equal to the data being dragged Private... on the name of the application using it and the location and host of the actual application As we discussed in Chapter 2, the host can be one of the following: • Standard managed executable The configuration file location for an application hosted by the standard executable host of a machine is the same directory as the application You will also name the configuration file with the same name as the. .. failure notification than the Assert message box there are a few things you can do The DefaultTraceListener (see the "Tracing and the Trace Class" section coming up) controls the output for the Assert method so you can turn off the message box (see the "Setting Assertions in Configuration Files" towards the end of this section The output can be directed to the Debug Output window, other listeners, log files,... handler when the link text is selected The following example creates a LinkLabel control that displays a link, and displays the Microsoft Web site in the default browser when the link defined in the control's text is clicked The example defines a method that initializes the LinkLabel control as well as a method that will handle the LinkClicked event of the control The event handler of the LinkClicked... specified messages if the condition is False Note You can use the Assert method from either the Debug class or the Trace class (both of which 619 The Debug Write Methods are included in the System.Diagnostics namespace) Debug class methods are not included in a release version of your program, so they do not increase the size or reduce the speed of your release code In the preceding methods, the first argument,... DragDropEffects.Move) End Sub The results of the drag are determined by the arguments provided to the DoDragDrop method This method interoperates with the DataEventArgs.Data property and the DataEventArgs.AllowedEffect Property to facilitate the event handling Any data can be used as a parameter in the DoDragDrop method In the preceding example, the Text property of the Button control is used (rather than hard−coding . Select the Set Hotspot tool and then Binding Events Dynamically 595 click the pixels you want to designate as the cursor's hot spot. The Hotspot property in the Properties window displays the. dereferencing the grid and instantiating a new one. The property tabs within the property grid appear as buttons on the toolbar at the top of the PropertyGrid. They vary in scope, as defined in the PropertyTabScope. its SelectedObject to the object to display the properties for. The information displayed in the grid is a once−only retrieval of the properties at the time the object is assigned to the grid. So, if