Custom Controls

If you have developed custom controls, you can place the code for the controls in a DLL. As detailed in the Toolkit, the Dialog Editor can then access the DLL to display your custom control during a dialog-box editing session.

For your control library to be used by the Dialog Editor and other applications, you will need to define and export the functions described in this section. The Rainbow example on the sample disk illustrates how to write a custom control DLL.

In the following function descriptions, Class is used as a placeholder for the class name of your control. The name of your custom control is the same name the Dialog Editor user employs to identify the control. The name of the control is typically the same as the module name of the DLL, but not necessarily.

Structure definitions, such as for CTLINFO, and constants that define the interface of a custom control with the Dialog Editor, are provided in CUSTCNTL.H.

This section describes six functions that your custom-control DLL must export. The DLL should export these functions by ordinal value, as shown in the following list:

Exported Function
Ordinal Value

WEP Any number except 2–6
ClassInit or LibMain Not required
ClassInfo 2
ClassStyle 3
ClassFlags 4
ClassWndFn 5
ClassDlgFn 6

For example, the functions exported by the example Rainbow custom control are declared in the RAINBOW.DEF file as shown in the following example:

EXPORTS

WEP @1 RESIDENTNAME

RAINBOWINFO @2

RAINBOWSTYLE @3

RAINBOWFLAGS @4

RAINBOWWNDFN @5

RAINBOWDLGFN @6

For more information on the LibMain function, see “Initializing a DLL”. For more information on the WEP function, see “Terminating a DLL”.

The ClassInit Function

Syntax

HANDLE FAR PASCAL ClassInit(hInstance, wDataSegment, wHeapSize, lpszCmdLine)

The ClassInit function is responsible for all the initialization necessary to use the dynamic-link control library. Your assembly-language entry point to the library normally calls this function. In addition to saving the library instance handle with a global static variable, this function should register the control window class and initialize the local heap by calling the LocalInit function if your assembly-language entry routine does not initialize the local heap.

If you link the custom-control DLL with LIBENTRY.OBJ instead of providing your own assembly-language entry point, this function is named LibMain. For more information about DLL entry points and initialization, see “Initializing a DLL”.

Parameter Type/Description  

hInstance HANDLE Identifies the instance of the library.  
wDataSegment WORD Specifies the library data segment.  
wHeapSize WORD Specifies the default library heap size.  
lpszCmdLine LPSTR Specifies the initial command line arguments.  

Return Value

The return value is a library-instance handle if the control class has been registered and if initialization has succeeded. The return value is NULL if the initialization process failed.

The ClassInfo Function

Syntax

HANDLE FAR PASCAL ClassInfo( )

The ClassInfo function provides the calling process with basic information about the control library. Based on the information returned, the application can create instances of the control using one of the supported styles. For example, the Dialog Editor calls this function to query a library about the different control styles it can display.

This function has no parameters.

The return value identifies a CTLINFO data structure. This information becomes the property of the caller. The caller must explicitly release it using the GlobalFree function when the data structure is no longer needed. If memory was insufficient to allocate and define this structure, the return value is a NULL handle.

The CTLINFO structure defines the class name and version number. The CTLINFO data structure also contains an array of CTLTYPE data structures that lists commonly used combinations of control styles (called “variants”) with a short description and suggested size information.

The following shows the definition of these structures and related values:

/* general style & size definitions */

#define CTLTYPES 12

#define CTLDESCR 22

#define CTLCLASS 20

#define CTLTITLE 94

/* control information structure */

typedef struct {

WORD wType;

WORD wWidth;

WORD wHeight;

DWORD dwStyle;

char szDescr[CTLDESCR];

} CTLTYPE;

typedef struct {

WORD wVersion;

WORD wCtlTypes;

char szClass[CTLCLASS];

char szTitle[CTLTITLE];

char szReserved[10];

CTLTYPE Type[CTLTYPES];

} CTLINFO;

typedef CTLINFO * PCTLINFO;

typedef CTLINFO FAR *LPCTLINFO;

