This chapter covers the classes used to build windows and command windows.
The classes covered in this chapter include:
A class to show a window with various command panes.
The vCmdWindow class is derived from the vWindow class. This class is intended as a class that serves as a main control window containing various vPane objects such as menu bars, canvases, and command bars. The main difference between the vCmdWindow class and the vWindow class is how they are treated by the host windowing system. You will normally derive your windows from the vCmdWindow class.
These construct a vCmdWindow with a title and a size specified in pixels. You can use theApp->DefaultHeight() and theApp->DefaultWidth() in the call to the constructor to create a ``standard'' size window. Note that the height and width are of the canvas area, and not the entire window.
See the section vWindow for details of the following methods.
vWindow
Used to define commands on a command bar.
A command pane is a horizontal bar in a command window that holds CommandObjects. You can use any of the CommandObjects, although they all might not make sense to use on a command bar (a List, for example, is a bit large for the visual paradigm, but it would work). The layout is left to right, so you don't need to fill in the RightOf and Below fields. You can include Frames in a command bar, and commands contained in that frame do use the RightOf and Below attributes.
You define the commands on a command bar using a CommandObject array. You first create the command pane with myCmdPane = new vCommandPane(CommandBar), and then add it to the window with AddPane(myCmdPane).
You then handle the command objects in a command bar pretty much like the same way as in a dialog. The main difference is that you use the vWindow versions of SetValue and WindowCommand instead of the corresponding methods of the vDialog class. Other than the left to right ordering, things are pretty much the same.
The discussion of CommandObject and vDialog contains several examples of defining command objects.
See the section vPane for a general description of panes.
vWindow, vStatus, CommandObject, vDialog, vPane
Used to define pull down menus.
The vMenu structure is used to define pulldown menus, which includes the top level item on the menu bar, as well as the items contained in the pulldown menu. These are passed to the constructor of a vCmdWindow type object.
See the section vPane for a general description of panes.
typedef struct vMenu { char* label; // The label on the menu ItemVal menuId; // A User assigned unique id unsigned sensitive : 1, // If item is sensitive or not checked : 1; // If item is checked or not (*) char* keyLabel; // Label for an accelerator key (*) vKey accel; // Value of accelerator key vMenu* SubMenu; // Ptr to a submenu unsigned int kShift; // Shift state of accelerator } MenuItem;
Note that the items marked with an asterisk ( checked and keyLabel) are not used when defining the top level menu bar items.
The label on the menu. See the description of the vWindow class for information on setting the label of menu bar items.
For some platforms (Windows, but not Athena X), you can add a & to indicate a shortcut for the command. For example, specifying a label &File allows Windows users to pull down the File menu by pressing Alt-F, and specifying a submenu label as &New allows the user to use Alt-N to select the New command. The Athena version of V strips the &, so you can (and probably should) denote shortcuts for menu items even in Athena versions.
A user assigned unique id. This id is passed to the MenuCommand (or WindowCommand) method when a menu item is selected. If a menu item with a submenu is selected, V will not return the id, but will cause the submenu to be displayed.
It will be common practice to use the same id for menu items and command objects defined on a command bar, and the same id value would then be passed to WindowCommand for either the menu selection or the equivalent button selection. Similarly, using the id to set the item's sensitivity will change both the menu and the button.
The values you use for your id in menus and controls should be limited to being less than 30,000. The predefined V values are all above 30,000, and are reserved. There is no enforcement of this policy. It is up to you to pick reasonable values.
If you want a separator line on a pulldown menu, you must use the predefined value M_Line for the MenuId.
Controls if item is initially sensitive or not. Insensitive items are displayed grayed out. The predefined symbols notSens and isSens can be used to define the MenuItem. Note that V uses the static definition of the MenuItem to store the current sensitive state, and all menus (or windows) sharing the same static definition will have the same sensitive state. See the description of the vWindow class for information on setting the sensitivity of menu bar items.
The user can put a check mark in front of the label of a menu item. This convention is often used to show a given setting is in effect. Like the sensitive member, this statically tracks the checked state. The predefined values isChk and notChk can be used to specify this value. This value is not used when defining the top level menu bar, and you can use the predefined value notUsed for that case. See the description of the vWindow class for information on setting checked state of menu items.
Label for an accelerator key. The predefined symbol noKeyLbl can be used to indicate there is no keyLabel. This value is not used when defining the top level menu bar, and you can use the predefined value notUsed accelerator key.
This is the value of the keystroke that is the accelerator for this menu item. When the user presses this key, the vWindow::MenuCommand method will be called just as though the user had used the mouse to select the menu item. This value may be used in combination with the kShift and keyLabel parameters. See the explanation of vWindow::KeyIn for a complete explanation of key codes.
Note that the Windows version really doesn't support Alt key codes. The Windows system intercepts Alt keys and tries to interpret them as menu accelerators. Unfortunately, there is no simple way to override this behavior, so Alt keys are essentially unsupported on Windows. Using functions keys with combinations of Shift and Control is supported, as are regular control keys.
Pointer to another MenuItem definition of a submenu. V will cause submenus to be shown automatically when selected. The predefined symbol noSub can be used to indicate there is no submenu.
This is the shift value to be used with the accel key definition. To use Ctrl-D as the accelerator key, you would specify the value for Control-D (easily specified as 'D'-'@') for accel, and leave kShift set to zero. If you use a Ctrl code, you must specify both the control code, and the VKM_Ctrl shift code. Note that this value is at the end of the vMenu structure because of it was forgotten in early implementations of V . By placing it at the end, earlier versions of V code are compatible with no changes to the source. Sigh, I didn't get this one right.
This example defines a menu bar with the items File and Edit. The MenuBar definition would be passed to the constructor of the appropriate vCmdWindow derived object.
Only the File submenu is shown here, and is an example of the menu as it might be included in a standard File menu. Note that this example menu includes items that can all be specified by using standard predefined values (see Predefined ItemVals). It also includes an optionally defined Debug item. A definition like this might be used for the FileMenu in the Menu example. Note that & is used to denote shortcuts for menu items.
static vMenu FileMenu[] = { {"&New", M_New, isSens,notChk,noKeyLbl,noKey,noSub}, {"&Open", M_Open, isSens,notChk,noKeyLbl, noKey, noSub}, {"&Save", M_Save, isSens,notChk,noKeyLbl,noKey,noSub}, {"Save &As", M_SaveAs, isSens,notChk,noKeyLbl,noKey,noSub}, #ifdef vDEBUG {"-", M_Line, notSens,notChk,noKeyLbl,noKey,noSub}, {"&Debug", M_SetDebug,isSens,notChk,noKeyLbl,noKey,noSub}, #endif {"-", M_Line, notSens,notChk,noKeyLbl,noKey,noSub}, {"E&xit", M_Exit, isSens,notChk,noKeyLbl,noKey,noSub}, {0} }; static vMenu EditMenu[] = {...}; // Define Edit pulldown // Define menu bar, which includes the File and Edit pulldown static vMenu MenuBar[] = { {"&File",M_File,isSens,notUsed,notUsed,noKey,&FileMenu[0]}, {"&Edit",M_Edit,isSens,notUsed,notUsed,noKey,&EditMenu[0]}, {0,0} // end of menubar }; ... vMenuPane myMenuPane = new vMenuPane(MenuBar); // construct pane AddPane(myMenuPane);
vWindow, vPane
The vPane class serves as a base class for various pane objects contained by the vWindow class. There are no methods or services provided by the vPane class that you need to use directly, but the class is used extensively by V internally.
There are four types of panes used by V in a vCmdWindow, including menu panes, canvas panes, command panes and status panes. To add a pane to a window, you will first define the contents of the pane (menu, commands, status info) using static arrays, then construct an instance of the pane with new vWhateverPane. Then you add the instance to the window using AddPane.
Note that the canvas panes are described in the Drawing
chapter. The commands used with a command pane are described in the Dialogs chapter, while menus and status bars are covered in vMenu and vStatus in this chapter.
CommandObject, vCanvasPane, vCmdWindow, vCommandPane, vMenu, vStatus
Used to define label fields on a status bar.
The vStatus structure is used to define the top level status bar included on a vCmdWindow, and the labels it contains. The vStatus array is usually passed to the vStatusPane constructor. See the section vPane for a general description of panes.
typedef struct vStatus // for status bars { char* label; // text label ItemVal statId; // id CmdAttribute attrs; // attributes - CA_NoBorder unsigned sensitive : 1; // if button is sensitive or not int width; // to specify width (0 for default) } vButton;
Text of label field. See the description of the vWindow class for information on changing the text of a label.
Id for the label. Use this value when changing value with SetString or SetValue.
The current implementation only uses the CA_NoBorder attribute. If CA_NoBorder is supplied, the label will be drawn on the command bar without a border or box around it. Not supplying CA_NoBorder (e.g., CA_None) will result in a label with a border or box around it. In general, unbordered labels don't change, and bordered labels are used to show changing status.
If label is sensitive or not. Use predefined symbols isSens and notSens to specify the initial state. On some implementations, the label will be grayed if it is insensitive. The sensitivity can be changed using vWindow::SetValue as described in the section vWindow.
This can be used to specify a fixed width for a label. Normally, the label will be sized to fit the length of the text. If you provide a non-zero width, then the label field will remain constant size.
This shows a sample status bar with two fields. It is added to a vCmdWindow using AddPane. The value of the file name would be changed by calling SetString(m_curFile, filename) somewhere in your program.
static vStatus sbar[] = { {"Current file:", m_curMsg,CA_NoBorder,isSens,0}, {" ", m_curFile,CA_None,isSens,100}, {0,0,0,0,0} }; ... vStatusPane myStatusPane = new vStatusPane(sbar); // construct AddPane(myStatusPane);
vWindow, vPane
A class to show a window on the display.
The vWindow class is an aggregate class that usually has associated vPane objects -- window panes, in other words. There several kinds of panes, including menu panes, command bar panes, status panes, and drawing canvas panes. As you would expect, classes derived from vWindow also include panes.
The vWindow class will probably never be used by your application - it serves primarily as a superclass for the vCmdWindow class. This class may be more useful in future versions of V , but for now it is not really useful by itself. You will typically derive your own class from vCmdWindow, and override several of the methods defined by vWindow and vCmdWindow.
Menus and commands in the panes send messages to the WindowCommand and MenuCommand methods when the user clicks on a command or menu item contained in the window. The application program can also change attributes of the various menu items and commands associated with a window. Canvas panes are designed to handle their own interaction with the user (mouse events, etc.).
Title to place in title bar.
The height and width of the window.
CMDWINDOW or WINDOW type for window.
The constructor for vWindow is normally called with a name, size, and possibly a window type. The name will be displayed in the window's title bar by default. The size is the initial size of the window's canvas work area in pixels. The type may be CMDWINDOW or WINDOW. The constructor for vCmdWindow invokes the proper vWindow constructor.
KeyIn is invoked when a key is pressed while a window has focus. The key value is the vKey value of the key pressed, and shift indicates the shift state of the key.
Handling the keystroke is not necessarily trivial. Regular ASCII characters in the range from a Space (0x40) up to a tilde (~ ) are passed to KeyIn directly, and shift will be 0, even for upper case letters. The current version of V does not have explicit support for international characters, so values between 0x80 and 0xFF are undefined, and correspond to whatever might be the local convention for the character set. (This will be one thing for X and another for Windows - but you can count on the values for each platform. Thus, you can use non-English characters on each platform, even though they won't be the same values on X and Windows. I would like a portable solution for this. If any non-English users of V have any ideas about this problem, I'd like to hear. The choice seems to be between the standard MS-DOS code page solution and the ANSI character set used on X platforms. I'm not ready to support multibyte characters for some time yet.) Values between 0xFF00 and 0xFFFF correspond to the various function keys and keypad keys found on a typical keyboard. The standard set by IBM PCs has determined what function keys are supported by V . The file <v/vkeys.h> has the definitions for the key codes supported.
Besides getting a keycode for the non-ASCII keys, KeyIn also gives a shift code corresponding to the Control, Shift, and Alt modifier keys. (These are defined as VKM_Ctrl, VKM_Shift, and VKM_Alt.) Pressing the F4 key would return the code for F4 (vk_F4), while the keystroke Alt-F4 will return the code for the F4 key, and the shift code set to VKM_Alt. More than one bit of the shift code can be set -- the shift values are really bit values. Control keys from the normal character set (Ctrl-A, etc.) are passed as their true control code, but not the VKM_Ctrl shift set.
In addition, you also need to check for the VKM_Alt modifier applied to regular Ascii keys. The keystroke Alt-K will be mapped to a lower case Ascii 'k' with the VKM_Alt bit set in shift. The top row keys (1,2, etc.) can also be pressed with the VKM_Ctrl bit set in shift, and your program will need to deal with these. It will quite often be the case that your program simply ignores many of these values.
KeyIn will also return a value when only a modifier key is pressed. For example, pressing the Alt key returns a key value of vk_Alt. A macro defined in <v/vkeys.h> called vk_IsModifer(x) can be used to determine if a key x is a modifier. Your program can usually ignore modifier keys.
If you have defined any keystroke combinations to be accelerators for menu commands, your program will never see those keystrokes in KeyIn. Instead, they are intercepted by the system and mapped to the appropriate command to pass to the MenuCommand method.
Note that the keystrokes are not displayed by the system. It is up to your program to handle keystrokes and to do something useful with them.
You should call vWindow::KeyIn from your derived method with any keystrokes you don't handle. The vWindow::KeyIn method passes these unhandled keystrokes up to the vApp::KeyIn method. Thus, you will have the choice of either handling keystrokes in the window or in the app class.
MenuCommand is called when a menu command is selected. This virtual function allows menu commands to be distinguished from other commands in a window, although it is not usually necessary to do so. The default method simply passes the menu command along to the WindowCommand method, so you don't need to override this method if you don't distinguish between menu and command events.
This method is invoked when a user activates a command object in a command pane. The Id of the command object is passed in in the Id field, and the value and type (e.g., C_Button or C_CheckBox) of the command are passed in in the Val and Type parameters. Note that command objects in a command pane are really no different than the command objects in a dialog. Most of the discussion for handling these commands is covered in the sections on dialogs. See vCommandPane and vDialog::DialogCommand for more details about the values passed to WindowCommand.
WindowCommand is also called by the default MenuCommand in response to menu picks. The Id is the id of the item that generated the call.
The default behavior of WindowCommand is to call the AppCommand method. However, you will almost always override the default WindowCommand method.
See vApp::WorkSlice for a description of this method.
This method is used to add the pane pane to a window. Panes will be displayed in the order they are added. You can add exactly one menu pane, plus canvas, command, and status panes. You typically first create a given pane (e.g., myPane = new XPane(PaneDef)), and then add the pane to the window with AddPane(myPane).
Returns the position and size of this window. These values reflect the actual position and size on the screen of the window. On X, this is the whole vCommandWindow frame. On the Windows MDI version, it is the size and position of just the drawing canvas and its scroll bars. The intent of this method is to allow you to find out where the active window is so you can move a window, or position a dialog so that it doesn't cover a window. It is most useful when used in conjunction with SetDialogPosition.
This method is used to retrieve the value of a menu or command object in a menu or command pane. The itemId is the id of the item as defined in the menu or command bar definition. For menu items, this will return the menu checked state. For other command objects, the value returned will be appropriate as described in the Dialog Commands section.
This method will raise the window to top of all windows on the display. Raising a window is often a result of mouse actions of the user, but this method allows a buried window to be moved to the top under program control. You will need to track which window instance you want raised, possibly through the vAppWinInfo object.
This method is used to change the state of command window items. The item with itemId is set to Val using the ItemSetType parameter to control what is set. Not all command items can use all types of settings. See vWindow::GetValue and vDialog::SetValue for a more complete description.
If a menu item and a command item in the same window share the same id, they will both be set to the same value (this usually applies to sensitivity). Only the controls in the window that sent this message are changed.
This method is similar to SetValue, except that the control with the given itemId in ALL currently active windows is set. This is useful to keep control values in different windows in sync.
Moves this window to the location left and top. This function is of limited usefulness. SetDialogPosition is more useful.
This can be used to change the label on a command bar button, status bar label, or menu item. The item identified by itemId will have its label changed to title.
This method is similar to SetString, except that the string with the given itemId in ALL currently active windows is set. This is useful to keep control strings in different windows in sync.
Set the name of the window shown on its title bar to title.
You can show or hide a command, status, or canvas pane with this method. The pane must first be defined, created, and added to the command window (which will show the pane). You can then hide the pane later by calling this method with the pointer to the pane and OnOrOff set to 0. A 1 will show the pane. Note that in some environments (e.g., X), the window may show up again in a different position in the window. For example, if you had a command bar above a status bar, and then hide the command bar, it will be placed under the status bar when you show it again. This is a ``feature'' of X.
You must call ShowWindow() after you have added all the panes to the window. You usually call ShowWindow() in the constructor to your vCmdWindow class after you have created all the panes and have used AddPane to add them to the window.
This method is called by the vApp::CloseAppWin method as part of closing down a window. The default vWindow::CloseWin() method's behavior is to take care of some critical housekeeping chores. You will normally never override this method. However, it is remotely conceivable that there will be an occasion you need to do something really low level after a window has been destroyed by the host GUI environment. In that case, your method must call the immediate superclass vWindow::CloseWin(), and then do whatever it has to do. Normally, you handle such details in your class's CloseAppWin method.
vCmdWindow