Working with the Dialog Editor
Dialog types (modal, modeless, child)
Menus and accelerators (hotkeys)
Common controls, other controls
Dialogs now and before QM 2.1.9
Dialog programming info at MSDN
To create new dialog, use menu File -> New -> New Dialog. It creates initial dialog definition (BEGIN DIALOG ... END DIALOG) and opens it in the Dialog Editor. You can add controls, order them, change text, etc. When you click Save, it updates the dialog definition.
To edit a dialog later, open the macro that contains the dialog definition and click 'Dialog Editor' button or menu item in QM window. If current macro does not contain a dialog definition, this button/menu creates new dialog.
You can also edit dialog definitions directly. The format is simple: The first line defines dialog window, other lines - controls. Line format: id class style exstyle x y width height text tooltip. Text and tooltip are optional. The position/size is in dialog units, not in pixels.
Add control | Click or drag&drop a control from the toolbox. |
Move control | Drag with the mouse left button. Or use arrow keys. |
Resize control or dialog | Drag with the mouse right button. Or use Shift+arrow keys. |
Select control | Click it. A small red rectangle will appear at the top-left corner. Also you can use Tab or Shift+Tab to select next or previous control in the Z order. |
Send control to the top of the Z order and tab order | Shift+click. |
Send control to the bottom of the Z order | Ctrl+click. |
Place control behind the currently selected control in the Z order | Ctrl+Shift+click. |
Z-order all controls | Select dialog, then Ctrl+Shift+click all controls starting from the control that must be at the top of the Z order. Alternatively, close the Dialog Editor and reorder lines in the dialog definition. The order of lines matches the Z order. |
Underline character in control's text | Place ampersand (&) before. |
Create group of option buttons | Add "Option first" and then several "Option next". |
Move multiple controls | If the controls are in a Group control, Shift+drag it. Else create/drag a temporary Group control for it. |
Move/resize with high precision. | Use Alt when you drag or right-drag. |
Add control similar to a control in a window | Move the mouse over the control and press the hotkey defined in Dialog Editor Options. |
In the Dialog Editor, you can set text for some controls. For other controls, text is used only as control's name, making it easier for you to recognize the control in the Dialog Editor. The first three characters also are used for variable name. Generally, controls are identified by an unique control id - numeric value that you can see in variable name. For example, if variable name is b3But, you know that control id is 3.
Use function ShowDialog. The Dialog Editor creates code for it. When you click Save, it updates the code or displays in output, depending on dialog settings. The code also may contain declarations of variables for controls (read below). By default the code must be in the same function as the dialog definition, but it can be anywhere if not using a sub-function dialog procedure.
The minimum code to show the dialog is created by the Dialog Editor. But ShowDialog has more parameters that you can use.
function# [$macro] [dlgproc] [!*controls] [hwndowner] [flags] [style] [notstyle] [param] [x] [y] [$icon] [$menu] ;;flags: 1 modeless, 4 set style (default is to add), 64 raw x y.
macro - where to look for dialog definition. Can be:
dlgproc - address of a dialog procedure. Optional. Used with smart dialogs (read below).
controls - array of strings (address of first str variable in the array) for controls, as explained later in this topic.
hwndowner - owner window handle. If the dialog has WS_CHILD style - parent window handle.
1 | Modeless dialog. |
4 | Replace dialog style with style. Default - add style. |
64 | Raw x y. Read more below. |
128 | QM 2.3.3. Start hidden.
|
0x100 | QM 2.4.2. Use x y specified in dialog definition. Read more below. Also you should remove DS_CENTER style. |
style - combination of window styles (WS_ and/or DS_ constants). Changes style that is set in the Dialog Editor.
notstyle - combination of styles to remove from default style.
param - some value to pass to the dialog procedure. The dialog procedure can retrieve it using DT_GetParam function.
x, y - dialog coordinates. Read more below.
icon - title bar icon.
menu - menu.
Actual dialog coordinates depend on x, y, hwndowner, some styles, flag 64, and _monitor. If x and y are omitted or 0, by default dialogs are shown in screen center.
If your dialog shows message boxes or other unowned dialogs, it should do it in the same monitor. Under case WM_INITDIALOG insert _monitor=hDlg. Without this, these unowned dialogs will be in the primary monitor regardless where your dialog is.
The return value depends on dialog type. Read the next chapter. Error if dialog cannot be shown, for example if a control class is not registered.
A dialog can be modal or modeless. If modal, ShowDialog returns only when the dialog is closed. If modeless, ShowDialog creates the dialog and returns immediately.
The Dialog Editor creates code to show modal dialog, but you can edit it to show modeless dialog (add flag 1, etc).
ShowDialog for a modal dialog returns 1 on OK, 0 on Cancel. When you click some other push-button in a dialog that does not have dialog function (that is, not a "smart" dialog), it closes the dialog, and ShowDialog returns button id.
ShowDialog for a modeless dialog returns dialog window handle. It does not wait until the dialog is closed, and does not populate dialog variables on OK. To make a modeless dialog useful, use dialog procedure (see smart dialogs). The thread must stay running and process messages. Example.
Dialogs also can be used as child windows. Add WS_CHILD style, and pass parent window handle to ShowDialog. Child dialogs are modeless.
QM 2.3.4. If a modeless dialog still exists when the thread ends, it receives WM_QM_ENDTHREAD message. It destroys the dialog, unless dialog procedure returns nonzero (then you must explicitly destroy the dialog before the thread completely ends).
The Dialog Editor craetes and updates ShowDialog code that may contain declarations of variables for some controls. You can use the variables to initialize the controls and get data from them. Example:
str controls = "3 5" str e3Nam c5Var if(!ShowDialog("Dialog2" 0 &controls)) ret if(c5Var=1) ;;checked out e3Nam
Don't edit the declarations (the first two lines) manually because the variables must be in a particular order. The first str variable contains identifiers of controls. Then follow str variables for each control whose id is included in the first variable, in the same order. Variable names include control id. The third argument of ShowDialog must be address of the first variable.
When the user clicks OK, ShowDialog gets data from controls and populates the variables. Data format:
Control type | Variable | Notes, examples |
---|---|---|
Check, Option | "1" if checked, "0" if unchecked. | if(c3Exa=1) out "checked" |
ComboBox, single-selection ListBox |
"index text". Here index is 0-based index of selected item, or -1 if no selection. |
int iSel=val(cb3) int i=TO_CBGetItem(cb4) out i; out cb3 |
Multi-selection ListBox | String consisting of '0' and '1' characters for unselected and selected items. For example, if selected are items 0 and 3 in a 4-item list box, the string will be "1001". |
if(lb3[0]='1') out "selected" |
Edit, QM_Edit, rich edit | Control text. | Before QM 2.3.4: unchanged if read-only. |
QM_Grid | Table in CSV format. | You can use ICsv interface to work with CSV. |
QM_ComboBox | Depends on control style and flags. | Editable: control text; read-only: item index; check boxes: string of '0' and '1' characters; flag 2: hex value; flag 0x100: CSV. |
Static, Button, Group, ActiveX | Unchanged. | The Dialog Editor does not add variables for most of these controls. |
Other | Control's text. Before QM 2.3.4: unchanged. | The Dialog Editor adds variables only for some control types. To add for others, you can use QmSetWindowClassFlags or Dialog Editor Options. |
To get data from controls in a dialog procedure, you can use function DT_GetControl or DT_GetControls. Also you can use window/control functions - str.getwintext, but (get check box state), CB_SelectedItem and other. Look in category control. Also you can use control messages, most of them are documented in the MSDN Library.
In the Dialog Editor you can set text for these controls: button, group, static text, read-only edit, SysLink. To initialize other controls, before showing dialog assign certain strings to the control variables.
Control type | Variable | Control contents | Notes, examples |
---|---|---|---|
Check, Option | "1" | Checked. | c3=1 |
ListBox, ComboBox | List of strings. Some strings can begin with &. | Each line adds item. The & selects the item. |
cb3="&Zero[]One[]Two" lb4="Zero[]&One[]&Two" |
Static icon | Icon file path or macro resource name. Can begin with &. Can contain exe resource id. | Displays the icon. The & displays 32x32 icon instead of 16x16 icon. |
si3="$my qm$\file.ico" si4="&shell32.dll,15" si6="resource:test.ico" ":150 file.ico" "&:150 file.ico" |
Static bitmap | bmp, jpg or gif file path or macro resource name. Can contain exe resource id. QM 2.3.4: can be png. | Displays the picture. |
sb3="$my qm$\file.gif" sb7="resource:test.png" sb8=":8 $personal$\file.bmp" |
Dialog itself (id=0) | Any text. | Displays the text in the title bar. |
d0="New Title"
Include 0 in Dialog Editor Options -> Add variables... |
Edit, QM_Edit | Any text. | Displays the text. | e3="text" |
Rich edit | Any text. Can be .rtf file path or macro resource name, preceded by &. The path can contain exe resource id (QM 2.3.0). | Displays the text or the file. |
rea3="text" rea4="&$personal$\rich text.rtf" rea8="&resource:Document.rtf" rea5="&:10 &$personal$\text.txt" |
Web browser control | Web page, folder or file that can be opened in web browser. | Opens the web page, folder or file. If "", opens empty page. |
ax3SHD="www.quickmacros.com" ax4SHD="$my qm$\animated.gif" ax5SHD="" |
QM_Grid | Table in CSV format. | Displays the table. | qmg3="a1,b1,c1[]a2,b2,c2"
You can use ICsv interface to work with CSV. |
QM_ComboBox | CSV. First row - control properties. Other rows - list items. |
qmcb3="0[]Zero[]One[]Two" qmcb4=",,1[]Zero[]One,1[]Two" |
|
Other | Any text. | Sets text of the control. The control can display it or not. | The Dialog Editor adds variables only for some control types. To add for others, you can use QmSetWindowClassFlags or Dialog Editor Options. |
Example:
str controls = "3 5 6 7 4" str c3 cb5 e6 si7 sb4 c3 = 1 ;;checkbox checked cb5 = "Sunday[]&Monday[]Tuesday" ;;combobox with three items; Monday is selected e6 = "Default text" ;;edit control's text is "Default text" si7 = "&files.ico" ;;32x32 icon from files.ico file sb4 = "c:\pictures\tree.bmp" ;;picture if(!ShowDialog("Dialog2" 0 &controls)) ret
To set control data in a dialog procedure, you can use function DT_SetControl or DT_SetControls. Also you can use window/control functions - str.setwintext, but (set check box state), CB_SelectItem and other. Look in category control. Also you can use control messages, most of them are documented in the MSDN Library.
The Dialog Editor creates names for control variables. A variable name is composed from abbreviated class name, id and max 3 characters of control's name. For example, if combo box with id 15 is named "Value", variable name is cb15Val.
If you change variable names (change variable's text in the Dialog Editor), need to update variable names in the macro. The Dialog Editor can do it automatically on Save, depending on dialog settings.
Instead of multiple str variables for controls, you can use a user-defined type. You can enter type name in Dialog Editor Options. Example:
type TYPE_A ~controls ~c3Che ~e4 ~cb5 TYPE_A d.controls="3 4 5" d.cb5="Sunday[]&Monday[]Tuesday" if(!ShowDialog("Dialog4" 0 +&d)) ret TO_CBGetItem d.cb5 out d.cb5
Examples of getting control values in a dialog procedure:
modal dialog (don't use this for modeless dialogs) TYPE_A& d=+DT_GetControls(hDlg) out d.e4 modal or modeless dialog TYPE_A d.controls="3 4 5" DT_GetControls(hDlg &d) out d.e4
Example of using the registry to save dialog data:
type DLGVAR ~controls ~e3 ~c4Che DLGVAR d.controls="3 4" if(rget(_s "DLGVAR" "\test")) _s.setstruct(d) if(!ShowDialog("Dialog33" 0 &d)) ret _s.getstruct(d); rset(_s "DLGVAR" "\test")
When you use a simple dialog, you can only initialize controls before calling ShowDialog, and get data from them when ShowDialog returns. While the dialog is open, the macro waits until it is closed. That is enough in many cases. But sometimes you need to execute some code while dialog is open. For example, show an Open File dialog when the user clicks a button. Then you need a special function - dialog procedure.
A dialog procedure is a user-defined function (can be sub-function) that begins with function# hDlg message wParam lParam. Its address is passed to ShowDialog as the second argument. To create a dialog with a dialog procedure, use menu File -> New -> New Dialog. Select 'New smart dialog'.
Example:
\Dialog_Editor This code defines and shows dialog. Everything is like with simple dialogs, but we use the second ShowDialog argument - address of dialog procedure. str dd= BEGIN DIALOG 0 "" 0x90C80AC8 0x0 0 0 224 136 "Dialog" 3 Button 0x54032000 0x0 8 8 48 14 "Test" 4 ComboBox 0x54230243 0x0 8 28 96 213 "" 1 Button 0x54030001 0x4 116 116 48 14 "OK" 2 Button 0x54030000 0x4 168 116 48 14 "Cancel" END DIALOG DIALOG EDITOR: "" 0x2040108 "*" "" "" "" str controls = "4" str cb4 cb4="&A[]B[]C" if(!ShowDialog(dd &sub.DlgProc &controls)) ret #sub DlgProc ;;this is the dialog procedure function# hDlg message wParam lParam sel message case WM_INITDIALOG out "dialog created" case WM_DESTROY out "closing" case WM_COMMAND goto messages2 ret messages2 sel wParam case IDOK out "button OK clicked" case 3 out "button Test clicked" case CBN_SELENDOK<<16|4 _i=CB_SelectedItem(lParam) out F"ComboBox item {_i} selected" ret 1
The dialog procedure is called by the system whenever the dialog receives a message (e.g., when the user clicks a button or selects a combobox item).
The first sel is for dialog-related messages. The second sel is for control-related messages (WM_COMMAND). When a message arrives, is executed code that follows the case statement for that message.
To add case statements for various messages, you can use the Events dialog in the Dialog Editor. Then add your code in or below the case line.
Parameters:
hDlg - dialog window handle. In dialog procedure always use hDlg, not win("Dialog name"). Example: int hwndControl=id(3 hDlg).
message - an integer value of the message, for example WM_INITDIALOG.
wParam, lParam - two integer values that depend on message.
The dialog procedure can return:
The control variables are used before and after ShowDialog, but not in the dialog procedure.
To get/set control values in dialog procedure, you can use functions from the control category. For example, str.getwintext/setwintext to get/set Edit control text; but to click button, check/uncheck or get checked; CB_SelectedItem to get combo box selected item index. Also you can send control messages with SendMessage. Control messages are documented in the MSDN Library.
Alternatively use function DT_GetControl to get control data in the format described in the How to get data from controls chapter. You can use function DT_GetControls to get data from multiple controls. Use function DT_SetControl or DT_SetControls to set control data.
Usually don't need to add code to close dialog. It is automatically closed on OK and Cancel, unless you return 0 on IDOK/IDCANCEL. To close explicitly from the dialog procedure, use clo hDlg or DT_Cancel (same as pressing Cancel) or DT_Ok (same as pressing OK). Don't use EndDialog and DestroyWindow. To close a dialog from outside if you don't have its handle, use clo like when you close any other window.
There are more functions that can be used in dialog procedures. Their names begin with DT_. They are in category _other.__in_dlgproc. For example, _other.__in_dlgproc.DT_SetAutoSizeControls.
Also you can look for examples in "\System\Tools" folder. Code toolbar dialogs are implemented there. They use several private functions, usually their names begin with TO_. Don't use the private functions in your macros, because they may be changed or deleted in the future, but you can make their copies. You can use public functions from folders "\System\Functions", "\System\Dialogs\Dialog Functions" and "\System\Dialogs\Dialog Control Classes". Also you can use private functions that don't show warning "private System function X in user code...".
QM dialogs don't have support for real property pages (child dialogs), but you can easily show and hide groups (pages) of related controls so that only one page would be visible at a time. In the Dialog Editor, use buttons < and > to switch pages and create new pages. Controls with id 1 to 999 are always visible (common). Controls with id greater or equal 1000 belong to pages that can be easily shown and hidden. Each page can have maximum 100 controls. For example, controls in page 0 have id 1000 to 1099, controls in page 1 have id 1100 to 1199, and so on.
To switch pages at run time, in the dialog procedure call function DT_Page.
function hDlg index [~map]
hDlg - hDlg.
index - 0-based page index. Use -1 to hide all pages.
map - can be used to map index to different page.
A macro can contain more than 1 dialog. Use sub-functions for it.
\Dialog_Editor str dd= BEGIN DIALOG ... if(!ShowDialog(dd &sub.DlgProc 0)) ret ... #sub DlgProc function# hDlg message wParam lParam ... #sub Dialog2 function# [hwndOwner] str dd= BEGIN DIALOG ... if(!ShowDialog(dd &sub.DlgProc2 0 hwndOwner)) ret ... #sub DlgProc2 function# hDlg message wParam lParam ...
In this example there are 2 dialogs. One in the parent function and one in sub-function Dialog2. When opening the Dialog Editor, you can choose which dialog to edit. If a sub-function or parent function contains multiple dialogs, the Dialog Editor uses the first dialog in it (the first dialog definition, ShowDialog statement, variable declarations, and the first found dialog procedure below it).
QM 2.3.0 and later versions support Unicode. To enable it for whole program, check the checkbox in Options. To enable it for a dialog, select "Unicode" or "As QM" in dialog editor Options. By default, dialogs work in ANSI mode, like in previous QM versions.
If QM is running in Unicode mode, most controls work well with any text regardless of dialog Unicode mode. To use Unicode text with rich edit controls, either set Unicode mode for the dialog, or use control of class RichEdit20W or RichEdit50W instead of RichEdit20A.
When Unicode is enabled for a dialog, its dialog procedure receives Unicode versions of some messages, particularly those that can pass or query text. Then the text is in Unicode UTF-16 format. QM string functions don't understand UTF-16. You can use str.ansi to convert the text to UTF-8 or ANSI. The _unicode variable tells you in which mode QM is running.
For example, in a dialog procedure of a Unicode dialog, lParam of WM_SETTEXT is UTF-16 text. If the dialog is ANSI, it is ANSI text. Common controls (tree view, list view, etc) have their own Unicode mode, which is enabled in Unicode dialogs, and disabled in ANSI dialogs. In Unicode mode they send different notification messages (codes used with WM_NOTIFY message). For example, in Unicode mode a tree view control sends TVN_SELCHANGEDW instead of TVN_SELCHANGED. Control Unicode mode can be turned on/off using CCM_SETUNICODEFORMAT message, documented in MSDN library.
QM 2.2.1. Use class __Font. Example.
ShowDialog has an optional menu parameter. It can be the name of a macro (or item of other type) that contains menu definition. It also can be menu definition itself.
To create menu definitions, use the Menu Editor. You can find it in code toolbar -> More tools.
Example menu definition:
BEGIN MENU >&File &Open : 101 0 0 Co - >&Recent Empty : 102 0 3 < < >&Edit Cu&t : 103 0 0 Cx - Select &All : 104 0 0 Ca < &Help : 105 0 END MENU
You can see that it is similar to QM menus. A single line (except <), creates a menu item. Items that open popup menus or submenus begin with >. They usually don't have an id and accelerator. The end of a popup menu or submenu is marked by < line. Hyphen is used for separators. A line can optionally begin with any number of spaces and tabs.
Syntax used for menu items:
Label : id [type] [state] [accelerator]
label - menu item text. Use ampersand to underline characters. Can be used escape sequences (not in Menu Editor).
id - menu item id. Should be 0 to 65535 (0xFFFF). When you click the menu item, the dialog procedure receives WM_COMMAND message that can be handled in the same way as it would be a button with the id. Use bigger values (e.g. above 10000) to avoid conflicts with buttons.
type - numeric combination of menu item types. Normally it is omitted or 0.
state - numeric combination of menu item states. Useful states: 3 disabled, 8 checked.
accelerator - a hotkey in QM format (same as with key). The hotkey string is appended to the menu item label automatically, unless label contains a tab character.
id, type and state must be single numbers, without operators and named constants. More info about menu item types and states can be found in MSDN Library (search for MENUITEMINFO structure).
In exe also can be used menus from resources. The menu argument of ShowDialog must be semicolon followed by resource id, e.g. ":15". If the resource contains accelerator table with the same id, the table is used for accelerators, although accelerator text is not added (must be included in label text, after tab).
To change or remove menu at run time, call DT_SetMenu in dialog procedure. To create or load menu, use DT_CreateMenu.
Menu bars and accelerators can be used with modal and modeless dialogs, but not with child dialogs.
QM 2.4.2. Menu definitions also can be used to show popup menus. Use ShowMenu or MenuPopup.Create.
QM 2.4.2. You can set menu icons with DT_SetMenuIcons.
The Dialog Editor and dialog functions support controls of the following classes: Button (push button, checkbox, group), Edit, RichEdit20A, RichEdit20W, Static (static text, bitmap, icon, line), ComboBox, LixtBox and QM_Grid. Working with controls of these classes is easy. You can initialize them before you call ShowDialog, and get data (text, checked, etc) from them when dialog is closed.
Dialogs can contain controls of other classes too. For example, TreeView32, SysTabControl32. However, only programmers can use them. The dialog must be a "smart" dialog, otherwise the controls will be useless. To interact with these controls, are used various messages (with SendMessage). To notify the dialog about various events, these controls usually send WM_NOTIFY message, not WM_COMMAND. Messages, styles and other information can be found in MSDN library. If you don't know the value of a constant, click it, press F1, and search for definition on the Internet.
Several samples can be found in the forum. Search for the class name.
Controls that you usually use in dialogs are Windows controls. Also you can use ActiveX controls. ActiveX controls are COM objects that provide graphical user interface. They are used differently than Windows controls. To work with Windows controls, are used messages. To work with ActiveX controls, are used functions that they provide.
To insert an ActiveX control, click "ActiveX controls..." in the Dialog Editor. It opens the COM Libraries dialog that displays available (registered) ActiveX controls. Select the control you need and click Add Control To Dialog.
ActiveX controls are defined in type libraries, as COM classes. To use an ActiveX control in a dialog, at first declare the type library where the control class is defined. To insert type library declarations, use the COM Libraries dialog. When adding a control to a dialog, QM prompts to insert type library declaration if it still does not exist in current macro. Several type libraries, including SHDocVw (web browser control) are already declared.
You can read more about type libraries and ActiveX controls in the Using COM Components topic.
When you have an ActiveX control created, you usually need some way to communicate with it. For this purpose, declare a variable of that class and call _getcontrol. Pass handle of ActiveX control's host window (which itself is a Windows control of "ActiveX" class). Then you can call functions with the variable to manipulate the control. To receive events, use _setevents. The variable must be local (not global or thread). Call _getcontrol every time before using it.
Example:
... sel message case WM_INITDIALOG ;;dialog created SHDocVw.WebBrowser b b._getcontrol(id(3 hDlg)) b._setevents("sub.b") b.Navigate("http://www.google.com") ... case 4 ;;Back button b._getcontrol(id(3 hDlg)) b.GoBack ...
There is a sample dialog with web browser control in the forum.
You cannot use str.setwintext with ActiveX controls, except web browser control. If the text is URL or path of a html, image or other file, web browser control opens that web page or file. Does not wait until finished loading. Sets silent mode to avoid script error messages. If the text is "", loads "about:blank" or clears the control. To load HTML, use function HtmlToWebBrowserControl.
ActiveX controls can be used in other windows (non-dialog) too. To create an ActiveX control, use CreateControl or CreateWindowEx. Class name and text must be like in dialog definitions: class "ActiveX", text like "Typelib.Class {GUID}".
QM supports run-time licensing of ActiveX controls. It allows you to add purchased ActiveX controls to macros and exes and distribute these macros and exes. When you insert an ActiveX control in the Dialog Editor using the COM Libraries dialog, QM automatically attaches encrypted run-time license key, if the control can generate it. With attached run-time license key, the control can be used on any computer. If you distribute macro (not exe), you should encrypt the macro that contains the dialog definition to prevent others to reuse the run-time license key in their macros. See Encrypted Macros. Even if the macro is not encrypted, the key can only be used in Quick Macros, because only QM can decrypt the key. Also, others will not be able to create exes with the key. Note that some controls may use different ways to verify license. For example, you may have to call certain function and pass the license key.
Some ActiveX controls don't work well in QM. This is because they are designed for full-featured containers, such as Visual Basic forms, or only for certain programs. At design time, you can only move and resize ActiveX controls (or control placeholders). Properties can be changed only at run time.
Many other COM components are not controls, and must be created with _create or other functions instead. Such components usually are in dll files. Controls usually are in ocx or dll files.
QM 2.3.4. It is possible to use some ActiveX controls even if the COM component is not registered on that computer. In dialog definition add full path of the COM component (dll or ocx) to the ActiveX text string, like "Typelib.Class {CLSID} ''dll:$qm$\file.ocx''". If the file not found, tries to create as registered. In exe, if path begins with "$qm$", searches for the dll in exe folder; if not found there, searches in QM folder if QM is installed on that computer.
QM 2.3.5. To create COM components without registration, you can use manifest and __ComActivator class.
See also: Using COM components.
If you encrypt macro that contains dialog definition, the dialog will not work unless the dialog definition is in a variable. Examples:
This macro will not work encrypted.
BEGIN DIALOG 0 "" 0x90C80AC8 0x0 0 0 224 136 "Dialog" 1 Button 0x54030001 0x4 116 116 48 14 "OK" 2 Button 0x54030000 0x4 168 116 48 14 "Cancel" END DIALOG DIALOG EDITOR: "" 0 "*" "" "" "" if(!ShowDialog("This macro" 0 0)) ret
This macro will work always.
str dd= BEGIN DIALOG 0 "" 0x90C80AC8 0x0 0 0 224 136 "Dialog" 1 Button 0x54030001 0x4 116 116 48 14 "OK" 2 Button 0x54030000 0x4 168 116 48 14 "Cancel" END DIALOG DIALOG EDITOR: "" 0 "*" "" "" "" if(!ShowDialog(dd 0 0)) ret
The same is with menu definitions. Use a variable if want to encrypt the dialog.
In QM versions < 2.1.9, the dialog procedure must call DT_Init on WM_INITDIALOG, DT_DeleteData on WM_DESTROY, DT_Ok on OK, and DT_Cancel on Cancel. Starting from QM 2.1.9, these functions are not necessary. Now you have to use them only if the dialog will be used by someone that has an older QM version (this does not apply to exe-macros). Also, to avoid any problems, you should leave these functions in dialogs where they already exist.
A note about IDOK and IDCANCEL. Before QM 2.1.9, DT_Ok and DT_Cancel functions were used to close the dialog. If they were not called, the dialog was not closed. Now dialogs are closed automatically. To prevent this, return 0 on IDOK or IDCANCEL. For backward compatibility, a dialog also is not closed automatically if it calls DT_Init on WM_INITDIALOG (it is the way QM recognizes old dialogs).
Search for ShowDialog or dialog in the forum.
Several topics to get started:
Tips how to copy/paste QM code in the forum, and how to use dialog examples.
A tutorial for a simplest dialog with checkboxes.
Running and ending macros from a dialog (without closing the dialog).
Executing code from a dialog with a combo box (without closing the dialog). An example with a list box.
Collection of dialogs and other code
Dialog box programming info at MSDN
Dialog programming in QM is similar to dialog programming in C++ using Windows API, as documented in MSDN. In QM it is simplified. When you know how dialogs work at Windows API level (dialog procedure, messages, notification messages, etc), you can also understand how it works in QM.