Tips-'N'-Tricks


  1. How can I define a task so that it is not displayed in Start Task and Edit menus?
  2. How can I pass arguments from command line to a task?
  3. How can I count weeks, e.g. start a task only on the second Monday of every month or on the third Sunday of December?
  4. How can I find out the name of the task which is currently being executed and the name of the crontab file where this task is located?
  5. How can I display a message box with a specified title and message?
  6. How can I "tell" nnCron that a certain task should be started only after startup/restart of my computer?
  7. How can I temporarily block mouse and keyboard input?
  8. How can I "instruct" nnCron to keep a single log file and not to create a new one every day?
  9. How can I stop a running task (e.g. in case of an error)?
  10. How can I stop a task from another task?
  11. How can I make the task Active/NoActive programmatically?
  12. How can I intercept exceptions so that I can handle them myself?
  13. How can I find out the meaning of error numbers that I see on Forth console, log file and in nncron.out?
  14. How can I change a string's encoding from WIN to OEM and vice versa?
  15. How can I use nnCron to change attributes of a file?
  16. How can I check a condition on one computer in a network and execute a task on another one (provided, of course, that a copy of nnCron is running on both computers)?
  17. How can I find out the current display resolution?
  18. How can I programmatically empty the recycle bin?
  19. How can I find short name of the file (8.3) when I'm inside the FOR-FILES: loop?
  20. How can I start my own task by double-clicking on nnCron system tray icon?
  21. How can I create my own pop-up menu which is shown when right-clicking on nnCron system tray icon?
  22. How can I launch a task using windows shortcut (*.lnk)?
  23. How can I launch a program using windows shortcut (*.lnk)?
  24. How can I copy all the files and all the subdirectories tree?
  25. How can I restart nnCron right from the given task?
  26. How can I determine the element of active window over which the mouse pointer is hovered?
  27. How can I hide any window to system tray by right-clicking on a Minimize button?

How can I define a task so that it is not displayed in Start Task and Edit menus?

Name a task this way: CLASSIC-TASK-#-.

#( CLASSIC-TASK-#-xxx
NoActive
Action:
    MSG: "CLASSIC-TASK-#-xxx"
)#

