=============================== CALENDAR.TXT =============================== Title: Windows Calendar Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform: Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: January 9, 1995 Keywords: Windows Custom Control, Calendar, Date Abstract: A windows custom control for date selection. The control shows a single month with the selected day highlighted. The user can change the day, month or year with the mouse or the keyboard. C++ source code only; no VBX file. The "CALENDAR" control is a simple control that you can display wherever the user is required to enter a date. It shows a single month at a time, as a standard tableau with four, five or six lines of numbers as required. The currently selected day is highlighted. When the control is disabled, its border and contents are gray. When the control has the input focus, its border becomes thicker. The user can change the date to another day in the same month by clicking on the desired day. The control will regain the input focus, if necessary, and the highlight will move. The user can change the date to the preceding or following month by clicking on the arrows on either side of the month name. Similarly, the user can change the year to the preceding or following year by clicking on the arrows on either side of the year. When the date is changed in this manner, it always changes to the first day of the month or year. If the control has the input focus, the user can also change the selection with the keyboard. The left and right arrow keys move the date backward or forward one day at a time. The up and down arrow keys move the date backward or forward one week at a time. The PgUp and PgDn keys move the date to the previous or following month, and if the Ctrl key is held down, the PgUp and PgDn keys move the date to the previous or following year. You can put a "CALENDAR" control into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL 0, control_id, "CALENDAR", WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, width, height You can also put a "CALENDAR" control into a dialog box with the Borland Resource Workshop, by selecting a custom control and then entering the class name "CALENDAR" instead of choosing one of the predefined classes. You can also create a "CALENDAR" control dynamically with an appropriate call on CreateWindow(). The control selects the largest font consistent with the specified height and width. Since the font size is not continuously variable, this may leave an unacceptable amount of blank space at the lower and right edges of the control. If this happens, simply reduce the height and width of the control until the excess space shrinks to an acceptable size. The control is initially blank, indicating that no date has been selected. To select an initial date, you must send it a message as follows: SendDlgItemMessage(parent_handle, control_id, CAL_SETDATE, 0, date); A zero date (0L) may be sent to clear the control. The date is a single value of type DWORD with fields as follows: bits 31-16 (the most significant) year bits 15-8 month (1=Jan, 2=Feb, etc.) bits 7-0 (the least significant) day (1-31) Since this control was designed to handle dates in the next century, you must use a four-digit year. The inline function MAKEDATE(), which is defined in the header file CALENDAR.H, can be used to assemble the month, day and year into a date of this form. Three inline functions GETDAY(), GETMONTH() and GETYEAR(), are available to extract the day, month or year from the date. A function called day_of_week() returns a code indicating the day of the week as follows: dow = day_of_week(date); DWORD date; date in format described above unsigned dow; 0 for Sunday, 1 for Monday, etc. The string arrays DAY_NAME[] and MONTH_NAME[] in the file CALENDAR.CPP may be modified for languages other than English. For example, here are the Spanish versions: static char DAY_NAMES[] = "Do Lu Ma Mi Ju Vi Sa"; char *MONTH_NAME[13] = { "???", "ENE", "FEB", "MAR", "AVR", "MAY", "JUN", "JUL", "AGO", "SEP", "OCT", "NOV", "DIC" }; The string array MONTH_NAME[] has been externally defined so other modules can use it to edit dates. To retrieve the date, you simply send the control a different message: date = SendDlgItemMessage(parent_handle, control_id, CAL_GETDATE, 0, 0L); By default, the control accepts only dates between January 1, 1800 and December 31, 2099, inclusive. You can change these limits by sending other messages to the control: SendDlgItemMessage(parent_handle, control_id, CAL_FIRSTDATE, 0, earliest_permitted_date); SendDlgItemMessage(parent_handle, control_id, CAL_LASTDATE, 0, latest_permitted_date); CAUTION: Dates before the adoption of the Gregorian calendar (1752 in England and its colonies) or in the distant future will not be handled properly by the control. The control does not check dates sent to it in messages, either for validity or range. (An invalid date such as February 30 will produce anomalous results, so the calling program should check the date if it comes from a questionable source.) Out-of-range dates are grayed, and if the user attempts to change the date to a new date that is out of range, the control will set the date to the nearest date that is in range. The control sends the notification message CAL_CHANGE to its parent when the user changes the date with either the mouse or keyboard. The control sends the notification message CAL_KILLFOCUS to its parent when it loses the input focus. The file CALENDAR.CPP must be compiled and linked with the rest of the application. The special messages CAL_CHANGE, CAL_FIRSTDATE, CAL_GETDATE, CAL_KILLFOCUS, CAL_LASTDATE and CAL_SETDATE are defined in the header file CALENDAR.H. The files CALTEST.H, CALTEST.CPP and CALTEST.RC contain a simple test program that uses the "CALENDAR" control. The main window contains three calendar controls of different sizes. The program displays the date from the first calendar whenever the date is changed. It displays the date from the second calendar whenever that calendar loses the input focus. The first calendar is limited to dates from January 10, 1980 to January 10, 2000. The other calendars use the default limits. =============================== CHECKBOX.TXT =============================== Title: Windows Checkbox Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: January 10, 1995 Keywords: Windows Custom Control, Checkbox Abstract: A windows custom control for a checkbox. Its size can be altered but it has no caption or three-state style. The focus rectangle surrounds the box. C++ source code only; no VBX file. The standard Windows 3.1 checkbox control consists of a square of fixed size, with a caption to the right or left. The checkbox may be checked, in which case an "X" is inscribed in the square, or unchecked, in which case inside of the square is left blank. A three-state checkbox also has an intermediate state in which the inside of the square is gray. The focus rectangle surrounds the caption, not the box. The standard control also "captures" the mouse. If the left mouse button is depressed and held down while the cursor is over the control, the mouse can be moved elsewhere without affecting other controls, as long as the left mouse button is held down. The checkbox itself is darkened, and is said to be "highlighted", while the mouse is captured. When the left mouse button is released, the highlight is removed. If the cursor is over the control at that time, the state of the control is changed from checked to unchecked or vice-versa. When the standard control has the input focus, depressing the space bar highlights the checkbox, and releasing it again removes the highlight and changes the state of the control from checked to unchecked or vice-versa. The "CHECKBOX" control has no caption. (If a caption is needed, a static text control can be used for that purpose.) The focus rectangle surrounds the box. The box itself is sized to fit into the rectangle provided for the control. The control has no three-state style. Therefore, "CHECKBOX" controls can be packed closely into arrays and other groupings. A "CHECKBOX" control can be put into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL 0, control_id, "CHECKBOX", WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, width, height Since the control is square, the height and width should be equal. The control will be sized to fit into the specified square. If the height and width are not equal, the control will still be square, but it will fill only the top or left portion of the specified rectangle. A "CHECKBOX" control can be put into a dialog box with the Borland Resource Workshop, by selecting a custom control and then entering the class name "CHECKBOX" instead of choosing one of the predefined classes. Then edit the resulting .RC file as text and replace "BorCheck" with "CHECKBOX" if necessary. A "CHECKBOX" control may also be created dynamically with an appropriate call on CreateWindow(). The accompanying code in CHECKBOX.CPP must be compiled and linked with the application. Like a standard checkbox control, a "CHECKBOX" control may be enabled or disabled, it processes the BM_SETCHECK, BM_GETCHECK, BM_SETSTATE and BM_GETSTATE messages, and it may gain or lose the input focus. It also sends a BN_CLICKED message to its parent when the user adds or removes the "X". Other features of the standard checkbox control are not supported. A simpler control of the class "SCHECKBOX", which does not capture the mouse and does not process the BM_SETSTATE and BM_GETSTATE messages, is also available. The files CHECTEST.CPP and CHECTEST.RC contain a simple test program that uses several "CHECKBOX" controls of various sizes. =============================== LINEIN.TXT =============================== Title: Windows Line Input Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform: Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: February 15, 1995 Keywords: Windows Custom Control, Line Input, Edit Abstract: A single-line edit control for Windows. Supports typeover mode and arbitrary selection of valid input characters, and indicates when there is hidden text outside the border. C++ source code only; no VBX file. The "LINEINPUT" control is a single-line edit control that you can display wherever the user is required to enter a single line of text. When the control is disabled, its border and contents are gray. When the control has the input focus, the caret appears. When there is hidden text past either end of the border, that side of the border thickens. The control has nearly all of the features of the standard Windows edit control, when operating in a single-line mode. The control has a maximum capacity of 127 characters, which should be sufficient for a single line. You can reduce this maximum by sending a standard message (EM_LIMITTEXT), but you can increase it only by recompiling the control. The control processes the following message in the same manner as a standard edit control: EM_GETFONT EM_GETMODIFY EM_GETSEL EM_LIMITTEXT EM_SETFONT EM_SETMODIFY EM_SETREADONLY WM_CLEAR WM_COPY WM_CUT WM_GETTEXT WM_GETTEXTLENGTH WM_PASTE WM_SETFOCUS WM_SETTEXT The control also passes the following notification messages to its parent in the same manner as a standard edit control: EN_CHANGE EN_KILLFOCUS EN_SETFOCUS Other messages and notification messages are not supported by this control, except for those described below and a few that are normally handled internally by Windows. The control accepts nearly all of same control keys as a standard edit control: The left arrow key moves the caret left one character position. The right arrow key moves the caret right one character position. The Home key moves the caret to the left end of the text. The End key moves the caret to the right end of the text. The Ctrl-X, Ctrl-C and Ctrl-V keys cut, copy and paste text to and from the Windows Clipboard. (The messages WM_CUT, WM_COPY and WM_PASTE are not supported.) The Backspace key erases the character to the left of the caret. However, if any text has been selected, the Backspace key erases it. The Del key erases the character to the right of the caret. However, if any text has been selected, the Backspace key erases it. If you hold the Shift key down while moving the caret, the text over which the caret moves is selected. If you move the caret without holding the Shift key down, the selection highlight is removed. The control also accepts one one nonstandard control key. If you type Ctrl-S, all of the text is selected. The control uses mouse input in the same way as a standard edit control, with two exceptions. If you double-click on the control it selects all of the text, whereas the standard control selects only a single word. The control does not capture the mouse; i.e., if you move the cursor away from the control while holding the left mouse button down, the cursor changes back to its standard form when it is no longer over the control. You can put a "LINEINPUT" control into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL initial_text, control_id, "LINEINPUT", WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, width, height You can also put a "LINEINPUT" control into a dialog box with the Borland Resource Workshop, by selecting a custom control and then entering the class name "LINEINPUT" instead of choosing one of the predefined classes. You can also create a "LINEINPUT" control dynamically with an appropriate call on CreateWindow(). There are two options that you can OR into the style list if you wish: option meaning -------------- ----------------------------------------- ES_TYPEOVER start the control in the typeover mode ES_NOSELECTALL start the control in the noselectall mode When the control is in the typeover mode, every character typed by the user will REPLACE the character to the right of the caret, if any. When the control is in the noselectall mode, the text will not be selected when the control receives the input focus. (The standard Windows edit control does not have either of these modes.) You can also enable or disable either of these modes dynamically by sending the control an appropriate message: SendDlgItemMessage(parent_handle, control_id, EM_SETTYPEOVER, enable, 0L); SendDlgItemMessage(parent_handle, control_id, EM_SETNOSELECTALL, enable, 0L); If the "enable" argument is TRUE (nonzero), the specified mode is enabled; otherwise it is disabled. There is another mode, called the uppercase mode, that you can enable or disable only dynamically, by sending the control an appropriate message: SendDlgItemMessage(parent_handle, control_id, EM_SETUPPERCASE, enable, 0L); When the control is in the uppercase mode, any small letters entered by the user will be converted to the corresponding capital letters before they are inserted into the control. Any small letters in the control at the time the message is received will also be converted. Another message can be used to specify which character or characters are to be deemed invalid: SendDlgItemMessage(parent_handle, control_id, EM_SETINVALID, 0, (LPARAM) buffer); WORD buffer[6]; Here the "buffer" parameter is a far pointer to a six-word buffer whose bits indicate which of the characters corresponding to ASCII codes from 32 to 126 are to be regarded as invalid. The bits are arranged in the most obvious fashion; the character corresponding to N is regarded as invalid if buffer[(N-32)/16] & 1 << ((N-32)%16) is nonzero. By default, all such characters are regarded as valid when the control is first created. This state of affairs can be restored by sending a buffer containing all zeros. When the control receives an invalid character from any source, it is simply ignored. Characters that become invalid when the EM_SETINVALID message is received are removed from the control and other characters are pushed together to fill the empty spaces. Characters corresponding to codes less than 32 or greater than 126 are regarded as invalid in all cases. Some of them are processed as control codes, rather than characters. The file LINEIN.CPP must be compiled and linked with the rest of the application. The special messages and style options are defined in the header file LINEIN.H. The files LINETEST.H, LINETEST.CPP and LINETEST.RC contain a simple test program that uses the "LINEINPUT" control. =============================== MARQUEE.TXT =============================== Title: Windows Marquee Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: January 13, 1995 Keywords: Windows Custom Control, Static Abstract: A windows custom control which displays text in a border consisting of a circulating dashed line. The resulting display resembles a theater marquee. C++ source code only; no VBX file. The "MARQUEE" control is a simple control that you can use as a substitute for the standard Windows STATIC control. It displays text in a circulating dashed line. The resulting display resembles a theater marquee. You can put a "MARQUEE" control into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL initial_text, control_id, "MARQUEE", WS_CHILD | WS_VISIBLE, x, y, width, height You can also put a "MARQUEE" control into a dialog box with the Borland Resource Workshop, by selecting a custom control and then entering the class name "MARQUEE" instead of choosing one of the predefined classes. You can also create a "MARQUEE" control dynamically with an appropriate call on CreateWindow(). The control handles the following messages in the same manner as a standard STATIC control: WM_SETTEXT WM_GETTEXT WM_SETFONT WM_GETFONT You can change the speed with which the border circulates by sending the control a message of the following form: SendDlgItemMessage(handle, control_id, MA_SETSPEED, speed, 0L); Here "speed" is normally in the range from about -40 to about +40. Positive values make the border circulate clockwise; negative values make it circulate counterclockwise. The value 0 stops the circulation altogether. Values near the extremes may produce aliasing, in which the direction of circulation seems to be reversed. The default speed is 20. You can retrieve the speed by sending the control another message: speed = SendDlgItemMessage(handle, control_id, MA_GETSPEED, 0, 0L); Each "MARQUEE" control with a circulating border uses a system timer. The number of system timers is limited. Therefore, when a "MARQUEE" control is not being used, you should either destroy it or set its speed to zero. The control does not handle other messages, except for a few that are normally generated internally by Windows. It generates no notification messages. The file MARQUEE.CPP must be compiled and linked with the rest of the application. The special messages MA_SETSPEED and MA_GETSPEED are defined in the header file MARQUEE.H. The files MARQTEST.CPP, MARQTEST.H and MARQTEST.RC contain a simple test program uses a "MARQUEE" control. =============================== PBUTTON.TXT =============================== Title: Windows Picture Button Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: February 15, 1995 Keywords: Windows Custom Control, Button Abstract: A windows custom control for a button with a bitmap picture on it. The focus rectangle is drawn around the picture. C++ source code only; no VBX file. The standard Windows button control shows only text. With the BS_OWNERDRAW style, you can put a picture on it, but the required procedures are rather complicated. The "PICTUREBUTTON" control lets you display two bitmaps on a button -- one when the button is enabled and the other when the bitmap is disabled. Just supply two bitmaps, and the control does the necessary drawing. A "PICTUREBUTTON" control can be put into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL bitmap_name, control_id, "PICTUREBUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, width, height The bitmap is specified by name, which must be enclosed in quotation marks. The bitmap should be included in the same resource (.RC) file. The file PBUTTEST.RC contains several examples. The bitmap name must not be more than 31 characters long. The specified bitmap is used when the button is enabled. The name of the bitmap to be used when the button is disabled is obtained by appending the letter "X" to the specified bitmap name. If either bitmap cannot be found, the control simply leaves its top blank when the unknown bitmap is to be displayed. You may adjust the size of the button, but the bitmap will not be stretched or compressed to fit. It will simply be centered. If the bitmap is too large to fit onto the button top, it will spill over onto the bottom and right edges, and parts of it may be trimmed. The result is usually a workable but aesthetically displeasing button. To put a "PICTUREBUTTON" control into a dialog box with the Borland Resource Workshop, select a custom control, enter the class name "PICTUREBUTTON" instead of choosing one of the predefined classes, and enter the name of the bitmap as the caption. Then edit the resulting .RC file as text and replace "BorCheck" with "PICTUREBUTTON" if necessary. The Resource Workshop can also be used to create and edit the bitmap. The bitmap will blend into the button top if the area surrounding the picture is painted light gray, which matches the rest of the button top. A "PICTUREBUTTON" control may also be created dynamically with an appropriate call on CreateWindow(). If you use a "PICTUREBUTTON" control on a toolbar, you may wish to omit the WS_TABSTOP style, which has meaning only for a dialog box control. The accompanying code in PBUTTON.CPP must be compiled and linked with the application. You may change the bitmaps dynamically by sending a somewhat nonstandard BM_SETSTYLE message: SendDlgItemMessage(window_handle, button_id, BM_SETSTYLE, 0, MAKELPARAM(enabled_bitmap_handle, disabled_bitmap_handle); The two bitmap handles need not be different, but they must both be valid. The "PICTUREBUTTON" control sends a BN_CLICKED notification message to its parent when it is selected. Other notification messages are not supported. The parent may enable, disable, show or hide a "PICTUREBUTTON" control in the same manner as a standard Windows button control. The bitmap on a button control is often insufficient to identify its purpose. Therefore, you may cause a "PICTUREBUTTON" to display specified text in a status bar by sending it a nonstandard BM_SETSTATE message: SendDlgItemMessage(window_handle, control_id, BM_SETSTATE, (WPARAM) GetDlgItem(window_handle, status_bar_id), (LPARAM) (char far *) text); The status bar should be a STATIC control and a sibling of the "PICTUREBUTTON" control. The "PICTUREBUTTON" control will then display the specified text in the specified status bar when it captures the mouse. That is, the text will appear in the status bar when you move the cursor over the button and depress the left mouse button, and will disappear when you release the left mouse button. The files PBUTTEST.CPP and PBUTTEST.RC contain a simple test program that uses five "PICTUREBUTTON" controls of various sizes. Clicking the rightmost button enables or disables the button next to it. Clicking the leftmost button closes the window and terminates the test program. Clicking the button next to it causes the bitmap on the leftmost button to cycle through all available OBM bitmaps. The center button lacks the WS_TABSTOP property, but it is otherwise normal. =============================== PROGRESS.TXT =============================== Title: Windows Progress Bar Control Author: Philip J. Erdelsky, pje@acm.org Language: Turbo C/C++ 3.1 for Windows Platform Windows 3.1 Portability: Other Windows C++ compilers, with slight changes Restrictions: Public domain, no restrictions on use Date: January 10, 1995 Keywords: Windows Custom Control, Progress, Completion Abstract: A windows custom control for a progress bar or completion bar, which shows the percentage of completion of a process as a numerical value and also by a partly filled-in bar. C++ source code only; no VBX file. The "PROGRESSBAR" control is a simple, common control that does not appear among the Windows standard controls. Its purpose is to show the percentage of completion of a process, both as a numerical value and by a partly filled-in bar. It is a completely passive control which changes only in response to messages sent by its parent. You can put a "PROGRESSBAR" control into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file: CONTROL 0, control_id, "PROGRESSBAR", WS_CHILD | WS_VISIBLE, x, y, width, height You can also put a "PROGRESSBAR" control into a dialog box with the Borland Resource Workshop, by selecting a custom control and then entering the class name "PROGRESSBAR" instead of choosing one of the predefined classes. You can also create a "PROGRESSBAR" control dynamically with an appropriate call on CreateWindow(). The control keeps track of two values, which are called "total" and "completed". The default values are 100 and 0, respectively, but they may be changed by sending messages as follows: SendDlgItemMessage(handle, control_id, PB_SETTOTAL, value, 0L); SendDlgItemMessage(handle, control_id, PB_SETCOMPLETED, value, 0L); The control displays the following percentage (rounded downward to the nearest integer) in the middle of the bar: (completed / total) * 100% It also darkens the left side of the bar so the width of the darkened portion and the width of the bar are in the same ratio as "completed" is to "total". The value of "total" must be positive, and the value of "completed" must lie between zero and "total", inclusive. The control will fail if this is not the case. The values of "total" and "completed" may also be retrieved by sending messages as follows: value = SendDlgItemMessage(handle, control_id, PB_GETTOTAL, 0, 0L); value = SendDlgItemMessage(handle, control_id, PB_GETCOMPLETED, 0, 0L); A "PROGRESSBAR" control does not process other messages, except for a few that are handled internally by Windows. The file PROGRESS.CPP must be compiled and linked with the rest of the application. The special messages PB_SETTOTAL, PB_SETCOMPLETED, PB_GETTOTAL and PB_GETCOMPLETED are defined in the header file PROGRESS.H. The files PROGTEST.CPP, PROGTEST.H and PROGTEST.RC contain a simple test program uses a "PROGRESSBAR" control.