News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Confused about windows messages

Started by ragdog, January 17, 2016, 05:39:41 AM

Previous topic - Next topic

ragdog

Hello Again

I´m a little confused about the windows messages i work with WM_Notify and this procedur works fine
My code use a Costum control this send Notify code and handle WM_Char /WM_Keydown etc messages
And send it to my dialog.


Works fine

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG

mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc,offset WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,DLGWINDOWEXTRA
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,IDM_MENU
mov wc.lpszClassName,offset ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx,addr wc
invoke CreateDialogParam,hInstance,IDD_DIALOG,NULL,addr WndProc,NULL
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
  .BREAK .if !eax
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endw
mov eax,msg.wParam
ret

WinMain endp


WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rc:RECT
mov eax,uMsg
.if eax==WM_INITDIALOG
push hWin
pop hWnd
.elseif uMsg==WM_NOTIFY
mov ebx, lParam   ; Get pointer to NMHDR
        mov eax, (NMHDR ptr [ebx]).hwndFrom
.if (eax == hMain)

.endif
.elseif uMsg==WM_SIZE
.elseif eax==WM_CLOSE
invoke DestroyWindow,hWin
.elseif uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
.endif
xor    eax,eax
ret

WndProc endp



But use i a Dialog Proc and Dialog in resource can i not work with other Messages like WM_CHAR or WM_KEYDOWN etc

Fail
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

.if uMsg==WM_INITDIALOG
.elseif uMsg==WM_NOTIFY

mov ebx, lParam   ; Get pointer to NMHDR
        mov eax, (NMHDR ptr [ebx]).hwndFrom
.if (eax == hMain)

.endif
      invoke SetWindowLong,hWnd,DWL_MSGRESULT, TRUE
mov eax,TRUE
ret

.elseif uMsg==WM_SIZE
.elseif uMsg==WM_CLOSE

invoke EndDialog,hWnd,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp


Is my SetWindowLong,hWnd,DWL_MSGRESULT wrong?
Or any an idea?

dedndave

EBX should be preserved

        push    ebx
        mov     ebx, lParam                        ; Get pointer to NMHDR
        mov     eax, [ebx].NMHDR.hwndFrom
;
;
;
        pop     ebx


i'm not sure that you use SetWindowLong to return a result

https://msdn.microsoft.com/en-us/library/windows/desktop/bb775583%28v=vs.85%29.aspx

ragdog

Hi Dave

My first address before i ask here Msdn

You have right with EBX should be preserved i have forgot ist but this is not the problem

Greets,

Fred Harris

