Loading ...
Sorry, an error occurred while loading the content.

Getting the Popup menu handle. It may work but it's hedious

Expand Messages
  • rafelafrance
    *Ugh* The current method (I ll space you the XS code): THERE HAS TO BE A BETTER WAY! 1) Call up the context menu using MouseClick() or SendKeys() 2) Set up an
    Message 1 of 7 , Sep 8, 2005
    • 0 Attachment
      *Ugh* The current method (I'll space you the XS code): THERE HAS TO
      BE A BETTER WAY!

      1) Call up the context menu using MouseClick() or SendKeys()
      2) Set up an event trap to look for the WM_MENUSELECT event
      3) SendKeys('{DOWN}'); #Which will post the WM_MENUSELECT
      4) In the callback HookProc() get the popup handle from lParam.
      5) Call another routine to retrive the popup handle GetPopupHandle()

      This should sound like nails on a chalkboard by about now. The
      problems are legion and here are just a few.

      - If you never call GetPopupHandle() the hook isn't released. BAD!
      Sure I test & release it if I can but there's no guarantee.
      - You have to dirty the menu by pressing {DOWN} to get its handle

      ==================================
      I've tried to get the popup handle all in one fell swoop by doing the
      SendKeys() etc in the C code but that wasn't working. Tho it seems
      like the way to go. Maybe...

      I'm looking for other events to trap that don't dirty the menu but I
      haven't found any that would be generally useful. Any suggestions?

      Maybe I can set up an XS object so that the trap will be set up once
      during New(). Have all popups post to this object and release the
      hook during the DESTROY method. A lot of work for little reward.
      =====================================

      Any ideas please.
    • Piotr Kaluski
      Hi, Some time ago I was trying to find a solution for the same problem. I was thinking on the way to handle IE menu bar and its submenus. This problem is
      Message 2 of 7 , Sep 8, 2005
      • 0 Attachment
        Hi,
        Some time ago I was trying to find a solution for the same problem. I
        was thinking on the way to handle IE menu bar and its submenus.
        This problem is related to what you write about, since IE menu is a
        toolbar with popup menus.
        And yes, you are right about the main problem - how to get a menu
        handle. Win32 API provides many fancy functions for managing menus
        but most of them expect menu handle as a parameter. I have found one
        promising function - GetMenuBarInfo. However I could not make the
        function work. I was getting really strange error messages
        (including "Function was successful", with an indication that there
        is an error). I tried to post the question to win32 programming
        newsgroup, but did not get any help. It would be good to have some
        real windows guru to have a look at it.
        -Piotr

        --- In perlguitest@yahoogroups.com, "rafelafrance"
        <rafelafrance@y...> wrote:
        > *Ugh* The current method (I'll space you the XS code): THERE HAS TO
        > BE A BETTER WAY!
        >
        > 1) Call up the context menu using MouseClick() or SendKeys()
        > 2) Set up an event trap to look for the WM_MENUSELECT event
        > 3) SendKeys('{DOWN}'); #Which will post the WM_MENUSELECT
        > 4) In the callback HookProc() get the popup handle from lParam.
        > 5) Call another routine to retrive the popup handle GetPopupHandle()
        >
        > This should sound like nails on a chalkboard by about now. The
        > problems are legion and here are just a few.
        >
        > - If you never call GetPopupHandle() the hook isn't released. BAD!
        > Sure I test & release it if I can but there's no guarantee.
        > - You have to dirty the menu by pressing {DOWN} to get its handle
        >
        > ==================================
        > I've tried to get the popup handle all in one fell swoop by doing
        the
        > SendKeys() etc in the C code but that wasn't working. Tho it seems
        > like the way to go. Maybe...
        >
        > I'm looking for other events to trap that don't dirty the menu but
        I
        > haven't found any that would be generally useful. Any suggestions?
        >
        > Maybe I can set up an XS object so that the trap will be set up
        once
        > during New(). Have all popups post to this object and release the
        > hook during the DESTROY method. A lot of work for little reward.
        > =====================================
        >
        > Any ideas please.
      • rafelafrance
        Thank you for your reply. After sleeping on it I realized that I can... 1) Set up a trap to WM_INITMENUPOPUP 2) Call a mouse right click (the hot key should
        Message 3 of 7 , Sep 9, 2005
        • 0 Attachment
          Thank you for your reply.

          After sleeping on it I realized that I can...

          1) Set up a trap to WM_INITMENUPOPUP
          2) Call a mouse right click (the hot key should work too) from the C
          XS code. That will put the handle into wparam
          3) I may need to sleep my process a bit (I haven't yet but I may?)
          4) Pick the handle returned from the callback
          5) Double check to make sure that the hook is released
          6) return the popup handle back up to perl

          ** It's working but i haven't been using it long

          Pros:
          1) It's done all in one call
          2) It doesn't dirty the menu

          Cons:
          1) I'm not 100% on how long i'll have to wait for a popup after the R-
          click. Maybe I should have use a timer as an optional argument? Right
          now the interface is GetPopupHandle($hwnd, $x, $y)
          2) Right now the $hwnd is the dialog's & not the control's handle.
          It's working but it does seem off.

          I can post code if anyone wants. More suggestions are welcome.

          Thanks again.

          --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
          wrote:
          > Hi,
          > Some time ago I was trying to find a solution for the same problem.
          I
          > was thinking on the way to handle IE menu bar and its submenus.
          > This problem is related to what you write about, since IE menu is a
          > toolbar with popup menus.
          > And yes, you are right about the main problem - how to get a menu
          > handle. Win32 API provides many fancy functions for managing menus
          > but most of them expect menu handle as a parameter. I have found
          one
          > promising function - GetMenuBarInfo. However I could not make the
          > function work. I was getting really strange error messages
          > (including "Function was successful", with an indication that there
          > is an error). I tried to post the question to win32 programming
          > newsgroup, but did not get any help. It would be good to have some
          > real windows guru to have a look at it.
          > -Piotr
          >
          > --- In perlguitest@yahoogroups.com, "rafelafrance"
          > <rafelafrance@y...> wrote:
          > > *Ugh* The current method (I'll space you the XS code): THERE HAS
          TO
          > > BE A BETTER WAY!
          > >
          > > 1) Call up the context menu using MouseClick() or SendKeys()
          > > 2) Set up an event trap to look for the WM_MENUSELECT event
          > > 3) SendKeys('{DOWN}'); #Which will post the WM_MENUSELECT
          > > 4) In the callback HookProc() get the popup handle from lParam.
          > > 5) Call another routine to retrive the popup handle GetPopupHandle
          ()
          > >
          > > This should sound like nails on a chalkboard by about now. The
          > > problems are legion and here are just a few.
          > >
          > > - If you never call GetPopupHandle() the hook isn't released. BAD!
          > > Sure I test & release it if I can but there's no guarantee.
          > > - You have to dirty the menu by pressing {DOWN} to get its handle
          > >
          > > ==================================
          > > I've tried to get the popup handle all in one fell swoop by doing
          > the
          > > SendKeys() etc in the C code but that wasn't working. Tho it
          seems
          > > like the way to go. Maybe...
          > >
          > > I'm looking for other events to trap that don't dirty the menu
          but
          > I
          > > haven't found any that would be generally useful. Any suggestions?
          > >
          > > Maybe I can set up an XS object so that the trap will be set up
          > once
          > > during New(). Have all popups post to this object and release the
          > > hook during the DESTROY method. A lot of work for little reward.
          > > =====================================
          > >
          > > Any ideas please.
        • Piotr Kaluski
          ... R- ... Right ... Timing is a recurring problem in GUI testing. I would just add a 4th optional parameter (as you suggest). If later on someone finds a
          Message 4 of 7 , Sep 9, 2005
          • 0 Attachment
            >
            > Cons:
            > 1) I'm not 100% on how long i'll have to wait for a popup after the
            R-
            > click. Maybe I should have use a timer as an optional argument?
            Right
            > now the interface is GetPopupHandle($hwnd, $x, $y)

            Timing is a recurring problem in GUI testing. I would just add a 4th
            optional parameter (as you suggest). If later on someone finds a
            cleaner solution, we will not use this timeout paramater any more.


            > 2) Right now the $hwnd is the dialog's & not the control's handle.
            > It's working but it does seem off.

            I don't get your point here. What do you mean by "control's handle" -
            control ID? What is exactly the problem you describe in point 2?


            > I can post code if anyone wants. More suggestions are welcome.

            Sure, go ahead - I want it very much :-). It would be great if you
            also send a documentation of the function you added, so I can add it
            in the module's documentation.

            --Piotr
          • rafelafrance
            ... the ... Done. ... handle. ... - ... Newbie mistake, sorry. Hwnd can be either the main dialog s or the control s handle in this case. ... Oops... I have
            Message 5 of 7 , Sep 11, 2005
            • 0 Attachment
              --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
              wrote:
              > >
              > > Cons:
              > > 1) I'm not 100% on how long i'll have to wait for a popup after
              the
              > R-
              > > click. Maybe I should have use a timer as an optional argument?
              > Right
              > > now the interface is GetPopupHandle($hwnd, $x, $y)
              >
              > Timing is a recurring problem in GUI testing. I would just add a 4th
              > optional parameter (as you suggest). If later on someone finds a
              > cleaner solution, we will not use this timeout paramater any more.
              >

              Done.

              >
              > > 2) Right now the $hwnd is the dialog's & not the control's
              handle.
              > > It's working but it does seem off.
              >
              > I don't get your point here. What do you mean by "control's handle"
              -
              > control ID? What is exactly the problem you describe in point 2?

              Newbie mistake, sorry. Hwnd can be either the main dialog's or the
              control's handle in this case.

              >
              > > I can post code if anyone wants. More suggestions are welcome.
              >
              > Sure, go ahead - I want it very much :-). It would be great if you
              > also send a documentation of the function you added, so I can add it
              > in the module's documentation.
              >

              Oops... I have made many changes, backing out the other changes for
              this post.

              Submitted for your approval. NB: I had to use the 'mickey' coordinate
              transformation. The comments suggest that this is an XP only thing.

              I hope unix style diffs are OK.

              $ diff -U5 Win32-GuiTest-1.50.3-ad/guitest.xs guitest_popuphandle.xs

              --- Win32-GuiTest-1.50.3-ad/guitest.xs 2005-02-02 19:06:52.000000000
              -0500
              +++ guitest_popuphandle.xs 2005-09-11 22:57:42.000000000 -0400
              @@ -36,10 +36,11 @@

              #pragma data_seg(".shared")
              // Used by hooking/injected routines
              HWND g_hWnd = 0;
              HHOOK g_hHook = NULL;
              +HWND g_popup = 0; //Hold's popup menu's handle
              BOOL g_bRetVal = 0;
              char g_szBuffer[MAX_DATA_BUF+1] = {NUL};
              UINT WM_LV_GETTEXT = 0;
              UINT WM_LV_SELBYINDEX = 0;
              UINT WM_LV_SELBYTEXT = 0;
              @@ -48,10 +49,11 @@
              UINT WM_TC_SELBYINDEX = 0;
              UINT WM_TC_SELBYTEXT = 0;
              UINT WM_TC_ISSEL = 0;
              UINT WM_TV_SELBYPATH = 0;
              UINT WM_TV_GETSELPATH = 0;
              +UINT WM_INITMENUPOPUPX = WM_INITMENUPOPUP; //Only needed to conform
              with SetHook()'s calling convention
              #pragma data_seg()
              #pragma comment(linker, "/SECTION:.shared,RWS")

              BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,
              LPVOID lpReserved)
              @@ -292,10 +294,13 @@
              if (lstrcmpi(g_szBuffer, szName) == 0) {
              // Yes, selected
              g_bRetVal = TRUE;
              }
              UnhookWindowsHookEx(g_hHook);
              + } else if (pCW->message == WM_INITMENUPOPUP) {
              + g_popup = (HWND) pCW->wParam;
              + UnhookWindowsHookEx(g_hHook);
              }

              return CallNextHookEx(g_hHook, code, wParam, lParam);
              }

              @@ -801,11 +806,26 @@
              safefree(text);
              }
              return sv;
              }

              -
              +/////////////////////////////////////////////////
              ///////////////////////////
              +HWND PopupHandleGet(HWND hWnd, int x, int y, int wait) {
              + g_popup = 0;
              + if (SetHook(hWnd, WM_INITMENUPOPUPX, "WM_INITMENUPOPUP_RM") ==
              NULL)
              + return 0;
              + int mickey_x = MulDiv(x, 0x10000, GetSystemMetrics(SM_CXSCREEN));
              + int mickey_y = MulDiv(y, 0x10000, GetSystemMetrics(SM_CYSCREEN));
              + simple_mouse(MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE, mickey_x,
              mickey_y);
              + simple_mouse(MOUSEEVENTF_RIGHTDOWN, 0, 0);
              + simple_mouse(MOUSEEVENTF_RIGHTUP, 0, 0);
              + Sleep(wait);
              + if (g_popup == 0)
              + UnhookWindowsHookEx(g_hHook);
              + return g_popup;
              +}
              +/////////////////////////////////////////////////
              ///////////////////////////

              MODULE = Win32::GuiTest PACKAGE = Win32::GuiTest

              PROTOTYPES: DISABLE

              @@ -1708,10 +1728,22 @@
              pt.y = y;
              RETVAL = WindowFromPoint(pt);
              OUTPUT:
              RETVAL

              +#################################################
              ###########################
              +HWND
              +GetPopupHandle(hWnd, x, y, wait=50)
              + HWND hWnd;
              + int x;
              + int y;
              + int wait;
              +CODE:
              + RETVAL = PopupHandleGet(hWnd, x, y, wait);
              +OUTPUT:
              + RETVAL
              +#################################################
              ###########################

              MODULE = Win32::GuiTest PACKAGE =
              Win32::GuiTest::DibSect

              PROTOTYPES: DISABLE


              **********************************************
              Now the guitest.pm
              **********************************************
              $ diff -U5 Win32-GuiTest-1.50.3-ad/guitest.pm guitest_popuphandle.pm
              --- Win32-GuiTest-1.50.3-ad/guitest.pm 2005-02-02 18:43:15.000000000
              -0500
              +++ guitest_popuphandle.pm 2005-09-11 23:41:21.000000000 -0400
              @@ -121,10 +121,11 @@
              GetSubMenu GetMenuItemIndex GetMenuItemId GetMenuItemCount
              GetMenuItemInfo
              GetListViewContents SelListViewItem SelListViewItemText
              IsListViewItemSel
              GetTabItems SelTabItem SelTabItemText IsTabItemSel
              SelTreeViewItemPath GetTreeViewSelPath MouseMoveWheel
              SelComboItem SelComboItemText
              + GetPopupHandle
              )],
              VARS => [ qw(
              $debug
              )],
              SW => [ qw(
              @@ -1042,10 +1043,18 @@
              SelTreeViewItemPath($window, "Parent|Child");
              SelTreeViewItemPath($window, $oldpath);

              =cut

              +=item $hpopup = GetPopupHandle($hwnd, $x, $y, [$wait])
              +
              + This function gets the handle of a popup window generated by
              + right-clicking at the $x and $y screen coordinates (absolute). An
              + optional delay can be entered which will wait the given number of
              + milliseconds after the right-click for the window to appear
              (default
              + is 50). Zero is returned when no popup menu is found.
              +
              =back

              =head2 DibSect

              A class to manage a Windows DIB section. Currently limited in
              functionality to
            • Piotr Kaluski
              Thank you very much, Please allow some time for reviewing your changes and putting them in the code base (it may take 2 weeks). I have just committed some
              Message 6 of 7 , Sep 11, 2005
              • 0 Attachment
                Thank you very much,
                Please allow some time for reviewing your changes and putting them in
                the code base (it may take 2 weeks). I have just committed some
                changes in the code and I am updating documentation. Once it is done
                I will have a look at your changes.

                -Piotr

                --- In perlguitest@yahoogroups.com, "rafelafrance"
                <rafelafrance@y...> wrote:
                > --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
                > wrote:
                > > >
                > > > Cons:
                > > > 1) I'm not 100% on how long i'll have to wait for a popup after
                > the
                > > R-
                > > > click. Maybe I should have use a timer as an optional argument?
                > > Right
                > > > now the interface is GetPopupHandle($hwnd, $x, $y)
                > >
                > > Timing is a recurring problem in GUI testing. I would just add a
                4th
                > > optional parameter (as you suggest). If later on someone finds a
                > > cleaner solution, we will not use this timeout paramater any more.
                > >
                >
                > Done.
                >
                > >
                > > > 2) Right now the $hwnd is the dialog's & not the control's
                > handle.
                > > > It's working but it does seem off.
                > >
                > > I don't get your point here. What do you mean by "control's
                handle"
                > -
                > > control ID? What is exactly the problem you describe in point 2?
                >
                > Newbie mistake, sorry. Hwnd can be either the main dialog's or the
                > control's handle in this case.
                >
                > >
                > > > I can post code if anyone wants. More suggestions are welcome.
                > >
                > > Sure, go ahead - I want it very much :-). It would be great if you
                > > also send a documentation of the function you added, so I can add
                it
                > > in the module's documentation.
                > >
                >
                > Oops... I have made many changes, backing out the other changes for
                > this post.
                >
                > Submitted for your approval. NB: I had to use the 'mickey'
                coordinate
                > transformation. The comments suggest that this is an XP only thing.
                >
                > I hope unix style diffs are OK.
                >
                > $ diff -U5 Win32-GuiTest-1.50.3-ad/guitest.xs
                guitest_popuphandle.xs
                >
                > --- Win32-GuiTest-1.50.3-ad/guitest.xs 2005-02-02
                19:06:52.000000000
                > -0500
                > +++ guitest_popuphandle.xs 2005-09-11 22:57:42.000000000 -0400
                > @@ -36,10 +36,11 @@
                >
                > #pragma data_seg(".shared")
                > // Used by hooking/injected routines
                > HWND g_hWnd = 0;
                > HHOOK g_hHook = NULL;
                > +HWND g_popup = 0; //Hold's popup menu's handle
                > BOOL g_bRetVal = 0;
                > char g_szBuffer[MAX_DATA_BUF+1] = {NUL};
                > UINT WM_LV_GETTEXT = 0;
                > UINT WM_LV_SELBYINDEX = 0;
                > UINT WM_LV_SELBYTEXT = 0;
                > @@ -48,10 +49,11 @@
                > UINT WM_TC_SELBYINDEX = 0;
                > UINT WM_TC_SELBYTEXT = 0;
                > UINT WM_TC_ISSEL = 0;
                > UINT WM_TV_SELBYPATH = 0;
                > UINT WM_TV_GETSELPATH = 0;
                > +UINT WM_INITMENUPOPUPX = WM_INITMENUPOPUP; //Only needed to
                conform
                > with SetHook()'s calling convention
                > #pragma data_seg()
                > #pragma comment(linker, "/SECTION:.shared,RWS")
                >
                > BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,
                > LPVOID lpReserved)
                > @@ -292,10 +294,13 @@
                > if (lstrcmpi(g_szBuffer, szName) == 0) {
                > // Yes, selected
                > g_bRetVal = TRUE;
                > }
                > UnhookWindowsHookEx(g_hHook);
                > + } else if (pCW->message == WM_INITMENUPOPUP) {
                > + g_popup = (HWND) pCW->wParam;
                > + UnhookWindowsHookEx(g_hHook);
                > }
                >
                > return CallNextHookEx(g_hHook, code, wParam, lParam);
                > }
                >
                > @@ -801,11 +806,26 @@
                > safefree(text);
                > }
                > return sv;
                > }
                >
                > -
                > +/////////////////////////////////////////////////
                > ///////////////////////////
                > +HWND PopupHandleGet(HWND hWnd, int x, int y, int wait) {
                > + g_popup = 0;
                > + if (SetHook(hWnd, WM_INITMENUPOPUPX, "WM_INITMENUPOPUP_RM") ==
                > NULL)
                > + return 0;
                > + int mickey_x = MulDiv(x, 0x10000, GetSystemMetrics
                (SM_CXSCREEN));
                > + int mickey_y = MulDiv(y, 0x10000, GetSystemMetrics
                (SM_CYSCREEN));
                > + simple_mouse(MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE, mickey_x,
                > mickey_y);
                > + simple_mouse(MOUSEEVENTF_RIGHTDOWN, 0, 0);
                > + simple_mouse(MOUSEEVENTF_RIGHTUP, 0, 0);
                > + Sleep(wait);
                > + if (g_popup == 0)
                > + UnhookWindowsHookEx(g_hHook);
                > + return g_popup;
                > +}
                > +/////////////////////////////////////////////////
                > ///////////////////////////
                >
                > MODULE = Win32::GuiTest PACKAGE = Win32::GuiTest
                >
                > PROTOTYPES: DISABLE
                >
                > @@ -1708,10 +1728,22 @@
                > pt.y = y;
                > RETVAL = WindowFromPoint(pt);
                > OUTPUT:
                > RETVAL
                >
                > +#################################################
                > ###########################
                > +HWND
                > +GetPopupHandle(hWnd, x, y, wait=50)
                > + HWND hWnd;
                > + int x;
                > + int y;
                > + int wait;
                > +CODE:
                > + RETVAL = PopupHandleGet(hWnd, x, y, wait);
                > +OUTPUT:
                > + RETVAL
                > +#################################################
                > ###########################
                >
                > MODULE = Win32::GuiTest PACKAGE =
                > Win32::GuiTest::DibSect
                >
                > PROTOTYPES: DISABLE
                >
                >
                > **********************************************
                > Now the guitest.pm
                > **********************************************
                > $ diff -U5 Win32-GuiTest-1.50.3-ad/guitest.pm
                guitest_popuphandle.pm
                > --- Win32-GuiTest-1.50.3-ad/guitest.pm 2005-02-02
                18:43:15.000000000
                > -0500
                > +++ guitest_popuphandle.pm 2005-09-11 23:41:21.000000000 -0400
                > @@ -121,10 +121,11 @@
                > GetSubMenu GetMenuItemIndex GetMenuItemId GetMenuItemCount
                > GetMenuItemInfo
                > GetListViewContents SelListViewItem SelListViewItemText
                > IsListViewItemSel
                > GetTabItems SelTabItem SelTabItemText IsTabItemSel
                > SelTreeViewItemPath GetTreeViewSelPath MouseMoveWheel
                > SelComboItem SelComboItemText
                > + GetPopupHandle
                > )],
                > VARS => [ qw(
                > $debug
                > )],
                > SW => [ qw(
                > @@ -1042,10 +1043,18 @@
                > SelTreeViewItemPath($window, "Parent|Child");
                > SelTreeViewItemPath($window, $oldpath);
                >
                > =cut
                >
                > +=item $hpopup = GetPopupHandle($hwnd, $x, $y, [$wait])
                > +
                > + This function gets the handle of a popup window generated by
                > + right-clicking at the $x and $y screen coordinates (absolute).
                An
                > + optional delay can be entered which will wait the given number
                of
                > + milliseconds after the right-click for the window to appear
                > (default
                > + is 50). Zero is returned when no popup menu is found.
                > +
                > =back
                >
                > =head2 DibSect
                >
                > A class to manage a Windows DIB section. Currently limited in
                > functionality to
              • Piotr Kaluski
                Rafe, Your code changes work for me. Good job. I commited your changes in CVS. Now we have to wait until the next package is released. Dear project
                Message 7 of 7 , Sep 25, 2005
                • 0 Attachment
                  Rafe,
                  Your code changes work for me. Good job.
                  I commited your changes in CVS. Now we have to wait until the next
                  package is released.
                  Dear project administrators,
                  Pleeeeeeaaaaaaase :-))
                  Once the package is released I will update documentation.

                  -Piotr
                Your message has been successfully submitted and would be delivered to recipients shortly.