The CTLTYPE structure has the following fields:

wType

Is reserved for future implementation. This field should be set to zero.

wWidth

Specifies the suggested width of the control when created with the Dialog Editor. If the most significant bit of this field is zero, then the lower byte is the default width in Resource Compiler coordinates. If the most significant bit is 1, then the remaining bits specify the default width in pixels.

wHeight

Specifies the suggested height of the control when created using the Dialog Editor. If the most significant bit of this field is zero, then the lower byte is the default height in Resource Compiler coordinates. If the most significant bit is 1, then the remaining bits specify the default height in pixels.

dwStyle

Specifies the initial style bits used to obtain this control type. This value includes both the control-defined flags in the high-order word and the Windows-defined flags in the low-order word.

szDescr

Defines the name to be used by other development tools when referring to this particular variant of the base control class. The Dialog Editor does not refer to this information.

The CTLINFO structure has the following fields:

wVersion

Specifies the control version number. Although you can start your numbering scheme from one, most implementations use the lower two digits to represent minor releases.

wCtlTypes

Specifies the number of control types supported by this class. This value should always be greater than zero and less than or equal to CTLTYPES.

szClass

Specifies a null-terminated string that contains the control class name supported by the DLL.

szTitle

Specifies a null-terminated string that contains various copyright or author information relating to the control library.

Type[]

Specifies an array of CTLTYPE data structures which contain information relating to each of the control types supported by the class.

The ClassStyle Function

Syntax

BOOL FAR PASCAL ClassStyle(hWnd, hCtlStyle, lpfnStrTold,lpfnIdToStr)

The Dialog Editor calls the ClassStyle function to display a dialog box to edit the style of the selected control. When this function is called, it should display a modal dialog box that enables the user to edit the CTLSTYLE parameters. The user interface of this dialog box should be consistent with that of the predefined controls supported by the Dialog Editor.

Parameter Type/Description  

hWnd HWND Identifies the parent window of the dialog box.  
hCtlStyle HANDLE Identifies the CTLSTYLE data structure.  
lpfnStrToId LPFNSTRTOID Points to a function supplied by the Dialog Editor that converts a string to a numerical ID value. See the following “Comments” section for more information.  
lpfnIdToStr LPFNIDTOSTR Points to a function supplied by the Dialog Editor that converts a numerical ID value to a string. See the following “Comments” section for more information.  

Return Value

The return value is TRUE if the CTLSTYLE data structure was changed. If the user canceled the operation or an error occurred, the return value is FALSE.

Comments

The CTLSTYLE structure specifies the attributes of the selected control, including the current style flags, location, dimensions, and associated text. The following shows the definition of the CTLSTYLE data structure:

/* control style structure */

typedef struct {

WORD wX;

WORD wY;

WORD wCx;

WORD wCy;

WORD wId;

DWORD dwStyle;

char szClass[CTLCLASS];

char szTitle[CTLTITLE];

} CTLSTYLE;

typedef CTLSTYLE * PCTLSTYLE;

typedef CTLSTYLE FAR * LPCTLSTYLE;

The CTLSTYLE structure has the following fields:

wX

Specifies in screen coordinates the x-origin of the control relative to the client region of the parent window.

wY

Specifies in screen coordinates the y-origin of the control relative to the client region of the parent window.

wCx

Specifies the current width of the control in screen coordinates.

wCy

Specifies the current height of the control in screen coordinates.

wId

Specifies the current ID number of the control. In most cases you should not allow the user to change this value as it is automatically coordinated by the Dialog Editor with an include file.

dwStyle

Specifies the current style of the control. The high-order word contains the control-specific flags, while the low-order word contains the Windows-specific flags. You may let the user change these flags to any values supported by your control library.

szClass

Specifies a null-terminated string representing the name of the current control class. You should not allow the user to edit this field, as it is provided for informational purposes only.

szTitle

Specifies with a null-terminated string the text associated with the control. This text is usually displayed inside the control or may be used to store other associated information required by the control.

