Sulaiman Chang Personal Website
Tutorial 22 : Superclassing

format PE GUI 4.0
entry start

include '%fasminc%\win32a.inc'

section '.data' data readable writeable
        wndH            dd ?
        insH            dd ?
        wndClsName      db 'TUT_22',0
        wndTitle        db 'Tutorial 22',0
        wndProcAddr     dd ?

        wndCls  WNDCLASS
        wndMsg  MSG
        
        ctlClsNameEdit          db 'EDIT',0
        ctlClsNameEditHex       db 'EDIT_HEX',0
        
        editH:          times 6 dd ?
        editHBuffer     dw 16   ;2 bytes here
                        rb 14   ;14 + 2 = 16 bytes required, 15 for text, 1 for null terminated byte
        
section '.code' code readable executable
   start:
        invoke  GetModuleHandle,0
                mov  [insH],eax
                mov  [wndCls.hInstance],eax
                mov  [wndCls.style],CS_HREDRAW or CS_VREDRAW
                mov  [wndCls.lpfnWndProc],window_procedure
                mov  [wndCls.lpszClassName],wndClsName
                mov  [wndCls.hbrBackground],COLOR_BTNFACE+1
        invoke  LoadIcon,NULL,IDI_APPLICATION
                mov  [wndCls.hIcon],eax
        invoke  LoadCursor,NULL,IDC_ARROW
                mov  [wndCls.hCursor],eax
        invoke  RegisterClass,wndCls

        invoke  CreateWindowEx,WS_EX_CLIENTEDGE,\
                wndClsName,wndTitle,\
                WS_OVERLAPPEDWINDOW + WS_VISIBLE,\
                CW_USEDEFAULT,CW_USEDEFAULT,\
                400,240,\
                NULL,NULL,[insH],NULL
                mov  [wndH],eax

   ;+---------------------------+
   ;| entering the message loop |
   ;+---------------------------+
   window_message_loop_start:
        invoke  GetMessage,wndMsg,NULL,0,0
                or    eax,eax
                je    window_message_loop_end
        invoke  TranslateMessage,wndMsg
        invoke  DispatchMessage,wndMsg
                jmp     window_message_loop_start

   window_message_loop_end:
        invoke  ExitProcess,0

   ;+----------------------+
   ;| the window procedure |
   ;+----------------------+
   proc window_procedure,hWnd,uMsg,wParam,lParam
        editCls WNDCLASSEX
        counter dd 0
        enter
                push ebx esi edi
                cmp  [uMsg],WM_CREATE
                je   wmCREATE
                cmp  [uMsg],WM_DESTROY
                je   wmDESTROY
        

        wmDEFAULT:
                invoke  DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
                        jmp  wmBYE
        wmCREATE:
                        mov  [editCls.cbSize],sizeof.WNDCLASSEX
                        lea  ebx,[editCls]
                invoke  GetClassInfoEx,NULL,ctlClsNameEdit,ebx
                        push [editCls.lpfnWndProc]
                        pop  [wndProcAddr]
                        mov  [editCls.lpfnWndProc],edit_hex_procedure
                        push [insH]
                        pop  [editCls.hInstance]
                        mov  [editCls.lpszClassName],ctlClsNameEditHex
                invoke  RegisterClassEx,ebx
                        xor  ebx,ebx
                        mov  edi,20
                @@:
                        cmp  ebx,3
                        je   @f
                invoke  CreateWindowEx,WS_EX_CLIENTEDGE,ctlClsNameEditHex,NULL,\
                        WS_CHILD + WS_VISIBLE + WS_BORDER,\
                        20,edi,300,24,\
                        [hWnd],NULL,[insH],NULL
                        mov  [editH + 4 * ebx],eax
                invoke  SendMessage,eax,EM_LIMITTEXT,15,0               ;limit to 15 chars
                        inc  ebx
                        add  edi,30
                        jmp  @b
                @@:
                invoke  SetFocus,[editH]
                        jmp  wmBYE
        wmDESTROY:
                invoke  PostQuitMessage,0

        wmBYE:
                pop edi esi ebx
                return
   endp
   
   proc edit_hex_procedure,hWnd,uMsg,wParam,lParam
                push ebx esi edi
                cmp  [uMsg],WM_CHAR
                je   edit_hex_wmCHAR
                cmp  [uMsg],WM_KEYDOWN
                je   edit_hex_wmKEYDOWN
                jmp  @f
        

        edit_hex_wmCHAR:
                        mov  eax,[wParam]
                        cmp  al,VK_BACK         ;compare with virtual key BACKSPACE
                        je   @f
                        cmp  al,0x30            ;compare with ascii 0
                        jb   edit_hex_wmBYE
                        cmp  al,0x39            ;compare with ascii 9
                        jbe  @f
                        cmp  al,0x41            ;compare with ascii A
                        jb   edit_hex_wmBYE
                        cmp  al,0x46            ;compare with ascii F
                        jbe  @f
                        cmp  al,0x61            ;compare with ascii a
                        jb   edit_hex_wmBYE
                        cmp  al,0x66            ;compare with ascii f
                        jbe  wmCHAR_add
                        jmp  edit_hex_wmBYE     ;something else
                
                wmCHAR_add:
                        sub  [wParam],0x20      ;so our AL become big letter
                        jmp  @f
                @@:
                        invoke  CallWindowProc,[wndProcAddr],[hWnd],[uMsg],[wParam],[lParam]
                                jmp  edit_hex_wmBYE
        

        edit_hex_wmKEYDOWN:
                        mov  eax,[wParam]
                        cmp  al,VK_RETURN       ;compare with virtual key RETURN
                        je   wmKEYDOWN_VK_RETURN
                        cmp  al,VK_TAB
                        je   wmKEYDOWN_VK_TAB
                        jne  @b

                wmKEYDOWN_VK_TAB:
                        invoke  GetKeyState,VK_SHIFT
                                test eax,0x80000000
                                je   VK_TAB_NEXT
                                jmp  VK_TAB_PREV
                        
                        VK_TAB_NEXT:
                                invoke  GetWindow,[hWnd],GW_HWNDNEXT
                                        cmp  eax,NULL
                                        jne  VK_TAB_BYE
                                invoke  GetWindow,[hWnd],GW_HWNDFIRST
                                        jmp  VK_TAB_BYE
                        VK_TAB_PREV:
                                invoke  GetWindow,[hWnd],GW_HWNDPREV
                                        cmp  eax,NULL
                                        jne  VK_TAB_BYE
                                invoke  GetWindow,[hWnd],GW_HWNDLAST
                                        jmp  VK_TAB_BYE
                        
                        VK_TAB_BYE:
                                invoke  SetFocus,eax
                                        xor  eax,eax
                                        jmp  edit_hex_wmBYE

                wmKEYDOWN_VK_RETURN:
                        invoke  SendMessage,[hWnd],EM_GETLINE,0,editHBuffer
                        invoke  MessageBox,[hWnd],editHBuffer,wndTitle,MB_OK
                        invoke  SetFocus,[hWnd]
                                jmp  edit_hex_wmBYE

        edit_hex_wmBYE:
                        pop  edi esi ebx
                        return
   endp

