Sign in to follow this  
Followers 0
Zohar

How Can I Optimize this ShowContextMenu() Function?

7 posts in this topic

#1 ·  Posted (edited)

Hi

Some while ago, with the help of members from this forum,

we created a Function that shows a ContextMenu to the User, even tho the current window is not created by our program.

Meaning, the current window was created by another application - any application, and our context menu will be shown on that window.

Here's the code as it is now, you can run it to see it's working and doing what it should:

#include <GuiMenu.au3>


Opt("GUIOnEventMode",1)


Local $SampleArray[4] =["A","B","C","D"]
Local $ChosenMenuItem =ShowContextMenu($SampleArray)
MsgBox(0,"",$ChosenMenuItem)



Func ShowContextMenu($Array_MenuItems)
Local $hActiveWindow =WinGetHandle("") ;Keeping a Handle to Current Window, for Reactivating it after the ContextMenu closes




;Creating a Window that will be a Parent for the ContextMenu
Local $hWindowThatHoldsTheContextMenu =GUICreate("",1,1,-10,-10,-1,-1,WinGetHandle(AutoItWinGetTitle()))
GUISetState()


;Creating the Menu
Local $ContextMenu   =GUICtrlCreateContextMenu()

;Creating the MenuItems
Local $ContextMenu_MenuItem

For $i=0 To UBound($Array_MenuItems)-1
     $ContextMenu_MenuItem =GUICtrlCreateMenuItem($Array_MenuItems[$i],$ContextMenu)
Next


;Showing the ContextMenu
Local $MenuItemID =_GUICtrlMenu_TrackPopupMenu(GUICtrlGetHandle($ContextMenu),$hWindowThatHoldsTheContextMenu,-1,-1,1,1,2)
Local $Result =GUICtrlRead($MenuItemID,1) ;1 = MenuItem.Text


WinActivate ($hActiveWindow) ;Reactivating the Window
WinWaitActive($hActiveWindow)


Return $Result
EndFunc

I have several questions regarding this code.

I will start with the 2 most impotant ones:

1) Is there any way to make it work without the delay?

It takes time until the ContextMenu is shown, and then also it takes time after it is closed

2) Why do I need to create a new Window?

I am talking about this line:

;Creating a Window that will be a Parent for the ContextMenu
Local $hWindowThatHoldsTheContextMenu =GUICreate("",1,1,-10,-10,-1,-1,WinGetHandle(AutoItWinGetTitle()))

Can I, for example, spare the code from creating a new window, and instead, use the Existing Window($hActiveWindow) as the Parent for the ContextMenu?

Thank you

Zohar

Edited by Zohar

Share this post


Link to post
Share on other sites



1) Is there any way to make it work without the delay?

It takes time until the ContextMenu is shown, and then also it takes time after it is closed

It doesn't seem to take a considerable amount of time on my end if you ask me (WinXP 32, versy slow little laptop).

#include <GuiMenu.au3>
#include <WindowsConstants.au3>

OnAutoItExitRegister("_UI_SetMouseHook")
HotKeySet("{ESC}", "_UI_SetMouseHook")

Opt("GUIOnEventMode",1)

Global $hMouseHook = -1
Global $hMouseProc = -1

Local $SampleArray[4] =["A","B","C","D"]

_UI_SetMouseHook(1)

For $I = 0 To 10e+100
    Sleep(100)
Next

Exit

Func ShowContextMenu($Array_MenuItems)
    Local $hActiveWindow =WinGetHandle("") ;Keeping a Handle to Current Window, for Reactivating it after the ContextMenu closes

    ;Creating a Window that will be a Parent for the ContextMenu
    Local $hWindowThatHoldsTheContextMenu =GUICreate("",1,1,-10,-10,-1,-1,WinGetHandle(AutoItWinGetTitle()))
    GUISetState()

    ;Creating the Menu
    Local $ContextMenu   =GUICtrlCreateContextMenu()

    ;Creating the MenuItems
    Local $ContextMenu_MenuItem

    For $i=0 To UBound($Array_MenuItems)-1
         $ContextMenu_MenuItem =GUICtrlCreateMenuItem($Array_MenuItems[$i],$ContextMenu)
    Next

    ;Showing the ContextMenu
    Local $MenuItemID =_GUICtrlMenu_TrackPopupMenu(GUICtrlGetHandle($ContextMenu),$hWindowThatHoldsTheContextMenu,-1,-1,1,1,2)
    Local $Result =GUICtrlRead($MenuItemID,1) ;1 = MenuItem.Text

    WinActivate ($hActiveWindow) ;Reactivating the Window
    WinWaitActive($hActiveWindow)

    Return $Result
