RadASM Custom Controls - mrfearless/RadASM2 GitHub Wiki
RadASM Custom Controls
Custom controls are dynamic link library files that add additional functionality to RadASM and to programs that make use of them. They can add new types of UI interaction that speeds up development for developers and potentially adds an ease of use quality to programs, for users that use them.
Custom controls can be added to RadASM in two ways: by using the menu Option->Custom Controls
and browsing for the the appropriate dll file that hosts the controls
or by manual editing the RadASM.ini
file and adding the dll file reference to the CustCtrl
section. Optionally the number of controls hosted in the dll file can be specified by manually editing the CustCtrl
entry and appending a comma and the count of the number of controls. Below is an example of a CustCtrl
entry:
[CustCtrl]
1=RACad.dll,1
2=RAEdit.dll,1
3=RAHexEd.dll,1
4=RAGrid.dll,1
5=SprSht.dll,1
6=WBDll.dll,1
7=RAFile.dll,1
8=RACodeComplete.dll,2
9=hl.dll,1
10=RAGraph.dll,1
11=RAVideo.dll,1
The maximum number of custom controls was 32 and was raised to 64 with v2.2.2.3 of RadASM. A number of custom controls are already included with RadASM packages and these controls are stored in the same folder as RadASM.exe by default.
Custom Control DLL
A custom control is a standard win32 dynamic link library file. The RadASM custom control dll requires at least two functions exported for it to be usable with RadASM (after it has been added to the CustCtrl section via manual entry or via menu option). These two functions are:
GetDef
GetDefEx
The prototypes for both functions are as follows:
GetDef PROTO :DWORD ; nInx
GetDefEx PROTO :DWORD ; nInx
Exported Functions
If you are developing the custom control using assembly (and using RadASM) you will also need to specify in the definition file the required functions for exporting, for example:
LIBRARY MyControl
EXPORTS GetDef
GetDefEx
Additionally the dll will require the DllEntry
function, and in this you should make a call to a function to register your controls class. Here is an example of the DllEntry
function:
DllEntry PROC PUBLIC hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
.IF reason == DLL_PROCESS_ATTACH
push hInst
pop hInstance
Invoke InstallControl, hInst, TRUE
.ELSEIF reason == DLL_PROCESS_DETACH
.ENDIF
mov eax,TRUE
ret
DllEntry ENDP
Registering The Custom Control Class
The above example shows a call to an InstallControl
function. It might look something like this example:
InstallControl PROC PUBLIC hInst:HINSTANCE, fGlobal:DWORD
LOCAL wc:WNDCLASSEX
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW or CS_PARENTDC or CS_DBLCLKS
.if fGlobal
mov wc.style, CS_HREDRAW or CS_VREDRAW or CS_PARENTDC or CS_DBLCLKS or CS_GLOBALCLASS
.endif
mov wc.lpfnWndProc, offset MyControlMainProc
mov eax, NULL
mov wc.cbClsExtra, eax
mov wc.hbrBackground, eax
mov wc.lpszMenuName, eax
mov wc.hIcon, eax
mov wc.hIconSm, eax
mov wc.cbWndExtra, 4
mov eax, hInst
mov wc.hInstance, eax
mov hInstance, eax
mov wc.lpszClassName, offset szMyControlClassName
Invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
Invoke RegisterClassEx, Addr wc
ret
InstallControl ENDP
Whatever the name of the function, the function used to register your control should include code to store the class information for your control in a WNDCLASSEX structure. The WNDCLASSEX structure is then used in a call to the RegisterClassEx function. The lpfnWndProc
field of the WNDCLASSEX has to point to the controls main window procedure, which is where the main controls functionality is handled along with any required windows events (WM_ messages) and painting of the control.
Once your control's class is registered then the control can be created by referencing the classname in calls to CreateWindow/CreateWindowEx or via a dialog creating its child controls from resources that reference the control's classname.
GetDef and GetDefEx functions
The GetDef
function was used by earlier versions of RadASM v1.2.0.5 until RadASM v2.1.0.4 when the GetDefEx
function was introduced to extend the functionality. GetDef
remains to provide backward compatible support for older custom controls.
GetDef
has one DWORD
parameter, which is nInx
, an index to the control hosted in the dll to fetch information for. GetDef
must return in eax
a valid pointer to a CCDEF
structure for the specified index (nInx
parameter) or 0
otherwise.
GetDefEx
has one DWORD
parameter, which is nInx
, an index to the control hosted in the dll to fetch information for. GetDefEx
must return in eax
a valid pointer to a CCDEFEX
structure for the specified index (nInx
parameter) or 0
otherwise.
Typically the GetDef
and GetDefEx
functions will look like the following example (for 1 hosted control)
GetDef PROC nInx:DWORD
mov eax, nInx
.IF !eax
Invoke LoadBitmap, hInstance, IDB_BMP ; Load the toolbox bitmap
mov ccdef.hbmp, eax ; Save handle of bitmap to ccdef struct
lea eax, ccdef ; Return pointer to inited ccdef struct
.ELSE
xor eax, eax
.ENDIF
ret
GetDef ENDP
GetDefEx PROC public nInx:DWORD
mov eax, nInx
.IF !eax
Invoke LoadBitmap, hInstance, IDB_BMP ; Load the toolbox bitmap
mov ccdefex.hbmp, eax ; Save handle of bitmap to ccdefex struct
lea eax, ccdefex ; Return pointer to inited ccdefex struct
.ELSE
xor eax, eax
.ENDIF
ret
GetDefEx ENDP
CCDEF and CCDEFEX structures
The CCDEF
and CCDEFEX
structures store information relating to each control hosted in the dll file. The CCDEF
structure is used with the GetDef
function and the CCDEFEX
structure is used with the GetDefEx
function. Both structures share mostly the same fields with a few exceptions - which are detailed below.
For a dll file that host multiple controls, additional CCDEF
and CCDEFEX
definitions will be required. For best practice the requirement should be for every control hosted, a pair of CCDEF
and CCDEFEX
definitions is required.
;Used by RadASM 1.2.0.5
CCDEF STRUCT
ID DD ? ; Controls uniqe ID
lptooltip DD ? ; Pointer to tooltip text
hbmp DD ? ; Handle of bitmap
lpcaption DD ? ; Pointer to default caption text
lpname DD ? ; Pointer to default id-name text
lpclass DD ? ; Pointer to class text
style DD ? ; Default style
exstyle DD ? ; Default ex-style
flist1 DD ? ; Property listbox 1
flist2 DD ? ; Property listbox 2
disable DD ? ; Disable controls child windows. 0=No, 1=Use method 1, 2=Use method 2
CCDEF ENDS
;Used by RadASM 2.1.0.4+
CCDEFEX STRUCT
ID DD ? ; Controls uniqe ID
lptooltip DD ? ; Pointer to tooltip text
hbmp DD ? ; Handle of bitmap
lpcaption DD ? ; Pointer to default caption text
lpname DD ? ; Pointer to default id-name text
lpclass DD ? ; Pointer to class text
style DD ? ; Default style
exstyle DD ? ; Default ex-style
flist1 DD ? ; Property listbox 1
flist2 DD ? ; Property listbox 2
flist3 DD ? ; Property listbox 3
flist4 DD ? ; Property listbox 4
lpproperty DD ? ; Pointer to properties text to add
lpmethod DD ? ; Pointer to property methods
CCDEFEX ENDS
Each field of the structures as pointed to by a defined .DATA variable should be filled in to help define how the control will work and respond. As example of a control using both structures could be like this:
.CONST
MYCTRLID EQU 70000
.DATA
szTip DB 'My New Control',0
szCap DB 'Some Text to display',0
szName DB 'IDC_MYCONTROL',0
szClass DB 'MyControlClass',0
; NILTWHCBCMMEVCSDAAMWMTLCSTFMCNAW SFSTFSGIUSOSMHTxxIIBPOTTAWAATWDD
ccdef CCDEF <MYCTRLID,offset szTip,0,offset szCap,offset szName,offset szClass,STYLE,EXSTYLE, 11111110000110000000000101000000b, 00010000000000011000000000000000b,0>
ccdefex CCDEFEX <MYCTRLID,offset szTip,0,offset szCap,offset szName,offset szClass,STYLE,EXSTYLE, 11111110000110000000000101000000b, 00010000000000011000000000000000b,0,0,offset szProperty,offset Methods>
CCDEF and CCDEFEX field details
Additional explanation and coverage of each field used in the CCDEF
and CCDEFEX
structures may help with understanding their purpose - using the example above.
ID (CCDEF
/CCDEFEX
) - This is a unique identifier for the custom control. Custom controls should use an value above 65535. In the example we are using a constant MYCTRLID with the value of 70000 to store in the CCDEF
and CCDEFEX
structures using the ccdef and ccdefex variables.
lptooltip (CCDEF
/CCDEFEX
) - A pointer to a string containing the tooltip to be displayed when the user hovers over the custom control's image button on the toolbox.
hbmp (CCDEF
/CCDEFEX
) - A handle to a bitmap used for the custom controls image button on the toolbox. Typically the bitmap is stored and compiled as a BITMAP
resource in the custom control, and a call to LoadBitmap (Invoke LoadBitmap,hInstance,IDB_BMP
) is used inside the GetDef
and GetDefEx
functions to obtain the handle and store it in the hbmp field before GetDef
and GetDefEx
return the pointer to the CCDEF / CCDEFEX variable.
lpcaption (CCDEF
/CCDEFEX
) - A pointer to a string containing the text associated with the control. This text is shown as the Caption
property in the properties list of the control when editing the dialog that uses this custom control. Controls will use this text in different ways: as a title, as some text to display etc.
lpname (CCDEF
/CCDEFEX
) - A pointer to a string containing the constant text name used to associate the controls id with. Not to be confused with the ID field above, the controls id is used in the resource file. The text representing this id can be used in code to interact with the control. This text is shown as the (Name)
property in the properties list of the control when editing the dialog that uses this custom control. The text is appended with a numeric for each new control of that type added to a dialog (IDC_MYCONTROL1
etc). Using the menu option Tools->Export IDs Equ
this will be exported to a constant equate (IDC_MYCONTROL1 EQU 1001
for example)
lpclass (CCDEF
/CCDEFEX
) - A pointer to a string containing the class to use when creating the control. The class must be registered before the control can be used by the RadASM IDE or by any program that creates the control either by a call to CreateWindow/CreateWindowEx or by reference to the class in a dialog when it loads its child resources.
style (CCDEF
/CCDEFEX
) - The default windows style flags used when creating the control, typically these will include WS_VISIBLE
and WS_CHILD
at least. Any custom flags you have defined with your control can also be included here. Windows reserves the lower 16bit word of dwStyle for use by the user. See Windows Styles for more details.
exstyle (CCDEF
/CCDEFEX
) - The default windows extended style flags used when creating the control. Typically this will be 0 unless you have a specific requirement. See Extended Windows Styles for more details.
flist1 (CCDEF
/CCDEFEX
) - A DWORD
size bitmask that indicates which properties are shown in the properties list of the control when editing the dialog that uses this custom control. Note: Only some of the properties are general and can be used by the custom control. These properties are marked with *
Bit Property Use
31 (Name) *
30 (ID) *
29 Left *
28 Top *
27 Width *
26 Height *
25 Caption *
24 Border *
23 SysMenu -
22 MaxButton -
21 MinButton -
20 Enabled *
19 Visible *
18 Clipping *
17 ScrollBar *
16 Default -
15 Auto -
14 Alignment -
13 Mnemonic -
12 WordWrap -
11 MultiLine -
10 Type -
09 Locked -
08 Child *
07 SizeBorder -
06 TabStop *
05 Font -
04 Menu -
03 Class -
02 Notify -
01 AutoScroll -
00 WantCr -
flist2 (CCDEF
/CCDEFEX
) - A second DWORD
size bitmask that indicates which properties are shown in the properties list of the control when editing the dialog that uses this custom control. Note: Only some of the properties are general and can be used by the custom control. These properties are marked with *
Bit Property Use
31 Sort -
30 Flat -
29 (StartID) -
28 TabIndex *
27 Format -
26 SizeGrip -
25 Group *
24 Icon -
23 UseTabs -
22 StartupPos -
21 Orientation -
20 SetBuddy -
19 MultiSelect -
18 HideSel -
17 TopMost -
16 xExStyle *
15 xStyle *
14 IntegralHgt -
13 Image -
12 Buttons -
11 PopUp -
10 OwnerDraw -
09 Transp -
08 Timer -
07 AutoPlay -
06 WeekNum -
05 AviClip -
04 AutoSize -
03 ToolTip -
02 Wrap -
01 Divider -
00 DragDrop -
disable (CCDEF
only) - Disable controls child windows. 0=No, 1=Use method 1, 2=Use method 2
flist3 (CCDEFEX
only) - A third DWORD
size bitmask that indicates which custom properties are shown in the properties list of the control when editing the dialog that uses this custom control. Custom properties are defined with the use of the lpproperty and lpmethod fields. See below for details.
flist4 (CCDEFEX
only) - A fourth DWORD
size bitmask that indicates which custom properties are shown in the properties list of the control when editing the dialog that uses this custom control. Custom properties are defined with the use of the lpproperty and lpmethod fields. See below for details.
lpproperty (CCDEFEX
only) - A pointer to a string containing a comma seperated list of custom properties to add to the control which will be shown in the properties list when editing the dialog that uses this control. An example of which is:
szProperty DB 'TextFontType,TextFontSize,Hand,TextAlign',0
lpmethod (CCDEFEX
only) - A pointer to an array containing information relating to each comma seperated property as defined in the lpproperty
field. The pointer to the array is defined in the CCDEFEX
structure using an offset (for example Offset Methods
where Methods
is the start of the array and the variable defined in the .DATA
section). Each array entry contains two DWORD
values. The first DWORD
value indicates the type of property: A true/false, or a multiple selection property. The second DWORD
value is a pointer to another structure - the structure it points to depends on the type of property (defined in the first DWORD
value), either an array of true/false entries or an array pointing to multiple options.
The supported property types are defined as:
.CONST
PROP_STYLETRUEFALSE EQU 1 ; TRUE/FALSE style
PROP_EXSTYLETRUEFALSE EQU 2 ; TRUE/FALSE extended style
PROP_STYLEMULTI EQU 3 ; Mulitple selection
PROP_STYLETRUEFALSE_DESC EQU 4 ; TRUE/FALSE style with custom property description (added in v2.2.2.3)
PROP_EXSTYLETRUEFALSE_DESC EQU 5 ; TRUE/FALSE extended style with custom property description (added in v2.2.2.3)
PROP_STYLEMULTI_DESC EQU 6 ; Mulitple selection with custom property description (added in v2.2.2.3
PROP_STYLETRUEFALSE example:
.CONST
HAND_POINTER EQU 80h
.DATA
szProperty db "Hand pointer",0
PropertyHand dd -1 xor HAND_POINTER,0
dd -1 xor HAND_POINTER,HAND_POINTER
Methods dd PROP_STYLETRUEFALSE,offset PropertyHand
PROP_STYLETRUEFALSE_DESC example:
.CONST
HAND_POINTER EQU 80h
.DATA
szProperty db "Hand Pointer",0
PropertyHand dd -1 xor HAND_POINTER,0
dd -1 xor HAND_POINTER,HAND_POINTER
db "Specifies if the mouse changes to a hand pointer.",0
Methods dd PROP_STYLETRUEFALSE_DESC,offset PropertyHand
PROP_STYLEMULTI example:
.CONST
ALIGN_LEFT EQU 128 ; left aligned text
ALIGN_RIGHT EQU 256 ; right aligned text
ALIGN_CENTER EQU 512 ; center aligned text
.DATA
szProperty DB 'TextAlign',0
PropertyTextAlign db 'Left,Right,Center',0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_LEFT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_RIGHT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_CENTER
dd -1,0
Methods dd PROP_STYLEMULTI,offset PropertyTextAlign
PROP_STYLEMULTI_DESC example:
.CONST
ALIGN_LEFT EQU 128 ; left aligned text
ALIGN_RIGHT EQU 256 ; right aligned text
ALIGN_CENTER EQU 512 ; center aligned text
.DATA
szProperty DB 'TextAlign',0
PropertyTextAlign db 'Left,Right,Center',0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_LEFT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_RIGHT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_CENTER
dd -1,0
db "Specifies the alignment of text displayed in the control",0
Methods dd PROP_STYLEMULTI_DESC,offset PropertyTextAlign
A PROP_STYLEMULTI and PROP_STYLETRUEFALSE combined example:
.CONST
HAND_POINTER EQU 80h
ALIGN_LEFT EQU 128 ; left aligned text
ALIGN_RIGHT EQU 256 ; right aligned text
ALIGN_CENTER EQU 512 ; center aligned text
.DATA
szProperty DB 'TextAlign,Hand Pointer',0
PropertyTextAlign db 'Left,Right,Center',0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_LEFT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_RIGHT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_CENTER
dd -1,0
PropertyHand dd -1 xor HAND_POINTER,0
dd -1 xor HAND_POINTER,HAND_POINTER
Methods dd PROP_STYLEMULTI_DESC,offset PropertyTextAlign
dd PROP_STYLETRUEFALSE_DESC,offset PropertyHand
A PROP_STYLEMULTI_DESC and PROP_STYLETRUEFALSE_DESC combined example:
.CONST
HAND_POINTER EQU 80h
ALIGN_LEFT EQU 128 ; left aligned text
ALIGN_RIGHT EQU 256 ; right aligned text
ALIGN_CENTER EQU 512 ; center aligned text
.DATA
szProperty DB 'TextAlign,Hand Pointer',0
PropertyTextAlign db 'Left,Right,Center',0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_LEFT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_RIGHT
dd -1,0
dd -1 xor (ALIGN_LEFT or ALIGN_RIGHT or ALIGN_CENTER),ALIGN_CENTER
dd -1,0
db "Specifies the alignment of text displayed in the control",0
PropertyHand dd -1 xor HAND_POINTER,0
dd -1 xor HAND_POINTER,HAND_POINTER
db "Specifies if the mouse changes to a hand pointer.",0
Methods dd PROP_STYLEMULTI_DESC,offset PropertyTextAlign
dd PROP_STYLETRUEFALSE_DESC,offset PropertyHand