Instead of "", you can put any characters except for blank spaces (e.g. CLASSIC-TASK-#-ABCD, CLASSIC-TASK-#-123456 or CLASSIC-TASK-#-my_task). To start such a task manually, execute from a command prompt:

nncron -run CLASSIC-TASK-#-my_task

Note, please: there is no records about execution of the CLASSIC-TASK-#- tasks in nnCron log file. If you need such a record in your log file - just use the words LOG: or CRON-LOG in the task body.


How can I pass arguments from command line to a task?

It can be done if you start a task with key -runfile:

nncron.exe -runfile <file_name>

Everything that follows the file name in command line is treated as an arguments and can be read by Forth construct BL WORD (blank space is used as a delimiter). Here is an example which displays a consecutive series of message boxes with all found arguments of command line:

\ ---begin of args.spf----
: main
    BEGIN
        BL WORD COUNT ?DUP
        \ Blank space as delimiter
        \ BL SKIP [CHAR] " SKIP [CHAR] " WORD COUNT ?DUP
        \ Skipping blank spaces, quote as delimiter
    WHILE
        MsgBox
    REPEAT
    DROP
;
\ ---end of args.spf---
\ start: nncron.exe -wp -runfile args.spf one two three four

Besides, nnCron has word get-string, which performs all the "menial" work when parsing an argument: if a string is surrounded by quotation marks, then everything inside the quotation marks is treated as an argument; otherwise, only that part of the string which precedes the first encountered blank space will be considered an argument.

Example:

\ ---begin of args1.spf---
CREATE str1 256 ALLOT
: main
    get-string str1 PLACE
    MSG: "%str1 COUNT%"
;
\ ---end of args1.spf---
\ start: 
\ nncron.exe -wp -runfile args1.spf "Very long argument in quotes"

How can I count weeks, e.g. start a task only on the second Monday of every month or on the third Sunday of December?

\ here is 2nd Monday of each January (08:00)
Time: 0 8 8-14 Jan Mon * 
\ and here is 3rd Sunday of each December (08:00)
Time: 0 8 15-21 Dec Sun * 

The same trick can be also used for the first (1-7) and fourth (22-28) week, but it won't work for the last week of the month. Here you should invent something more complicated. But the value of the day of the month is easily accessible (Day@), and so is the value of the day of the week (WDay@). So you can get as complicated as you wish—and please also keep in mind word OnceAWeek.


How can I find out the name of the task which is currently being executed and the name of the crontab file where this task is located?

Name of task:

%CUR-NODE CRON-NAME @ COUNT% 

Name of crontab file:

%CUR-NODE CRON-FILENAME @ COUNT% 

To get the task name from the task itself, use word CUR-TASK-NAME ( -- a u ).


How can I display a message box with a specified title and message?

This is rather simple:

0 S" Title" DROP S" Message" DROP 0 MessageBoxA DROP

You can control message box icon and available message box buttons as well. Just use one of the following values instead of first zero when calling a message box:

0         MB_OK                                   
1         MB_OKCANCEL                             
2         MB_ABORTRETRYIGNORE                     
3         MB_YESNOCANCEL                          
4         MB_YESNO                                
5         MB_RETRYCANCEL                          
6         MB_CANCELTRYAGAINCONTINUE               
16        MB_ICONERROR                            
32        MB_ICONQUESTION                         
48        MB_ICONEXCLAMATION                      
64        MB_ICONINFORMATION                      
128       MB_USERICON                             
4096      MB_SYSTEMMODAL                          
8192      MB_TASKMODAL                            
16384     MB_HELP                                 
32768     MB_NOFOCUS                              
262144    MB_TOPMOST                              
524288    MB_RIGHT                                
1048576   MB_RTLREADING                           

Examples:

\ displaying messagebox with error-icon:
16 S" Title" DROP S" Message" DROP 0 MessageBoxA DROP
\ displaying messagebox with three buttons (Yes, No, Cancel):
3 S" Title" DROP S" Message" DROP 0 MessageBoxA DROP

MessageBoxA returns a numerical value which can be used to determine which button was pressed by the user. Here is the list of return values:

1      OK          
2      CANCEL      
3      ABORT       
4      RETRY       
5      IGNORE      
6      YES         
7      NO          
10     TRY AGAIN    
11     CONTINUE    

Examples:

#( test_retrycancel 
NoActive
Action:
    5 S" test_retrycancel" DROP S" Click me!" DROP 0 MessageBoxA
    4 =
    IF
        MSG: "Retry"
    ELSE
        MSG: "Cancel"    
    THEN
)#

#( test_yesnocancel 
NoActive
Action:
    3 S" test_yesnocancel" DROP S" Click me!" DROP 0 MessageBoxA
    DUP 6 =
    IF
        DROP
        MSG: "Yes"
    ELSE
        7 =
        IF
            MSG: "No"    
        ELSE
            MSG: "Cancel"
        THEN
    THEN
)#


How can I "tell" nnCron that a certain task should be started only after startup/restart of my computer?

Solution of this problem consists of two simple steps:

1) We must make sure first that on each startup a special flag file is created. For example, we can place in Startup folder a link to a batch file containing the following line:

echo started > c:\started.sem

2) Now it only remains to write the task itself:

#( after_system_start
WatchFile: "c:\started.sem"
Action:
    FILE-DELETE: "c:\started.sem"
    \ after this, we perform all the required action
)#

Voilà! Now this task will be started only after system startup. And, unlike the tasks which are started with the help of word START-TIME, our task will be started immediately after startup, without waiting for a new minute to begin.

Here is another method: word GetTickCount puts on stack the time that has passed since the system startup (in milliseconds). Therefore, we can check this time and if it is less then a minute or two, that would mean that the system has just started.

