═══ 1. Trademarks ═══ The following are trademarks of the Prominare Inc. Prominare Prominare Designer PM Control Extension PMCX The following are trademarks of the IBM Corporation. CUA Common User Access IBM Operating System/2 OS/2 Presentation Manager Workplace Shell ═══ 2. Copyright ═══ Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. ═══ 3. Introduction ═══ Prominare Designer's PM Control Extension (PMCX) allows you to design and create custom controls, similar to those of OS/2 Presentation Manager, that can be accessed from within your applications. PMCX has been designed so the controls you create can be accessed through Prominare Designer. As with normal OS/2 Presentation Manager controls, you can view the final control as it would appear in your application. And as with Prominare Designer's other controls, you can define a control in terms of its style, text, and other related information. OS/2 Presentation Manager is designed to allow custom or user-defined controls to be included within dialogues. PMCX uses this feature to let you create controls not found in the default OS/2 Presentation Manager environment. In reality, a custom control is similar to any of the windows created for an application. OS/2 Presentation Manager also provides a mechanism for run-time binding of libraries--namely, dynamic-link libraries. PMCX uses this mechanism to make the custom control accessible to applications including Prominare Designer. ═══ 4. PMCX Architecture ═══ The PM Control Extension is based on a simple foundation that allows both your application and Prominare Designer to interact with it. With the conventions and methodology that follow, you will learn to create PMCX controls. The architecture of a PMCX control, shown in the following diagram, can be described as three publicly defined functions and a window procedure. The three functions have to follow the naming and usage conventions of PMCX, whereas the window procedure is similar to any other window procedure for a custom control. PMCX architecture The first convention deals with naming the control and the functions provided in the PMCX control's DLL. For example, the definition of the initialization routine is: XxxxRegister(HAB hAB); Xxxx is the formal name of the control, and also the name of the dynamic-link library. Therefore, for a control called Ruler, the initialization routine would be RulerRegister(HAB hAB); and the dynamic-link library name would be RULER.DLL This convention, the corner-stone for PMCX, allows Prominare Designer to interact properly with the PMCX control DLL. PMCX defines three required public functions: Function Purpose XxxxRegister Controls registration routine. XxxxQuery Controls information query routine used by Prominare Designer to determine capabilities of the control. XxxxStyles Control's styles dialogue procedure, used by Prominare Designer to allow styles, text, ID symbol and value. When included within a design, controls specific information to be defined and edited. A PMCX control must also provide certain resources used by Prominare Designer. The first resource is a dialogue template used for the XxxxStyles dialogue. The second resource, although not absolutely required, makes reading resource script files easier, is a set of entries within a string table. These entries correspond to the style flags of the PMCX control and are used by Prominare Designer during resource script generation, allowing the entry for the control to look exactly like a normal PM control. ═══ 5. How it works ═══ Given the dual nature of a PMCX control, there is an easy part and a hard part to the design process. The easy part is how your application interacts with the control. You only need to use the XxxxRegister function in your application to register the control with PM; let PM do the rest. If the control is part of a dialogue template, PM will create the control as thought it were a normal PM control. It is that simple. The hard part is how the control interacts with Prominare Designer. This is a little more complicated, as you have to fill in a structure describing the control's capabilities to Prominare Designer, as well as create the styles dialogue. PMCX defines a set of structures that allow the custom control to pass information between itself and Prominare Designer. The structures are at all times controlled by Prominare Designer, which is responsible for allocating and de-allocating necessary memory for the structures. Only through a callback routine to Prominare Designer are you allowed to reallocate one area of these structures--the area containing the variable sized control data. Some of the structures are used only once, whereas others must be used many times, by both Prominare Designer and the control. The methods of using the structures within the control are defined to allow the control to access and update the elements of the structure. The best place to start is with the header that defines the structures you will use to interact with Prominare Designer. ═══ 6. PMCX Definitions Header - PMCX.H ═══ The PMCX definitions header include file, PMCX.H, is used to define constants, structures, and macros, allowing information to be passed between Prominare Designer and the custom control. The contents of PMCX.H are shown below. /* pmcx.h Created: 1993-12-14 Revised: 1994-09-18 */ /* PM Control Extensions (PMCX) */ /* Definitions Header */ /* Consult User's Guide for complete description of PM Control */ /* Extensions */ /* Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. */ /* -------------------------------------------------------------------- */ /* Function Prototypes (32-bit definition) */ /* ------------------- */ /* */ /* Control Initialization: */ /* */ /* BOOL EXPENTRY XxxxRegister(HAB hAB); */ /* */ /* Styles Dialogue Procedures: */ /* */ /* MRESULT EXPENTRY XxxxStyles(HWND hWnd, ULONG msg, */ /* MPARAM mp1, MPARAM mp2); */ /* */ /* Window Procedure: */ /* */ /* MRESULT EXPENTRY XxxxWndProc(HWND hWnd, ULONG msg, */ /* MPARAM mp1, MPARAM mp2); */ /* */ /* Control Information Procedure: */ /* */ /* BOOL EXPENTRY XxxxQuery(PUSERINFO pUserInfo); */ /* --- Constant Definitions ------------------------------------------- */ #define CTYPES 1 /* Maximum Number of User Types */ #define CCHCLASS 32 /* Maximum Classname Length */ #define CCHNAME 32 /* Maximum Name Length */ #define CCHAUTHOR 64 /* Maximum Author Name Length */ #define CCHDESC 32 /* Maximum Type Description Length */ #define CCHID 32 /* Maximum ID Symbol Length */ #define CCHTEXTMAX 512 /* Maximum Control Text Length */ #define UTYPE_PRIVATE 0x0002 /* Type: Private */ #define UTYPE_PUBLIC 0x0004 /* Type: Public */ #define USER_CWINDOWWORDS 8UL /* Control Reserved Memory Size */ #define QWW_USER (QWL_USER + 0UL) /* Pointer to User Data */ #define QWW_CDATA (QWL_USER + 4UL) /* Pointer to Private Data Pointer */ #define CUACHK_MNEMONIC 0 /* CUA Check: Mnemonic */ #define CUACHK_CAPS 1 /* CUA Check: Capitalization */ #define CUACHK_ELLIPSIS 2 /* CUA Check: Ellipsis */ #define STYLETYPE_BITFLAGS 0x0001 /* Style Type: Bit Flags */ #define STYLETYPE_SEQUENCE 0x0002 /* Style Type: Sequential */ #define PMCXOPT_NONE 0x00000000UL #define PMCXOPT_REFRESH 0x00000001UL #define PMCXOPT_VARICDATA 0x00000002UL #define PMCXOPT_STYLECHG 0x00000004UL #define PMCXOPT_TABABLE 0x00000008UL #define PMCXOPT_HELP 0x00000010UL /************************************************************************/ /************************************************************************/ /* */ /* PMCX 32-Bit Structure Definitions */ /* */ /************************************************************************/ /************************************************************************/ /* --- User Control Styles Structure ---------------------------------- */ typedef struct _STYLE /* st */ { /* Size: 8 bytes */ ULONG flStyleMask; /* Style Flag Mask */ ULONG idStyle; /* Resource String ID */ } STYLE ; /* --- User Control Type Structure ------------------------------------ */ typedef struct _USERTYPE /* ut */ { /* Size: 348 bytes */ LONG cx; /* Suggested Width of Control */ LONG cy; /* Suggested Height of Control */ ULONG flStyle; /* Initial Style Flags */ ULONG flOptions; /* Options Flag */ ULONG cMaxText; /* Maximum Text Required */ ULONG idDlg; /* Dialog ID */ ULONG idReserved; /* Reserved */ ULONG flStyleType; /* Style Type */ ULONG cCtlData; /* Control Data Count */ ULONG ulType; /* Control Type */ ULONG cMasks; /* Style Masks Count */ CHAR szDescription[CCHDESC];/* Control Name */ STYLE stMasks[32]; /* Style Masks Array */ ULONG aulReserved[4]; /* Reserved */ } USERTYPE ; /* --- User Control Information Structure ----------------------------- */ typedef struct _USERINFO /* ui */ { /* Size: 512 bytes */ ULONG ulMajor; /* Control Version Number: Major */ ULONG ulMinor; /* Control Version Number: Minor */ CHAR szAuthor[CCHAUTHOR]; /* Control Author */ CHAR szClassname[CCHCLASS];/* Classname */ CHAR szName[CCHNAME]; /* Library Name */ ULONG aulReserved[6]; /* Reserved */ ULONG cTypes; /* Number of Control Types Supported */ USERTYPE utDefined[CTYPES]; /* Define User Types Array */ } USERINFO ; typedef USERINFO *PUSERINFO; /* --- User Control Style Structure ----------------------------------- */ typedef struct _USERSTYLE /* ust */ { /* Size: 112 bytes */ PFN pfnSetSymbolID; /* Symbol/ID Set Function Address */ PFN pfnGetSymbolID; /* Symbol/ID Get Function Address */ PFN pfnGetFontClr; /* Font/Colours Function Address */ PFN pfnCUACheck; /* CUA Compliance Function Address */ PFN pfnRealloc; /* Reallocation Function Address */ ULONG flStyle; /* Style */ ULONG id; /* ID Value */ CHAR szid[CCHID]; /* ID Symbol */ PSZ pszText; /* Text Pointer */ ULONG cText; /* Text Count (Including NULL) */ PFN pfnGetBidi; /* Bidi Params Function Address */ ULONG aulReserved[8]; /* Reserved */ PBYTE pbCtlData; /* Variable Control Data Pointer */ ULONG cbCtlData; /* Control Data Size */ BYTE abCtlData[1]; /* Control Data */ } USERSTYLE ; typedef USERSTYLE *PUSERSTYLE; /* --- Macro Helpers for Setting or Retrieving User Style Pointer ------ */ #define PDATATODLG(hwndClient) ((WinSetWindowPtr(hwndClient, QWL_USER,\ (PVOID)mp2))) #define PDATAFROMDLG(hwndClient) (((PUSERSTYLE)WinQueryWindowPtr(hwndClient,\ QWL_USER))) There are a set of constant definitions, provided in the header, that you can use in your implementation of the PMCX control. They are a mixture of limits, options, flags, and service requests: Constant Definition CTYPES Defines the maximum length of the class name definition, including null terminating byte. CCHCLASS Defines the maximum length of the class name definition, including null terminating byte. CCHNAME Defines the maximum length of the control's name, including the null terminating byte. CCHAUTHOR Defines the maximum length of the author's name for the control, including null terminating byte. CCHDESC Defines the maximum length of the control's description, including the null terminating byte. CCHID Defines the maximum length of the ID symbol, including the null terminating byte. CCHTEXTMAX Defines the maximum length of text that can be defined for the control, including the null terminating byte. UTYPE_PRIVATE Defines the control as a private class; it must be registered specifically by the application before it is used. This registration is provided the XxxxRegister function within the DLL. UTYPE_PUBLIC Defines the control as a public class that has been registered with OS/2 Presentation Manager and does not need to be registered by the application. USER_CWINDOWWORDS Defines the minimum amount of reserved memory that must be allocated for the control when it is registered with OS/2 Presentation Manager. Additional reserved memory can be allocated by adding the value to the constant in the XxxxRegister function. QWW_USER Used as an index into the control's reserved memory, where the pointer to the user data is located. QWW_CDATA Used as an index into the control's reserved memory, where the pointer to the private control data memory allocated for the control is located. CUACHK_MNEMONIC Used as an option with the pfnCUACheck function to check the text of the control for CUA compliance in terms of mnemonic inclusion. CUACHK_CAPS Used as an option with the pfnCUACheck function to check the text of the control for CUA compliance in terms of capitalization. CUACHK_ELLIPSIS Used as an option with the pfnCUACheck function to check the text of the control for CUA compliance in terms of a space between the text and ellipsis. STYLETYPE_BITFLAGS Indicates that the style masks are bitflags and that the style generated in the resource script can be multiple values when bitwise compared to the style masks. STYLETYPE_SEQUENCE Indicates that the style masks are sequential in nature and that the styles generated within the resource script should be based on a single value that must match the style mask. PMCXOPT_NONE Indicates that no special options are required. PMCXOPT_REFRESH Indicates that the control should be refreshed through Prominare Designer, where Prominare Designer will delete the previous instance of the control and create a new one to show the revised styles selected. PMCXOPT_VARICDATA Indicates that the control supports variable length control data. PMCXOPT_STYLECHG Indicates that the control supports the changing of the style flags using the WinSetWindowULong function and the index of QWL_STYLE. PMCXOPT_TABABLE Indicates that the control supports tabbing and cursor movement selections. PMCXOPT_HELP Indicates that the control allows the help to be selected when it receives focus. Four structures are defined within the header. Three are used to describe the PMCX control to Prominare Designer; the fourth is used by Prominare Designer to communicate with the styles dialogue: Name Purpose STYLE Defines a control style mask and the corresponding resource file string table ID. Used by the USERTYPE structure. USERTYPE Defines the user control type. The information within the structure is for the default characteristics of the control, the ID of the dialogue template within the control's DLL for the styles dialogue, the room necessary for additional control data (i.e. picture masks, ranges, limits, etc.), control type, styles count, and style masks. Used by the USERINFO structure. USERINFO Defines information for the control initially queried by Prominare Designer to determine the capabilities of the control. The control's version number, author, class, and types are defined. Used only by the XxxxQuery function. USERSTYLE Used by Prominare Designer and the XxxxStyles functions to allow a method of communication regarding data information entered or edited through the dialogue procedure. The structure provides helper function addresses that can be used to reference the control's style, ID symbol and value, and text, and to control specific data. The STYLE structure is defined as: Field Purpose flStyleMask Contains a style flag mask for a possible style of the control. Should be in the form of 0x0000UL. The style mask must correspond with a resource string indicated in the idStyle field. idStyle Contains the ID of the resource string for the corresponding style mask in the flStyleMask field. The following is an example of how the structure is used: /* Constants definitions within an include header file */ #define EC_NORMALBORDER 0x0001L #define EC_THICKBORDER 0x0002L #define EC_NOBORDER 0x0004L #define IDS_NORMALBORDER 800 #define IDS_THICKBORDER 801 #define IDS_NOBORDER 802 /* Within source code file */ USERTYPE utExample; utExample.flStyleType = STYLETYPE_BITFLAGS; utExample.stMasks[0].flStyleMask = EC_NORMALBORDER; utExample.stMasks[0].idStyle = IDS_NORMALBORDER; utExample.stMasks[1].flStyleMask = EC_THICKBORDER; utExample.stMasks[1].idStyle = IDS_THICKBORDER; utExample.stMasks[2].flStyleMask = EC_NOBORDER; utExample.stMasks[2].idStyle = IDS_NOBORDER; /* Within resource script file */ STRINGTABLE BEGIN IDS_NORMALBORDER, "EC_NORMALBORDER" IDS_THICKBORDER, "EC_THICKBORDER" IDS_NOBORDER, "EC_NOBORDER" END The USERTYPE structure is defined as: Field Purpose cx Contains the suggested width of the control in dialogue units. This value will be used by Prominare Designer as the initial width of the control when it is added to a window or dialogue. cy Contains the suggested height of the control in dialogue units. This value will be used by Prominare Designer as the initial height of the control when it is added to a window or dialogue. flStyle Contains initial style flags of the control when it is created by Prominare Designer. flOptions Contains the options flag, which can be one of the PMCXOPT_* flags. cMaxText Contains the maximum number of characters that the control is capable of handling. This value is used by Prominare Designer to allocate space for the control text addressed in the pszText field in the USERSTYLE structure. idDlg Contains the resource ID of the styles dialogue displayed by Prominare Designer when the control is first added to a window or dialogue or when the user requests to edit the styles of the control. idReserved Reserved. flStyleType Contains the style type flag that indicates to Prominare Designer how the style masks should be interpreted when the resource script statement for the control is generated. The current style types defined are STYLETYPE_BITFLAGS for bitflag styles and STYLETYPE_SEQUENCE for sequential styles. cCtlData Contains the number of bytes that should be allocated for private data used by the control. This data is allocated by Prominare Designer and is addressed in the abCtlData field in the USER_STYLE structure. ulType Contains the control type, which may be either UTYPE_PRIVATE or UTYPE_PUBLIC. cMasks Contains the total count of style masks defined in stMasks field. szDescription[CCHDESC] Contains a short description that can be displayed by Prominare Designer. stMasks[32] Contains the control style flag masks and ID string values. aulReserved[4] Reserved. The following is an example of how the structure is used: USERTYPE utDefined; utDefined.cx = 50L; utDefined.cy = 12L; utDefined.flStyle = 0UL; utDefined.idDlg = Dialogue id; utDefined.ulType = UTYPE_PRIVATE; utDefined.cCtlData = 20UL; utDefined.cMasks = 2UL; utDefined.cMaxText = 5UL; utdefined.flStyleType = STYLETYPE_BITFLAGS; utDefined.stMasks[0].flStyleMask = 0x0001UL; utDefined.stMasks[0].idStyle = String id; utDefined.stMasks[1].flStyleMask = 0x0002UL; utDefined.stMasks[1].idStyle = String id; strcpy(utDefined.szDescription, "Description"); The USERINFO structure is defined as: Field Purpose ulMajor Contains the control's major version number. ulMinor Contains the control's minor version number. szAuthor[CCHAUTHOR] Contains the control's author name. szClassname[CCHCLASS] Contains the classname of the control. szName[CCHNAME] Contains the common name for the control. This name should correspond to the Xxxx component of the required functions as well as to the dynamic-link library name. aulReserved[6] Reserved. cTypes Contains the number of types supported by the control. In Version 1.0 of PMCX, only one type is allowed and this field must be 1. utDefined[CTYPES] Contains the type information of each of the controls supported by the control. In Version 1.0 of PMCX, only the first array element is used. The following is an example of how the structure is used: USERINFO uiControl; uiControl.ulMajor = 1UL; uiControl.ulMinor = 0UL; uiControl.cTypes = 1UL; strcpy(uiControl.szAuthor, "Author"); strcpy(uiControl.szClassname, "Classname"); strcpy(uiControl.szName, "Common Name"); uiControl.utDefined[0].cx = 50L; uiControl.utDefined[0].cy = 12L; uiControl.utDefined[0].flStyle = 0UL; uiControl.utDefined[0].idDlg = Dialogue id; uiControl.utDefined[0].ulType = UTYPE_PRIVATE; uiControl.utDefined[0].cCtlData = 20UL; uiControl.utDefined[0].cMasks = 2UL; uiControl.utDefined[0].cMaxText = 5UL; uiControl.utDefined[0].flStyleType = STYLETYPE_BITFLAGS; uiControl.utDefined[0].stMasks[0].flStyleMask = 0x0001UL; uiControl.utDefined[0].stMasks[0].idStyle = String id; uiControl.utDefined[0].stMasks[1].flStyleMask = 0x0002UL; uiControl.utDefined[0].stMasks[1].idStyle = String id; strcpy(uiControl.utDefined[0].szDescription, "Description"); The USERSTYLE structure is defined as: Field Purpose pfnSetSymbol Contains the function address for the function in Prominare Designer that sets the ID field symbol and value. pfnGetSymbol Contains the function address for the function in Prominare Designer that causes the ID field symbol and value to be validated and placed within the USERSTYLE structure. pfnGetFontClr Contains the function address for the Font & Colours dialogue. Prominare Designer internally records the font and colours selected by the user on behalf of the control. pfnCUACheck Contains the function address for the CUA Compliance checking function. Compliance for mnemonics, capitalization, and ellipsis can be checked via this function if the control supports any of these features. A value of TRUE is returned if non-compliance is determined. A value of FALSE is returned if the control is compliant. pfnRealloc Contains the function address for the control data reallocation function, which allows the control to reallocate the necessary control data memory when it supports variable control data. flStyle Contains the current style flags set for the control. id Contains the current ID value for the control. szid[CCHID] Contains the current ID symbol for the control. pszText Contains the address of the text for the control. cText Contains the count of characters for the control. pfnGetBidi Contains the function address for the Bidirectional Support dialogue. Prominare Designer internally records the bidirectional options selected by the user on behalf of the control. aulReserved[8] Reserved. pbCtlData Contains the variable control data buffer pointer. Used only when the control supports variable control data; used in place of the abCtlData field. cbCtlData Contains the size of the control data buffer pbCtlData when the control supports variable control data. abCtlData[1] First element of the private control data. When control data is used, the control should cast the appropriate structure to the address of the array, so it can easily address areas of the data. Two helper macros are defined in the header: Macro Purpose PDATATODLG Places the passed address of the USERSTYLE pointer in the dialogue's reserved memory. The passed address is contained within the second message parameters (MPARAM mp2) and must be placed in the dialogue's reserved memory when it receives the WM_INITDLG message. PDATAFROMDLG References the memory location in the dialogue procedure where the USERSTYLE pointer passed to the dialogue is placed. A pointer returned by the macro allows reference to the elements of the USERSTYLE structure. ═══ 7. PMCX construction ═══ The first item of concern is the naming convention. The best way to illustrate this is by considering the example below: Functions XxxxRegister XxxxQuery XxxxStyles Dynamic-Link Library Xxxx.DLL Xxxx is the common name for the control. (The common name should be restricted to eight letters to allow for FAT disk systems unless it is to be used specifically with HPFS disk systems.) The common name is allowed to be a maximum of 32 bytes long, including the NULL terminating character; the szName field of the USERINFO structure will accept only that number of characters. The second item of concern is who is responsible for allocating and de-allocating memory for the structures. Prominare Designer allocates and de-allocates the necessary memory for structures used to communicate with the PMCX control. It provides a pointer to the memory address of the structure and to the function when communication is required. It is the responsibility of the PMCX control's style function to save the address of the structure. Any pointers to memory elements within the structures are also allocated and deallocated by Prominare Designer on behalf of the control. The only exception is in the case of a control that allows for variable length control data. In this case, the control can, through a callback function to Prominare Designer, reallocate the control data memory. Since the PMCX control's dialogue procedure is responsible for saving the address of the USERSTYLE structure address passed to it by Prominare Designer, you can use the two helper macros defined by the styles dialogue procedure to save and retrieve the address. To save the USERSTYLE structure address in the QWL_USER reserved memory location of the dialogue's reserved memory, use the PDATATODLG macro. To retrieve the USERSTYLE structure address, use PDATAFROMDLG macro. To ensure the success of any PMCX control, you must encapsulate its use to permit multiple usage, which means that the control must be totally re-entrant. One way to do this is with dynamically allocated memory. Save this memory address within the control's reserved memory. These addresses can be referenced with the QWW_* indices. Prominare Designer provides a set of helper functions for the control's style dialogue, which ensure that the dialogue remains consistent with similar dialogues provided with Prominare Designer. These helper functions must give the control's dialogue access to the ID field, the Font & Colours dialogue, symbol verification, and CUA compliance. Prominare Designer must provide the addresses of these routines within the USERSTYLE structure in the following elements: Callback Purpose pfnSetSymbol ID field symbol and value set helper function pfnGetSymbol Symbol ID and value validation and retrieval helper function pfnGetFontClr Font and colours helper function pfnCUACheck CUA Compliance helper function pfnRealloc Memory reallocation function similar to C library function realloc( ) Prominare Designer constructs the necessary statements in the resource script on behalf of the PMCX control. In turn, the control must provide style masks and a string table containing the ASCII style definitions in its resources, if styles are permitted for the control. The style masks and ID values for the string that corresponds to the style masks are to be placed in the provided structure elements of the USERINFO structure, along with the count of masks. The control must also provide the number of control data bytes it requires through the USERINFO structure. This structure must be completed in the function XxxxQuery, through the structure address passed to the function when it is called by Prominare Designer. The functions defined for the control must be exported in the controls definition file. The name of the function should be entered along with an ordinal value. The following ordinals are required: Function Ordinal XxxxRegister 1 XxxxQuery 2 XxxxStyles 3 The following describes the use of each of the required functions of the PMCX control. ═══ 7.1. XxxxRegister ═══ ═══ 7.1.1. Purpose ═══ The XxxxRegister function is used to register a private control with OS/2 Presentation Manager. It is also used to provide any control specific initialization. ═══ 7.1.2. Prototype Definition ═══ BOOL EXPENTRY XxxxRegister(HAB hAB); ═══ 7.1.3. Upon entry ═══ hAB contains the calling application's anchor block handle. When the control is a UTYPE_PRIVATE, the function must register the control with OS/2 Presentation Manager using the WinRegisterClass function, as follows: WinRegisterClass(hAB, pszClassname, XxxxWndProc, CS_CLIPSIBLINGS | CS_SYNCPAINT | CS_SIZEREDRAW, USER_CWINDOWWORDS); Additional memory can be reserved for the control by adding the required value to the USER_CWINDOWWORDS constant. Additional class styles can also be defined for the control. The pszClassname must contain the classname of the control and be consistent with the value placed in the USERINFO structure element szClassname in the XxxxQuery function. The control can use other style flags as is appropriate. ═══ 7.1.4. Upon exit ═══ XxxxRegister must return a value of TRUE, denoting successful registration of the control with OS/2 Presentation Manager. A returned value of FALSE indicates that the control could not be registered and therefore should not be used. ═══ 7.2. XxxxQuery ═══ ═══ 7.2.1. Purpose ═══ The XxxxQuery function is called by Prominare Designer to determine the capabilities of the control and to receive information critical to its successful use within Prominare Designer. The USERINFO structure is completed through this function, in which Prominare Designer passes the function the address of the structure. ═══ 7.2.2. Prototype Definition ═══ BOOL EXPENTRY XxxxQuery (PUSERINFO pUserInfo); ═══ 7.2.3. Upon entry ═══ pUserInfo contains the address of the USERINFO structure allocated within Prominare Designer in which the XxxxQuery function can complete. The information placed within the structure is done as follows: pUserInfo->ulMajor = 1UL; pUserInfo->ulMinor = 0UL; pUserInfo->cTypes = 1UL; strcpy(pUserInfo->szAuthor, "Author"); strcpy(pUserInfo->szClassname, "Classname"); strcpy(pUserInfo->szName, "Common Name"); pUserInfo->utDefined[0].cx = 50L; pUserInfo->utDefined[0].cy = 12L; pUserInfo->utDefined[0].flStyle = 0UL; pUserInfo->utDefined[0].idDlg = Dialogue id; pUserInfo->utDefined[0].ulType = UTYPE_PRIVATE; pUserInfo->utDefined[0].cCtlData = 20UL; pUserInfo->utDefined[0].cMasks = 2UL; pUserInfo->utDefined[0].cMaxText = 5UL; pUserInfo->utDefined[0].flStyleType = STYLETYPE_BITFLAGS; pUserInfo->utDefined[0].stMasks[0].flStyleMask = 0x0001UL; pUserInfo->utDefined[0].stMasks[0].idStyle = String id; pUserInfo->utDefined[0].stMasks[1].flStyleMask = 0x0002UL; pUserInfo->utDefined[0].stMasks[1].idStyle = String id; strcpy(pUserInfo->utDefined[0].szDescription, "Description"); ═══ 7.2.4. Upon exit ═══ XxxxQuery must return a value of TRUE, denoting successful completion of the structure. A returned value of FALSE indicates that the structure was not completed and the control therefore should not be used. ═══ 7.3. XxxxStyles ═══ ═══ 7.3.1. Purpose ═══ The XxxxStyles function is the PMCX control's style dialogue used through Prominare Designer. ═══ 7.3.2. Prototype Definition ═══ MRESULT EXPENTRY XxxxStyles(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); ═══ 7.3.3. Upon entry ═══ Normal dialogue procedure coding except as noted in Special Considerations. below. ═══ 7.3.4. Upon exit ═══ XxxxStyles should return values consistent with normal dialogue procedures. ═══ 7.3.5. Special considerations ═══ During the processing of the WM_INITDLG message, the control should reference message parameter 2 (MPARAM mp2) as follows: PDATATODLG(hWnd); This causes the address of the USERSTYLE structure allocated within Prominare Designer to be saved in the dialogue's reserved memory. The dialogue can then reference the information in the USERSTYLE structure with the following method: pust = PDATAFROMDLG(hWnd); Also, the entry fields for the dialogue along with any styles should be completed during processing of the WM_INITDLG message. For example, with a control that supported text, the following could be used to fill in the Text and ID fields: if ( (pust = (PUSERSTYLE)mp2) != NULL ) { WinSetDlgItemText(hWnd, ID_TEXT, pust->szText); pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust); } When the dialogue is dismissed, the function must return either TRUE through the WinDismissDlg function, to indicate to Prominare Designer changes have been made to the USERSTYLE structure, or FALSE, to indicate that no changes were made. The USERSTYLE structure contains the addresses of the five Prominare Designer helper routines, defined as follows: VOID (EXPENTRY *pfnSetSymbolID)(HWND hWnd, ULONG idSymbol, PUSERSTYLE pust); BOOL (EXPENTRY *pfnGetSymbolID)(HWND hWnd, ULONG idSymbol, PUSERSTYLE pust); VOID (EXPENTRY *pfnGetFontClr)(HWND hWnd); BOOL (EXPENTRY *pfnCUACheck)(HWND hWnd, ULONG idEntryField, LONG iCUACompliance); BOOL (EXPENTRY *pfnRealloc)(PVOID pv, INT cSize); In this case, you would use the pfnSetSymbol in conjunction with the ID field. The function is used to set the symbol and value of the control within the ID field, as shown here: if ( (pust = (PUSERSTYLE)mp2) != NULL ) pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust); The pfnGetFontClr function allows the user to display the Font & Colours dialogue when he or she clicks on the Font & colours... button. The function allows the user to set the font and colours for the control, as shown here: case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { case ID_FONTCLR : if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) pust->pfnGetFontClr(hWnd); break; . . . } break; The pfnGetBidi function allows the user to display the Bidirectional Support dialogue when he or she clicks on the Bidi... button. The function allows the user to set the bidirectional options as shown here: case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { case ID_BIDI : if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) pust->pfnGetBidi(hWnd); break; . . . } break; Use the pfnGetSymbol function when the user tells the dialogue to accept the changes made. The function checks the values in the ID field for validity and displays any required error message boxes. If the function returns a value of FALSE, the dialogue procedure should not retrieve any changes made but should simply break the current processing, allowing the user to correct values within the dialogue as he or she sees fit. A return value of TRUE indicates that the dialogue should retrieve all changes made and save them in the USERSTYLE structure before dismissing the dialogue. The function also retrieves the ID symbol and value and places them in the USERSTYLE structure, as shown here: case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { case DID_OK : if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) if ( !pust->pfnGetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust) ) { . . /* Continue processing */ . WinDismissDlg(hWnd, TRUE); } break; . . . } break; Use the pfnCUACheck function when the user tells the dialogue to accept the changes made. Depending on the option selected, the function checks the values in the Text entry field for CUA compliance and displays any required error message boxes. If the function returns a value of FALSE, the dialogue procedure should not retrieve any changes made but should simply break the current processing, allowing the user to correct values in the dialogue as he or she sees fit. A return value of TRUE indicates that the dialogue should retrieve all changes made, saving them in the USERSTYLE structure before dismissing the , as shown here: case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { case DID_OK : if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) if ( pust->pfnCUACheck(hWnd, ID_TEXT, CUACHK_CAPS) ) break; else { . /* Continue processing */ . . WinDismissDlg(hWnd, TRUE); } break; . . } break; Finally, use the pfnRealloc function when the control allows variable-length control data and the user has indicated a wish to save the information for the control. You must use the function to reallocate the data buffer for the control data, since Prominare Designer controls memory allocation for the structures. The function utilizes the memory management routines of Prominare Designer; care must therefore be exercised so the function is not misused. Otherwise, Prominare Designer may develop a fatal unrecoverable error condition. The function is exactly like the C library realloc( ) function in usage. It is shown here: case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { case DID_OK : if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) { if ( !(pust->pbCtlData = (PBYTE)pust->pfnRealloc(pust->pbCtlData, sizeof(COMBOBOXCDATA) - 1L)) ) { WinMessageBox(HWND_DESKTOP, hWnd, "Memory error on reallocating control data!", "Super Combo Box Control", 0, MB_OK | MB_ICONEXCLAMATION); return(0L); } pust->cbCtlData = sizeof(COMBOBOXCDATA) - 1 + n; pcbd = (PCOMBOBOXCDATA)pust->pbCtlData; pcbd->cb = sizeof(COMBOBOXCDATA) - 1 + n; pcbd->cItems = cItems; memcpy(pcbd->abList, pchData, n); } break; . . } break; ═══ 8. DLL construction ═══ To correctly construct a custom control according to the PMCX, use the following outline: File Contents PMCX.H PMCX constants, macros, and structure definitions. This file is provided with the Prominare Designer package and can be found in the PD\Include sub-directory. Xxxx.Lnk Contains the link response file needed by the linker. Xxxx.C Contains source code for the custom code using PMCX. Xxxx.Def Contains the definition statements required by the linker to construct the final dynamic link library. Xxxx.Mak Contains the MAKE file necessary to create the object and resource files. Xxxx.Rc Contains the resource script file with the control's style dialogue template and styles string table. ═══ 9. Example control ═══ Following are listings of an example control provided with the Prominare Designer package. It is shown here to help you understand the construction of a PMCX control. A check mark control that allows the usage of a static control to denote if an option is selected or available, it is similar to a check box control except that the user does not interact with it. The final check mark styles dialogue is shown here: PMCX control Check Mark Styles dialogue The check mark control created and managed by the PMCX control DLL appears as: Check mark control appearance The following example control code shows the necessary methods defined by PMCX to successfully create a custom control that can be used within your own applications and Prominare Designer. #pragma title("Check Mark Control -- Version 1.00 -- (ChkMark.C)") #pragma subtitle(" Check Mark Control Control DLL - Interface Definitions") #pragma info(noext) #define INCL_GPI /* Include OS/2 PM GPI Interface */ #define INCL_WIN /* Include OS/2 PM Windows Interface */ static char *MODID = "@(#)chkmark.c:1.02"; #include #include #include #include "chkmark.h" /* This module contains an example installable control that can be used */ /* within applications where additional facilities are provided that */ /* are not found within the default controls of OS/2 PM. */ /* */ /* For complete details regarding the PM Control Extensions (PMCX) */ /* consult the User's Guide. */ /* */ /* The DLL is created using the following command line invocation: */ /* */ /* Icc -G3e- -O+ -Rn -W3 -C ChkMark.C */ /* Filename: ChkMark.C */ /* Version: 1.00 */ /* Created: 1993-12-21 */ /* Revised: 1994-09-18 */ /* Routines: BOOL EXPENTRY ChkMarkRegister(HAB hAB); */ /* BOOL EXPENTRY ChkMarkQuery(PUSERINFO pUserInfo); */ /* MRESULT EXPENTRY ChkMarkWndProc(HWND hWnd, ULONG msg, */ /* MPARAM mp1, MPARAM mp2); */ /* MRESULT EXPENTRY ChkMarkStyles(HWND hWnd, ULONG msg, */ /* MPARAM mp1, MPARAM mp2); */ /* Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. */ /* -------------------------------------------------------------------- */ /************************************************************************/ /************************************************************************/ /* DISCLAIMER OF WARRANTIES. */ /************************************************************************/ /************************************************************************/ /* The following [enclosed] code is library code created by */ /* Prominare Inc. This library code is provided to you solely */ /* for the purpose of assisting you in the development of your */ /* applications. The code is provided "AS IS", without */ /* warranty of any kind. Prominare Inc. shall not be liable */ /* for any damages arising out of your use of the library code, */ /* even if they have been advised of the possibility of such */ /* damages. */ /************************************************************************/ /************************************************************************/ /* --- Control Data Structures ---------------------------------------- */ typedef struct _CHECKMARK /* cmrk */ { HWND hwndOwner; /* Owner Window Handle */ CHAR szText[512]; /* Text Holder */ BOOL fChecked; /* Check Mark State Flag */ RECTL rclChecked; /* Bitmap Rectangle Checked */ RECTL rclUnChecked; /* Bitmap Rectangle UnChecked */ POINTL ptlChkMark; /* Bitmap Rectangle UnChecked */ POINTL ptlText; /* Text Display Point */ RECTL rclText; /* Text Display Rectangle */ RECTL rcl; /* Bitmap Display Rectangle */ HBITMAP hbm; /* Check Mark Bitmap Handle */ LONG aClr[7]; /* Presentation Colours Array */ } CHECKMARK ; typedef CHECKMARK *PCHECKMARK; /* --- Module Prototype Definitions ----------------------------------- */ static VOID SetDefaultColours(HWND hWnd, PCHECKMARK pcmrk); static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG ulID2, LONG lDefault); BOOL EXPENTRY ChkMarkRegister(HAB hAB); BOOL EXPENTRY ChkMarkQuery(PUSERINFO pUserInfo); MRESULT EXPENTRY ChkMarkWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); MRESULT EXPENTRY ChkMarkStyles(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); #define CLENpszClassname 10 static PSZ pszClassname = "CheckMark"; static HMODULE hmodDLL; #pragma subtitle(" Check Mark Control - DLL Initialization/Termination Procedure") #pragma page( ) /* --- _Dll_InitTerm ----------------------------------- [ Public ] --- */ /* */ /* This function is used to provide the DLL initialization and */ /* termination. The function is called by the C startup code */ /* and allows the control to register itself and provide any */ /* necessary startup. */ /* */ /* This function is designed for IBM C Set/2 Version 1.0 and */ /* IBM C Set++ Version 2.x */ /* */ /* Upon Entry: */ /* */ /* ULONG hModule; = DLL Module Handle */ /* ULONG fl; = Startup / Termination Flag */ /* */ /* Upon Exit: */ /* */ /* _Dll_InitTerm = 0 : Error Return */ /* = 1 : Successful Startup / Termination */ /* */ /* -------------------------------------------------------------------- */ ULONG _System _Dll_InitTerm(ULONG hModule, ULONG fl) { /* Determine if in startup or termination mode */ if ( fl == 0 ) /* DLL being initialized, save the DLL module */ /* handle to allow the bitmap loading routines */ /* routines a means of loading the default */ /* bitmaps when required */ hmodDLL = hModule; return(1UL); } #pragma subtitle(" Check Mark Control DLL - Control Initialization Function") #pragma page ( ) /* --- ChkMarkInit ------------------------------------- [ Public ] --- */ /* */ /* This function is used to register the installable control class */ /* with OS/2 Presentation Manager. The registration must use the */ /* USER_CWINDOWWORDS to reserve memory for the control to allow for */ /* proper usage by Resource Editor and for use by the control */ /* dialog and window procedures. The information for the control */ /* containing the style, Font & Colours and control data */ /* is pointed to by a pointer that can be referenced by the */ /* control's dialog and window procedure as required. The memory */ /* for the structure is allocated and controlled through Resource */ /* Editor. The control can reserve more memory for its use */ /* by adding the memory required to that of the USER_CWINDOWWORDS */ /* constant. */ /* */ /* Upon Entry: */ /* */ /* HAB hAB; = Application Anchor Block Handle */ /* */ /* Upon Exit: */ /* */ /* ChkMarkInit = TRUE : Class Registration Successful */ /* = FALSE : Class Registration Failed */ /* */ /* -------------------------------------------------------------------- */ BOOL EXPENTRY ChkMarkRegister(HAB hAB) { /* Register the control class with OS/2 */ /* Presentation Manager and return registration */ /* result */ return(WinRegisterClass(hAB, pszClassname, ChkMarkWndProc, CS_SYNCPAINT | CS_SIZEREDRAW, USER_CWINDOWWORDS)); } #pragma subtitle(" Check Mark Control DLL - Query Control Information Function") #pragma page ( ) /* --- ChkMarkQuery ------------------------------------ [ Public ] --- */ /* */ /* This function is used to return to the caller information */ /* regarding the installable control and its capabilities. The */ /* function should return a true value otherwise Resource */ /* Editor will not register the control as being usable. */ /* */ /* Upon Entry: */ /* */ /* PUSERINFO pUserInfo; = User Information Pointer */ /* */ /* Upon Exit: */ /* */ /* ChkMarkQuery = TRUE : User Information Being Returned */ /* = FALSE : No User Information Available */ /* */ /* -------------------------------------------------------------------- */ BOOL EXPENTRY ChkMarkQuery(PUSERINFO pUserInfo) { /* Complete the User Information structure */ /* passed to the function by Resource Editor */ /* Complete the version and number of control */ /* types. In Version 1.00 of CCRS, only one */ /* control type is used. */ pUserInfo->ulMajor = 2UL; pUserInfo->ulMinor = 0UL; /* Complete the author and control classname */ memcpy(pUserInfo->szAuthor, "Prominare Inc.", 15); memcpy(pUserInfo->szClassname, pszClassname, CLENpszClassname); memcpy(pUserInfo->szName, "ChkMark", 8); /* Complete the default size and style of the */ /* first user control type */ pUserInfo->utDefined[0].cx = 25L; pUserInfo->utDefined[0].cy = 10L; pUserInfo->utDefined[0].flStyle = WS_VISIBLE; /* Set the maximum amount of text control can */ /* accept including NULL termination byte */ pUserInfo->utDefined[0].cMaxText = CCHTEXTMAX; /* Save the style's dialogue ID, type, control */ /* data size and count of style masks */ pUserInfo->utDefined[0].idDlg = DLG_CTRLUSER; pUserInfo->utDefined[0].flOptions = PMCXOPT_REFRESH; pUserInfo->utDefined[0].ulType = UTYPE_PRIVATE; pUserInfo->utDefined[0].cCtlData = 0UL; pUserInfo->utDefined[0].cMasks = 1UL; pUserInfo->utDefined[0].flStyleType = STYLETYPE_BITFLAGS; pUserInfo->utDefined[0].stMasks[0].flStyleMask = CMS_CHECKED; pUserInfo->utDefined[0].stMasks[0].idStyle = IDS_CMS_CHECKED; /* Save the description of the control */ memcpy(pUserInfo->utDefined[0].szDescription, "Check Mark", 11); /* Return the success flag back to Resource */ /* Editor */ return(TRUE); } #pragma subtitle(" Check Mark Control DLL - Control Window Procedure") #pragma page( ) /* --- lGetPresParam ---------------------------------- [ Private } --- */ /* */ /* This function is used to retrieve a Font & Colours */ /* that may be present. If the Font & Colours is not, */ /* the default colour passed to the function will be used. */ /* */ /* Upon Entry: */ /* */ /* HWND hWnd; = Window Handle */ /* ULONG ulID1; = Font & Colours 1 ID */ /* ULONG ulID2; = Font & Colours 2 ID */ /* LONG lDefault; = Default Colour */ /* */ /* Upon Exit: */ /* */ /* lGetPresParam = Colour to Use */ /* */ /* -------------------------------------------------------------------- */ LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG ulID2, LONG lDefault) { HPS hPS; /* Presentation Space Handle */ LONG lClr; /* Font & Colours Colour */ ULONG ulID; /* Font & Colours ID */ if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, 4UL, (PVOID)&lClr, QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) ) return(lClr); else if ( (lDefault >= SYSCLR_SHADOWHILITEBGND) && (lDefault <= SYSCLR_HELPHILITE) ) return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L)); else if ( (lClr = GpiQueryRGBColor(hPS = WinGetPS(hWnd), LCOLOPT_REALIZED, lDefault)) == GPI_ALTERROR ) { WinReleasePS(hPS); return(lDefault); } else { WinReleasePS(hPS); return(lClr); } } #pragma subtitle(" Check Mark Control DLL - Default Colours Procedure") #pragma page( ) /* --- SetDefaultColours ------------------------------ [ Private ] --- */ /* */ /* This function is used to set the default colours that the */ /* image button should use within the internal paint routines. */ /* The colour can either be a Font & Colours that has */ /* been set or it can be the default colour as defined within */ /* control. */ /* */ /* Upon Entry: */ /* */ /* HWND hWnd; = Window Handle */ /* PCHECKMARK pcmrk; = Check Mark Structure Pointer */ /* */ /* Upon Exit: */ /* */ /* Nothing */ /* */ /* -------------------------------------------------------------------- */ static VOID SetDefaultColours(HWND hWnd, PCHECKMARK pcmrk) { /* Set up the colours that will be used within */ /* the painting of the control. The colour */ /* indices are: */ /* */ /* 0 : Foreground (PP_FOREGROUND*) */ /* 1 : Background (PP_BACKGROUND*) */ /* 2 : Hilight Foreground (PP_HILITEFOREGROUND*) */ /* 3 : Hilight Background (PP_HILITEBACKGROUND*) */ /* 4 : Disabled Foreground (PP_DISABLEDFORE*) */ /* 5 : Disabled Foreground (PP_DISABLEDFORE*) */ /* 6 : Border (PP_BORDER*) */ pcmrk->aClr[0] = lGetPresParam(hWnd, PP_FOREGROUNDCOLOR, PP_FOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); pcmrk->aClr[1] = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR, PP_BACKGROUNDCOLORINDEX, SYSCLR_FIELDBACKGROUND); pcmrk->aClr[2] = lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR, PP_HILITEFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); pcmrk->aClr[3] = lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR, PP_HILITEBACKGROUNDCOLORINDEX, SYSCLR_BACKGROUND); pcmrk->aClr[4] = lGetPresParam(hWnd, PP_DISABLEDFOREGROUNDCOLOR, PP_DISABLEDFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); pcmrk->aClr[5] = lGetPresParam(hWnd, PP_DISABLEDBACKGROUNDCOLOR, PP_DISABLEDBACKGROUNDCOLORINDEX, SYSCLR_BACKGROUND); pcmrk->aClr[6] = lGetPresParam(hWnd, PP_BORDERCOLOR, PP_BORDERCOLORINDEX, SYSCLR_BUTTONDARK); } #pragma subtitle(" Check Mark Control DLL - Display Point Calculation Procedure") #pragma page ( ) /* --- CalcDisplayPoints ------------------------------ [ Private ] --- */ /* */ /* This function is used to calculate the display points for the */ /* installed control. */ /* */ /* Upon Entry: */ /* */ /* PCHECKMARK pcmrk; = Control Data Structure Pointer */ /* LONG cx; = control Width */ /* LONG cy; = Control Height */ /* */ /* Upon Exit: */ /* */ /* Nothing */ /* */ /* -------------------------------------------------------------------- */ static VOID CalcDisplayPoints(HWND hWnd, PCHECKMARK pcmrk, LONG cx, LONG cy) { BITMAPINFOHEADER bmp; /* Bitmap Information Holder */ HPS hPS; /* Presentation Space Handle */ FONTMETRICS fm; /* Font Metrics */ GpiQueryBitmapParameters(pcmrk->hbm, &bmp); GpiQueryFontMetrics(hPS = WinGetPS(hWnd), sizeof(FONTMETRICS), &fm); WinReleasePS(hPS); pcmrk->rclChecked.xRight = bmp.cx; pcmrk->rclChecked.xLeft = (bmp.cx = (USHORT)(bmp.cx / 2)); pcmrk->rclUnChecked.xRight = bmp.cx; pcmrk->rclChecked.yTop = pcmrk->rclUnChecked.yTop = bmp.cy; pcmrk->ptlChkMark.y = cy / 2L - bmp.cy / 2L; pcmrk->ptlText.x = bmp.cx + fm.lAveCharWidth / 2L; pcmrk->ptlText.y = (cy / 2L) - (fm.lMaxBaselineExt / 2L) + fm.lMaxDescender; pcmrk->rclText.xLeft = bmp.cx; pcmrk->rclText.xRight = cx; pcmrk->rclText.yTop = cy; pcmrk->rcl.xRight = cx; pcmrk->rcl.yTop = cy; } #pragma subtitle(" Check Mark Control DLL - 3D Text Window Procedure") #pragma page ( ) /* --- ChkMarkWndProc --------------------------------- [ Private ] --- */ /* */ /* This function is used to handle the messages sent to the */ /* installed control. The window procedure is designed to */ /* allow for multiple instances and to be totally re-entrant. */ /* */ /* Upon Entry: */ /* */ /* HWND hWnd; = Window Handle */ /* ULONG msg; = PM Message */ /* MPARAM mp1; = Message Parameter 1 */ /* MPARAM mp2; = Message Parameter 2 */ /* */ /* Upon Exit: */ /* */ /* ChkMarkWndProc = Message Handling Result */ /* */ /* -------------------------------------------------------------------- */ MRESULT EXPENTRY ChkMarkWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { HPS hPS; /* Presentation Space Handle */ PCREATESTRUCT pcrst; /* Create Structure Pointer */ PCHECKMARK pcmrk; /* Check Mark Structure Pointer */ PWNDPARAMS pwprm; /* Window Parameters Pointer */ switch ( msg ) { /* Perform control initialization when the */ /* control is created */ case WM_CREATE : /* Create a heap for the control using a */ /* segment */ DosAllocMem((PPVOID)(PVOID)&pcmrk, 4096UL, PAG_READ | PAG_WRITE | PAG_COMMIT); /* Save the address of the text string pointer */ /* in the control's reserved memory to allow it */ /* to be referenced as required by the control */ WinSetWindowPtr(hWnd, QWW_CDATA, (PVOID)pcmrk); /* Get the control's creation structure address */ /* to copy the default text of the control to */ /* the memory in the heap */ pcrst = (PCREATESTRUCT)PVOIDFROMMP(mp2); pcmrk->hwndOwner = pcrst->hwndOwner; if ( pcrst->flStyle & CMS_CHECKED ) pcmrk->fChecked = TRUE; /* Set up the colours that will be used within */ /* the painting of the control. The colour */ /* indices are: */ /* */ /* 0 : Foreground (PP_FOREGROUND*) */ /* 1 : Background (PP_BACKGROUND*) */ /* 2 : Hilight Foreground (PP_HILITEFOREGROUND*) */ /* 3 : Hilight Background (PP_HILITEBACKGROUND*) */ /* 4 : Disabled Foreground (PP_DISABLEDFORE*) */ /* 5 : Disabled Foreground (PP_DISABLEDFORE*) */ /* 6 : Border (PP_BORDER*) */ SetDefaultColours(hWnd, pcmrk); if ( pcrst->pszText ) strcpy(pcmrk->szText, pcrst->pszText); pcmrk->hbm = GpiLoadBitmap(hPS = WinGetPS(hWnd), hmodDLL, IDB_CHECKMARKS, 0L, 0L); WinReleasePS(hPS); CalcDisplayPoints(hWnd, pcmrk, pcrst->cx, pcrst->cy); break; case WM_SIZE : /* Text being set, get the address of the text */ /* string stored in the heap */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); CalcDisplayPoints(hWnd, pcmrk, (LONG)(SHORT)SHORT1FROMMP(mp2), (LONG)(SHORT)SHORT2FROMMP(mp2)); break; /* Process window parameters setting */ case WM_SETWINDOWPARAMS : /* Get the address for the windows parameters */ /* structure */ pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1); /* Check to see if the text for the control is */ /* being set */ if ( pwprm->fsStatus & WPM_TEXT ) { /* Text being set, get the address of the text */ /* string stored in the heap */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); /* Check to see if any text is being set */ if ( pwprm->cchText ) /* Check to make sure that the text that is to */ /* be set is not greater than the memory */ /* allocated */ if ( pwprm->cchText > 511 ) { strncpy(pcmrk->szText, pwprm->pszText, 511); pcmrk->szText[511] = 0; } else strcpy(pcmrk->szText, pwprm->pszText); else /* No text is being set, clear any existing text */ pcmrk->szText[0] = 0; } break; /* Process window parameters query */ case WM_QUERYWINDOWPARAMS : /* Get the address for the windows parameters */ /* structure */ pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1); /* Determine the type of query */ switch ( pwprm->fsStatus ) { /* Query type: get text */ case WPM_TEXT : /* Text being asked for, get the address of the */ /* text string stored in the heap */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); /* Copy the text from the string to the */ /* structure */ strcpy(pwprm->pszText, pcmrk->szText); break; /* Query type: get text length */ case WPM_CCHTEXT : /* Text length being asked for, get the address */ /* of the text string stored in the heap */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); /* Place the length the string within the */ /* structure */ pwprm->cchText = (ULONG)strlen(pcmrk->szText); break; /* Query type: get control data length */ case WPM_CBCTLDATA : /* Set the control data length to zero */ pwprm->cbCtlData = 0; break; default : return(WinDefWindowProc(hWnd, msg, mp1, mp2)); } break; /* Font & Colours changed, record the */ /* change internally */ case WM_PRESPARAMCHANGED : /* Check to see if an individual presentation */ /* parameter has changed if so, get the new */ /* colour value for use by the painting routines */ if ( LONGFROMMP(mp1) && (LONGFROMMP(mp1) < PP_FONTNAMESIZE) ) { /* Get the address of the control info from the */ /* control's reserved memory */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); /* Get the new Font & Colours colour for */ /* the Font & Colours that has changed. */ /* Get the colour as a RGB value so as to be */ /* able to get an exact value and not an */ /* approximation which could happen if the */ /* Font & Colours was set as a RGB but */ /* queried as an index. When WinQueryPresParam */ /* returns a 0, it indicates that no */ /* Font & Colours set and the default */ /* colours should be used. */ switch ( LONGFROMMP(mp1) ) { case PP_FOREGROUNDCOLOR : case PP_FOREGROUNDCOLORINDEX : pcmrk->aClr[0] = lGetPresParam(hWnd, PP_FOREGROUNDCOLOR, PP_FOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); break; case PP_BACKGROUNDCOLOR : case PP_BACKGROUNDCOLORINDEX : pcmrk->aClr[1] = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR, PP_BACKGROUNDCOLORINDEX, SYSCLR_DIALOGBACKGROUND); break; case PP_HILITEFOREGROUNDCOLOR : case PP_HILITEFOREGROUNDCOLORINDEX : pcmrk->aClr[2] = lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR, PP_HILITEFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); break; case PP_HILITEBACKGROUNDCOLOR : case PP_HILITEBACKGROUNDCOLORINDEX : pcmrk->aClr[3] = lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR, PP_HILITEBACKGROUNDCOLORINDEX, SYSCLR_DIALOGBACKGROUND); break; case PP_DISABLEDFOREGROUNDCOLOR : case PP_DISABLEDFOREGROUNDCOLORINDEX : pcmrk->aClr[4] = lGetPresParam(hWnd, PP_DISABLEDFOREGROUNDCOLOR, PP_DISABLEDFOREGROUNDCOLORINDEX, SYSCLR_OUTPUTTEXT); break; case PP_DISABLEDBACKGROUNDCOLOR : case PP_DISABLEDBACKGROUNDCOLORINDEX : pcmrk->aClr[5] = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR, PP_BACKGROUNDCOLORINDEX, SYSCLR_DIALOGBACKGROUND); break; case PP_BORDERCOLOR : case PP_BORDERCOLORINDEX : pcmrk->aClr[6] = lGetPresParam(hWnd, PP_BORDERCOLOR, PP_BORDERCOLORINDEX, SYSCLR_BUTTONDARK); break; } /* Invalidate the button to force to use the */ /* new colours just set or removed */ WinInvalidateRect(hWnd, (PRECTL)NULL, TRUE); } else /* Determine if the Scheme Palette has forced a */ /* global scheme update in which case, check all */ /* of the Font & Colours to see if they */ /* have been added or removed */ if ( LONGFROMMP(mp1) == 0L ) /* Set up the colours that will be used within */ /* the painting of the control. */ SetDefaultColours(hWnd, pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA)); break; /* Mouse being passed over the control, imply */ /* that the control is transparent to the */ /* system */ case WM_HITTEST : return(MRFROMLONG(HT_TRANSPARENT)); /* Erase control background */ case WM_ERASEBACKGROUND : return(MRFROMLONG(TRUE)); case CKM_SETCHECK : /* Get the address of the text from the */ /* control's reserved memory */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); pcmrk->fChecked = (BOOL)LONGFROMMP(mp1); WinInvalidateRect(hWnd, (PRECTL)NULL, TRUE); break; /* Paint the Control */ case WM_PAINT : /* Get the address of the text from the */ /* control's reserved memory */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); /* Get the presentation space for the control */ /* and set the colour table to RGB mode */ GpiCreateLogColorTable(hPS = WinBeginPaint(hWnd, (HPS)NULL, (PRECTL)NULL), 0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL); WinFillRect(hPS, &pcmrk->rcl, pcmrk->aClr[1]); WinDrawBitmap(hPS, pcmrk->hbm, pcmrk->fChecked ? &pcmrk->rclChecked : &pcmrk->rclUnChecked, &pcmrk->ptlChkMark, 0L, 0L, DBM_IMAGEATTRS | DBM_NORMAL); GpiCharStringPosAt(hPS, &pcmrk->ptlText, &pcmrk->rclText, CHS_CLIP, (LONG)strlen(pcmrk->szText), pcmrk->szText, NULL); WinEndPaint(hPS); break; /* Control being destroyed */ case WM_DESTROY : /* Get the address of the text from the */ /* control's reserved memory */ pcmrk = (PCHECKMARK)WinQueryWindowPtr(hWnd, QWW_CDATA); GpiDeleteBitmap(pcmrk->hbm); /* Release the heap allocated for use by the */ /* control */ DosFreeMem((PVOID)pcmrk); break; /* Default message processing */ default : return(WinDefWindowProc(hWnd, msg, mp1, mp2)); } return(0L); } #pragma subtitle(" Check Mark Control DLL - Control Styles Dialogue Procedure") #pragma page ( ) /* --- ChkMarkStyles -------------------------------------------------- */ /* */ /* This function is used for the custom control's styles dialogue */ /* box procedure. */ /* */ /* When the dialogue is invoked from Resource Editor, the */ /* address of the user style information is contained in message */ /* parameter 2. The dialogue is responsible for saving the */ /* address. The best method to do this is to save the pointer */ /* in the dialogue's reserved memory where it can be retrieved as */ /* needed. */ /* */ /* Upon Entry: */ /* */ /* HWND hWnd; = Dialog Window Handle */ /* ULONG msg; = PM Message */ /* MPARAM mp1; = Message Parameter 1 */ /* MPARAM mp2; = Message Parameter 2 */ /* */ /* Upon Exit: */ /* */ /* ChkMarkStyles = Message Handling Result */ /* */ /* -------------------------------------------------------------------- */ MRESULT EXPENTRY ChkMarkStyles(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { PUSERSTYLE pust; /* User Style Pointer */ SWP swp; /* Screen Window Position Holder */ switch ( msg ) { /* Perform dialogue initialization */ case WM_INITDLG : /* Save the pointer to user style information */ /* within the dialog's reserved memory */ WinSetWindowPtr(hWnd, QWL_USER, (PVOID)mp2); /* Get the pointer to the user style information */ if ( (pust = (PUSERSTYLE)mp2) != NULL ) { /* Set the text, ID symbol and value for the */ /* control */ WinSetDlgItemText(hWnd, EF_TEXT, pust->pszText); pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust); if ( pust->flStyle & CMS_CHECKED ) WinSendDlgItemMsg(hWnd, CB_CMS_CHECKED, BM_SETCHECK, MPFROMSHORT(TRUE), 0L); if ( pust->flStyle & WS_VISIBLE ) WinSendDlgItemMsg(hWnd, CB_VISIBLE, BM_SETCHECK, MPFROMSHORT(TRUE), 0L); if ( pust->flStyle & WS_GROUP ) WinSendDlgItemMsg(hWnd, CB_GROUP, BM_SETCHECK, MPFROMSHORT(TRUE), 0L); if ( pust->flStyle & WS_DISABLED ) WinSendDlgItemMsg(hWnd, CB_DISABLED, BM_SETCHECK, MPFROMSHORT(TRUE), 0L); if ( pust->flStyle & WS_TABSTOP ) WinSendDlgItemMsg(hWnd, CB_TABSTOP, BM_SETCHECK, MPFROMSHORT(TRUE), 0L); } /* Centre dialog on the screen */ WinQueryWindowPos(hWnd, (PSWP)&swp); WinSetWindowPos(hWnd, HWND_TOP, (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN) - swp.cx) / 2L, (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - swp.cy) / 2L, 0L, 0L, SWP_MOVE); break; /* Process push button selections */ case WM_COMMAND : switch ( SHORT1FROMMP(mp1) ) { /* Font & Colours push button selected */ case DID_PRESPARAM : /* Get the pointer to the user style information */ if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) /* Get the address of the look up function from */ /* user style information structure and display */ /* the dialog. The value selected within the */ /* dialogue will be automatically placed within */ /* the required entry fields */ pust->pfnGetFontClr(hWnd); break; /* Bidi push button selected */ case DID_BIDI : /* Get the pointer to the user style information */ if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) /* Get the address of the look up function from */ /* user style information structure and display */ /* the dialog. The value selected within the */ /* dialogue will be automatically placed within */ /* the required entry fields */ pust->pfnGetBidi(hWnd); break; /* Enter push button selected get the */ /* definitions for the control */ case DID_OK : /* Get the pointer to the user style information */ if ( (pust = PDATAFROMDLG(hWnd)) != NULL ) { /* Get the address of the CUA compliance */ /* function from the user style information */ /* structure. The function will check the text */ /* for CUA compliance according to index value */ /* selected. A return value of TRUE from the */ /* compliance function indicates that the text */ /* entered is acceptable. Conversely, a FALSE */ /* return value indicates that text is non- */ /* compliant. In this case, the dialogue should */ /* not be exited from and the values within the */ /* the entry fields should not be saved. */ if ( !pust->pfnCUACheck(hWnd, EF_TEXT, CUACHK_CAPS) ) break; /* Get the address of the symbol validation */ /* function from the user style information */ /* structure. The function will validate the */ /* symbol and will check for duplications of */ /* values. A return value of TRUE from the */ /* validation function indicates that the symbol */ /* and value are acceptable. Conversely, a */ /* FALSE return value indicates that symbol or */ /* value was not acceptable. In this case, */ /* the dialogue should not be exited from and */ /* the values within the entry fields should not */ /* be saved. */ if ( !pust->pfnGetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust) ) break; else { /* Symbol and value validated, get the text of */ /* the control and save within the user style */ /* information structure for use by Resource */ /* Editor */ pust->cText = WinQueryDlgItemText(hWnd, EF_TEXT, CCHTEXTMAX, pust->pszText); /* Mask out current edit field styles clearing */ /* selectable styles and save new style */ pust->flStyle = 0UL; /* Get raised/depressed style */ if ( SHORT1FROMMR(WinSendDlgItemMsg(hWnd, CB_CMS_CHECKED, BM_QUERYCHECK, 0L, 0L)) ) pust->flStyle |= CMS_CHECKED; /* Save completed edit field style in internal */ /* window information */ if ( WinSendDlgItemMsg(hWnd, CB_VISIBLE, BM_QUERYCHECK, 0L, 0L) ) pust->flStyle |= WS_VISIBLE; if ( WinSendDlgItemMsg(hWnd, CB_GROUP, BM_QUERYCHECK, 0L, 0L) ) pust->flStyle |= WS_GROUP; if ( WinSendDlgItemMsg(hWnd, CB_DISABLED, BM_QUERYCHECK, 0L, 0L) ) pust->flStyle |= WS_DISABLED; if ( WinSendDlgItemMsg(hWnd, CB_TABSTOP, BM_QUERYCHECK, 0L, 0L) ) pust->flStyle |= WS_TABSTOP; } } /* Exit the dialogue indicating changes made */ WinDismissDlg(hWnd, TRUE); break; /* Cancel selected, exit the dialogue without */ /* changing anything */ case DID_CANCEL : WinDismissDlg(hWnd, FALSE); break; } break; /* Close received, exit dialog */ case WM_CLOSE : WinDismissDlg(hWnd, FALSE); break; /* Pass through unhandled messages */ default : return(WinDefDlgProc(hWnd, msg, mp1, mp2)); } return(0L); } The constants header file is defined below. The constants used by Prominare Designer, ChkMark.Rc and ChkMark.C, reference the controls in the styles dialogue. /* chkmark.h Created: 1993-12-21 Revised: 1994-09-18 */ /* PMCX Control Constants Header */ /* Copyright й 1989-1994 Prominare Inc. All Rights Reserved. */ #define CMS_CHECKED 0x0001L #define CKM_SETCHECK (WM_USER + 128UL) /* --- Miscellaneous Constants ---------------------------------------- */ #define DID_HELP 3 /* Help Push Button ID */ #define DID_FONTCLR 11 /* Font & Colours Push Button ID */ #define DID_BIDI 12 /* Bidi Push Button ID */ #define CB_VISIBLE 256 /* Visible Check Box ID */ #define CB_GROUP 257 /* Group Check Box ID */ #define CB_DISABLED 258 /* Disabled Check Box ID */ #define CB_TABSTOP 259 /* Tab Stop Check Box ID */ /* --- Control Dialogue ----------------------------------------------- */ #define DLG_CTRLUSER 1000 /* User Defined Dialog */ #define CB_CMS_CHECKED 4042 /* Left Aligned Radio Button */ #define EF_TEXT 4051 /* Text Edit Field */ #define IDBX_SYMBOLVALUE 4053 /* ID Value Edit Field */ /* --- Styles String ID's --------------------------------------------- */ #define IDS_CMS_CHECKED 512 /* --- Bitmap ID's ---------------------------------------------------- */ #define IDB_CHECKMARKS 784 The resource file for the style dialogue is shown below. /* PMCX Example Created: 1994-06-26 */ /* Resource File Revised: 1994-08-12 */ /* Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. */ #define INCL_WINSYS #define INCL_WINSTDDLGS #define INCL_WINSTDSPIN #define INCL_NLS #define INCL_SW #include #include "chkmark.h" /* --- Custom Control Styles Dialogue --------------------------------- */ BITMAP IDB_CHECKMARKS ChkMark.Bmp DLGTEMPLATE DLG_CTRLUSER 850 BEGIN DIALOG "Check Mark Styles", DLG_CTRLUSER, 22, 62, 220, 121, FS_NOBYTEALIGN | FS_DLGBORDER | WS_CLIPSIBLINGS | WS_SAVEBITS | WS_VISIBLE, FCF_TITLEBAR | FCF_SYSMENU PRESPARAMS PP_FONTNAMESIZE, "8.Helv" BEGIN CONTROL "Select style and type text and ID symbol.", -1, 5, 110, 123, 8, WC_STATIC, SS_TEXT | DT_VCENTER | WS_GROUP | WS_VISIBLE PRESPARAMS PP_FOREGROUNDCOLORINDEX, CLR_BLACK CONTROL "Text:", -1, 5, 99, 16, 8, WC_STATIC, SS_TEXT | DT_RIGHT | DT_VCENTER | WS_VISIBLE CONTROL "", EF_TEXT, 25, 70, 190, 36, WC_MLE, MLS_BORDER | MLS_HSCROLL | MLS_IGNORETAB | MLS_VSCROLL | MLS_DISABLEUNDO | WS_TABSTOP | WS_VISIBLE CONTROL "ID:", -1, 5, 60, 16, 8, WC_STATIC, SS_TEXT | DT_RIGHT | DT_VCENTER | WS_VISIBLE CONTROL "", IDBX_SYMBOLVALUE, 25, 60, 190, 8, "ID.Box", WS_TABSTOP | WS_VISIBLE CONTROL "Check mark options", -1, 5, 40, 210, 18, WC_STATIC, SS_GROUPBOX | WS_VISIBLE CONTROL "~Checked", CB_CMS_CHECKED, 8, 42, 40, 8, WC_BUTTON, BS_AUTOCHECKBOX | WS_TABSTOP | WS_VISIBLE CONTROL "Base styles", -1, 5, 20, 210, 18, WC_STATIC, SS_GROUPBOX | WS_GROUP | WS_VISIBLE CONTROL "~Visible", CB_VISIBLE, 8, 22, 32, 8, WC_BUTTON, BS_AUTOCHECKBOX | WS_TABSTOP | WS_VISIBLE CONTROL "~Group", CB_GROUP, 110, 22, 31, 8, WC_BUTTON, BS_AUTOCHECKBOX | WS_TABSTOP | WS_VISIBLE CONTROL "~Disabled", CB_DISABLED, 58, 22, 40, 8, WC_BUTTON, BS_AUTOCHECKBOX | WS_TABSTOP | WS_VISIBLE CONTROL "~Tab stop", CB_TABSTOP, 165, 22, 39, 8, WC_BUTTON, BS_AUTOCHECKBOX | WS_TABSTOP | WS_VISIBLE CONTROL "Enter", DID_OK, 5, 5, 50, 12, WC_BUTTON, BS_PUSHBUTTON | BS_DEFAULT | WS_GROUP | WS_TABSTOP | WS_VISIBLE CONTROL "Cancel", DID_CANCEL, 58, 5, 50, 12, WC_BUTTON, BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE CONTROL "Help", DID_HELP, 110, 5, 50, 12, WC_BUTTON, BS_PUSHBUTTON | BS_HELP | BS_NOPOINTERFOCUS | WS_TABSTOP | WS_VISIBLE CONTROL "Font & Colours...", DID_PRESPARAM, 165, 5, 50, 12, WC_BUTTON, BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE END END CODEPAGE 850 STRINGTABLE MOVEABLE DISCARDABLE BEGIN IDS_CMS_CHECKED, "CMS_CHECKED" END The MAKE file is shown below. # MAKE file for ChkMark Version 1.00.00 # Revised: 1994-08-12 # Copyright ╕ 1989-1994 Prominare Inc. All Rights Reserved. ChkMark.Dll: ChkMark.Obj ChkMark.Res Link386 /EXEPACK /BASE:0x1200000 @ChkMark.Lnk; Rc ChkMark.Res ChkMark.Dll ChkMark.Obj: ChkMark.C Icc -G4e- -Ox -Rn -Fo$* ChkMark.C ChkMark.Res: ChkMark.Rc Rc -r $(@B).Rc $*.Res The link response file is shown below. ChkMark ChkMark.Dll ChkMark.Map ChkMark.Def The definitions file is shown below. LIBRARY ChkMark INITINSTANCE TERMINSTANCE DESCRIPTION 'Check Mark Control - 32-Bit Version' CODE LOADONCALL EXECUTEREAD NOIOPL NONCONFORMING DATA LOADONCALL READWRITE NOIOPL MULTIPLE NONSHARED PROTMODE EXETYPE OS2 EXPORTS ChkMarkRegister @ 1 ChkMarkQuery @ 2 ChkMarkStyles @ 3 Examples using PMCX (including full source code) are contained in the Source\Designer subdirectories, if you allowed the source code to be installed on your system during installation of Prominare Designer. Following are some of the PMCX controls implemented. Directory Purpose 3D Example of a PMCX control 3D text field. ChkMark Example of a static control with check mark. ComboBox Example of a variable control data usage PMCX control using a combo box. ComboMin Example of a variable control data usage PMCX control using a combo box and also allowing for the combo box to specify the depth of the drop down when used with tight areas. Control Example of a simple PMCX control. DateFld Example of a PMCX control for a date entry field. Frame Example of a PMCX control for a shadowed frame. This PMCX example shows how to utilize font and colours within a custom control. ImageBtn Example of a PMCX control push button containing a graphic bitmap image. Line3D Example of a PMCX control 3D line. ListBox Example of a variable control data usage PMCX control using a list box. Notebook Example of notebook usage in a design. NotePage Example of a variable control data usage PMCX control using a notebook. Pattern Example of a PMCX control pattern field. SpinBtn Example of a variable control data usage PMCX control using a spin button. TestBed Facility to test PMCX controls. The utility provides the means to debug and test the control dialogues. TimeFld Example of a PMCX control for a time entry field.