EndFunc

Func _UI_SetMouseHook($DoWhat = 0)
    If Not IsDeclared("DoWhat") Then $Dowhat = 0
    Switch $Dowhat
        Case 1

            If $hMouseProc = -1 Then
                $hMouseProc = DllCallbackRegister("WM_MOUSEMOVE", "int", "uint;wparam;lparam")
            EndIf

            If $hMouseHook = -1 Then
                Local $hM_Module = _WinAPI_GetModuleHandle(0)
                $hMouseHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMouseProc), $hM_Module, 0)
            EndIf

        Case 0

            If $hMouseHook <> -1 Then
                _WinAPI_UnhookWindowsHookEx($hMouseHook)
                $hMouseHook = -1
            EndIf

            If $hMouseProc <> -1 Then
                DllCallbackFree($hMouseProc)
                $hMouseProc = -1
            EndIf

            OnAutoItExitUnRegister("_UI_SetMouseHook")
            Exit

    EndSwitch
    Return
EndFunc

Func WM_MOUSEMOVE($nCode, $wParam, $lParam)
    #forceref $nCode, $wParam, $lParam
    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($hMouseHook, $nCode, $wParam, $lParam) ;let other hooks continue processing if any
    EndIf

    Switch $wParam
        Case $WM_RBUTTONDOWN

        Case $WM_RBUTTONUP
            Local $ChosenMenuItem =ShowContextMenu($SampleArray)
            MsgBox(0,"",$ChosenMenuItem)
    EndSwitch
    Return _WinAPI_CallNextHookEx($hMouseHook, $nCode, $wParam, $lParam) ;let other hooks continue processing if any
EndFunc   ;==>WM_MOUSEMOVE

2) Why do I need to create a new Window?

Can I, for example, spare the code from creating a new window, and instead, use the Existing Window($hActiveWindow) as the Parent for the ContextMenu?

I think you can do it, but it's going to make the code at least x10^100 as complicated and x10^1000 as long.

The reason for creating a new window as a child window to AutoIts existing default window is in order to avoid making the script very complicated and long, people have done it before and there are windows APIs for just such the occasion but ask yourself, do I really need to not create a new window?

It would just clutter up the script and make it slower as it is.


Things that I've done..

Icon Resource Editor: icon resource editor 

AutoIt Piano: a piano

AutoIt Unlocker: unlocks files when you want to delete them

Colorful tooltips: a wrapper for the tool tips UDF

Rouge GoogleBot: a full screen animation

ASciTE text editor: a text editor written in autoit

Warning: Posts by this user are subject to change or may disappear without notice.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

It doesn't seem to take a considerable amount of time on my end if you ask me (WinXP 32, versy slow little laptop).

I am on Windows XP SP3.

MY computer runs very fast with everything,

but this ContextMenu, takes almost 1 second to appear,

and also, after disappearing, it takes almost 1 second after it resumes operation to the lines of code after it.

Other than that, things in AutoIt work very fast.

I think you can do it, but it's going to make the code at least x10^100 as complicated and x10^1000 as long.

Well, the purpose was, to get rid of the line of code that creates the new window.

But you say it will make it more complicated, not less, so I guess we should stay with it? :)

Maybe the Parent for the ContextMenu can be the AutoItWindow itself, directly?

(if not the Current Active Window - which was the most logical choice, because that's what it's displayed for)

Edited by Zohar

Share this post


Link to post
Share on other sites

Well, I personally think you should leave it as it is, if something works, don't fix it.

About the delay, are you running an antivirus? Maybe you might need to add an exception, I can picture anything else causing the code to execute that slowly.

Did you try the code I posted? On my system, it takes no time to appear and disappear.


Things that I've done..

Icon Resource Editor: icon resource editor 

AutoIt Piano: a piano

AutoIt Unlocker: unlocks files when you want to delete them

Colorful tooltips: a wrapper for the tool tips UDF

Rouge GoogleBot: a full screen animation

ASciTE text editor: a text editor written in autoit

Warning: Posts by this user are subject to change or may disappear without notice.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

OK I will experiment with it more.

BTW, what about

Maybe the Parent for the ContextMenu can be the AutoItWindow itself, directly?

(if not the Current Active Window - which was the most logical choice, because that's what it's displayed for)

Edited by Zohar

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Share this post


Link to post
Share on other sites

Hi

I tried it now..

And even when defining the Window+ContextMenu once,

all calls to it still have a delay.

The delay is especially noticed after the ContextMenu closes, and the code that appears after it needs to run..

BTW I get this same delay when opening an InputBox too..

Is it some general UI Delay in AutoIt, when creating GUI?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0