Example:

#( system_restart
Time: START-TIME
Rule: GetTickCount 90000 <
Action:
    \ here we perform all the required actions
)#

If a computer starts slowly, we might want to increase the length of time to which we compare GetTickCount (90000 - 150000).


How can I temporarily block mouse and keyboard input?

Here's how:

WINAPI: BlockInput USER32.DLL
: BlockTheInput TRUE BlockInput DROP ;
: UnblockTheInput FALSE BlockInput DROP ;

But this will only work in Windows 9*/2000/XP. Besides, it has been found that in Win9*, the above construct doesn't just block the user's activities, but also blocks key words SEND-KEYS: and (apparently) MOUSE* as well. Be careful!

Example:

#( test_hint
WINAPI: BlockInput USER32.DLL
: BlockInput TRUE BlockInput DROP ;
: UnblockInput FALSE BlockInput DROP ;
Action:
    BlockInput
    HINT: ">>>>> Warning! <<<<<%crlf%User input is blocked!%crlf%"
    PAUSE: 2000
    START-APP: "Notepad"
    PAUSE: 1000
    SEND-KEYS-DELAY: 200 500
    WIN-SEND-KEYS: "*Notepad" "t{ENTER}te{ENTER}tes{ENTER}test"
    SEND-KEYS: "{ENTER}test{ENTER}tes{ENTER}te{ENTER}t"
    PAUSE: 1000
    HINT-OFF
    UnblockInput
    THINT: "User input unblocked!" 3
)#

Please note also that the user input will be only blocked for the time or execution of the task which has called BlockTheInput. As soon as the task is completed, the user input is automatically unblocked.


How can I "instruct" nnCron to keep a single log file and not to create a new one every day?

To do this, you should change values of variables Cronlog and (optionally) LogTimeFormat in nncron.ini:

\ path of log
Cronlog: "log\nncron.log" 
 \ log time pattern
LogTimeFormat: "%DD% %MMM% %hh%:%mm%:%ss% %ThreadId%"

Here is how information in the log will look:

11 Jul 13:25:04 436 Start nnCron
11 Jul 13:25:07 436 Load crontab
11 Jul 13:25:08 436 D:\TOOLS\NNCRON\nncron.tab
11 Jul 13:25:08 436 D:\TOOLS\NNCRON\vk.tab
11 Jul 13:25:08 436 D:\TOOLS\NNCRON\hotkey.tab
11 Jul 13:25:08 436 D:\TOOLS\NNCRON\test.tab
11 Jul 13:25:10 988 TASK: system_restart
11 Jul 13:25:35 508 TASK: hotkey_Ctrl+Alt+F
11 Jul 13:25:36 508 Start: d:\tools\far\far.exe
11 Jul 13:25:36 508 Start result: 0

By the way, the single log can be "cut down" from time to time with the help of word FILE-CROP:.


How can I stop a running task (e.g. in case of an error)?

Use word EXIT (it belongs to Forth kernel), which is used to exit the current word. It can be used because Action: also is a Forth word.

#( test_exit
NoActive
Action:
    \ ... doing something useful 
    \ and checking for any errors:
    FILE-EXIST: "error.log"
    IF
        \ there is an error,
        \ deleting the file and stopping the task
        FILE-DELETE: "error.log"
        EXIT
    THEN
    \ ... if there are no errors, going on with our work
)#

Attention, please: word EXIT cannot be used within DO ... LOOP construct. To exit both a loop and a task, use UNLOOP EXIT: construct

DO ... IF UNLOOP EXIT THEN ... LOOP

How can I stop a task from another task?

For example, this way (it will only work in Windows NT/2000/):

#( task1
VARIABLE t1-id
Action:
    GetCurrentThreadId t1-id !
)#
#( task2 WINAPI: OpenThread KERNEL32.DLL Action: t1-id @ ?DUP IF 0 1 OpenThread ?DUP IF STOP THEN THEN )#