Custom Controls usually send WM_NOTIFY messages.  Its conceivable they could send WM_CHAR or WM_KEYDOWN, but in any I have made (and I've made a lot), I always create my own custom messages and send them within the NMHDLR object.  The custom messages might be my version of WM_CHAR or WM_KEYDOWN.  Do you have a reference to how the custom control is sending the messages? 

Also, maybe it would be easier to use CreateWindow() than resource dialog windows.  I think DlgProcs might be more limited than dialog procedures.  Not sure why you are calling SetWindowLong().

Fred Harris

Quote
can i not work with other Messages like WM_CHAR or WM_KEYDOWN

To elaborate, the custom controls I write package WM_CHAR and WM_KEYDOWN message notifications within an 'extended' NMHDLR struct.  It may be possible that the custom control you are attempting to use behaves similiarly.  Here are some of the details of a grid custom control I wrote.  In the dll I have these equates...


%GRID_CELL_CHAR          = 40000             'sends keypress, keydown, lbuttondown, paste and cell
%GRID_CELL_KEYDOWN       = 40001             'double click notifications back to its host in the WM_NOTIFY
%GRID_CELL_LBUTTONDOWN   = 40002             'message.
%GRID_CELL_LBUTTONDBLCLK = 40003
%GRID_CELL_PASTE         = 40004             'My intentions in creating this control were three-fold.  First,
%GRID_VBUTTON_CLICK      = 40005             'I wanted to replace the SIGrid control which I'm presently


Then, I have this PowerBASIC Type...


Type dllGridMessage                    'Used for shipping data back to client through WM_NOTIFY message
  lpnmh                  As NMHDR
  ptCell                 As Points
  iCol                   As Long
  iRow                   As Long
  wParam                 As Long
  lParam                 As Long
End Type


When the dll is loaded and its window created, there are grid cells that register WM_CHAR and WM_KEYDOWN messages, and they are handled there.  But here is, for example, my code to handle a WM_CHAR message in the grid...


Select Case As Long wMsg
    Case %WM_CHAR
      #If %Def(%DEBUG)
      Print #fp, "    Got WM_CHAR Message In fnEditSubClass!"
      #EndIf
      dgm.lpnmh.code=%GRID_CELL_CHAR
      iReturn=SendMessage(hHost,%WM_NOTIFY,GetDlgCtrlID(hGrid),Varptr(dgm))
      #If %Def(%DEBUG)
      Print #fp, "    iReturn = " iReturn
      #EndIf
      If iReturn=-1 Then
         Function=0 : Exit Function
      End If
      If wParam=%VK_RETURN Then
         #If %Def(%DEBUG)
         Print #fp, "    Got WM_CHAR Message %VK_RETURN In fnEditSubClass!"
         #EndIf
         Call blnFlushEditControl(hGrid)
         Call Refresh(hGrid)
         #If %Def(%DEBUG)
         Print #fp, "  Leaving fnEditSubClass"
         Print #fp,
         #EndIf
         Exit Function
      Else
         @pGridData.hEdit=hEdit
      End If
    Case %WM_KEYDOWN
      #If %Def(%DEBUG)
      Print #fp, "    Got WM_KEYDOWN Message In fnEditSubClass!"
      #EndIf
      dgm.lpnmh.code=%GRID_CELL_KEYDOWN
      iReturn=SendMessage(hHost,%WM_NOTIFY,GetDlgCtrlID(hGrid),Varptr(dgm))
      #If %Def(%DEBUG)
      Print #fp, "    iReturn = " iReturn
      #EndIf


And the most critical part of that is this...


dgm.lpnmh.code=%GRID_CELL_CHAR
iReturn=SendMessage(hHost,%WM_NOTIFY,GetDlgCtrlID(hGrid),Varptr(dgm))


What that is doing is filling in the dgm object of Type dllGridMessage with the info on what occurred in the grid cell, i.e., a key press (WM_CHAR), and sending that message back to the client in WM_NOTIFY transport.  Note that a WM_NOTIFY is being sent to the client/host of the custom control, but the fact that the message is informing the client of a WM_CHAR is part of the LPNMHDLR::code member.  Also note what is being sent is the address in the dll of the object.

So, getting to the client, here is a rather wordy and verbose WM_NOTIFY handler showing how the WM_CHAR was extracted from the pointer sent from the custom control...


Function fnWndProc_OnNotify(Wea As WndEventArgs) As Long
  Local dgm As dllGridMessage Ptr
  Local hGrid As Dword

  Print #fp, "Entering fnWndProc_OnNotify()"
  hGrid=GetWindowLong(Wea.hWnd,0)
  dgm=Wea.lParam
  Select Case As Long @dgm.lpnmh.idFrom
    Case %IDC_GRID1
      Select Case As Long @dgm.lpnmh.code
        Case %GRID_CELL_KEYDOWN
          Print #fp, "  %GRID_CELL_KEYDOWN"
          Print #fp, "  hGrid                = " hGrid
          Print #fp, "  Wea.lParam           = " Wea.lParam
          Print #fp, "  @dgm.ptCell.x        = " @dgm.ptCell.x
          Print #fp, "  @dgm.ptCell.y        = " @dgm.ptCell.y
          Print #fp, "  @dgm.iCol            = " @dgm.iCol
          Print #fp, "  @dgm.iRow            = " @dgm.iRow
          Print #fp, "  @dgm.lpnmh.idFrom    = " @dgm.lpnmh.idFrom
          Print #fp, "  @dgm.lpnmh.code      = " @dgm.lpnmh.code
          Print #fp, "  @dgm.lpnmh.hwndFrom  = " @dgm.lpnmh.hwndFrom
          Print #fp, "  @dgm.wParam          = " @dgm.wParam
          Print #fp, "  Chr$$(@dgm.wParam)   = " Chr$$(@dgm.wParam)
          Print #fp, "Leaving fnWndProc_OnNotify()"
          Print #fp,
        Case %GRID_CELL_CHAR
          Print #fp, "  %GRID_CELL_CHAR"
          Print #fp, "  hGrid                = " hGrid
          Print #fp, "  Wea.lParam           = " Wea.lParam
          Print #fp, "  @dgm.ptCell.x        = " @dgm.ptCell.x
          Print #fp, "  @dgm.ptCell.y        = " @dgm.ptCell.y
          Print #fp, "  @dgm.iCol            = " @dgm.iCol
          Print #fp, "  @dgm.iRow            = " @dgm.iRow
          Print #fp, "  @dgm.lpnmh.idFrom    = " @dgm.lpnmh.idFrom
          Print #fp, "  @dgm.lpnmh.code      = " @dgm.lpnmh.code
          Print #fp, "  @dgm.lpnmh.hwndFrom  = " @dgm.lpnmh.hwndFrom
          Print #fp, "  @dgm.wParam          = " @dgm.wParam
          Print #fp, "  Chr$$(@dgm.wParam)   = " Chr$$(@dgm.wParam)
          Print #fp, "Leaving fnWndProc_OnNotify()"
          Print #fp,
        Case %GRID_CELL_LBUTTONDOWN
          Print #fp, "  %GRID_CELL_LBUTTONDOWN"
          Print #fp, "  hGrid                = " hGrid
          Print #fp, "  Wea.lParam           = " Wea.lParam
          Print #fp, "  @dgm.ptCell.x        = " @dgm.ptCell.x
          Print #fp, "  @dgm.ptCell.y        = " @dgm.ptCell.y
          Print #fp, "  @dgm.iCol            = " @dgm.iCol
          Print #fp, "  @dgm.iRow            = " @dgm.iRow
          Print #fp, "  @dgm.lpnmh.idFrom    = " @dgm.lpnmh.idFrom
          Print #fp, "  @dgm.lpnmh.code      = " @dgm.lpnmh.code
          Print #fp, "  @dgm.lpnmh.hwndFrom  = " @dgm.lpnmh.hwndFrom
          Print #fp, "  @dgm.wParam          = " @dgm.wParam
          Print #fp, "  Chr$$(@dgm.wParam)   = " Chr$$(@dgm.wParam)
          Print #fp, "Leaving fnWndProc_OnNotify()"
          Print #fp,
        Case %GRID_CELL_LBUTTONDBLCLK
          Print #fp, "  %GRID_CELL_LBUTTONDBLCLK"
          Print #fp, "  hGrid                = " hGrid
          Print #fp, "  Wea.lParam           = " Wea.lParam
          Print #fp, "  @dgm.ptCell.x        = " @dgm.ptCell.x
          Print #fp, "  @dgm.ptCell.y        = " @dgm.ptCell.y
          Print #fp, "  @dgm.iCol            = " @dgm.iCol
          Print #fp, "  @dgm.iRow            = " @dgm.iRow
          Print #fp, "  @dgm.lpnmh.idFrom    = " @dgm.lpnmh.idFrom
          Print #fp, "  @dgm.lpnmh.code      = " @dgm.lpnmh.code
          Print #fp, "  @dgm.lpnmh.hwndFrom  = " @dgm.lpnmh.hwndFrom
          Print #fp, "  @dgm.wParam          = " @dgm.wParam
          Print #fp, "  Chr$$(@dgm.wParam)   = " Chr$$(@dgm.wParam)
          Print #fp, "Leaving fnWndProc_OnNotify()"
          Print #fp,
        Case %GRID_CELL_PASTE
          Print #fp, "  %GRID_CELL_PASTE"
          Print #fp, "  hGrid                = " hGrid
          Print #fp, "  Wea.lParam           = " Wea.lParam
          Print #fp, "  @dgm.ptCell.x        = " @dgm.ptCell.x
          Print #fp, "  @dgm.ptCell.y        = " @dgm.ptCell.y
          Print #fp, "  @dgm.iCol            = " @dgm.iCol
          Print #fp, "  @dgm.iRow            = " @dgm.iRow
          Print #fp, "  @dgm.lpnmh.idFrom    = " @dgm.lpnmh.idFrom
          Print #fp, "  @dgm.lpnmh.code      = " @dgm.lpnmh.code
          Print #fp, "  @dgm.lpnmh.hwndFrom  = " @dgm.lpnmh.hwndFrom
          Print #fp, "  @dgm.wParam          = " @dgm.wParam
          Print #fp, "  Chr$$(@dgm.wParam)   = " Chr$$(@dgm.wParam)
          Print #fp, "Leaving fnWndProc_OnNotify()"
          Print #fp,
      End Select
  End Select

  fnWndProc_OnNotify=0
End Function


Hope this helps!