Announcement

Collapse
No announcement yet.

Menu message hook

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Menu message hook

    Hi all,
    Does anyone know of a another source of info on doing message
    hooks besides msdn? I want to tinker around with it for a dropdown
    menu being shown as a result of clicking a button on a toolbar.
    The info over at msdn is a little too general and although I have
    gotten a basic understanding of it and what to use it for - I haven't gotten enough
    to construct a proper message hook. The hook I meatballed together
    is not put together right from the info I got because it generates
    gpf's when I attempt to examine the code parameter in the hook or examine
    the lparam(Which points to a msg structure if I understand it correctly.)
    I will continue to look myself, I just wanted to know if anyone knew of
    a good source of info about hooks on the net somewhere.

    Adam

    ------------------

  • #2
    Not sure what you mean there, but here is one take on it. I found
    a way to create toolbar buttons with attached down arrow and have
    used that to pop up a menu - here a "Reopen" menu with last opened
    files. Code is a bit cut to pieces, but maybe still can be of some help.

    Code:
    'In WndProc,
         CASE %WM_CREATE
     
            tbb(1).iBitmap = 1                : tbb(1).idCommand = %IDM_OPEN
            tbb(1).fsState = %TBSTATE_ENABLED : tbb(1).fsStyle   = %TBSTYLE_DROPDOWN
     
            '.. etc, with standard toolbar creation stuff..
            SendMessage hToolbar, %TB_SETEXTENDEDSTYLE, 0, %TBSTYLE_EX_DRAWDDARROWS
     
         CASE %WM_NOTIFY
            LOCAL lpToolTip AS TOOLTIPTEXT PTR, rc AS RECT
            lpToolTip = lParam
     
            IF @lpToolTip.hdr.code = %TBN_DROPDOWN THEN
               SELECT CASE @tbn.iItem
                  CASE %IDM_OPEN
                     CALL SendMessage(@tbn.hdr.hwndFrom, %TB_GETRECT, @tbn.iItem, VARPTR(rc))
                     CALL MapWindowPoints(@tbn.hdr.hwndFrom, %HWND_DESKTOP, BYVAL VARPTR(rc), 2)
                     CALL TrackPopupMenu (hMnuReopen, 0, rc.nLeft, rc.nBottom, 0, hWnd, BYVAL %NULL)
               END SELECT
            END IF
            FUNCTION = 0 : EXIT FUNCTION

    ------------------

    Comment


    • #3
      Hi Borje,
      I am sorry for not being very clear, I already know how to display
      popup menus when I click on toolbar buttons. What I am doing is
      creating a menu style toolbar and I want to mimic the behaviour of
      a standard menubar. From what I understand, the menus displayed with
      TrackPopupMenu are modal; so you app doesn't receive
      low-level keyboard and mouse messages while the menu is displayed because
      they are directed to the menu. I want to be able to intercept
      those messages and do some processing and msdn states to do that
      you have to use a message hook.
      I hope this is a little more clear.

      Adam

      ------------------

      Comment


      • #4
        Adam --
        below is one of my test. MsgName (you can find in source code section) simply converts numeric value to text.
        You can easy convert it to _CALLWNDPROC hook.
        But I think that you need WH_CBT hook to retrieve hWnd of popup menu and to subclass it.

        Right-click, type something and watch a caption of dialog.
        Code:
           #Compile Exe
           #Dim All
           #Register None
           #Include "Win32Api.Inc"
        
           Global hHook As Long, hDlg As Long, OldProc As Long
        
           Function SBProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
              If lMsg = %HCBT_CREATEWND Then
                 PostMessage hDlg, %WM_USER + 401, wParam, 0
                 UnhookWindowsHookEx hHook
              End If
           End Function
        
           CallBack Function DlgProcM
              Select Case CbMsg
                 Case %WM_CHAR
                   If CbWparam >= 32 And CbWparam <=255 Then _
                      SetWindowText hDlg, Chr$(CbWparam)
                   Exit Function
              End Select
                    Function = CallWindowProc(OldProc, CbHndl, CbMsg, CbWparam,CbLparam)
           End Function
        
           CallBack Function DlgProc
              Local hPopup As Long
              Select Case CbMsg
                 Case %WM_CONTEXTMENU
                    hHook = SetWindowsHookEx(%WH_CBT, CodePtr(SBProc), GetModuleHandle(ByVal 0&), GetCurrentThreadId)
                    Menu New Popup To hPopup
                    Menu Add String, hPopup, "First Choice", 1, %MF_ENABLED
                    Menu Add String, hPopup, "Second Choice", 2, %MF_ENABLED
                    Menu Add String, hPopup, "Third Choice", 3, %MF_ENABLED
                    TrackPopupMenu hPopup, %TPM_LEFTALIGN Or %TPM_RIGHTBUTTON, LoWrd(CbLparam), HiWrd(CbLparam), 0, CbHndl, ByVal 0
                Case %WM_COMMAND
                   Select Case CbCtl
                      Case 1 To 3: MsgBox "Menu Id" + Str$(CbCtl)
                   End Select
                Case %WM_USER + 401
                   OldProc = SetWindowLong (CbWparam, %GWL_WNDPROC, CodePtr(DlgProcM))
              End Select
           End Function
        
           Function PbMain
              Dialog New 0, "Msgbox Demo", 50, 50, 400, 200, %WS_CAPTION Or %WS_SYSMENU To hDlg
              Dialog Show Modal hDlg Call DlgProc
           End Function

        A sample of CALLWNDPROCRET hook.

        Code:
           #Compile Exe
           #Dim All
           #Register None
           #Include "Win32Api.Inc"
           #Include "MsgName.Inc"
        
           Sub CPrint (SOut As String)
              Static hConsole As Long, cWritten As Long
              If hConsole = 0 Then AllocConsole: hConsole = GetStdHandle(-11&)
              WriteConsole hConsole, ByCopy sOut + $CrLf, Len(sOut) + 2, cWritten, ByVal 0&
           End Sub
        
           Global gHook As Long
           Global hDlg As Long
           Global j As Long
        
           Type CWPRETSTRUCT
              lResult As Dword
              lParam As Dword
              wParam As Dword
              Msg As Dword
              hwnd As Dword
           End Type
           
           Type CWPSTRUCT
              lParam As Dword
              wParam As Dword
              Msg As Dword
              hwnd As Dword
           End Type
        
           Function MsgProc(ByVal nCode As Integer, ByVal wParam As Long, _
              ByVal lParam As Long) Export As Long
              Dim a As CWPRETSTRUCT Ptr
              Function = CallNextHookEx(gHook, nCode, wParam, ByVal lParam)
              a = lParam
              If nCode < 0 Or IsFalse(a) Then
              Else
                 Incr j
                 Cprint Str$(j) + ". " + MessageName(ByCopy @a.Msg) + _
                    " hWnd =&H" + Hex$(@a.hWnd) + " wParam = &H" + Hex$(@a.wParam) + _
                    " lParam = &H" + Hex$(@a.lParam)
              End If
        
           End Function
        
           %ID_Text1 = 201
        
           CallBack Function DlgProc
              Select Case CbMsg
                 Case %WM_INITDIALOG
                    %WH_CALLWNDPROCRET = 12
                     ghook = SetWindowsHookEx(%WH_CALLWNDPROCRET, CodePtr(MsgProc), _
                             0, GetWindowThreadProcessId(CbHndl, 0&))
                 Case %WM_DESTROY: UnhookWindowsHookEx gHook
             End Select
           End Function
        
           Function PbMain ()
              Dialog New 0 ,"Test",0, 0, 105, 90, %DS_CENTER Or %WS_SYSMENU Or %WS_CAPTION To hDlg
              Control Add TextBox, hDlg, %ID_Text1,"", 9, 35, 82, 30, %ES_WANTRETURN Or %ES_MULTILINE, %WS_EX_CLIENTEDGE
              Dialog Show Modal hDlg, Call DlgProc
           End Function
        [This message has been edited by Semen Matusovski (edited February 11, 2001).]

        Comment


        • #5
          Instead of using complicated hooks, why not use a modeless dialog
          without caption? I have used that way myself and by putting closing
          code in WM_KILLFOCUS, it acts just like any menu, but still gives
          users chance to click in check boxes, etc. Just as an idea..


          ------------------

          Comment


          • #6
            Thank you gentlemen; I will give these ideas a try.

            Adam

            ------------------

            Comment


            • #7
              Hmmmm, well I am not sure if these will work. I just want to interept
              the mouse messages while the dropdown menu is down so I can make
              the dropdown menu collapse if I move the cursor to a different
              button. I am already subclassing my menubar\toolbar and that allows
              me to process %WM_MENUSELECT messages so I am ok there. Well I will
              continue to chisel away at it, maybe something will "popup".

              Adam




              ------------------

              Comment


              • #8
                Semen,
                Where can I find the "MsgName.inc" file?
                TIA.
                Arthur

                ------------------



                Arthur Kohl

                Comment


                • #9
                  arthur - http://www.powerbasic.com/support/pb...ad.php?t=22819
                  (inc = function messagename)

                  adam --
                  i think, borje is correct about own dialog instead of trackpopupmenu.
                  about mouse event : yesterday (under win2000) i saw strange cbmsg = &h1e5 (?), if to move a mouse over menu.
                  probably, you need to explain exactly what do you want and exist another, more simple solution.




                  ------------------
                  e-mail: [email protected]

                  Comment


                  • #10
                    Semen,

                    Thanks.

                    Arthur

                    ------------------



                    Arthur Kohl

                    Comment


                    • #11
                      I have a customized toolbar that I have made look like a menubar.
                      I have 90% of the functionality done to mimic a standard menubar -
                      like the one in the pb editor or Internet Explorer. The thing
                      I am missing is the collapsing and showing of the dropdown menus
                      after you click one of the main menu buttons and then move the cursor
                      over one of the other buttons on the toolbar. I am not
                      talking about displaying the dropdown menu when you click the
                      button, that's not a problem. When you click the File menu item in the
                      pb editor - the shortcut menu drops down, now what happens when you
                      move the mouse over the Edit menu item without clicking anything. The
                      File dropdown menu collapses, the File item becomes "inactive";
                      the Edit item becomes hot and automatically
                      drops the edit shortcut menu down and so forth and so on with the
                      other menu items. I think you will know exactly
                      what I mean when you do it yourself. That's what I want to mimic and
                      then this baby will be complete. Just another one of those
                      curiousity binges I am on. It's been pretty interesting and
                      informative working on this - hot-tracking buttons, dropdown buttons
                      with arrows,rebar controls, owner-drawn menus w\bitmaps.
                      Pretty neat stuff to play around with. The reason I am looking
                      into message hooking is that after poking around over at msdn,
                      they say you need to implement a mesage hook because the menus
                      displayed ussing TrackPopupMenu are modal and you app no longer
                      receives low-level keyboard and mouse messages. They say to
                      implement a message hook in reponse to a %TBN_DROPDOWN noftification
                      when the dropdown menu is displayed and then handle mouse messages
                      and such in the message hook. It's not that Borje idea isn't a good one;
                      actually, I think it is a good idea, it's just that I almost have this
                      baby done and it would be a big chore to redo alot of the stuff
                      I have already done. Besides, I would like to
                      learn how to do message hooks and this would give me a good excuse since
                      I haven't done it before. Now that I have just worn out
                      several keys on my keyboard, I think I will "shut-up" for the
                      time being.

                      Adam

                      ------------------

                      Comment


                      • #12
                        I think that to imitate how File ... Edit work, it's possible to use a timer and to control cursor position.
                        Something similar following.
                        Code:
                           #Compile Exe
                           #Dim All
                           #Register None
                           #Include "WIN32API.INC"
                        
                           CallBack Function DlgProc
                              Select Case CbMsg
                                 Case %WM_INITDIALOG
                                    Control Add Label, CbHndl, 101, "Label", 10, 10, 40, 12,%SS_CENTER, %WS_EX_CLIENTEDGE
                                    Control Add Button, CbHndl, 102, "&Ok", 190, 10, 40, 14
                                    Control Add TextBox, CbHndl, 103, "", 10, 30, 170, 60, _
                                       %ES_MULTILINE Or %ES_WANTRETURN Or %WS_TABSTOP, %WS_EX_CLIENTEDGE
                                    Control Add ListBox, CbHndl, 104, , 10, 100, 170, 60
                                    SetTimer CbHndl, 1, 50, ByVal 0
                                 Case %WM_TIMER
                                    If CbCtl = 1 Then
                                       Dim pt As pointApi, id As Long, hWnd As Long, Msg As Asciiz * 50, MsgC As Static Asciiz * 50
                                       GetCursorPos pt
                                       If ScreenToClient (CbHndl, pt) Then
                                          hWnd = ChildWindowFromPoint (CbHndl, pt.x, pt.y)
                                          If hWnd = 0 Then
                                             Msg = "Out of dialog"
                                          Else
                                             If hWnd = CbHndl Then Msg = "Dialog" Else _
                                                id = GetDlgCtrlId(hWnd): Msg = "Id =" + Str$(id)
                                             Msg = Msg + " MouseX =" + Str$(pt.x) + " MouseY = " + Str$(pt.y)
                                          End If
                                          If Msg <> MsgC Then MsgC = Msg: SetWindowText CbHndl, Msg
                                       End If
                                    End If
                                 Case %WM_DESTROY
                                    KillTimer CbHndl, 1
                              End Select
                           End Function
                        
                           Function PbMain
                              Local hDlg As Long
                              Dialog New 0, "Context Help", , , 240, 180, %WS_CAPTION Or %WS_SYSMENU To hDlg
                              Dialog Show Modal hDlg Call DlgProc
                           End Function
                        ------------------
                        E-MAIL: [email protected]

                        Comment


                        • #13
                          Excellent idea with the timer Semen! It's works great.

                          Thanks,
                          Adam

                          ------------------

                          Comment

                          Working...
                          X