How can I make the task Active/NoActive programmatically?

From inside the current task:

\ activating
CUR-NODE CF-ACTIVE SET-CRON-FLAG 
\ deactivating
CUR-NODE CF-ACTIVE CLR-CRON-FLAG 

From the another task:

\ activating
<task_name> @ CF-ACTIVE SET-CRON-FLAG
\ deactivating
<task_name> @ CF-ACTIVE CLR-CRON-FLAG

Note, please: you are not changing the crontab physically, when programmatically setting or clearing NoActive task option. Thus, the task keeps it's new active/non-active status until you reload crontabs for the next time.

Using the following words you can check if the task is active or not:

\ checking if the task is active from the task itself
CF-ACTIVE?
IF
    \ ...
THEN 
\ checking if the task is active from another task
<task_name> @ CRON-FLAGS @ CF-ACTIVE AND?
IF
    \ ...
THEN 

How can I intercept exceptions so that I can handle them myself?

nnCron provides a possibility to intercept any exception and decide afterwards what you are going to do with them.

This is how exceptions are intercepted :

['] word_name CATCH

['] looks up the following word in a dictionary (in compilation mode) and compiles its address xt (execution token) into the definition as a numeric literal.
CATCH takes xt from the stack, "remembers" state of the stack (broadly speaking) and executes this xt. If an exception arises while xt is being executed, it won't go anywhere beyond CATCH. World CATCH returns 0 if there are no exceptions, and error code if there was one.

Therefore, in a "real-life" situation this will look somewhat like this:

word_attributes ['] word_name CATCH ?DUP
IF  \ processing the error
    \ error code will be on top of the stack
    \ and below it there will be some garbage,  
    \ depending on parameters
THEN

Example:

S" from-path" S" to-path" ['] FCOPY CATCH ?DUP
IF
    \ writing error code to 'nncron.out' and to the console
    ." Copy error # " . CR 
    \ removing the garbage
    2DROP 2DROP 
ELSE
    \ this branch doesn't have to exist, actually
    ." Copied successfully" CR 
THEN

You can only use CATCH directly with "postfix" words. If it is necessary to process an exception of a "prefix" word, you should first create a new postfix word based on this "prefix" word.

Example:

#( task1
: copy1 FILE-COPY: "path-from" "path-to" ;
\ ...
Action:
    ['] copy1 CATCH ?DUP
    IF \ ...
)#

Sometimes, when a task is large and there are several operators that can throw an exception, the following trick can help: we can place the entire content of Action: section into a new word and use CATCH to "watch" it.

Example:

#( task2
NoActive
: task-body
    \ placing the content of  Action: section 
    \ into a new word task-body
    \ ... 
 ;
 Action:
    \ executing the new word and catching the mistakes at the same time
    ['] task-body CATCH ?DUP IF ." Error # " . CR THEN
)# 

How can I find out the meaning of error numbers that I see on Forth console, log file and in nncron.out?

If you want the errors to be displayed on console in user-friendly (verbose) format rather then as numerical codes (5, 2003, FILE ERROR # 3 etc.), download and extract to nnCron home directory the following file: http://www.nncron.ru/download/spf_err.rar (~24k). Here you can also find descriptions of errors recorded in log file and nncron.out (you can look them up by error number).


How can I change a string's encoding from WIN to OEM and vice versa?

nnCron's kernel contains definitions of "recoding" words OemToCharBuffA and CharToOemBuffA. Here is how you can use them to change encoding of a string:

#( test_recode
NoActive
\ defining "recoding" words
: WIN2OEM ( a u -- a u ) 2DUP SWAP DUP CharToOemBuffA DROP ;
: OEM2WIN ( a u -- a u ) 2DUP SWAP DUP OemToCharBuffA DROP ;
\ creating a buffer to place a string 
\ whose encoding is going to be changed
CREATE RECODE_BUFFER 256 ALLOT
Action:
    S" a test string" RECODE_BUFFER PLACE
    \ writing text in OEM (ASCII) encoding:
    RECODE_BUFFER COUNT WIN2OEM S" c:\test_oem.txt" FWRITE
    \ writing text in WIN (ANSI) encoding:
    RECODE_BUFFER COUNT OEM2WIN S" c:\test_win.txt" FWRITE
)#

Nicholas strongly recommends to copy a string to a buffer and change its encoding there (as in above example), instead of changing encoding right where the the string is stored.


How can I use nnCron to change attributes of a file?

Let's look up what Windows API says about this:

BOOL SetFileAttributes(
LPCTSTR lpFileName, // file name
DWORD dwFileAttributes // attributes
);

That means, for example, that we can do the following :

#( test_file_attrib
WINAPI: SetFileAttributesA Kernel32.dll
NoActive
Action:
    \ setting the "hidden file" attribute:
    2 S" c:\temp\test.txt" DROP SetFileAttributesA DROP
)#

Here is a list of constants (with their values) that can be used instead of dwFileAttributes:

FILE_ATTRIBUTE_READONLY   1
FILE_ATTRIBUTE_HIDDEN     2
FILE_ATTRIBUTE_SYSTEM     4
FILE_ATTRIBUTE_DIRECTORY  16 
FILE_ATTRIBUTE_ARCHIVE    32
FILE_ATTRIBUTE_NORMAL     128 
FILE_ATTRIBUTE_COMPRESSED 2048

How can I check a condition on one computer in a network and execute a task on another one (provided, of course, that a copy of nnCron is running on both computers)?

The simplest way to do this is to use an intermediate file created on a shared network drive accessible from both computers.

In the first place, you can use this file as a flag: one computer is used to create it, and the other one to watch for it.

You can also use such a file to pass to the second copy of nnCron the text of the task to be executed. Here is an example: one copy of nnCron creates a file named remote_task.spf with the following content:

S" Hello" MsgBox

And on the second computer, the following task is being executed:

#( remote_task
WatchFile: remote_task.spf
Action:
    1000 PAUSE
    S" remote_task.spf" INCLUDED
    S" remote_task.spf" DELETE-FILE DROP
)#

Please also keep in mind that it is possible to run a task stored in a text file by using command line key -runfile


How can I find out the current display resolution?

Word WIN-RECT returns four values which are coordinates of upper left and lower right corners of a specified window. This word takes the window handle of this window as its argument. Therefore, to learn the display resolution you only have to learn the coordinates of Program Manager window: the last two values will show the current display resolution.

Example:

#( test_screen_resolution
NoActive
Action:
\ getting window handle of Program Manager WIN-EXIST: "Progman" IF \ printing the coordinates of Program Manager window to console WIN-HWND WIN-RECT . . . . CR THEN )#

How can I programmatically empty the recycle bin?

1. Create a file clearbin.spf with the following contents:

WINAPI: SHEmptyRecycleBinA shell32.dll
: main 7 0 0 SHEmptyRecycleBinA DROP ;

2. Define a task:

#( clear_task
\ Clearing the recycle bin on hotkey combination Ctrl+Alt+Shift+
AsLoggedUser
LoadProfile
WatchHotKey: "^@+c"
Action:
    ShowNormal NormalPriority
    START-APP: %ModuleDirName%nncron.exe -wp -runfile clearbin.spf
)#

