Sub-Classing Windows
The CMACW macro language provides a method to subclass a window so that you may customize a windows action to the fullest extent. Those of you familiar with Windows programming can understand how powerful a feature like this can be. It allows the macro language to fully customize any windows action by intercepting the messages destined for it. The syntax for sub-classing is:
SubClass_With_Macro (int window_handle, str macro_name, str additional_params);
where window_handle is the HWND of the window, macro_name is the name of the macro to execute for the window sub-class and additional_params is a string which may contain any added information to be passed to the window sub-class macro. The window sub-class macro must be of the type:
int macro_proc (int &retval, int window, wparam, lparam, str params);
where retval is the value of the message, window the HWND of the window, wparam, lparam are specific to each message and params is what you passed to the Subclass_with_Macro statement.
In order to show some of this power I have written a little macro sub-class that will log the Windows messages for a Multi-Edit buffer window to a file. This is similar to programs such as Winsight for Borland.
int MsgLogProc (int &retval, int window, message, wparam, lparam, str parms) { int rv = 0; int tw = cur_window; int lognum = parse_int ("/MSGLOG=", parms); int tr = Refresh; Refresh = False; // switch to log if(!switch_win_id(global_int("~MSGLOG-"+str(lognum)))) { return (rv); } str message_text; eof; // if not a beginning the go down a line. if (c_col > 1) down; switch ( message ) { case 0x0000 : message_text = "wm_Null"; break; case 0x0001 : message_text = "wm_Create"; break; case 0x0002 : message_text = "wm_Destroy"; break; case 0x0003 : message_text = "wm_Move"; break; case 0x0005 : message_text = "wm_Size"; break; case 0x0006 : message_text = "wm_Activate"; break; case 0x0007 : message_text = "wm_SetFocus"; break; case 0x0008 : message_text = "wm_KillFocus"; break; case 0x000A : message_text = "wm_Enable"; break; case 0x000B : message_text = "wm_SetRedraw"; break; case 0x000C : message_text = "wm_SetText"; break; case 0x000D : message_text = "wm_GetText"; break; // insert here other cases default: if(message >= 0x400) { message_text = "wm_user + 0x" + hex_str(message - 0x400); } else { message_text = "unknown 0x" + hex_str(message); } } pad_str ( message_text, 22, " " ); str wp[6] = hex_str (wparam & 0xffff), lp[10] = hex_str (lparam) ; wp = copy("0000", 1, 4 - svl(wp) ) + wp; lp = copy("00000000", 1, 8 - svl(lp) ) + lp; put_line( hex_str (window) + ": " + caps( message_text ) + " WP: 0x" + wp + " LP: 0x" + lp ); switch_window (tw); Refresh = tr; return (rv); } void Message_Log (int lognum, int window) { int tw = cur_window; int tr = refresh; refresh = False; // see if it exists if(!switch_win_id(global_int("~MSGLOG-"+str(lognum)))) { rm ("CreateWindow"); set_global_int("~MSGLOG-" + str(lognum), window_id); file_name = "MSG-" + str(lognum) + ".LOG"; } switch_window (tw); refresh = tr; subclass_with_macro (window, "MsgLogProc", "/MSGLOG=" + str(lognum)); }