The Dialog Editor keeps track of user-specified control ID names and their corresponding symbolic-constant names, maintaining them in a header file which is included when the application is compiled. The control style function accesses this information by using the lpfnStrToId and lpfnIdToStr functions.

The lpfnStrToId and lpfnIdToStr parameters point to two function entry points within the Dialog Editor itself. To call these functions, you should prototype them as shown:

/* ID to string translation function prototypes */

typedef WORD (FAR PASCAL *LPFNIDTOSTR)(WORD, LPSTR, WORD);

typedef DWORD (FAR PASCAL *LPFNSTRTOID)(LPSTR);

The lpfnIdToStr entry point into the Dialog Editor allows you to translate the numeric ID provided in the CTLSTYLE data structure into a text string containing the symbolic-constant name defined in the include file. This text string can then be displayed in place of a numeric value in your custom control's style dialog box. The first parameter is the control ID. The second parameter is a long pointer to a buffer that receives the string, and the third parameter is the maximum length of that buffer. The lpfnIdToStr function returns the number of characters copied to the string. If the function returns zero, the function call failed.

The lpfnStrToId function works in reverse, translating a string to a numeric ID value. The function accepts the string containing a symbolic-constant name and returns the corresponding control ID value. If the low-order word of the return value is nonzero, the high-order word contains the control ID value which you can use to update the wID field of the CTLSTYLE data structure. If the low-order word of the return value is zero, the constant name was undefined and ClassStyle should generate an error message.

Typically, whenever ClassStyle is called, it will call lpfnIdToStr, passing it the value contained in the CTLSTYLE.wID field. If lpfnIdToStr returns a value greater than zero, then ClassStyle displays the resulting string in an edit field so the user can change it. Otherwise, it displays the numerical value of the control ID. If the user changes the edit field, ClassStyle calls lpfnStrToId to verify that the string does, in fact, contain a valid symbolic-constant name and replaces the CTLSTYLE.wID field with the high-order word of the return value.

The ClassDlgFn Function

Syntax

BOOL FAR PASCAL ClassDlgFn(hDlg, wMessage, wParam, lParam)

The ClassDlgFn function is the dialog procedure responsible for processing all the messages sent to the style dialog box. The style dialog box is invoked when the ClassStyle function is called. The ClassDlgFn function should enable the user to edit selected portions of the CTLSTYLE data structure passed to the ClassStyle function.

Parameter Type/Description  

hDlg HWND Identifies the window receiving the message.  
wMessage WORD Specifies the message.  
wParam WORD Specifies the 16-bit message parameter.  
lParam LONG Specifies the 32-bit message parameter.  

Return Value

The return value is TRUE if the dialog procedure processed the message. Otherwise, it is FALSE.

The ClassFlags Function

Syntax

WORD FAR PASCAL ClassFlags(dwFlags, lpStyle, wMaxString)

The ClassFlags function translates the class style flags provided into a corresponding text string for output to a resource script (.RC) file. This function should not interpret the flags contained in the high-order word since these are managed by the Dialog Editor. Note that you should use the same control style definitions specified in your control include file.

Parameter Type/Description  

dwFlags DWORD Specifies the current control flags.  
lpStyle LPSTR Points to a buffer to receive the style string.  
wMaxString WORD Specifies the maximum length of the style ring.  

Return Value

The return value is the number of characters copied to the buffer identified by the lpStyle parameter. If an error occurred, the return value is zero.

The ClassWndFn Function

Syntax

LONG FAR PASCAL ClassWndFn(hWnd, wMessage, wParam, lParam)

The ClassWndFn function is the window procedure responsible for processing all the messages sent to the control.

Parameter Type/Description  

hWnd HWND Identifies the window receiving the message.  
wMessage WORD Specifies the message.  
wParam WORD Specifies the 16-bit message parameter.  
lParam LONG Specifies the 32-bit message parameter.  

Return Value

The return value indicates the result of message processing and depends on the actual message sent.