Why all these complexities? Well, a user profile should be loaded in order to empty the recycle bin correctly, and a user profile will not load properly without starting a separate thread. However, if you are using Windows 9, this problem does not affect you, for you can use the following construct right within a task:

 7 0 0 SHEmptyRecycleBinA DROP

By the way, here are some constants you can use in emptying the recycle bin:

SHERB_NOCONFIRMATION 0x00000001
SHERB_NOPROGRESSUI   0x00000002
SHERB_NOSOUND        0x00000004 

How can I find short name of the file (8.3) when I'm inside the FOR-FILES: loop?

You can define a special word (say, FOUND-SHORTFILENAME) and use it inside the FOR-FILES: loop.

Example:

<%
: FOUND-SHORTFILENAME
  __FFB cAlternateFileName ASCIIZ> DUP 0=
  IF
      2DROP
      FOUND-FILENAME
  THEN
;
%> 

#( test_shortnames
NoActive
Action:
    FOR-FILES: "c:\temp\*"
        MSG: "%FOUND-FILENAME% : %FOUND-SHORTFILENAME%"
    ;FOR-FILES
)#

How can I start my own task by double-clicking on nnCron system tray icon?

Just create a postfix word (you can do this right in nncron.ini):

: launch-your-task
  S" your-task-name" SFIND IF EXECUTE LAUNCH ELSE 2DROP THEN
