News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Windows messages and controls

Started by zekyr, August 06, 2011, 09:02:21 AM

Previous topic - Next topic

zekyr

Sorry to bring this up! But I was curious about how windows messages work :)

I made a dialog that just had a single textbox on it and was hoping to use WM_KEYDOWN to handle when a key was pressed on it, but nothing happens when i try it! :(

So i looked at some msdn stuff or maybe it was a tutorial.. i dont remember but anyways they did something weird stuff with SendMessage, Im guessing the control has its own messages to be handled or something?

can someone point me in the right direction? sorry to bother!


include \masm32\include\masm32rt.inc

WinProc PROTO :HWND, :UINT, :WPARAM, :LPARAM

.code
start:

invoke DialogBoxParam, rv(GetModuleHandle, 0), 1, 0, OFFSET WinProc, 0
invoke ExitProcess, 0

WinProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    mov eax, uMsg
    .if eax == WM_CLOSE
        invoke EndDialog, hWnd, 0
    .elseif eax == WM_KEYDOWN
        .if wParam == VK_RETURN
            invoke EndDialog, hWnd, 0
        .endif
    .else
        mov eax, 0
    .endif
    ret           
WinProc endp

end start

MichaelW

WM_KEYDOWN and similar messages are posted to the window with the keyboard focus. In a dialog with only an edit control the edit control will have the keyboard focus. One easy method of intercepting the edit control messages is to subclass the edit control, see Subclassing a Window.

;==============================================================================
; Build as console app.
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================

IDC_EDIT equ 101

;==============================================================================
    .data
      lpPrevEditProc dd 0
      hwndEdit       dd 0
    .code
;==============================================================================

EditProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

    SWITCH uMsg
        CASE WM_KEYDOWN
            print "WM_KEYDOWN",13,10
        CASE WM_KEYUP
            print "WM_KEYUP",13,10
    ENDSW

    invoke CallWindowProc, lpPrevEditProc, hwnd, uMsg, wParam, lParam

    ret

EditProc endp

;==============================================================================

DialogProc proc hwndDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

    SWITCH uMsg

        CASE WM_INITDIALOG

            invoke GetDlgItem, hwndDlg, IDC_EDIT
            mov hwndEdit, eax

            invoke SetWindowLong, hwndEdit, GWL_WNDPROC, EditProc
            mov lpPrevEditProc, eax

        CASE WM_SIZE

            mov eax, lParam
            movzx eax, ax
            mov edx, lParam
            shr edx, 16
            invoke MoveWindow, hwndEdit, 0, 0, eax, edx, TRUE

      CASE WM_COMMAND

          SWITCH wParam

              CASE IDCANCEL

                  invoke EndDialog, hwndDlg, NULL

          ENDSW

      CASE WM_CLOSE

        invoke EndDialog, hwndDlg, NULL

    ENDSW

    return 0

DialogProc endp
;==============================================================================
start:
;==============================================================================

    Dialog "Test", \
           "FixedSys", 11, \
            WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
            1, \
            0,0,100,75, \
            1024

    DlgEdit WS_BORDER or ES_MULTILINE or ES_WANTRETURN or WS_VSCROLL or \
            WS_HSCROLL or ES_AUTOVSCROLL or ES_AUTOHSCROLL, \
            0,0,0,0,IDC_EDIT  ; will be sized in WM_SIZE handler

    invoke GetModuleHandle, NULL
    CallModalDialog eax, 0, DialogProc, NULL

    exit
;==============================================================================
end start

eschew obfuscation

dedndave

#2
one thing i have learned...
dialogs are very different from client windows
in a client window, WM_KEYDOWN acts as you might expect   :P
dialogs may be a little harder to learn, but more useful - they do a lot more stuff

MichaelW

Regarding where the WM_KEYDOWN and similar messages get posted, an application window with a child control that can and does have the keyboard focus will behave the same way as the dialog.

;==============================================================================
; Build as a console app.
;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
      hInst       dd          0
      hWnd        dd          0
      hwndEdit    dd          0
      _x          dd          0
      _y          dd          0
      wc          WNDCLASSEX  <>
      msg         MSG         <>
      className   db          "test_class",0
    .code
;==============================================================================

WndProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

    SWITCH uMsg

        CASE WM_CREATE

            invoke CreateWindowEx,0,chr$("EDIT"),0,
                   WS_VISIBLE or WS_CHILDWINDOW or \
                   ES_MULTILINE or ES_WANTRETURN or WS_VSCROLL or \
                   WS_HSCROLL or ES_AUTOVSCROLL or ES_AUTOHSCROLL,
                   0,0,0,0,hwnd,1000,0,0
            mov hwndEdit, eax

            invoke SetFocus, hwndEdit

        CASE WM_SIZE

            mov eax, lParam
            movzx eax, ax
            mov edx, lParam
            shr edx, 16
            invoke MoveWindow, hwndEdit, 0, 0, eax, edx, TRUE

        CASE WM_KEYDOWN

            print "WM_KEYDOWN",13,10

        CASE WM_KEYUP

            print "WM_KEYUP",13,10

        CASE WM_CLOSE

            invoke DestroyWindow, hwnd

        CASE WM_DESTROY

            invoke PostQuitMessage, NULL

        DEFAULT

            invoke DefWindowProc, hwnd, uMsg, wParam, lParam

    ENDSW

    ret

WndProc endp

;==============================================================================
start:
;==============================================================================

    mov hInst, rv(GetModuleHandle, NULL)
    mov wc.cbSize,        sizeof WNDCLASSEX
    mov wc.style,         CS_BYTEALIGNWINDOW
    mov wc.lpfnWndProc,   OFFSET WndProc
    mov wc.cbClsExtra,    NULL
    mov wc.cbWndExtra,    NULL
    m2m wc.hInstance,     hInst
    mov wc.hbrBackground, rv(GetStockObject, BLACK_BRUSH)
    mov wc.lpszMenuName,  NULL
    mov wc.lpszClassName, OFFSET className
    mov wc.hIcon,         rv(LoadIcon, NULL, IDI_APPLICATION)
    mov wc.hCursor,       rv(LoadCursor, NULL, IDC_ARROW)
    mov wc.hIconSm,       0
    invoke RegisterClassEx, ADDR wc

    W = 400
    H = 300
    invoke GetSystemMetrics, SM_CXSCREEN
    shr eax, 1
    sub eax, W / 2
    mov _x, eax
    invoke GetSystemMetrics, SM_CYSCREEN
    shr eax, 1
    sub eax, H / 2
    mov _y, eax

    invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
                           ADDR className,
                           chr$("Test"),
                           WS_OVERLAPPED or WS_SYSMENU,
                           _x, _y, W, H,
                           NULL, NULL,
                           hInst, NULL
    mov hWnd, eax

    invoke ShowWindow, hWnd, SW_SHOWNORMAL
    invoke UpdateWindow, hWnd

  msgLoop:

    invoke GetMessage, ADDR msg, NULL, 0, 0
    .IF eax != 0
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage, ADDR msg
      jmp   msgLoop
    .ENDIF

    exit msg.wParam

;==============================================================================
end start


eschew obfuscation

zekyr

"Regarding where the WM_KEYDOWN and similar messages get posted, an application window with a child control that can and does have the keyboard focus will behave the same way as the dialog."

So WM_KEYDOWN can only be intercepted by hijacking the WndProc stuff with the SetWindowLong?

I got it to work by the way!! Thanks a lot MichaelW!


include \masm32\include\masm32rt.inc

WinProc PROTO :HWND, :UINT, :WPARAM, :LPARAM

.data
hEdit dd 0
.code

start:
main proc
LOCAL wcex :WNDCLASSEX
LOCAL msg  :MSG

mov wcex.hInstance, rv(GetModuleHandle, 0)
mov wcex.lpszClassName, chr$("GUIClass")
mov wcex.lpfnWndProc,  OFFSET WinProc
mov wcex.hbrBackground, COLOR_WINDOW
mov wcex.hCursor, rv(LoadCursor, 0, IDC_ARROW)
mov wcex.cbSize, SIZEOF WNDCLASSEX

invoke RegisterClassEx, ADDR wcex
invoke CreateWindowEx, 0, wcex.lpszClassName, chr$("Gui stuff"), 010c80000h, 0,0,200,200,0,0, wcex.hInstance, 0


.while 1
    invoke GetMessage, ADDR msg, 0, 0, 0
    .break .if eax == 0 || eax == -1
    invoke TranslateMessage, ADDR msg
    invoke DispatchMessage, ADDR msg
.endw
invoke ExitProcess, 0

ret
main endp




EditProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    mov eax, uMsg
    .if eax == WM_KEYDOWN
        print "KEYDOWN!"
    .endif
    invoke CallWindowProc, hEdit, hWnd, uMsg, wParam, lParam
    ret
EditProc endp

WinProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    mov eax, uMsg
    .if eax == WM_CLOSE
        invoke PostQuitMessage, 0
    .elseif eax == WM_CREATE
        invoke CreateWindowEx, 0, chr$("EDIT"), 0, 010000000h + WS_CHILD + ES_MULTILINE, 0,0,200,200, hWnd, 1000,0,0
        invoke SetWindowLong, eax, GWL_WNDPROC, OFFSET EditProc
        mov hEdit, eax
    .elseif eax == WM_KEYDOWN
        print "WM_KEYDOWN that doesn't post on typing"
    .else
        invoke DefWindowProc, hWnd, uMsg, wParam, lParam
    .endif
    ret
WinProc endp


end start