I can't do what I want with DDT so started with SDK (on Saturday). I don't like the structure that is forced on you by having to process events from each control via the class wndproc, so I forced all the events into a single function by superclassing each control type to use the same class wndproc, which seems to work as long as you CallWindowProc the correct original wndproc for the control's class. Also, redirected WM_COMMAND messages from the parent wndproc. The superclassing is borrowed from Semen Matusovski and modified as necessary.
It's early days but so far I find adding events to this program structure very simple, maybe because I am not "steeped in Windows". SDKers, tell me where I went so wrong!
It's early days but so far I find adding events to this program structure very simple, maybe because I am not "steeped in Windows". SDKers, tell me where I went so wrong!
Code:
#COMPILE EXE #REGISTER NONE #DIM ALL #INCLUDE "Win32Api.Inc" ' ' SDK attempt at doing event processing all in one place ' Chris Holbrook 14-jan-2008 '-------------------------------------------------------------- TYPE ourClassnProc ' old WNDPROC and new classname ClassName AS STRING * 64 WindProc AS DWORD END TYPE ' %IDC_LAB1 = 1001 %IDC_LB1 = 1002 %IDC_BN1 = 1003 %IDC_BN2 = 1004 %IDC_CB1 = 1005 %IDC_EDIT1 = 1006 %OUR_WMCOMMAND = 100 ' GLOBAL ghinst AS DWORD ' global handle to current instance '------------------------------------------------------------------------------ ' borrowed from Semen Matusovski FUNCTION CreateSuperClass(OldClassName AS STRING, NewClassName AS STRING, lpfnNewWndProc AS LONG, cbWndExtra AS LONG) AS LONG LOCAL wc AS WNDCLASSEX STATIC tClassProc AS ourClassnProc LOCAL sz AS ASCIZ * 64 sz = NewClassName wc.cbSize = SIZEOF(wc) IF GetClassInfoEx(BYVAL 0&, BYVAL STRPTR(OldClassName), wc) THEN ' store new classname together with old class windproc for use in AllSuperProc tClassProc.Classname = NewClassName tClassProc.WindProc = wc.lpfnWndProc ' CallWindowProc lpfnNewWndProc, 0, 0, BYREF tClassProc, wc.cbWndExtra wc.hInstance = GetModuleHandle(BYVAL 0&) wc.lpszClassName = STRPTR(NewClassName) wc.lpfnWndProc = lpfnNewWndProc wc.cbWndExtra = wc.cbWndExtra + cbWndExtra FUNCTION = RegisterClassEx(wc) END IF END FUNCTION '------------------------------------------------------------------ CALLBACK FUNCTION AllSuperProc LOCAL l, levent, lcontrolid, lmsg AS DWORD LOCAL OldProc AS LONG, OffsetWndExtra AS LONG LOCAL sz AS ASCIZ * 64 LOCAL pClassProc AS ourClassnProc PTR DIM tClass_Windprocs(0 TO 10 ) AS STATIC ourClassnProc ' 10 classes? should be enough! STATIC lstate AS LONG ' whenever CreateSuperClass is called, we need to add a classname and oldWNDPROC ' to the array IF CBHNDL = 0 THEN ' CreateSuperClass is talking to us pClassProc = CBWPARAM OffsetWndExtra = CBLPARAM ' add a classname and OldClassWndProc to array WHILE tClass_Windprocs(l).WindProc <> 0 INCR l WEND tClass_Windprocs(l).Classname = @pClassProc.Classname tClass_Windprocs(l).WindProc = @pClassProc.WindProc EXIT FUNCTION ' don't need to pass this message on END IF lmsg = CBMSG IF CBMSG = %WM_USER + %OUR_WMCOMMAND THEN sz="WM_COMMAND" lmsg = %WM_COMMAND ' pretend that we got the WM_COMMAND message END IF lControlId = getDlgCtrlId(CBHNDL) levent = MAK(DWORD, lControlId, lMsg) sz = sz + " " + STR$(lControlId) + " &H" + HEX$(lmsg) ' uncomment this to see all msgs ' sendmessage( getdlgitem(getparent(CBHNDL), %idc_lb1), %LB_INSERTSTRING, 0, varptr(sz)) ' SELECT CASE levent CASE MAK(DWORD, %IDOK, %WM_COMMAND) : GOSUB IDOK_WM_COMMAND CASE MAK(DWORD,%IDC_LAB1, %WM_MOUSEMOVE) : GOSUB IDC_LAB1_WM_MOUSEMOVE CASE MAK(DWORD,%IDC_BN2, %WM_COMMAND) : GOSUB IDC_BN2_WM_COMMAND CASE MAK(DWORD, %IDC_BN2, %WM_LBUTTONDOWN) : GOSUB IDC_BN2_WM_LBUTTONDOWN CASE MAK(DWORD, %IDC_BN2, %WM_ENABLE) : GOSUB IDC_BN2_WM_ENABLE CASE MAK(DWORD, %IDC_EDIT1, %WM_VSCROLL) : GOSUB IDC_EDIT1_WM_VSCROLL END SELECT ' how to call the correct windowproc? i.e. for original class? getclassname ( CBHNDL, BYREF sz, SIZEOF(sz)) l = 0 WHILE tClass_Windprocs(l).WindProc <> 0 IF INSTR(tClass_Windprocs(l).Classname, sz) = 1 THEN oldProc = tClass_Windprocs(l).Windproc FUNCTION = CallWindowProc(OldProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM) EXIT FUNCTION END IF INCR l WEND ? "can't find windproc for class " + sz + " msg id &H" + HEX$(CBMSG) EXIT FUNCTION ' using explicit label names! IDOK_WM_COMMAND: IF CBCTLMSG <> %BN_CLICKED THEN RETURN ' toggle state IF lstate = 0 THEN 'instr(sz, "ENABLE") = 0 then lstate = 1 sz = "Click me to ENABLE Button" enableWindow (getdlgitem(getparent(CBHNDL),%IDC_BN2), %FALSE) sendmessage(getdlgitem(getparent(CBHNDL),%IDOK), %WM_SETTEXT, 0, BYREF sz) ELSE lstate = 0 sz = "Click me to DISABLE Button" enableWindow (getdlgitem(getparent(CBHNDL),%IDC_BN2), %TRUE) sendmessage(getdlgitem(getparent(CBHNDL),%IDOK), %WM_SETTEXT, 0, BYREF sz) END IF IDC_LAB1_WM_MOUSEMOVE: sz = "you moved the mouse over the label!" sendmessage( getdlgitem(getparent(CBHNDL), %idc_lb1), %LB_INSERTSTRING, 0, VARPTR(sz)) RETURN IDC_BN2_WM_COMMAND: IF CBCTLMSG <> %BN_CLICKED THEN RETURN BEEP sendmessage(getparent(CBHNDL), %wm_close, 0, 0) RETURN IDC_BN2_WM_LBUTTONDOWN: sz = "IDC_BN2 " + $TAB + "WM_LBUTTONDOWN" sendmessage( getdlgitem(getparent(CBHNDL), %idc_lb1), %LB_INSERTSTRING, 0, VARPTR(sz)) RETURN IDC_EDIT1_WM_VSCROLL: sz = "you scrolled the edit box" sendmessage( getdlgitem(getparent(CBHNDL), %idc_lb1), %LB_INSERTSTRING, 0, VARPTR(sz)) RETURN IDC_BN2_WM_ENABLE: sz = "IDC_BN2 " + $TAB + "WM_ENABLE" sendmessage( getdlgitem(getparent(CBHNDL), %idc_lb1), %LB_INSERTSTRING, 0, VARPTR(sz)) RETURN END FUNCTION '----------------------------------------------------------------------------------- FUNCTION My_MainWndProc _ ( _ BYVAL hWnd AS DWORD, _ ' window handle BYVAL uMsg AS DWORD, _ ' type of message BYVAL wParam AS DWORD, _ ' first message parameter BYVAL lParam AS LONG _ ' second message parameter ) EXPORT AS LONG LOCAL hWndChild AS DWORD LOCAL sz AS ASCIZ * 64 LOCAL i, lCid, lCtlNo AS LONG STATIC lstate AS LONG SELECT CASE uMsg CASE %WM_COMMAND lCid = LOWRD(wParam) ' control identifier sendmessage getdlgitem(hWnd, lCid), %WM_USER + %OUR_WMCOMMAND, wParam, lParam ' CASE %WM_PAINT LOCAL hdc AS LONG LOCAL ps AS PAINTSTRUCT LOCAL r AS rect hdc = beginpaint ( hWnd, BYREF ps) GetclientRect ( hwnd, BYREF r) 'drawtext( hdc, "HELLO MOTHER", -1, BYREF r, %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER ) endpaint (hwnd,BYREF ps) FUNCTION = 0 EXIT FUNCTION CASE %WM_DESTROY PostQuitMessage 0 EXIT FUNCTION ' CASE %WM_CREATE DIALOG SET TEXT hwnd, "BLAH" ' Create a label control hWndChild = CreateWindowEx(%NULL, _ "OurStatic", _ "I'm label1!", _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %SS_CENTER _ OR %SS_CENTERIMAGE OR %SS_NOTIFY,_ 5,40, 85, 30, _ hWnd, %IDC_LAB1, _ ghInst, BYVAL %NULL) INCR lCtlNo ' Create a superclassed button control hWndChild = CreateWindowEx(%NULL, _ "OurButton", _ "Goodnight!", _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_NOTIFY OR _ %BS_PUSHBUTTON OR %BS_TEXT OR %BS_CENTER OR %BS_VCENTER, _ 5, 75, 190, 20, _ hWnd, %IDC_BN2, _ ghInst, BYVAL %NULL) ' Create a superclassed Edit control hWndChild = CreateWindowEx(%NULL, _ "OurEdit", _ "Edit box!", _ %WS_CHILD OR %WS_VISIBLE OR %WS_hscroll OR %WS_VSCROLL OR _ %WS_BORDER OR %ES_LEFT OR %ES_MULTILINE OR %ES_MULTILINE OR %ES_WANTRETURN, _ 5, 120, 190, 100, _ hWnd, %IDC_EDIT1, _ ghInst, BYVAL %NULL) INCR lCtlNo ' Create a button control hWndChild = CreateWindowEx(%NULL, _ "ourBUTTON", _ "Press me to DISABLE Button!", _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_NOTIFY OR _ %BS_PUSHBUTTON OR %BS_TEXT OR %BS_CENTER OR %BS_VCENTER, _ 5, 95, 190, 20, _ hWnd, %IDOK, _ ghInst, BYVAL %NULL) INCR lCtlNo ' create a checkbox control hWndChild = CreateWindowEx(%NULL, _ "Button", _ "I'm a checkbox!", _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %SS_CENTER _ OR %SS_CENTERIMAGE OR %SS_NOTIFY OR %BS_CHECKBOX, _ 5, 5, 135, 30, _ hWnd, %IDC_CB1, _ ghInst, BYVAL %NULL) INCR lCtlNo ' create a listbox control hWndchild = CreateWindowEx(%WS_EX_CLIENTEDGE OR %ws_ex_rightscrollbar, _ "Listbox", _ "", _ %WS_CHILD OR %WS_VISIBLE OR %WS_VSCROLL OR _ %WS_BORDER OR %WS_TABSTOP OR _ %LBS_HASSTRINGS OR %LBS_NOTIFY, _ 200, 5, 285, 345, _ hWnd, %IDC_LB1, _ ' parent HWND, control ID ghInst, BYVAL %NULL) FUNCTION = 0 EXIT FUNCTION END SELECT FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam) END FUNCTION '-------------------------------------------------------------------------- FUNCTION WINMAIN _ ( BYVAL hInstance AS LONG, _ ' handle of current instance BYVAL hPrevInstance AS LONG, _ ' handle of previous instance(not used in Win32) BYVAL pszCmdLine AS ASCIIZ PTR, _ ' address of command line BYVAL nCmdShow AS LONG _ ' show state of window ) AS LONG LOCAL szClassName AS ASCIIZ * 32 ' class name LOCAL tWCX AS WNDCLASSEX ' class information LOCAL tmsg AS tagMsg ' message information LOCAL hWnd, i, lresult AS DWORD ' Save the handle of the application instance ghInst = hInstance ' Register the Form1 window szClassName = "MY_CLASS" tWCX.cbSize = SIZEOF(tWCX) ' size of WNDCLASSEX structure tWCX.style = %CS_DBLCLKS OR %CS_HREDRAW OR %CS_VREDRAW ' class styles tWCX.lpfnWndProc = CODEPTR(My_MainWndProc) ' address of window procedure used by class tWCX.cbClsExtra = 0 ' extra class bytes tWCX.cbWndExtra = 0 ' extra window bytes tWCX.hInstance = hInstance ' instance of the EXE/DLL that is registering the window tWCX.hIcon = LoadIcon(%NULL, BYVAL %IDI_APPLICATION) ' handle of class icon tWCX.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW) ' handle of class cursor tWCX.hbrBackground = getstockobject(%white_brush) ' brush used to fill background of window's client area tWCX.lpszMenuName = %NULL ' resource identifier of the class menu tWCX.lpszClassName = VARPTR(szClassName) ' class name tWCX.hIconSm = LoadIcon(%NULL, BYVAL %IDI_APPLICATION) ' handle of small icon shown in caption/system Taskbar IF ISFALSE RegisterClassEx(tWCX) THEN FUNCTION = %FALSE EXIT FUNCTION END IF ' superclass the button, STATIC, Edit, ListBox and ListView classes IF ISFALSE(CreateSuperClass("STATIC", "OurStatic", CODEPTR(AllSuperProc), 4)) THEN EXIT FUNCTION END IF IF ISFALSE(CreateSuperClass("BUTTON", "OurButton", CODEPTR(AllSuperProc), 4)) THEN EXIT FUNCTION END IF IF ISFALSE(CreateSuperClass("EDIT", "OurEdit", CODEPTR(AllSuperProc), 4)) THEN EXIT FUNCTION END IF IF ISFALSE(CreateSuperClass("LISTBOX", "OurLB", CODEPTR(AllSuperProc), 4)) THEN EXIT FUNCTION END IF ' IF ISFALSE(CreateSuperClass("SysListView32_1", "OurLVt", CODEPTR(CB1_Handler), 4)) THEN ' EXIT FUNCTION ' END IF ' Create main window hWnd = CreateWindowEx(%WS_EX_WINDOWEDGE, _ szClassName, _ "MY CREATEWINDOWEX TEST", _ %WS_OVERLAPPED OR %WS_VISIBLE OR %WS_SYSMENU, _ 50, 50, 500, 400, _ %NULL, %NULL, _ ' desktop, menu handle ghInst, BYVAL %NULL) ' fail if window is not created IF ISFALSE hWnd THEN FUNCTION = %FALSE EXIT FUNCTION END IF ' Activate window ShowWindow hWnd, %SW_SHOW ' Paint client area UpdateWindow hWnd WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0) ' if tmsg.message = %WM_COMMAND then beep IF ISFALSE IsDialogMessage(hWnd, tmsg) THEN TranslateMessage tmsg DispatchMessage tmsg END IF WEND FUNCTION = tmsg.wParam END FUNCTION
Comment