;

and edit the value of nncron.ini variable TrayIconDoubleClick:

TrayIconDoubleClick: launch-your-task

How can I create my own pop-up menu which is shown when right-clicking on nnCron system tray icon?

Create a plain text file menu.f in nnCron home directory and place the following definitions inside this file:

201 CONSTANT MI_ITEM1
202 CONSTANT MI_ITEM2
204 CONSTANT MI_ITEM31
205 CONSTANT MI_ITEM32
206 CONSTANT MI_ITEM33
     
: make-my-popup ( -- h )
   POPUPMENU
   S" item1 " MI_ITEM1 MENUITEM
   S" item2 " MI_ITEM2 MENUITEM
   POPUP
   S" item31 " MI_ITEM31 MENUITEM
   MENUSEPARATOR
   S" item32 " MI_ITEM31 MENUITEM
   S" item33 " MI_ITEM31 MENUITEM
   S" item3" END-POPUP
   END-MENU
;
   
: def-item-action S" item2" MsgBox ;

\ setting the action for each menu item
: start-my-menu-item ( id --   )
   CASE
   MI_ITEM1 OF S" item1" MsgBox ENDOF
   MI_ITEM2 OF def-item-action ENDOF
   MI_ITEM31 OF S" item31" MsgBox ENDOF
   MI_ITEM32 OF S" item32" MsgBox ENDOF
   MI_ITEM33 OF S" item33" MsgBox ENDOF
   ENDCASE
;
   
: my-menu 
   CronIcon hWnd @ SetForegroundWindow DROP
   make-my-popup >R
   
   \ setting one of the menu item as 'default' (should be
   \ executed by double-clicking on nnCron tray icon)
   0 MI_ITEM2 R@ SetMenuDefaultItem DROP
   
   0 CronIcon hWnd @ CalcMenuYX
   ( TPM_RETURNCMD) 256 R@ TrackPopupMenuEx
   ?DUP IF start-my-menu-item THEN
   R> DestroyMenu DROP
;

Now just edit your nncron.ini like this:

S" menu.f" INCLUDED
TrayIconDoubleClick: def-item-action
TrayIconRightButton: my-menu

That's all! Now you have an example of fully-functional multilevel pop-up menu, that will be shown by right-clicking on nnCron tray icon. Note, please, that the default menu item (the bold one) will be executed by double-clicking on nnCron tray icon as well.


How can I launch a task using windows shortcut (*.lnk)?

This is rather easy if you use the -run <task_name> command line option. Here is the procedure:

1) Create a task. Mark this task NoActive if you don't want this task to be executed automatically:

#( test_task_shortcut
NoActive
Action:
    MSG: "Hi there!"
)#

2) Now create windows shortcut in the desired location: mouse right-click - New - Shortcut and browse to 'nncron.exe'. Edit the Location of the item field like this:

<path_where_nncron_is_installed>\nncron.exe -run test_task_shortcut

Press Next and give the meaningful name for the newly created shortcut (test_task_shortcut for example). Press Finish.

3) That's it. Your shortcut is ready! Double-click it with your mouse to run test_task_shortcut task.


How can I launch a program using windows shortcut (*.lnk)?

It is not difficult at all:

#( test_shortcut 
NoActive
Action:
    5 0 0 Z" c:\temp\cmd.exe.lnk" Z" open" 0 ShellExecuteA DROP
    5 0 0 Z" c:\temp\notepad.exe.lnk" Z" open" 0 ShellExecuteA DROP
)#

The example will look slightly different if you need to authorize the task:

#( test_shortcut_authorized
NoActive
AsLoggedUser
Action:
    START-APP: tm.exe 5 0 0 Z" c:\temp\cmd.exe.lnk" Z" open" 0 ShellExecuteA HALT
    START-APP: tm.exe 5 0 0 Z" c:\temp\notepad.exe.lnk" Z" open" 0 ShellExecuteA HALT
)#

There is another one example of launching an application from the windows shortcut with authorization. This example uses JScript. Note the forward slashes in shortcut paths:

#( test_shortcut_authorized1
NoActive
AsLoggedUser
Action:
    <JScript>
        var WshShell = new ActiveXObject("WScript.Shell");
        WshShell.Run("c:/temp/cmd.exe.lnk");
        WshShell.Run("c:/temp/notepad.exe.lnk");
    </SCRIPT>
)#

How can I copy all the files and all the subdirectories tree?

The easiest solution is to use the nnBackup utility, which was created especially for this purpose:

#( test_backup
NoActive
Action:
    START-APP: nnbackup.exe copy -i "c:\data" -o "d:\backup" -v -s
)#    

On the other hand, the problem can be solved by using nnCron as the only available tool. Since FILE-COPY: does not create subdirectories when copying files, you need to have nnCron create them as shown:

#( test_backup1
NoActive
Action:
    RECURSIVE
    FOR-FILES: "c:\data\*"
        IS-DIR? 
        IF
            \ creating intermediate directories
            DIR-CREATE: "d:\backup\%FOUND-RELPATH%"
        ELSE 
            \ copying files
            FILE-COPY: "%FOUND-FULLPATH%" "d:\backup\%FOUND-RELPATH%"
        THEN 
    ;FOR-FILES 
)#

How can I restart nnCron right from the given task?

Take a look at the example (restarting nnCron every night, at 23:59):

#( test_restart
Time: 59 23
Action:
    SWHide
    StartIn: "d:\TOOLS\NNCRON"
    START-APP: %COMSPEC% /c net stop nncron && \
start/wait nncron.exe 5000 PAUSE BYE && \
net start nncron
)#

How can I determine the element of active window over which the mouse pointer is hovered?

Just send the windows message WM_NCHITTEST to the active window and analyze the numerical value that was returned. Here is the list of possible return values:

0   On the screen background or on a dividing line between windows (HTNOWHERE).	
1   In a client area (HTCLIENT).	
2   In a title bar (HTCAPTION).	
3   In a window menu or in a Close button in a child window (HTSYSMENU).	
4   In a size box (same as HTGROWBOX) (HTSIZE, HTGROWBOX).	
5   In a menu (HTMENU).	
6   In a horizontal scroll bar (HTHSCROLL).	
7   In the vertical scroll bar (HTVSCROLL).	
8   In a Minimize button (HTMINBUTTON, HTREDUCE).	
9   In a Maximize button (HTMAXBUTTON, HTZOOM).	
10  In the left border of a resizable window (the user can click the mouse to 
    resize the window horizontally) (HTLEFT).
11  In the right border of a resizable window (the user can click the mouse to 
    resize the window horizontally) (HTRIGHT).	
12  In the upper-horizontal border of a window (HTTOP).	
13  In the upper-left corner of a window border (HTTOPLEFT).	
14  In the upper-right corner of a window border (HTTOPRIGHT).	
15  In the lower-horizontal border of a resizable window (the user can click the 
    mouse to resize the window vertically) (HTBOTTOM).
16  In the lower-left corner of a border of a resizable window (the user can click 
    the mouse to resize the window diagonally) (HTBOTTOMLEFT).	
