Compiler directives:
#sub
Syntax
#sub name [attributes]
Parameters
name - name of the sub-function.
attributes - one or more characters to specify sub-function properties:
| c |
This sub-function is a class member function of its parent function's class. Example: #sub Member c. To call: sub.Member or var.sub.Member. |
| m |
Text of this sub-function is used as menu item text in a menu, toolbar or autotext. The menu item must be like Label :sub.SubName. Cannot be called as function. |
| v |
This sub-function can use parent's local and thread variables declared above the first sub call statement. Be careful with this, read more in Remarks -> More. |
| r |
This sub-function sees parent's ref and typlib statements that are above the first sub call statement. |
| p |
QM 2.4.3. Private. In a function containing shared sub-functions this sub-function is not shared. Sub-functions in other functions are always private, don't need this attribute. |
Remarks
Begins a sub-function.
Added in QM 2.4.1.
Sub-functions are user-defined functions that are embedded in text of their parent QM item (macro etc). Unlike usual QM user-defined functions, they aren't separate QM items that you could manage in the list of macros. Sub-functions can be used in macros, functions, member functions, menus, toolbars and autotexts.
To call a sub-function, use its name with "sub." prefix. Such sub-functions can be called from parent and its sub-functions, but not from other QM items. QM 2.4.3 also supports shared sub-functions.
Sub-functions can be used like usual functions:
- Called directly, like sub.SubName(1 2) or classVar.sub.SubName(1 2).
- As callback function, for example with atend, win, ShowDialog. To get address: &sub.SubName.
- Run in separate thread with mac, like mac "sub.SubName".
- As timer function with tim, like tim 1 sub.SubName.
- With COM events.
- With directives #compile and #set. QM 2.4.3: also with #err.
When you may want to use sub-function instead of usual function:
- You need a private function that cannot be used in other macros.
- You don't want to have the function in the list of macros.
- You want to edit it together (in same text) with parent function.
- When menu item text is multiline and you don't want to create macro/function for it.
- To use features specific to sub-functions, for example attribute v (use parent variables).
When you cannot use sub-function:
- The function is used by more than one macro/function/etc.
- The function must have a trigger or other properties of QM items that sub-functions don't have.
- Where sub-functions are not supported (error when trying to use).
- You want to make your macro compatible with older QM versions (< 2.4.1).
Sub-functions cannot be nested. This directive ends current code (parent or another sub-function).
All sub-functions can access private/protected members of class of parent function, even if they don't have c attribute.
Like in all functions, default speed (spe) in sub-functions is 0. In sub-functions with m attribute it is like in macros and menu items, default 100.
More
When compiling a sub-function, QM creates a temporary hidden QM item for it. These QM items have own QM item id and name (see getopt), but don't have own text, trigger and most other properties of QM items. The names are like "<00001>SubName", where the number is parent QM item id, although usually displayed like "ParentName:SubName" or just "SubName". Most QM functions that find QM item by name support both "<00001>SubName" and "ParentName:SubName", but can find only if the temporary QM item already exists.
When a sub-function is specified, in most cases QM uses its parent instead:
- str.getmacro gets parent text (all, including text of sub-functions).
- qmitem gets parent properties.
- dis disables/enables parent.
- str.setmacro replaces text of parent.
- All functions that use macro resources and settings.
- Functions that use the above functions. For example, ShowDialog("" ...) gets dialog definition from caller's text. If caller is a sub-function, looks in all parent text, not just in its part containing the sub-function. Similarly, CsExec "" etc look for script code in all parent text.
- When creating exe, if need to add sub-function's text to exe, adds parent text.
When a sub-function is specified, QM does not use its parent with IsThreadRunning, EnumQmThreads, shutdown -6 (end thread), EndThread, WaitForThreads, trigger "End thread". Example: IsThreadRunning("ParentName:SubName").
Some other featues that sub-functions don't have:
- Cannot be encrypted separately from parent.
- Cannot run in other process than parent.
- Cannot be the main function in exe.
- Cannot be a class special function - constructor, destructor, operator=.
Be careful with attribute v (use parent variables):
- When the sub-function is a callback function, in some cases it may be called when parent function is already returned, or even run in other thread. Then will be run-time error "cannot access variable". This attribute is not allowed with mac and in menus.
- When the parent function is called recursively (calls itself), its sub-functions with v attribute use variables of the nearest parent function instance in the call stack. If it is not what you need, the parent function should not be recursive.
Sub-function threads and timers are hidden by default in the 'Running items' pane. Right-click a folder to show.
Examples
sub.Test
#sub Test
out "sub-function Test"
out sub.Test2(3 4)
#sub Test2
function# a b
out "sub-function Test2"
ret a+b
Shared sub-functions
By default, sub-functions can be called only from parent and its sub-functions, but not from other QM items. QM 2.4.3 and later also supports shared sub-functions. They can be global and class.
Global shared sub-functions can be called from anywhere. They must be in functions named "__sub_X", where X can be any name. They are called like sub_X.Func(1 2).
Class shared sub-functions can be called from any member functions of that class, and from their sub-functions. They must be in class member functions named "Class.__subX", where Class is class name and X can be any name. They are called like subX.Func(1 2) or classVar.subX.Func(1 2). Use attribute c for class member sub-functions, like #sub Member c. Functions without this attribute are like global functions, but they can be called only from functions of that class, and they can call any functions of that class (public, private and protected).
Shared sub-functions cannot have attributes v, r and m. Can have attribute p that makes the sub-function non-shared.
The __sub_X and Class.__subX functions can be used only as containers of shared sub-functions. They cannot be called etc. If you try to cal, run or compile such a function, instead are compiled all its shared sub-functions, which can be useful in debugging (eg to check for errors all at once).