section '.idata' import data readable
    library     KERNEL32, 'KERNEL32.DLL',\
                USER32,   'USER32.DLL'
    
    import      KERNEL32,\
                GetModuleHandle,        'GetModuleHandleA',\
                ExitProcess,            'ExitProcess'
    import      USER32,\
                RegisterClass,          'RegisterClassA',\
                RegisterClassEx,        'RegisterClassExA',\
                CreateWindowEx,         'CreateWindowExA',\
                DefWindowProc,          'DefWindowProcA',\
                LoadCursor,             'LoadCursorA',\
                LoadIcon,               'LoadIconA',\
                SendMessage,            'SendMessageA',\
                GetMessage,             'GetMessageA',\
                MessageBox,             'MessageBoxA',\
                GetClassInfoEx,         'GetClassInfoExA',\
                GetKeyState,            'GetKeyState',\
                GetWindow,              'GetWindow',\
                SetFocus,               'SetFocus',\
                SetWindowLong,          'SetWindowLongA',\
                CallWindowProc,         'CallWindowProcA',\
                DestroyWindow,          'DestroyWindow',\
                TranslateMessage,       'TranslateMessage',\
                DispatchMessage,        'DispatchMessageA',\
                PostQuitMessage,        'PostQuitMessage'
Result :
Copyright © 2004 Sulaiman Chang. All Rights Reserved.