17  In the lower-right corner of a border of a resizable window (the user can click 
    the mouse to resize the window diagonally) (HTBOTTOMRIGHT).	
18  In the border of a window that does not have a sizing border (HTBORDER).	
20  In a Close button (HTCLOSE).	
21  In a Help button (HTHELP).	
-1  In a window currently covered by another window in the same thread (the message 
    will be sent to underlying windows in the same thread until one of them returns a 
    code that is not HTTRANSPARENT) (HTTRANSPARENT).
-2 On the screen background or on a dividing line between windows (same as HTNOWHERE, except that the DefWindowProc function produces a system beep to indicate an error) (HTERROR).

Example:

#( test_buttons
\ appropriate message is shown when you hover your mouse over 
\ 'Minimize', 'Maximize' or 'Close' buttons in active window
SingleInstance
Action:
    BEGIN
        MOUSE-POS 16 LSHIFT OR \ converting x,y to lParam
        \ checking the cursor position:
        0 132 GetForegroundWindow SendMessageA
        DUP 8 =  \ cursor is over the Minimize button:
        IF
            DROP
            MSG: "Minimize Button!"
        ELSE
            DUP
            9 = \ cursor is over the Maximize button:
            IF
                DROP
                MSG: "Maximize Button!"
            ELSE
                20 = \ cursor is over the Close button:
                IF
                    MSG: "Close Button!"
                THEN
            THEN
        THEN 
        PAUSE: 100
    AGAIN
)#

Use the keystate.spf plugin to monitor the mouse-click on a specified element of active window instead of mouse pointer hovering: this plugin allows you to determine wheter specified mouse button is pressed or not.

Example:

#( test_buttons_rightclick
\ appropriate message is shown when you right-click on
\ 'Minimize', 'Maximize' or 'Close' buttons in active window.
\ Make sure that plug-in 'keystate.spf' is loaded.
SingleInstance
VARIABLE allowMB \ this flag allows to work with the current window
Action:
    BEGIN
        VK_RBUTTON KEY-PRESSED? \ right mouse button
        IF
            allowMB @ \ first press?
            IF
                MOUSE-POS 16 LSHIFT OR \ converting x,y to lParam
                \ checking the cursor position:
                0 132 GetForegroundWindow SendMessageA
                DUP 8 =  \ cursor is over the Minimize button:
                IF
                    DROP
                    MSG: "Minimize Button!"
                ELSE
                    DUP
                    9 = \ cursor is over the Maximize button:
                    IF
                        DROP
                        MSG: "Maximize Button!"
                    ELSE
                        20 = \ cursor is over the Close button:
                        IF
                            MSG: "Close Button!"
                        THEN
                    THEN
                THEN
            THEN
        ELSE  
            \ the mouse button was released, set the flag to ON:
            allowMB ON
        THEN
        PAUSE: 100
    AGAIN
)#

There is another one useful example: "How can I hide any window to system tray by right-clicking on a Minimize button?".


How can I hide any window to system tray by right-clicking on a Minimize button?

There is an example from the RU.NNCRON news-group (make sure taht plugins keystate.spf and win2tray.spf are loaded):

#( test_min2tray_mouseRB
\ put the current window into system tray by 
\ right-clicking on the 'Minimize' button
SingleInstance
VARIABLE allowMB1 \ this flag allows to minimize the current window
Action:
    BEGIN
        VK_RBUTTON KEY-PRESSED? \ right mouse button
        IF
            allowMB1 @ \ first press?
            IF
                MOUSE-POS 16 LSHIFT OR \ converting x,y to lParam
                \ checking the cursor position:
                0 132 GetForegroundWindow SendMessageA
                8 =  \ if the cursor is on the Minimize button:
                IF WIN-TO-TRAY: "%GetForegroundWindow%" THEN 
                allowMB1 OFF \ set flag to OFF 
            THEN
        ELSE  
            \ the mouse button was released, set the flag to ON:
            allowMB1 ON
        THEN
        PAUSE: 100
    AGAIN
)#