CLRCTRL Color Selector Custom Dialog Control for Microsoft Windows (tm) Applications Version 1.2 8/25/1991 Copyright (c) 1991 Clickon Software Scott Gourley Compuserve ID 72311,613 105 Union Street, Watertown, MA 02172 (617)-924-5761 Thank you for trying this product! CLRCTRL is a kit that makes it easy for Microsoft Windows 3.0 programmers to include color selection controls in their application dialogs. The core of the kit is a "dynamic link library," CLRCTRL.DLL, which provides the dialog control in a self-contained package that can easily be integrated into any program. The design of the DLL allows the custom control to be manipulated the same way a built-in control is manipulated, using the Dialog Editor found in the Microsoft Software Development Kit. The design of the control is that of a combobox that contains rectangles of color that can be selected by the user using the normal input actions for comboboxes. The advantage of this method of color selection is that it allows an easy, familiar way for the user to make a color selection, while requiring minimal space for the control on the dialog box. By default, the color selector uses the standard 16 "pure" colors as its selection palette, but this can be changed using normal combobox messages. The following table gives the "pure" colors and their positions in the default color selector control. Index in Color RGB value combobox list ---------------------------------------------------------------- Black RGB (0x00, 0x00, 0x00) 0 Dark Red RGB (0x80, 0x00, 0x00) 1 Dark Green RGB (0x00, 0x80, 0x00) 2 Dark Yellow RGB (0x80, 0x80, 0x00) 3 Dark Blue RGB (0x00, 0x00, 0x80) 4 Dark Magenta RGB (0x80, 0x00, 0x80) 5 Dark Cyan RGB (0x00, 0x80, 0x80) 6 Dark Grey RGB (0x80, 0x80, 0x80) 7 Bright Grey RGB (0xC0, 0xC0, 0xC0) 8 Bright Red RGB (0xFF, 0x00, 0x00) 9 Bright Green RGB (0x00, 0xFF, 0x00) 10 Bright Yellow RGB (0xFF, 0xFF, 0x00) 11 Bright Blue RGB (0x00, 0x00, 0xFF) 12 Bright Magenta RGB (0xFF, 0x00, 0xFF) 13 Bright Cyan RGB (0x00, 0xFF, 0xFF) 14 White RGB (0xFF, 0xFF, 0xFF) 15 FILES INCLUDED IN THIS KIT The following files are included in this kit: Custom control files -------------------- CLRCTRL.DLL This is the dynamic link library containing the code that defines and maintains the color selector control. The library includes code to interface with the user program as well as code to interface with the SDK Dialog Editor. CLRCTRL.H This is the header file that defines the source-code interface to the control. It contains information that the user program can use to access the control and its DLL library. Sample program files -------------------- CLRTEST This is the makefile for the CLRTEST.EXE program. It should be generic enough to build the program in your environment. If not, it can be easily modified. CLRTEST.C This is the source code for the CLRTEST.EXE program. This program provides a simple test of the functioning of the color selector, and serves as an example of using the custom control kit. CLRTEST.H This is the main header file for the CLRTEST.EXE test program. It contains menu IDs, prototypes, variable defaults, and other information needed by the program. CLRTESTD.H This is the header that contains the dialog IDs used for controls defined in the dialog in CLRTEST.DLG. WINSTD.H This is a general header file of information to configure Windows applications. CLRTEST.DEF This is the module definition file for the CLRTEST.EXE program. All Windows applications require a module definition file. CLRTEST.RC This is the resource script file for the CLRTEST.EXE test program. It contains a definition of the application menu structure. CLRTEST.DLG This is the dialog definition for CLRTEST.EXE test program. The dialog allows the user to select a text color and a background color, and uses this data to paint the program's main window. CLRTEST.ICO This is the program icon for the CLRTEST.EXE test program. CLRTEST.EXE This is a pre-built copy of the color selector test program. Documentation files ------------------- CLRCTRL.HLP This is the Windows help file that explains this software kit and how to use it. It contains largely the same information as this text. README.TXT This text. OBJ Interface files (registered kit only) ----------------------------------------- CLRCTRLS.OBJ Small model object code for control's OBJ interface CLRCTRLM.OBJ Medium model object code for control's OBJ interface CLRCTRLL.OBJ Large model object code for control's OBJ interface USES FOR THIS PRODUCT This custom dialog control gives the Windows programmer a tool to easily include color selection in Windows dialogs. Also, because the control is flexible enough to allow its behavior to be modified by the programmer, it is useful in any situation where a selection of color must be provided. These situations range from simple text and background color selection in a text-based application to palette definition in a paint program. It can be up to the programmer what color choices are available and what the color choice means to the application program. COLOR SELECTOR CONTROL BEHAVIOR Because the color selector control is defined as a combobox, all of the behavior associated with a normal combobox is supported in the color selector. The only exception to this is that direct text entry in the edit field is not implemented. Because of this, the style of the control is more appropriately described as a "drop-down listbox," rather than a "combobox," which is used in this discussion for consistency with Microsoft's use of the terminology. The following paragraphs briefly describe the normal functioning of a color selector control. Keyboard interface The color selector control receives and relinquishes the keyboard input focus as any other control does. If the programmer defines the control to have the WS_TAB style, the user can give the control input focus by moving to the control with the TAB key. If the programmer defines the control to be in a group using WS_GROUP, the left and right arrow keys also can be used to give the control the input focus. Moving the input focus out of the color selector works in the same way. Once the control has the input focus, the up and down arrows cause the currently selected color as displayed in the edit box, to change, moving through the defined set of color choices. Pressing Alt-Up arrow or Alt-Down arrow will both cause the listbox to be alternately dropped down and removed. While dropped down, the list box will display up to six of the colors defined in the list. The up and down arrows then still work in the normal way, moving the "item selected" highlighting through the list box as appropriate. Mouse interface With a mouse, the interface is also straightforward. Clicking the mouse on the control will give the control the input focus if it does not already have it. When it has the input focus, clicking on another control will cause the control to lose the input focus. Clicking on the drop-down button of the control will cause the listbox to be displayed (or removed if it is already displayed) as described above. When the list box is dropped down, a new color can be selected by using the mouse to scroll through the list and click on another color. IMPLEMENTING COLOR SELECTORS The following sections describe what needs to be done to add color selector controls to an application. The process divides into three main parts: accessing the control's DLL; creating and editing the dialog with the Dialog Editor; and accessing the control from the dialog procedure using the Windows messaging scheme. Accessing the DLL ----------------- To use the color selector control, the application must access the dynamic link library (DLL) file for the control. To accomplish this, the following steps are necessary: 1. Load the library. During program initialization, the DLL library must be loaded and initialized by the program. Add the following code to the WinMain function somewhere before the main message loop: HANDLE hClrLib; . . . if ((hClrLib = LoadLibrary ("clrctrl.dll")) < 32) return 0; This code loads the library for the color selector control. If it cannot be loaded, returning a zero value from WinMain will cause the program to end. (If program clean-up is necessary, do it before the return statement.) Note that the name of the DLL file is defined in the clrctrl.h header file under the symbol "CLRCTRL_DLLNAME." This symbol can be used in the LoadLibrary call, provided the clrctrl.h file is included by the .c file that contains WinMain. 2. Free the library. During program shutdown, the DLL library must be released by the application. Add the following code to the WinMain function somewhere after the main message loop: FreeLibrary (hClrLib); This code releases the program's access to the DLL library. The parts of the library that have been loaded into memory can be discarded by Windows once no applications are still accessing the library, so it is important that any application that uses the DLL frees it during shutdown. Note that the hClrLib parameter needs to be the same value as that returned from the call to LoadLibrary. If the calls are both made directly from WinMain, hClrLib can simply be a local variable used in both calls. If the calls are instead made from subordinate functions defined in the application, programmer needs to provide a way of keeping the value around during the life of the program's execution. 3. Distribute the DLL with the application Since the DLL becomes a separate but integral part of the application, it must be distributed with the application. The rules for where Windows looks for the DLL file are documented in the Windows SDK Guide to Programming, among other places. Normally, however, it is easiest to keep the DLL in the same directory as the application's .EXE file. Accessing the OBJ Version ------------------------- An optional OBJ interface to the control is available to registered users of this kit, which allows an application to access the control's code without the need for including a separate .DLL file with the application. Among the files included in the registered copy of this kit are the CLRCTRLS.OBJ, CLRCTRLM.OBJ and CLRCTRLL.OBJ files. Linking one of these files directly into a small-, medium-, or large- model application replaces all of the run-time functionality of the control that is defined in the .DLL. The advantages of using the OBJ interface are: - fewer files to add to the application's distribution kit and copy during installation, especially when using many custom controls - less chance that the user will delete, misplace, or overwrite the .DLL file, causing the application to fail The disadvantages of using the OBJ interface are: - the application's .EXE file is larger - the control's .OBJ file must be linked into the application, in contrast to the pre-linked .DLL file (which means that implementing new versions of the control with the application requires a relink) - the .DLL file may still need to be kept in the development environment in order to allow using the Dialog Editor to modify dialog boxes that use the control - the .OBJ file used must match the memory model that the application uses The following steps are necessary to implement access to the control using the OBJ interface; these steps replace the above section, "Accessing the DLL": 1. Add a ClrCtrlRegisterClass() call ClrCtrlRegisterClass() should be called from WinMain sometime during the program initialization process. This function registers with Windows the special window class that is needed by the color selector control. The function takes an argument that is the program's instance handle, as in the following example: ClrCtrlRegisterClass (hInstance); 2. Export the ClrCtrlWndProc() function Since the window procedure (ClrCtrlWndProc) for the color selector control will be called by Windows' Dialog Manager code, this function must be exported. Add the function to the list of exported functions in the application's .DEF file, as in the following example: EXPORTS ... various function names ... ClrCtrlWndProc ... various function names ... 3. Link the .OBJ file with the application Depending on the memory model used by the application, link the proper .OBJ file (CLRCTRLS.OBJ, CLRCTRLM.OBJ, or CLRCTRLL.OBJ) into the executable file for the application. To implement a color selector in a dialog, refer to the procedures in the following sections. Using the Dialog Editor ----------------------- The easiest way to add color selector controls to an application's dialog is to edit the dialog using the Dialog Editor found in the Microsoft SDK. The following paragraphs describe the steps necessary to add color selector controls to a dialog using the Dialog Editor. Install the custom control library To access the color selector custom control from within the Dialog Editor, the CLRCTRL.DLL file that defines the control must be "installed" in the Dialog Editor. To do this, execute the Add Custom Control menu option from the File menu of the Dialog Editor, and give the full pathname of the control's .DLL file. This pathname will point to wherever this custom control kit is installed. If the .DLL file ever needs to be de-installed, use the Remove Control option from the Dialog Editor's file menu, and choose the control library to be removed from the list presented. Create a color selector in a dialog To use the color selector in a dialog, choose the Custom menu option from the Control menu. Then choose the CLRCTRL control from the list presented. The control also can be chosen from the Toolbox, if it is displayed. Once the control has been selected, position the plus sign cursor where the upper left corner of the control should be on the dialog, and click the left mouse button to add the control. Modify the control in the dialog After adding a color selector to a dialog, it can be moved and resized in the same way as a standard control. Keep in mind that the size of the control is really larger than the visible portion of the control, because of the drop-down area. To make a color selector the current object in the Dialog Editor, click the mouse in the drop-down area, instead of in the visible area, because the latter mouse click will be interpreted by the control and not the Dialog Editor. Also, it is important to note how the vertical size of the control affects the control. The default vertical size of a color selector control is sixty dialog units. At this size, the height of the edit box and drop down button are the same as the height of their standard Windows counterparts. When dropped down, six color rectangles are displayed (or fewer if there are less than six color choices in the list.) If the size of the control is changed the size of the color rectangles and the size of the edit box and drop down button also change. There will still be six colors displayed in the dropped down list. Within the Dialog Editor, the behavior is different. If the size of the control is changed and the dialog is then tested within the Dialog Editor, the edit box and drop down button do not change size. In addition, the number of color rectangles displayed when the list box is dropped down changes, instead of the size. Keep this difference in mind when sizing the color selector controls within a dialog. Control styles A color selector's ID value is the only "style" associated with this type of control. To modify this value, double-click the mouse on the control or make the control the current object and press Control-C. Choosing the Styles menu option in the Edit menu also works. These actions cause the control's styles dialog box to be presented, which has an edit field for the control's ID value. This ID value field can be used in the same way as with a standard control; a number can be entered or a string value can be used that equates to a number using a #define in the header file associated with the dialog. See the SDK's Tools manual for information on how to maintain a header file of ID values for the dialog. Modifying the dialog by hand It is also possible to modify the dialog file without using the Dialog Editor using a standard text editor. A color selector control in a dialog uses the CONTROL statement in the dialog file and its format is the same as the CONTROL statement for a standard control. The class string for color selector's CONTROL statement is "ClrCtrl" -- see the SDK tools manual for information on the full format of the CONTROL statement. Dialog procedure handling ------------------------- To access a dialog's color selector control from the application, code must be added to the dialog procedure to initialize the state of the color selector and retrieve its current selected color at the end of dialog processing. To implement this access, perform the following steps: 1. Include the color control header file. The header file for color selector control access, clrctrl.h, should be included in any .c modules that define dialogs using the color selector control. This header file defines message codes specific to the color selector and other information useful to access the control. 2. Modify the color choices for the control. During WM_INITDIALOG message processing for the dialog, it is possible to modify the color choices available in the control. To do this, the standard Windows messages for modifying items in a combobox can be used. For the following examples, hClrCtrl is assumed to be an HWND value, initialized to be a color selector's window handle. This value can be obtained in several ways, as explained in any Windows programming reference. To add a color selection to the end of the control's list, use the CB_ADDSTRING message. For example, SendMessage(hClrCtrl, CB_ADDSTRING, 0, RGB(0xC0,0x40,0x00)); will add an orange color to the end of the color selector's list. (Keep in mind that the color capability of the video hardware that the application is being run on will determine whether a particular RGB color is rendered as a pure color.) To remove a color choice from the list, determine the index of the color in the list (starting at 0) and send the CB_DELETESTRING message to the control. For example, SendMessage (hClrCtrl, CB_DELETESTRING, 3, 0L); will remove the fourth color selection in the list. Note that removing an item will cause the indices assigned to all colors below the removed color to be decremented by one, so if more than one color selection is to be removed, it is best to remove them from the bottom up. To insert a color choice in the middle of the list, determine the index of the position at which to insert the item and send the CB_INSERTSTRING message to the control. For example, SendMessage (hClrCtrl, CB_INSERTSTRING, 7, RGB (0x80,0x00,0xFF)); will insert a lavender color after the first seven colors in the list. Note that inserting an item will cause the indices assigned to all colors below the inserted color to be incremented by one, so if more than one color selection is to be inserted, it is best to insert them from the bottom up. For special situations, it may be desirable to remove all color selections and then add back a complete set. To do this, send the CB_RESETCONTENT message to the control to remove all current color selections in the list. For example, Sendmessage (hClrCtrl, CB_RESETCONTENT, 0, 0L); will remove all color selections. (The last two parameters are ignored.) 3. Set the default color choice for the control. During WM_INITDIALOG processing, it is also possible to select the default color choice for a color selector. This can either be a hardcoded default choice, or it can be the saved value of the choice that was selected during the last time the dialog was processed. If the index of the desired default color choice is known, the CB_SETCURSEL message can be sent to the control. For example, SendMessage (hClrCtrl, CB_SETCURSEL, 6, 0L); sets the seventh color in the list as the default. If the RGB color value of the desired default color is known, but the index of the color is not known, a special color selector message, CLRM_SETCURCOLOR can be used. For example, SendMessage (hClrCtrl, CLRM_SETCURCOLOR, 0, RGB (0xFF,0x00,0x00)); sets the current color selection to be red. Note that if the exact RGB color specified does not exist in the control's list, the current color selection will not be changed, and a CB_ERR value will be returned. (When a combobox control is created, its initial current selection is index 0, until changed by a message such as those above.) 4. Retrieve the current color choice when the dialog is closed. When a user action indicates that the current dialog control values should be retrieved and used (such as when the user presses an "OK" or "Apply" button), the current color value for a color selector can be retrieved as an RGB value by using the special color selector message, CLRM_GETCURCOLOR. For example, COLORREF rgbColor; . . . rgbColor = SendMessage (hClrCtrl, CLRM_GETCURCOLOR, 0, 0L); will store in rgbColor the current RGB color selected in the control. (The last two parameters are ignored.) Message handling ---------------- To make the color selector control as flexible as possible, most of the standard Windows messages and notification codes that are supported by a combobox control also are supported by the color selector control. The following sections contain further information about this support. Color selector messages CLRM_GETCURCOLOR retrieve the RGB color of the current selected item in the control. wParam and lParam are not used. The return value of the SendMessage call is the current selected RGB value. See the previous section for information on using this message. CLRM_SETCURCOLOR set the current selected item of the control to the specified RGB color. wParam is not used for this message. lParam is used to pass the desired RGB color value. The return value of the SendMessage call is CB_ERR if the specified RGB color is not in the control's list. See the previous section for information on using this message. Windows messages The following Windows messages are supported in the color selector control, either by special processing or by default processing handled within Windows. See the SDK Reference manual (volume 2) for more information on these messages. WM_CREATE create the control on the dialog WM_DESTROY remove the control from the dialog WM_SIZE resize the control WM_PAINT repaint the control WM_COMMAND process commands from the user WM_ACTIVATE activate or inactivate the control WM_CHAR process a keyboard character sent to the control WM_ENABLE enable or disable the control WM_KEYDOWN process a key press for a non-system key WM_KEYUP process a key release for a non-system key WM_KILLFOCUS remove the input focus from the control WM_MOVE move the control onthe dialog WM_SETFOCUS give the input focus to the control WM_SYSCHAR process a system keystroke sent to the control WM_SYSKEYDOWN process a key press for a system key WM_SYSKEYUP process a key release for a system key The control sends the following messages to its dialog parent: WM_CTLCOLOR ask the dialog to change the drawing attributes used to paint the control (note that these attributes are used to draw the structural aspects of the control, and do not affect the color choices in the color selector's list) WM_DELETEITEM tell the dialog that a color choice has been removed from the color selector's list These messages control the comobox-specific aspects of the color control: CB_ADDSTRING add an item to the end of a combobox's list CB_DELETESTRING delete an item from a combobox's list CB_GETCOUNT determine the number of items in a combobox's list CB_GETCURSEL determine the index of the currently selected item in a combobox CB_GETITEMDATA retrieve the data associated with an item in a combobox (for color selectors, this data is the stored RGB color value) CB_INSERTSTRING insert an item in the middle of a combobox's list CB_RESETCONTENT remove all items from a combobox's list CB_SETITEMDATA store a data value in a combobox item (for color selectors, this data is the RGB color value) CB_SETCURSEL change the currently selected item in a combobox Windows notification codes The color selector control returns the following combobox notification codes to its parent window, in WM_COMMAND messages: See the SDK Reference manual (volume 2) for more information on these codes. CBN_DROPDOWN notify the dialog that the color selector listbox has been dropped down CBN_KILLFOCUS notify the dialog that the color selector control has lost the input focus CBN_SELCHANGE notify the dialog that the color selector current color has changed CBN_SETFOCUS notify the dialog that the color selector control has gained the input focus CBN_EDITCHANGE notify the dialog that the color selector control's edit box value may have changed CBN_EDITUPDATE notify the dialog that the color selector control's edit box value will be changed SAMPLE PROGRAM This kit comes with a sample Windows program, CLRTEST.EXE. This program serves two purposes: first, it provides a good test of most of the important functionality of the control and the interface between the control and the application that uses it; second, it represents a clean example of the control's implementation and use in a program, without any complicated "applicaton-specific" code to get in the way. Other than that, this program does not do any useful work--it is unlikely that anyone will want add it to one of their Program Manager groups! On the other hand, it may come in handy as a starting point for testing special ways of interfacing with the control, whenever changes to the control's standard behavior are desired. Using the sample program ------------------------ Using the CLRTEST.EXE program is easy. When run, the program consists of a normal application window and a short application menu. The window contains a line of sample text that is colored according to a default color value defined in the test program, displayed on a background that is colored by another default color value. The application menu is described below. Application menu The test program's application menu contains three choices: File, Options, and Help. File menu The File menu has a standard meaning on most Windows applications, but in this program, only one standard File menu option is defined: Exit. When Exit is chosen, the program simply shuts down. Options menu Under the Options menu, there is one option: Test Color Selector. This option displays the "Color Test Attributes" dialog. Color Test Attributes Dialog This dialog is used to test the functionality of the color selector control. It contains a color selector control for "text color" and one for "background color." Changing the currently selected color in either of these controls changes the corresponding current color attribute for the program. The pushbuttons on the dialog work in the expected way: The OK button causes the main application window to be redrawn using the current colors choices in the color selectors. The Cancel button leaves the current color settings for the program as they were before the dialog box was displayed. The Reset button resets the current colors in the controls to the default values defined in the program code. Note that each color selector has had colors added or removed from the default set of sixteen pure colors. The standard Dark Magenta pure color has been removed from the text color selector, and a sky-blue color has been added in the fourth position in the list. Also, an orangish color has been added to the end of the background color selector's list. This is to test (and illustrate) the ability to modify the control's behavior with standard Windows messages, as standard controls (including comboboxes) allow. Help menu The help menu provides access to the Windows help file for the CLRCTRL kit, which is an enhanced version of this text. Besides help information for the test program, it contains information about using the color selector control in other applications. In addition, an "About Color Test..." option is defined, which provides general information about the kit. REGISTRATION This software product is SHAREWARE. You are permitted to evaluate this software product for a period of 30 days. If, after that period, you find the software product useful, you must register the software product and send $15 with your name and address to the address shown at the top of this text. You will then receive a registered copy of the kit, including the files necessary to use the OBJ interface to the control. You will also be entitled to receive a registered copy of the next major revision of this software product plus technical support at no charge. You may also make additional copies for the purpose of allowing others to evaluate the software product, as long as no modifications or additions are made to the software, its documentation, or any associated files, and this kit is not bundled in a distribution of any other software except that which is distributed as Shareware or Public Domain. Since this product is a programmer's kit, the RUN-TIME version of this product, which consists of the .DLL file alone plus code compiled against the .H file, may be distributed as part of a RUN-TIME ONLY distribution of a commercial, shareware, or public domain application. In the case of the OBJ interface to the code, the run-time portion of the product consists of the appropriate .OBJ file for the control, plus code compiled against the .H file. FEEDBACK Lastly, if you find this software product useful and have any interesting comments or ideas on how it might be improved, please let me know! I will attempt to incorporate the best of these suggestions in future versions of this software product. And, if you happen to provide particularly valuable feedback, I will, at my discretion, register you free of charge. Also, watch for other custom controls to be available as shareware soon. If I get a positive response from this product, I have many more that I will upload in the future! Thanks again for evaluating this product! DISCLAIMER This software product is made available on an "as is" basis, and carries no warranties, express or implied, including, but not limited to, merchantability or fitness for a particular purpose. The author shall in no way be held liable for any damages resulting from the use of this software product or the media on which it is distributed, including, without limitation, loss of business profits, interruption of business, loss of information, damage to equipment, or any other incidental or consequential damages.