Controlling Data in the Edit Field

Q. Is it possible to control information input into the edit field?

Yes, and in Chapter 10, you saw how to do this correctly using hotkeys. However, hotkeys can easily block the arrival of certain characters into the edit field. In some cases, it might be required to convert the information being entered on the fly. In this case, the subclasses mechanism can be used. To demonstrate this mechanism, consider the program provided in Listing 3.2. Now, I will modify this program to ensure that it is possible to control the information input.

Listing 18.2: The use of subclasses
image from book
 ; The EDIT.INC file ; Constants WM_CHAR              equ 102h WM_SETFOCUS          equ 7h ; This message arrives when the window is closed WM_DESTROY           equ 2 ; This message arrives when the window is created WM__CREATE           equ 1 ; This message arrives when something happens to the window elements WM_COMMAND           equ 111h ; This message allows you to get a string WM_GETTEXT           equ 0Dh ; The constant for the SetWindowLong function GWL_WNDPROC          equ -4 ; Window properties CS_VREDRAW           equ 1h CS_HREDRAW           equ 2h CS_GLOBALCLASS       equ 4000h WS_TABSTOP           equ 10000h WS_SYSMENU           equ 80000h WS_OVERLAPPEDWINDOW  equ 0+WS_TABSTOP+WS_SYSMENU STYLE                equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS CS_HREDRAW           equ 2h BS_DEFPUSHBUTTON     equ 1h WS_VISIBLE           equ 10000000h WS_CHILD             equ 40000000h WS_BORDER            equ 800000h STYLBTN              equ WS_CHILD+BS_DEFPUSHBUTTON+WS_VISIBLE+WS_TABSTOP STYLEDT              equ WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP ; Standard icon identifier IDI_APPLICATION      equ 32512 ; Cursor identifier IDC_ARROW            equ 32512 ; Window display mode - Normal SW_SHOWNORMAL        equ 1 ; Prototypes of external procedures IFDEF MASM        EXTERN CallWindowProcA@ 2 0:NEAR        EXTERN SetWindowLongA@12:NEAR        EXTERN SetFocus@4:NEAR        EXTERN SendMessageA@16:NEAR        EXTERN MessageBoxA@16:NEAR        EXTERN CreateWindowExAg 48:NEAR        EXTERN DefWindowProcA@16:NEAR        EXTERN DispatchMessageA@4:NEAR        EXTERN ExitProcess@4:NEAR        EXTERN GetMessageA@16:NEAR        EXTERN GetModuleHandleA@ 4:NEAR        EXTERN LoadCursorA@ 8:NEAR        EXTERN LoadIconAg 8:NEAR        EXTERN PostQuitMessage@4:NEAR        EXTERN RegisterClassA@4:NEAR        EXTERN ShowWindow@ 8:NEAR        EXTERN TranslateMessage@4:NEAR        EXTERN UpdateWindow@4:NEAR ELSE        EXTERN CallWindowProcA:NEAR        EXTERN SetWindowLongA:NEAR        EXTERN SetFocus:NEAR        EXTERN SendMessageA:NEAR        EXTERN MessageBoxA:NEAR        EXTERN CreateWindowExA:NEAR        EXTERN DefWindowProcA:NEAR        EXTERN DispatchMessageA:NEAR        EXTERN ExitProcess:NEAR        EXTERN GetMessageA:NEAR        EXTERN GetModuleHandleA:NEAR        EXTERN LoadCursorA:NEAR        EXTERN LoadIconA:NEAR        EXTERN PostQuitMessage:NEAR        EXTERN RegisterClassA:NEAR        EXTERN ShowWindow:NEAR        EXTERN TranslateMessage:NEAR        EXTERN UpdateWindow:NEAR        CallWindowProcA@20 = CallWindowProcA        SetWindowLongA@12 = SetWindowLongA        SetFocus@4 = SetFocus        SendMessageA@16 = SendMessageA        MessageBoxA@16 = MessageBoxA        CreateWindowExA@48 = CreateWindowExA        DefWindowProcA@16 = DefWindowProcA        DispatchMessageA@4 = DispatchMessageA        ExitProcess@4 = ExitProcess        GetMessageA@16 = GetMessageA        GetModuleHandleA@4 = GetModuleHandleA        LoadCursorA@8 = LoadCursorA        LoadIconA@8 = LoadlconA        PostQuitMessage@4 = PostQuitMessage        RegisterClassA@4 = RegisterClassA        ShowWindow@8 = ShowWindow        TranslateMessage@4 = TranslateMessage        UpdateWindow@4 = UpdateWindow ENDIF ; Structures ; Message structure MSGSTRUCT STRUC        MSHWND     DD ?        MSMESSAGE  DD ?        MSWPARAM   DD ?        MSLPARAM   DD ?        MSTIME     DD ?        MSPT       DD ? MSGSTRUCT ENDS ;---- Window class structure WNDCLASS STRUC        CLSSTYLE   DD ?        CLWNDPROC  DD ?        CLSCBCLSEX DD ?        CLSCBWNDEX DD ?        CLSHINST   DD ?        CLSHICON   DD ?        CLSHCURSOR DD ?        CLBKGROUND DD ?        CLMENNAME  DD ?        CLNAME     DD ? WNDCLASS ENDS ; The EDIT.'ASM file .586P ; Flat memory model .MODEL FLAT, stdcall include editn.inc ; INCLUDELIB directives for the linker IFDEF MASM        includelib c:\masm32\lib\user32.lib        includelib c:\masm32\lib\kernel32.lib ELSE        includelib c:\tasm32\lib\import32.lib ENDIF ;---------------------------------------------- ; Data segment _DATA SEGMENT        NEWHWND    DD 0        MSG        MSGSTRUCT  <?>        WC         WNDCLASS  <?>        HINST      DD 0 ; Application descriptor        TITLENAME  DB 'Controlling the edit field', 0        CLASSNAME  DB 'CLASS32', 0        CPBUT      DB 'Exit', 0 ; Exit        CPEDT      DB ' ', 0        CLSBUTN    DB 'BUTTON1, 0        CLSEDIT    DB 'EDIT', 0        HWNDBTN    DWORD 0        HWNDEDT    DWORD 0        CAP        BYTE 'Message', 0        MES        BYTE 'Exiting the program', 0        TEXT       DB 100 DUP(0)        OLDWND     DD 0        CHAR       DD ? _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the application handle        PUSH  0        CALL  GetModuleHandleA@4        MOV   [HINST], EAX REG_CLASS: ; Fill the window structure ; Style        MOV   [WC.CLSSTYLE], STYLE ; Message-handling procedure        MOV   [WC.CLWNDPROC], OFFSET WNDPROC        MOV   [WC.CLSCBCLSEX], 0        MOV   [WC.CLSCBWNDEX], 0        MOV   EAX, [HINST]        MOV   [WC.CLSHINST], EAX ;---------- Window icon        PUSH  IDI_APPLICATION        PUSH  0        CALL  LoadIconA@8        MOV   [WC.CLSHICON], EAX ;---------- Window cursor        PUSH  IDC_ARROW        PUSH  0        CALL  LoadCursorA@8        MOV   [WC.CLSHCURSOR], EAX        MOV   [WC.CLBKGROUND], 17 ; Window color        MOV   DWORD PTR [WC.CLMENNAME], 0        MOV   DWORD PTR [WC.CLNAME], OFFSET CLASSNAME        PUSH  OFFSET WC        CALL  RegisterClassA@4 ; Create a window of the registered class        PUSH  0        PUSH  [HINST]        PUSH  0        PUSH  0        PUSH  150      ; DY - Window height        PUSH  400      ; DX - Window width        PUSH  100      ; Y - Coordinate of the top left corner        PUSH  100      ; X - Coordinate of the top left corner        PUSH  WS_OVERLAPPEDWINDOW        PUSH  OFFSET TITLENAME ; Window name        PUSH  OFFSET CLASSNAME ; Class name        PUSH  0        CALL  CreateWindowExA@48 ; Check for an error        CMP   EAX, 0        JZ    _ERR        MOV   [NEWHWND], EAX ; Window descriptor ;------------------------------        PUSH  SW_SHOWNORMAL        PUSH  [NEWHWND]        CALL  ShowWindow@8 ; Show the newly-created window ;------------------------------        PUSH  [NEWHWND]        CALL  UpdateWindow@4      ; Redraw the visible part                                  ; of the window, the WM_PAINT message ; Message-processing loop MSG_LOOP:        PUSH  0        PUSH  0        PUSH  0        PUSH  OFFSET MSG        CALL  GetMessageA@16        CMP   AX, 0        JE    END_LOOP        PUSH  OFFSET MSG        CALL  TranslateMessage@4        PUSH  OFFSET MSG        CALL  DispatchMessageA@4        JMP   MSG_LOOP END_LOOP: ; Exit the program (close the process)        PUSH  [MSG.MSWPARAM]        CALL  ExitProcess@4 _ERR:        JMP   END_LOOP ;---------------------------------------- ; Window procedure ; Position of parameters in the stack ; [EBP+014H] ; LPARAM ; [EBP+10H]  ; WAPARAM ; [EBP+0CH]  ; MES ; [EBP+8]    ; HWND WNDPROC  PROC        PUSH  EBP        MOV   EBP, ESP        PUSH  EBX        PUSH  ESI        PUSH  EDI        CMP   DWORD PTR [EBP+0CH], WM_DESTROY        JE    WMDESTROY        CMP   DWORD PTR [EBP+0CH], WM_CREATE        JE    WMCREATE        CMP   DWORD PTR [EBP+0CH], WM_COMMAND        JE    WMCOMMND        JMP   DEFWNDPROC WMCOMMND:        MOV   EAX, HWNDBTN        CMP   DWORD PTR [EBP+14H], EAX        JNE   NODESTROY        JMP   WMDESTROY NODESTROY:        MOV   EAX, 0        JMP   FINISH WMCREATE: ; Create the button window        PUSH  0        PUSH  [HINST]        PUSH  0        PUSH  DWORD PTR [EBP+08H]        PUSH  20      ; DY        PUSH  60      ; DX        PUSH  10      ; Y        PUSH  10      ; X        PUSH  STYLBTN        PUSH  OFFSET CPBUT   ; Window name        PUSH  OFFSET CLSBUTN ; Class name        PUSH  0        CALL  CreateWindowExA@48        MOV   HWNDBTN, EAX ; Save the button descriptor ; Create the edit field        PUSH  0        PUSH  [HINST]        PUSH  0        PUSH  DWORD PTR [EBP+08H]        PUSH  20       ; DY        PUSH  350      ; DX        PUSH  50       ; Y        PUSH  10       ; X        PUSH  STYLEDT        PUSH  OFFSET CPEDT   ; Window name        PUSH  OFFSET CLSEDIT ; Class name        PUSH  0        CALL  CreateWindowExA@48        MOV   HWNDEDT, EAX ; Set the focus to the edit field        PUSH  HWNDEDT        CALL  SetFocus@4 ; Set the custom handler procedure        PUSH  OFFSET WNDEDIT        PUSH  GWL_WNDPROC        PUSH  [HWNDEDT]        CALL  SetWindowLongA@12        MOV   OLDWND, EAX        MOV   EAX, 0        JMP   FINISH DEFWNDPROC:        PUSH  DWORD PTR [EBP+14H]        PUSH  DWORD PTR [EBP+10H]        PUSH  DWORD PTR [EBP+0CH]        PUSH  DWORD PTR [EBP+08H]        CALL  DefWindowProcA@16        JMP   FINISH WMDESTROY: ; Get the edited string        PUSH  OFFSET TEXT        PUSH  150        PUSH  WM_GETTEXT        PUSH  HWNDEDT        CALL  SendMessageA@16 ; Show the edited string        PUSH  0        PUSH  OFFSET CAP        PUSH  OFFSET TEXT        PUSH  DWORD PTR [EBP+08H] ; Window descriptor        CALL  MessageBoxA@16 ; Go to exit        PUSH  0        CALL  PostQuitMessage@4 ; Message WM_QUIT        MOV   EAX, 0 FINISH:        POP   EDI        POP   ESI        POP   EBX        POP   EBP        RET   16 WNDPROC    ENDP ;-------------------------------------------- ; New message-handling procedure for the edit field WNDEDIT PROC        PUSH  EBP        MOV   EBP, ESP        MOV   EAX, DWORD PTR [EBP+10H]        MOV   CHAR, EAX        CMP   DWORD PTR [EBP+0CH], WM_CHAR        JNE   _OLD ; Check the input character        CMP   AL, 13        JNE   _OLD ; Send the message about closing the main window        PUSH  0        PUSH  0        PUSH  WM_DESTROY        PUSH  [NEWHWND]        CALL  SendMessageA@16 _OLD: ; Call the old procedure        PUSH  DWORD PTR [EBP+014H]        PUSH  DWORD PTR [EBP+10H]        PUSH  DWORD PTR [EBP+0CH]        PUSH  DWORD PTR [EBP+8H]        PUSH  [OLDWND]        CALL  CallWindowProcA@20 FIN:        POP   EBP        RET   16 WNDEDIT ENDP _TEXT ENDS END START 
