Hello all, I reciently ran across a need to subclass edit boxes on a dialog box. My first hack had some problems, and I eventually goto them figured out. Now that i have the "method" understood i thought i would toss the code out for anyone who cares :) BTW: Credit also goes to Iczelion's Tutorial as a starting point. Create the Dialog box:
DialogProc Initialization Code:
invoke CreateDialogParam,hInstance,Dialog_ID,NULL,addr DialogProc,NULL mov hDlg,eax
The New Edit SubClass:
.if uMsg == WM_INITDIALOG invoke GetDlgItem, hWnd, 3001 ; Edit box 1 mov hEdit0, eax invoke GetDlgItem, hWnd, 3002 ; Edit box 2 mov hEdit1, eax invoke GetDlgItem, hWnd, 3003 ; Edit box 3 mov hEdit2, eax invoke GetDlgItem, hWnd, 3004 ; Edit box 4 mov hEdit3, eax ; SubClass them all to same Proc... invoke SetWindowLong,hEdit0,GWL_WNDPROC,addr SubEditProc mov OldEdit0,eax invoke SetWindowLong,hEdit1,GWL_WNDPROC,addr SubEditProc mov OldEdit1,eax invoke SetWindowLong,hEdit2,GWL_WNDPROC,addr SubEditProc mov OldEdit2,eax invoke SetWindowLong,hEdit3,GWL_WNDPROC,addr SubEditProc mov OldEdit3,eax
The Subclassed Edit windows in the dialog box are to restict only numeric input. As well, I added a revision to hEdit0 (Edit 1) such that it will not allow any form of input. Anywho, this is my hack of subclassing dialog boxes.. Hope it helps someone :) NaN
SubEditProc proc hEdit:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD LOCAL DoIt:DWORD mov DoIt, 0 .if uMsg==WM_CHAR mov eax,wParam .if (al>="0" && al<="9") || al==VK_BACK mov DoIt, 1 .endif .endif mov ecx, hEdit .if( ecx == hEdit0) mov DoIt, 0 .endif .if ((DoIt==1) || (uMsg!=WM_CHAR) ) .if (ecx == hEdit1) invoke CallWindowProc,OldEdit1,hEdit,uMsg,wParam,lParam .elseif (ecx == hEdit2) invoke CallWindowProc,OldEdit2,hEdit,uMsg,wParam,lParam .elseif (ecx == hEdit3) invoke CallWindowProc,OldEdit3,hEdit,uMsg,wParam,lParam .elseif (ecx == hEdit0) invoke CallWindowProc,OldEdit0,hEdit,uMsg,wParam,lParam .endif ret .endif xor eax,eax ret SubEditProc endp
Your method works but it's not efficient. If you want to create multiple controls with the same characteristics, use superclassing, not subclassing. Of course, you can subclass every control but it's quite tedious.
Thanx for the tip.. I didnt realize this :) Iczelion's Superclassing Tut:
In your programming career, you will surely encounter a situation where you need several controls with *slightly* different behavior. For example, you may need 10 edit controls which accept only number. There are several ways to achieve that goal: Create your own class and instantiate the controls Create those edit control and then subclass all of them Superclass the edit controlHowever, Im now a bit lost :( The window i made was a dialog-based main window, and all controls are defined by the resource file. It appears i dont have any control 'how' the resourced edit windows are created, and thus i can't superclass them directly as outlined in your tutorial. A bit of brain storming suggests that perhaps i could build the WINCLASS structure (derived from edit) before i call the CreateDialogParam, but i would need to somehow tell the resource file to use 'this class' for the control. Is this even remotely possible? NaN This message was edited by NaN, on 5/2/2001 12:39:23 PM
the custom control is the way to go if you want to use your own window class in a dialog. you create the wndclass and register it before you create the dialog, and specify the class name in the resource file. i'm not sure it's really worth all the trouble though.
I tried a hack at it, and appearently hitting a wall with no answers (since the window abruptly destroyes itself as fast as it is created.. ???). I would like to be as flexible with dialog boxes as normal window classes so i dont want to leave this alone untill i understand the nature of this beast.. :) Here is my latest hack, if anyone can see my flaw lemme know: The main.asm:
Nothing too special here, except im registering the main window instance, as well trying to register a new EditClass. (szEditClass == "EDIT",0 ) and (szNEWEDIT == "NEWEDIT",0). The Resource file has a new control added: (At the end)
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hDlg:HWND szText szClassName, "POINTS" mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET DialogProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,DLGWINDOWEXTRA push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_BTNFACE+1 mov wc.lpszMenuName, NULL mov wc.lpszClassName,OFFSET szClassName invoke LoadIcon,hInstance,500 mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc ; ############################ SUPERCLASSING ############################## mov wc.cbSize,sizeof WNDCLASSEX invoke GetClassInfoEx,NULL,addr szEditClass,addr wc push wc.lpfnWndProc pop OldEdit4 mov wc.lpfnWndProc, OFFSET SubEditProc push hInstance pop wc.hInstance mov wc.lpszClassName,OFFSET szNEWEDIT invoke RegisterClassEx, addr wc ; ############################ SUPERCLASSING ############################## MAKEMESSAGE "HERE" invoke CreateDialogParam,hInstance,6000,NULL,addr DialogProc,NULL mov hDlg,eax MAKEMESSAGE "HERE TO" invoke GetDlgItem,hDlg,3002 invoke SetFocus,eax invoke SetWindowText, hDlg, addr szDisplayName INVOKE ShowWindow, hDlg,SW_SHOWNORMAL INVOKE UpdateWindow, hDlg .WHILE TRUE INVOKE GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) invoke IsDialogMessage, hDlg, ADDR msg .if eax==FALSE INVOKE TranslateMessage, ADDR msg INVOKE DispatchMessage, ADDR msg .endif .ENDW mov eax,msg.wParam ret WinMain endp
I added this control with a resource editor, and assume correct (could be wrong tho), Im leaning this way because when tested, if the above code runs fine if i comment out the control ('//') above, but if i dont, the above code simple intantiates and quits in a few milli-seconds.. (nothing to learn from)! :( The SubEditClass is still the same, (expanded to handle for this control, but same none the less). The two messages were my testing points. Again, when not commented, i get the first message box (HERE), and only hear the ding of the second but never see its box (since the i
6000 DIALOGEX MOVEABLE IMPURE LOADONCALL DISCARDABLE 10, 10, 191, 74, 0 STYLE DS_MODALFRAME | 0x0004 | DS_SETFOREGROUND | DS_CENTER |\ WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_POPUP CAPTION "Ponts Finder" CLASS "POINTS" FONT 8, "MS Sans Serif", 700, 0 /*FALSE*/ BEGIN LTEXT "A", -1, 8,4,60,12, SS_LEFT, , 0 LTEXT "B", -1, 8,20,60,12, SS_LEFT, , 0 LTEXT "C", -1, 8,36,60,12, SS_LEFT, , 0 LTEXT "D", -1, 116,4,60,12, SS_LEFT, , 0 EDITTEXT 3001, 116,16,68,12, ES_AUTOHSCROLL | ES_LEFT, , 0 PUSHBUTTON "Calculate", 5000, 116,32,72,16, 0, , 0 EDITTEXT 3002, 68,4,36,12, ES_AUTOHSCROLL | ES_LEFT, , 0 EDITTEXT 3003, 68,20,36,12, ES_AUTOHSCROLL | ES_LEFT, , 0 EDITTEXT 3004, 68,36,36,12, ES_AUTOHSCROLL | ES_LEFT, , 0 CONTROL "NEWEDIT", 3005,"NEWEDIT" , WS_TABSTOP, 68,56,36,12, , 0 END
Common, someone has to have tried using a resource 'CONTROL' with a specially registered class?? How do you do it right? NaN
The syntax of your control statement in the RC file is correct. You could try replacing the NEWEDIT with EDIT, and use the standard edit control, but defined as a 'CONTROL', just to check that it works (you don't need the extra bits on the end of the line either, as the resource compiler should take defaults if they're not specified).
Also worth trying to comment out the lines that change the behaviour of your new class, and leave the default behaviour of the edit control, but use your newly registered class. You could also check the error condition of each function when it returns! Hope this is useful Nick
CONTROL "", 3005,"EDIT", WS_TABSTOP, 68, 56, 36, 12