image from book
 

There isn't anything new in this mechanism. Even in the MS-DOS operating system, it was possible to trap interrupts and build custom procedures into their handling. As a result, the custom procedure was called prior to the previously installed one if a call was made to this interrupt. It also was possible to proceed in a different way: first, to call the existing procedure, and then, to call the custom one. Because it was possible to catch interrupts multiple times, a chain of sequentially executing procedures might appear as a result. I have already compared the calls with the window procedure and the interrupt calls. They are similar, aren't they? For object-oriented programming, this is nothing else but the creation of the parent class.

The foundation of this mechanism is formed by the SetWindowLong function, which can change the attributes of the existing window. The parameters of this function are as follows :

  • First parameterThe descriptor of the window created by the current process.

  • Second parameterThe value that defines what has to be changed. Generally, this is only an offset in a certain memory area. You will be interested only in the value that defines the address of the window procedure. This value is defined by the DWL_DLGPROC = 4 constant (for the dialog) or by GWL_WNDPROC = ˆ 4 (for a normal window). Hence, this operation can be carried out not only over normal windows but also over dialog boxes.

  • Third parameterThe new value of the window attribute.

It is also necessary to mention that this function returns the old attribute value.

I must note that all window elements that you create on a window are also windows with their own window functions. In everyday practice, you usually will be dealing only with messages arriving at the main window procedure.

The next question you might ask is as follows: How do I call the old window procedure? The standard CALL command is not suitable in this case. You'll have to use a special function for this purpose CallWindowProc . Parameters of this function are as follows:

  • First parameterThe address of the called procedure

  • Second parameterThe window descriptor

  • Third parameterThe message code

  • Fourth parameterThe WPARAM parameter

  • Fifth parameterThe LPARAM parameter

To translate the program presented in Listing 18.2, issue the following commands for, MASM32:

 ml /c /coff /DMASM editn.asm     link /subsystem:windows editn.obj 

Issue the following commands for TASM32:

 tasm32 /ml editn.asm     tlink32 -aa editn.obj 

When studying the program presented in Listing 18.2, notice that the method provided in this listing allows you to do practically any trick to the edit field. For example, you can block any character by sending the zero code instead of it, or you can replace the sent character with any other one.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net