Jump to content

Popup Menu UDF


Mat
 Share

Recommended Posts

PopUp Menu UDF

Version 1.3: 26/09/2009 23:57:17

* fixed: Bug when holding down the hotkey setting off the function multiple times. (MrCreator)

* Added: New example showing the OnShow Functionality

* Added: Google-code project page for organizing the downloads easier!

Version 1.2: 26/09/2009 19:44:07

* Added: OnShow option. Gives the ability to run a function before the menu shows (to update etc)

* fixed: OnEvent handling (now uses Dummy control) (Wraithdu)

* fixed: OnEvent mode still setting Msg-loop array (Wraithdu)

* fixed: Sleep (10) added to GetMsg function (MrCreator)

* fixed: some variable warnings from Au3Check (Wraithdu)

* fixed: OnEvent Functions with 1 or 0 parameters.

* fixed: OnShow can run both global and menu specific functions. (Wraithdu)

* Added: Version info!

Version 1.1: 26/09/2009 12:38:05

* Added: OnEvent mode

* Added: SetOption function ("OnEventMode" and "DataSeperatorChar")

* fixed: Clicking off now hides the menu (Wraithdu fixed, Yashieds found)

* fixed: Handling of Msg-Loop functions (Wraithdu)


Yer, its been done before, but not without some fiddling and mucking around! Heres a UDF, that can register as many of them as you like at any one time, and handle them too! It's not completely perfect, however, but i think its almost 100%. Becouse of some problems I had with GUI events not being triggered when the GUI was hidden, despite the context menu being shown, the project doubled in size as I wrote the message handler, and then realized I would have to write my own menu creation functions as well (I was planning on using the GUICtrlCreateMEnu etc.). So after a bit of headbanging. I got there.

Current Functions:

* _PopUpMenuCreate

* _PopUpMenuDelete

* _PopUpMenuDeleteAll

* _PopUpMenuCreateMenu

* _PopUpMenuCreateMenuItem

* _PopUpMenuDeleteMenu

* _PopUpMenuDeleteMenuItem

* _PopUpMenuGetMsg

* _PopUpMenuGetCount

* _PopUpMenuSetOption

* _PopUpMenuItemSetOnEvent

as well as a ton of inbuilt ones that are you used in various places. I also copied _ArrayDelete in there! (renaming it) to save on the include.

The downloads page (google code)

Should be able to create a lot of interesting programs from this, I already have made myself a kinda shortcuts menu with it, and i've got that running in the background! It would be relatively easy to add an onevent mode, if anyones interested! DONE!!

Mat

Edited by Mat
Link to comment
Share on other sites

Severely good stuff here Mat - and yes, for me it would be total icing on the cake if you could also add onevent option.

Thanks for the work you put in here.

Oh, and btw, AU3Check is reporting error in these two functions:

_PopUpMenuDeleteMenu()

_PopUpMenuDeleteMenuItem()

Seems you're using undeclared $x that should simply be $iExt

Cheers,

Sunaj

Link to comment
Share on other sites

Link to comment
Share on other sites

I looked through more. I like it! But I don't really see the point of the AdLib function. You seem to be using it to clear any old events. Few problems though:

1) you're using a TimerDiff() in there, but I don't see a TimerInit() call anywhere to use with it

2) using the timer as you are (once you would get it working correctly that is) would produce a race condition: does the AdLib reset the event before the GetMsg function retireves it???

2) you don't need the AdLib anyway, simply clear the event if it's found in the _PopupGetMsg() function

I'd like to see an OnEvent mode to this as well. Really great start!

Edited by wraithdu
Link to comment
Share on other sites

Good job, but there is one problem. How can I hide a popup menu without selecting the item from it? Clicking on the desktop does not work.

:D

Ah yes, this problem. Solution: in the UDF set the parent GUI (the one created off screen to hold all the controls) to the foreground (SetForegroundWindow) before sending the message to trigger the appearance of the menu.

Link to comment
Share on other sites

My proposed changes eliminate the need for the AdLib functions and fixes Yashied's problem too.

; #INDEX# ========================================================================================================================
; Title .........: _PopUpMenu
; AutoIt Version : 3.3.0.0+
; Language ......: English
; Description ...: For Creation and handling of popup context menus
; ================================================================================================================================

; #CURRENT# ======================================================================================================================
; _PopUpMenuCreate
; _PopUpMenuDelete
; _PopUpMenuDeleteAll
; _PopUpMenuCreateMenu
; _PopUpMenuCreateMenuItem
; _PopUpMenuDeleteMenu
; _PopUpMenuDeleteMenuItem
; _PopUpMenuGetMsg
; _PopUpMenuGetCount
; ================================================================================================================================

; #INTERNAL_USE_ONLY# ============================================================================================================
; __PopupMenuStart
; __PopUpMenuGetIndexFromHotkey
; __PopUpMenuGetIndexFromHWnd
; __PopUpMenuResetEvent
; __PopUpMenu_WM_COMMAND
; __ArrayDelete
; ================================================================================================================================

; #VARIABLES# ====================================================================================================================
Global $POPUP_MENU_INFO[1][3] ; hotkey, label, menu
   $POPUP_MENU_INFO[0][0] = 0
   $POPUP_MENU_INFO[0][1] = GUICreate ("", 0, 0, -200, -200)
   GUIRegisterMsg (0x0111, "__PopUpMenu_WM_COMMAND")
Global $POPUP_MENU_EVENT[1][3]
; ================================================================================================================================

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreate
; Description ...: Creates the context menu
; Syntax.........: _PopupMenuCreate ($sHotKey)
; Parameters ....: $sHotKey        - The hotkey to bring up the context menu
; Return values .: Success         - The handle to the newly created context menu
;                  Failure         - Returns 0, this is becouse the Hotkey cannot be set.
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuDelete
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopupMenuCreate ($sHotKey)
   If $POPUP_MENU_INFO[0][0] <> 0 Then
      For $i = 1 to $POPUP_MENU_INFO[0][0]
         If $sHotkey = $POPUP_MENU_INFO[$i][0] Then Return _PopUpMenuDelete ($sHotkey)
      Next
   EndIf
   $POPUP_MENU_INFO[0][0] += 1
   ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][3]
   $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][0] = $sHotkey
   $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][1] = GUICtrlCreateLabel ("", 0, 0, 0, 0)
   $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][2] = GUICtrlCreateContextMenu ($POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][1])
   ReDim $POPUP_MENU_EVENT[$POPUP_MENU_INFO[0][0] + 1][3]
   If HotKeySet ($sHotkey, "__PopUpMenuStart") = 0 Then
      ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][3]
      $POPUP_MENU_INFO[0][0] -= 1
      Return SetError (1, 0, 0)
   EndIf
   Return $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][2]
EndFunc ; ==> _PopUpMenuCreate

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDelete
; Description ...: Deletes the context menu
; Syntax.........: _PopupMenuDelete ( [$sHotKey] )
; Parameters ....: $sHotKey        - The hotkey whose context menu you want to delete. If -1 (default) then deletes all
; Return values .: Success         - 1
;                  Failure         - 0
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreate
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDelete ($sHotkey = -1)
   If $sHotkey = -1 Then Return _PopUpMenuDeleteAll ()
   $i = __PopUpMenuGetIndexFromHotkey ($sHotkey)
   If $i = -1 then Return SetError (1, 0, 0)
   HotKeySet ($sHotkey)
   __ArrayDelete ($POPUP_MENU_INFO, $i)
   Return 1
EndFunc ; ==> _PopUpMenuDelete

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteAll
; Description ...: Deletes all the current context menus
; Syntax.........: _PopupMenuDeleteAll ()
; Parameters ....: none
; Return values .: 1
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuDelete
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteAll ()
   For $i = 1 to $POPUP_MENU_INFO[0][0]
      HotKeySet ($POPUP_MENU_INFO[$i][0])
   Next
   ReDim $POPUP_MENU_INFO[1][3]
   $POPUP_MENU_INFO[0][0] = 0
   Return 1
EndFunc ; ==> _PopUpMenuDeleteAll

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreateMenu
; Description ...: Creates a sub menu.
; Syntax.........: _PopupMenuCreateMenu ($sText, $hWnd)
; Parameters ....: $sText          - The text for the control to display
; Return values .: Success         - The handle to the menu.
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
;                                    > 2: Error Creating the menu
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenuItem, _PopUpMenuDeleteMenu
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuCreateMenu ($sText, $hWnd)
   $i = __PopUpMenuGetIndexFromHWnd ($hWnd)
   If $i = -1 Then Return SetError (1, 0, 0)
   $temp = GUICtrlCreateMenu ($sText, $hWnd)
   If $temp = 0 Then Return SetError (2, 0, 0)
   If $POPUP_MENU_INFO[$i][UBound ($POPUP_MENU_INFO, 2) - 1] <> 0 Then _
      ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][UBound ($POPUP_MENU_INFO, 2) + 1]
   $POPUP_MENU_INFO[$i][UBound ($POPUP_MENU_INFO, 2) - 1] = $temp
   Return $temp
EndFunc ; ==> _PopUpMenuCreateMenu

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteMenu
; Description ...: Deletes a sub menu.
; Syntax.........: _PopupMenuDeleteMenu ($hWnd)
; Parameters ....: $hWnd           - The Handle to the menu
; Return values .: Success         - 1
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......: Doesn't delete sub items... but they can not be shown after a call to this function
; Related .......: _PopUpMenuCreateMenu, _PopUpMenuDeleteMenuItem
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteMenu ($hWnd)
   $i = __PopUpMenuGetIndexFromHWnd ($hWnd)
   $iExt = @Extended
   If $i = -1 Then Return SetError (1, 0, 0)
   If $iExt = -1 Then ; first level menu
      Return _PopUpMenuDelete ($POPUP_MENU_INFO[$i][0])
   Else
      $temp = GUICtrlDelete ($hWnd)
      $POPUP_MENU_INFO[$i][$iExt] = ""
   EndIf
   Return $temp
EndFunc ; ==> _PopUpMenuDeleteMenu

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreateMenuItem
; Description ...: Creates a menu Item
; Syntax.........: _PopupMenuCreateMenuItem ($sText, $hWnd)
; Parameters ....: $sText          - The text for the item to display
;                  $hWnd           - The Handle to the menu
; Return values .: Success         - The handle to the new menu item
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenu, _PopUpMenuDeleteMenuItem
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuCreateMenuItem ($sText, $hWnd)
   $i = __PopUpMenuGetIndexFromHWnd ($hWnd)
   If $i = -1 Then Return SetError (1, 0, 0)
   $temp = GUICtrlCreateMenuItem ($sText, $hWnd)
   If $temp = 0 Then Return SetError (2, 0, 0)
   If $POPUP_MENU_INFO[$i][UBound ($POPUP_MENU_INFO, 2) - 1] <> 0 Then _
      ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][UBound ($POPUP_MENU_INFO, 2) + 1]
   $POPUP_MENU_INFO[$i][UBound ($POPUP_MENU_INFO, 2) - 1] = $temp
   Return $temp
EndFunc ; ==> _PopUpMenuCreateMenuItem

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteMenuItem
; Description ...: Creates a menu Item
; Syntax.........: _PopupMenuDeleteMenuItem ($hWnd)
; Parameters ....: $hWnd           - The Handle to the menu
; Return values .: Success         - The handle to the new menu item
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenuItem, _PopUpMenuDeleteMenu
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteMenuItem ($hWnd)
   $i = __PopUpMenuGetIndexFromHWnd ($hWnd)
   $iExt = @Extended
   If $i = -1 Then Return SetError (1, 0, 0)
   $temp = GUICtrlDelete ($hWnd)
   $POPUP_MENU_INFO[$i][$iExt] = ""
   Return $temp
EndFunc ; ==> _PopUpMenuDeleteMenuItem

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuGetMsg
; Description ...: Checks for any event messages
; Syntax.........: _PopUpMenuGetMsg ($hWnd)
; Parameters ....: $hWnd           - The Handle to the menu
; Return values .: Success         - The Message event code (or zero if no message)
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuGetMsg ($hWnd)
    Local $i = __PopUpMenuGetIndexFromHWnd ($hWnd)
    If $i = -1 Then Return SetError (1, 0, 0)
    Local $ret = $POPUP_MENU_EVENT[$i][1] ; save return value
    ; reset events
    $POPUP_MENU_EVENT[$i][0] = 0
    $POPUP_MENU_EVENT[$i][1] = 0
    $POPUP_MENU_EVENT[$i][2] = 0
    Return $ret
EndFunc ; ==> _PopUpMenuGetMsg

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuGetCount
; Description ...: Returns the amount of context menus currently created
; Syntax.........: _PopUpMenuGetCount ()
; Parameters ....: none
; Return values .: Success         - The count
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuGetCount ()
   Return $POPUP_MENU_INFO[0][0]
EndFunc ; ==> _PopUpMenuGetCount

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuStart
; Description ...: Sends the open context menu message on hotkey pressed
; Syntax.........: __PopupMenuStart ()
; Parameters ....: none
; Return values .: none
; Author ........: Mat
; Modified.......:
; Remarks .......: do NOT run except from a hotkey, as it uses the @HOTKEYPRESED macro
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopupMenuStart ()
   $x = __PopUpMenuGetIndexFromHotkey (@HOTKEYPRESSED)
   If $x = -1 Then Return SetError (1, 0, 0)
   DllCall("user32.dll", "int", "SetForegroundWindow", "hwnd", $POPUP_MENU_INFO[0][1])
   DllCall("user32.dll", "ptr", "SendMessage", _
      "hwnd", ControlGetHandle ($POPUP_MENU_INFO[0][1], _
      "", $POPUP_MENU_INFO[$x][1]), _
      "int", 0x007B, _
      "int", $POPUP_MENU_INFO[$x][1], _
      "int", 0)
EndFunc ; ==> __PopupMenuStart

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenu_WM_COMMAND
; Description ...: The Message handler
; Syntax.........: __PopupMenu_WM_COMMAND ($hWnd, $msgID, $l, $r)
; Parameters ....: Standard windows message params.
; Return values .: none
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenu_WM_COMMAND ($hWnd, $msgID, $l, $r)
   If $hWnd <> $POPUP_MENU_INFO[0][1] Then Return "GUI_RUNDEFMSG"
   $i = __PopUpMenuGetIndexFromHwnd ($l)
   $POPUP_MENU_EVENT[$i][0] = $hWnd
   $POPUP_MENU_EVENT[$i][1] = $l
EndFunc ; ==> __PopUpMenu_WM_COMMAND

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuResetEvent
; Description ...: Sets any old event messages to zero
; Syntax.........: __PopupMenuResetEvent ()
; Parameters ....: none
; Return values .: none
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

;~ Func __PopUpMenuResetEvent ()
;~    For $x = 1 to $POPUP_MENU_INFO[0][0]
;~       If TimerDiff ($POPUP_MENU_EVENT[$x][2]) > 250 Then
;~          $POPUP_MENU_EVENT[$x][0] = 0
;~          $POPUP_MENU_EVENT[$x][1] = 0
;~          $POPUP_MENU_EVENT[$x][2] = 0
;~       EndIf
;~    Next
;~ EndFunc ; ==> _PopUpMenuResetEvent

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuGetIndexFromHotkey
; Description ...: Returns the index of the item using the given hotkey
; Syntax.........: __PopupMenuGetIndexFromHotkey ($sHotkey)
; Parameters ....: $sHotkey        - The hotkey to search for
; Return values .: Success         - The index
;                  Failure         - -1, and @ERROR is set to 1
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenuGetIndexFromHotkey ($sHotkey)
   For $i = 1 to $POPUP_MENU_INFO[0][0]
      If $sHotkey = $POPUP_MENU_INFO[$i][0] Then Return $i
   Next
   Return SetError (1, 0, -1)
EndFunc ; ==> __PopUpGetIndexFromHotkey

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuGetIndexFromHWnd
; Description ...: Returns the index of the item using the given handle
; Syntax.........: __PopupMenuGetIndexFromHWnd ($hWnd)
; Parameters ....: $sHotkey        - The handle to search for
; Return values .: Success         - The index
;                  Failure         - -1, and @ERROR is set to 1
; Author ........: Mat
; Modified.......:
; Remarks .......: @EXTENDED is set to the sub index, if it exists. If not it is set to -1.
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenuGetIndexFromHWnd ($hWnd)
   For $i = 1 to $POPUP_MENU_INFO[0][0]
      If $hWnd = $POPUP_MENU_INFO[$i][2] Then Return SetExtended (-1, $i)
      For $x = 3 to UBound ($POPUP_MENU_INFO, 2) - 1 ; sub menus + items
         If $hWnd = $POPUP_MENU_INFO[$i][$x] Then Return SetExtended ($x, $i)
      Next
   Next
   Return SetError (1, 0, 1)
EndFunc ; ==> __PopUpGetIndexFromHWnd

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __ArrayDelete
; Description ...: Deletes the specified element from the given array.
; Syntax.........: __ArrayDelete ($avArray, $iElement)
; Parameters ....: $avArray        - Array to modify
;                  $iElement       - Element to delete
; Return values .: Success         - New size of the array
;                  Failure         - 0, sets @error to:
;                                  > 1: $avArray is not an array
;                                  > 3: $avArray has too many dimensions (only up to 2D supported)
; Author ........: Cephas <cephas at clergy dot net>
; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef
;                  Ultima - 2D arrays supported, reworked function (no longer needs temporary array; faster when deleting from end)
; Remarks .......: If the array has one element left (or one row for 2D arrays), it will be set to "" after _ArrayDelete() is used on it.
; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __ArrayDelete($avArray, $iElement)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    Local $iUBound = UBound($avArray, 1) - 1
    If Not $iUBound Then
        $avArray = ""
        Return 0
    EndIf
    If $iElement < 0 Then $iElement = 0
    If $iElement > $iUBound Then $iElement = $iUBound
    Switch UBound($avArray, 0)
        Case 1
            For $i = $iElement To $iUBound - 1
                $avArray[$i] = $avArray[$i + 1]
            Next
            ReDim $avArray[$iUBound]
        Case 2
            Local $iSubMax = UBound($avArray, 2) - 1
            For $i = $iElement To $iUBound - 1
                For $j = 0 To $iSubMax
                    $avArray[$i][$j] = $avArray[$i + 1][$j]
                Next
            Next
            ReDim $avArray[$iUBound][$iSubMax + 1]
        Case Else
            Return SetError(3, 0, 0)
    EndSwitch
    Return $avArray
EndFunc ; ==> __ArrayDelete

Nice job on a really functional UDF!

Edited by wraithdu
Link to comment
Share on other sites

Yes, I liked this UDF too. This is one way to simplify it (I think).

#Include <Constants.au3>
#Include <GUIMenu.au3>
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>

Global Enum $idOpen = 1000, $idSave, $idInfo

$hWnd = GUICreate('')
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')

$hMenu = _GUICtrlMenu_CreatePopup()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, 'Open', $idOpen)
_GUICtrlMenu_InsertMenuItem($hMenu, 1, 'Save', $idSave)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, '', 0)
_GUICtrlMenu_InsertMenuItem($hMenu, 3, 'Info', $idInfo)
DllCall('user32.dll', 'int', 'SetForegroundWindow', 'hwnd', $hWnd)
_GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd)
_GUICtrlMenu_DestroyMenu($hMenu)

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case $idOpen
            MsgBox(0, '', 'Open')
        Case $idSave
            MsgBox(0, '', 'Save')
        Case $idInfo
            MsgBox(0, '', 'Info')
    EndSwitch
EndFunc   ;==>WM_COMMAND
Edited by Yashied
Link to comment
Share on other sites

Nice.

But am i the only one who notice the high CPU usage?

To fix it just add Sleep(10) to _PopUpMenuGetMsg.

Yashied

This is one way to simplify it

Yes, but as we can see in the help file:

Warning: blocking of running user functions which executes window messages with commands such as "Msgbox()" can lead to unexpected behavior, the return to the system should be as fast as possible !!!

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

!!!!!!!!!!!!!!!!!!!!!!!!!!

wow. That was a good response. And gives me a lot to talk about!

I haven't looked all the way through it, but you should consider revising this for 3.3.1.x beta compatibility which now uses the AdLibRegister function. It's much more flexible, allowing you to register multiple AdLib functions.

I have done that in previous scripts and have found that its a lot easier to use the old method as until 3.3.1.1 is out of beta, I have to assume that the user is running the latest non beta version. (incidently, I run beta most of the time, the reason I do this is becouse I've had people complain at "unkown function: FileFlush"!!)

Yashied, I had not noticed that problem, as I had been very busy testing out the message handling, so clicking off was not an option!

The adlib, wraithdu, was there to clear old events. I'd left out the code for the timerinit, but it was supposed to take he third part of the $POPUP_MENU_EVENT array. The idea was the adlib would check to see if any were older than 250ms. Your right it probably isn't needed, and i'll lokk over your changes soon!

Mr Creator, I do not know where the high cpu usage is coming from, "To fix it just add Sleep(10) to _PopUpMenuGetMsg." I presume you mean the user created loop not the actual function, as the function is just returning once. Its the same as GUIGetMsg (), only I set the events off. Adding Sleeps to the loop is up to the users discretion, and is not my problem.

Yashied, That simplification will lead to problems, but is similar to the way I will have to do the onevent mode (only launching functions). It is easier and shorter but does mean that the user needs to think a bit more about it, and is basicly what we had before where people could make them, as long as they knew what they were doing.

I am reading through wraithdu's edits now, that SetForground I did not know about, but appears to fix the bug, so thanks there! On the message handling, I'll work on the OnEvent mode then! As for the GetMsg... That does mean you can pick up the message ten seconds afterwards provided you don't call the function in that time. maybe thats acceptable? I don't know, i'll do some testing into how GUIGetMsg () works.

Thanks all of you, theres a lot to work on, but its looking better all the time.

Mat

Mat

Link to comment
Share on other sites

Mat, you can also use HotKey.au3 that would enhance the ability of hot keys.

Funny you should mention it... I was considering doing something like that!! I have used Hotkey.au3 before, and it would help. However, I don't want to force it on users. Luckily, I have just built in the Options function, and I will add an option to use it, and the user will have to add the include?? I will build that in soon, I have almost finished the onevent mode handling. I have also made other improvements to the code, and addded in all of wraithdu's.

Mat

Link to comment
Share on other sites

Its the same as GUIGetMsg (), only I set the events off. Adding Sleeps to the loop is up to the users discretion, and is not my problem.

GUIGetMsg() have 10 ms of sleep built-in, i think the same should be in your msg function. And as for the "up to the user" issue, when you showing an example, you are the user :D, and you should add the sleep in the main loop (at least, if you are not planing to add it to the _PopUpMenuGetMsg).

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

Nice update. I made some small changes again to fix a few things:

1) added Sleep(10) to getmsg function (you can take it or leave it)

2) fixed OnEvent mode - as mentioned by MrCreatoR above, you have the same issue with blocking a message function. I fixed it using the GuiCtrlSendToDummy() technique which works great. To see the problem, take your original example and try to use _ArrayDisplay() in your onevent function....script will crash. As part of this, I had to show your main GUI. AutoIt won't send messages to a hidden GUI, so I showed it and changed the style to WS_POPUP and Ex style to WS_EX_TOOLWINDOW so there's no toolbar button and it doesn't show in the Alt-Tab menu.

3) small change to the WM_COMMAND function: if using OnEvent mode you shouldn't set the events to the GetMsg array, as they won't be cleared by the GetMsg function anymore. This could lead to random code execution if the user were to switch back to GetMsg mode sometime in their script.

4) fixed some vars not being declared (warnings from Au3Check)

Hope you don't mind my changes, I don't mean to intrude, it's just that I've used this same technique and it's nice to see it in UDF form.

; #INDEX# ========================================================================================================================
; Title .........: _PopUpMenu
; AutoIt Version : 3.3.0.0+
; Language ......: English
; Description ...: For Creation and handling of popup context menus
; ================================================================================================================================

; #CURRENT# ======================================================================================================================
; _PopUpMenuCreate
; _PopUpMenuDelete
; _PopUpMenuDeleteAll
; _PopUpMenuCreateMenu
; _PopUpMenuCreateMenuItem
; _PopUpMenuDeleteMenu
; _PopUpMenuDeleteMenuItem
; _PopUpMenuGetMsg
; _PopUpMenuGetCount
; _PopUpMenuSetOnEventMode
; _PopUpMenuItemSetOption
; ================================================================================================================================

; #INTERNAL_USE_ONLY# ============================================================================================================
; __PopupMenuStart
; __PopUpMenuGetIndexFromHotkey
; __PopUpMenuGetIndexFromHWnd
; __PopUpMenu_WM_COMMAND
; __PopUpMenu_OnEventFunction
; __ArrayDelete
; ================================================================================================================================

; #OUT_DATED# ====================================================================================================================
; __PopUpMenuResetEvent
; ================================================================================================================================

; #VARIABLES# ====================================================================================================================
Global $POPUP_MENU_INFO[1][3] ; hotkey, label, menu
$POPUP_MENU_INFO[0][0] = 0
$POPUP_MENU_INFO[0][1] = GUICreate("", 0, 0, -200, -200, 0x80000000, 0x00000080) ; $WS_POPUP, $WS_EX_TOOLWINDOW
Global $DUMMY = GUICtrlCreateDummy()
GUICtrlSetOnEvent($DUMMY, "__PopUpMenu_OnEventFunction")
GUIRegisterMsg(0x0111, "__PopUpMenu_WM_COMMAND")
GUISetState()
Global $POPUP_MENU_EVENT[1][3]
Global $POPUP_MENU_ONEVENT[1][3]
$POPUP_MENU_ONEVENT[0][0] = 0 ; default is not on event
Global $POPUP_MENU_LASTUSED = 0
Global $POPUP_MENU_DATASEPERATOR = "|"
Global $OLDMODE = -1
; ================================================================================================================================

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreate
; Description ...: Creates the context menu
; Syntax.........: _PopupMenuCreate ($sHotKey)
; Parameters ....: $sHotKey        - The hotkey to bring up the context menu
; Return values .: Success         - The handle to the newly created context menu
;                  Failure         - Returns 0, this is becouse the Hotkey cannot be set.
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuDelete
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopupMenuCreate($sHotKey)
    Local $nCur = GUISwitch($POPUP_MENU_INFO[0][1])
    If $POPUP_MENU_INFO[0][0] <> 0 Then
        For $i = 1 To $POPUP_MENU_INFO[0][0]
            If $sHotKey = $POPUP_MENU_INFO[$i][0] Then Return _PopUpMenuDelete($sHotKey)
        Next
    EndIf
    $POPUP_MENU_INFO[0][0] += 1
    ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][3]
    $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][0] = $sHotKey
    $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][1] = GUICtrlCreateLabel("", 0, 0, 0, 0)
    $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][2] = GUICtrlCreateContextMenu($POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][1])
    ReDim $POPUP_MENU_EVENT[$POPUP_MENU_INFO[0][0] + 1][3]
    $POPUP_MENU_LASTUSED = $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][2]
    GUISwitch($nCur)
    If HotKeySet($sHotKey, "__PopUpMenuStart") = 0 Then
        ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][3]
        $POPUP_MENU_INFO[0][0] -= 1
        Return SetError(1, 0, 0)
    EndIf
    Return $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0]][2]
EndFunc   ;==>_PopupMenuCreate

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDelete
; Description ...: Deletes the context menu
; Syntax.........: _PopupMenuDelete ( [$sHotKey] )
; Parameters ....: $sHotKey        - The hotkey whose context menu you want to delete. If -1 (default) then deletes all
; Return values .: Success         - 1
;                  Failure         - 0
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreate
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDelete($sHotKey = -1)
    If $sHotKey = -1 Then Return _PopUpMenuDeleteAll()
    Local $i = __PopUpMenuGetIndexFromHotkey($sHotKey)
    If $i = -1 Then Return SetError(1, 0, 0)
    HotKeySet($sHotKey)
    __ArrayDelete($POPUP_MENU_INFO, $i)
    Return 1
EndFunc   ;==>_PopUpMenuDelete

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteAll
; Description ...: Deletes all the current context menus
; Syntax.........: _PopupMenuDeleteAll ()
; Parameters ....: none
; Return values .: 1
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuDelete
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteAll()
    For $i = 1 To $POPUP_MENU_INFO[0][0]
        HotKeySet($POPUP_MENU_INFO[$i][0])
    Next
    ReDim $POPUP_MENU_INFO[1][3]
    $POPUP_MENU_INFO[0][0] = 0
    Return 1
EndFunc   ;==>_PopUpMenuDeleteAll

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreateMenu
; Description ...: Creates a sub menu.
; Syntax.........: _PopupMenuCreateMenu ($sText, $hWnd)
; Parameters ....: $sText          - The text for the control to display
;                  $hWnd           - The Handle to the menu (default is last used)
; Return values .: Success         - The handle to the menu.
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
;                                    > 2: Error Creating the menu
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenuItem, _PopUpMenuDeleteMenu
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuCreateMenu($sText, $hWnd = -1)
    If $hWnd = -1 Then $hWnd = $POPUP_MENU_LASTUSED
    Local $i = __PopUpMenuGetIndexFromHWnd($hWnd)
    If $i = -1 Then Return SetError(1, 0, 0)
    Local $temp = GUICtrlCreateMenu($sText, $hWnd)
    $POPUP_MENU_LASTUSED = $temp
    If $temp = 0 Then Return SetError(2, 0, 0)
    If $POPUP_MENU_INFO[$i][UBound($POPUP_MENU_INFO, 2) - 1] <> 0 Then _
            ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][UBound($POPUP_MENU_INFO, 2) + 1]
    $POPUP_MENU_INFO[$i][UBound($POPUP_MENU_INFO, 2) - 1] = $temp
    Return $temp
EndFunc   ;==>_PopUpMenuCreateMenu

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteMenu
; Description ...: Deletes a sub menu.
; Syntax.........: _PopupMenuDeleteMenu ( [$hWnd] )
; Parameters ....: $hWnd           - The Handle to the menu (default is last used)
; Return values .: Success         - 1
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......: Doesn't delete sub items... but they can not be shown after a call to this function
; Related .......: _PopUpMenuCreateMenu, _PopUpMenuDeleteMenuItem
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteMenu($hWnd = -1)
    Local $temp = 0
    If $hWnd = -1 Then $hWnd = $POPUP_MENU_LASTUSED
    Local $i = __PopUpMenuGetIndexFromHWnd($hWnd)
    Local $iExt = @extended
    If $i = -1 Then Return SetError(1, 0, 0)
    If $iExt = -1 Then ; first level menu
        Return _PopUpMenuDelete($POPUP_MENU_INFO[$i][0])
    Else
        $temp = GUICtrlDelete($hWnd)
        $POPUP_MENU_INFO[$i][$iExt] = ""
    EndIf
    Return $temp
EndFunc   ;==>_PopUpMenuDeleteMenu

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuCreateMenuItem
; Description ...: Creates a menu Item
; Syntax.........: _PopupMenuCreateMenuItem ($sText [, $hWnd] )
; Parameters ....: $sText          - The text for the item to display
;                  $hWnd           - The Handle to the menu (default is last used)
; Return values .: Success         - The handle to the new menu item
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenu, _PopUpMenuDeleteMenuItem
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuCreateMenuItem($sText, $hWnd = -1)
    If $hWnd = -1 Then $hWnd = $POPUP_MENU_LASTUSED
    Local $i = __PopUpMenuGetIndexFromHWnd($hWnd)
    If $i = -1 Then Return SetError(1, 0, 0)
    Local $temp = GUICtrlCreateMenuItem($sText, $hWnd)
    If $temp = 0 Then Return SetError(2, 0, 0)
    $POPUP_MENU_LASTUSED = $temp
    If $POPUP_MENU_INFO[$i][UBound($POPUP_MENU_INFO, 2) - 1] <> 0 Then _
            ReDim $POPUP_MENU_INFO[$POPUP_MENU_INFO[0][0] + 1][UBound($POPUP_MENU_INFO, 2) + 1]
    $POPUP_MENU_INFO[$i][UBound($POPUP_MENU_INFO, 2) - 1] = $temp
    Return $temp
EndFunc   ;==>_PopUpMenuCreateMenuItem

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuDeleteMenuItem
; Description ...: Creates a menu Item
; Syntax.........: _PopupMenuDeleteMenuItem ( [$hWnd] )
; Parameters ....: $hWnd           - The Handle to the menu
; Return values .: Success         - The handle to the new menu item
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......: _PopUpMenuCreateMenuItem, _PopUpMenuDeleteMenu
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuDeleteMenuItem($hWnd = -1)
    If $hWnd = -1 Then $hWnd = $POPUP_MENU_LASTUSED
    Local $i = __PopUpMenuGetIndexFromHWnd($hWnd)
    Local $iExt = @extended
    If $i = -1 Then Return SetError(1, 0, 0)
    Local $temp = GUICtrlDelete($hWnd)
    $POPUP_MENU_INFO[$i][$iExt] = ""
    Return $temp
EndFunc   ;==>_PopUpMenuDeleteMenuItem

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuGetMsg
; Description ...: Checks for any event messages
; Syntax.........: _PopUpMenuGetMsg ($hWnd)
; Parameters ....: $hWnd           - The Handle to the menu
; Return values .: Success         - The Message event code (or zero if no message)
;                  Failure         - 0 and sets @Error:
;                                    > 1: hWnd parameter invalid
; Author ........: Mat
; Modified.......: Wraithdu        - Resetting the events after being called
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuGetMsg($hWnd)
    Sleep(10) ; throttle CPU
    Local $i = __PopUpMenuGetIndexFromHWnd($hWnd)
    If $i = -1 Then Return SetError(1, 0, 0)
    Local $ret = $POPUP_MENU_EVENT[$i][1] ; save return value
    ; reset events
    $POPUP_MENU_EVENT[$i][0] = 0
    $POPUP_MENU_EVENT[$i][1] = 0
    $POPUP_MENU_EVENT[$i][2] = 0
    Return $ret
EndFunc   ;==>_PopUpMenuGetMsg

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuGetCount
; Description ...: Returns the amount of context menus currently created
; Syntax.........: _PopUpMenuGetCount ()
; Parameters ....: none
; Return values .: Success         - The count
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuGetCount()
    Return $POPUP_MENU_INFO[0][0]
EndFunc   ;==>_PopUpMenuGetCount

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuSetOption
; Description ...: Returns the amount of context menus currently created
; Syntax.........: _PopUpMenuSetOption ($sOption [, $iFlag] )
; Parameters ....: $sOption        - A string Showing the option. Currently supported:
;                                  > OnEventMode       | 1 = OnEventMode, 0 = NOT OnEventMode, -1 = Opposite to current
;                                  > DataSeperatorChar | The character to use when seperating Arguments etc. ("|" = default)
;                  $iFlag           - The flag for the option
; Return values .: Success         - 1
;                  Failure         - 0 And sets @ERROR:
;                                  > 1: Invalid $sOption parameter.
;                                  > 2: Invalid $iFlag parameter.
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuSetOption($sOption, $iFlag = -1)
    Switch $sOption
        Case "OnEventMode"
            If $iFlag = -1 Then
                If $POPUP_MENU_ONEVENT[0][0] = 1 Then
                    $POPUP_MENU_ONEVENT[0][0] = 0
                Else
                    $POPUP_MENU_ONEVENT[0][0] = 1
                EndIf
            ElseIf ($iFlag = 0) Or ($iFlag = 1) Then
                $POPUP_MENU_ONEVENT[0][0] = $iFlag
            Else
                Return SetError(2, 0, 0)
            EndIf
        Case "DataSeperatorChar"
            If StringLen($iFlag) > 1 Then Return SetError(2, 0, 0)
            $POPUP_MENU_DATASEPERATOR = $iFlag
        Case "UseExtendedHotkeys"
            MsgBox(0, "Error", "Functionality Not Built in!")
        Case Else
            Return SetError(1, 0, 0)
    EndSwitch
    Return 1
EndFunc   ;==>_PopUpMenuSetOption

; #FUNCTION# =====================================================================================================================
; Name...........: _PopUpMenuSetOnEventMode
; Description ...: Returns the amount of context menus currently created
; Syntax.........: _PopUpMenuItemSetOnEvent ($hWnd, $sFunc, $sArgs)
; Parameters ....: $hWnd           - Handle to the Item. -1 = last used
;                  $sFunc          - The function to call on event
;                  $sArgs          - A string seperated by POPUP_MENU_DATASEOERATOR to show the arguments for the function.
; Return values .: Success         - 1
;                  Failure         - 0 And sets @ERROR:
;                                  > 1: Invalid $hWnd parameter.
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func _PopUpMenuItemSetOnEvent($hWnd, $sFunc, $sArgs)
    If $hWnd = -1 Then $hWnd = $POPUP_MENU_LASTUSED
    For $i = 1 To UBound($POPUP_MENU_ONEVENT, 1) - 1
        If $hWnd = $POPUP_MENU_ONEVENT[$i][0] Then Return __ArrayDelete($POPUP_MENU_ONEVENT, $i)
    Next
    ReDim $POPUP_MENU_ONEVENT[UBound($POPUP_MENU_ONEVENT, 1) + 1][3]
    $POPUP_MENU_ONEVENT[UBound($POPUP_MENU_ONEVENT, 1) - 1][0] = $hWnd
    $POPUP_MENU_ONEVENT[UBound($POPUP_MENU_ONEVENT, 1) - 1][1] = $sFunc
    $POPUP_MENU_ONEVENT[UBound($POPUP_MENU_ONEVENT, 1) - 1][2] = $sArgs
EndFunc   ;==>_PopUpMenuItemSetOnEvent

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuStart
; Description ...: Sends the open context menu message on hotkey pressed
; Syntax.........: __PopupMenuStart ()
; Parameters ....: none
; Return values .: none
; Author ........: Mat
; Modified.......: Wraithdu        - SetForeGroundWindow, means clicking off the menu hides it.
; Remarks .......: do NOT run except from a hotkey, as it uses the @HOTKEYPRESED macro
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopupMenuStart()
    Local $x = __PopUpMenuGetIndexFromHotkey(@HotKeyPressed)
    If $x = -1 Then Return SetError(1, 0, 0)
    DllCall("user32.dll", "int", "SetForegroundWindow", "hwnd", $POPUP_MENU_INFO[0][1])
    DllCall("user32.dll", "ptr", "SendMessage", _
            "hwnd", ControlGetHandle($POPUP_MENU_INFO[0][1], _
            "", $POPUP_MENU_INFO[$x][1]), _
            "int", 0x007B, _
            "int", $POPUP_MENU_INFO[$x][1], _
            "int", 0)
EndFunc   ;==>__PopupMenuStart

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenu_WM_COMMAND
; Description ...: The Message handler
; Syntax.........: __PopupMenu_WM_COMMAND ($hWnd, $msgID, $l, $r)
; Parameters ....: Standard windows message params.
; Return values .: none
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenu_WM_COMMAND($hWnd, $msgID, $l, $r)
    #forceref $hWnd, $msgID, $l, $r
    If $hWnd <> $POPUP_MENU_INFO[0][1] Then Return "GUI_RUNDEFMSG"
    Local $i = __PopUpMenuGetIndexFromHwnd($l)
    If $POPUP_MENU_ONEVENT[0][0] Then
        ; on event mode
        $OLDMODE = Opt("GUIOnEventMode", 1) ; change to OnEventMode temporarily, save old state
        GUICtrlSendToDummy($DUMMY, $l) ; send trigger to Dummy control with control ID
    Else
        ; getmsg mode
        $POPUP_MENU_EVENT[$i][0] = $hWnd
        $POPUP_MENU_EVENT[$i][1] = $l
    EndIf
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>__PopUpMenu_WM_COMMAND

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopUpMenu_OnEventFunction
; Description ...: The OnEvent Mode Function Handler
; Syntax.........: __PopUpMenu_OnEventFunction()
; Parameters ....: none
; Return values .: none
; Author ........:
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......;
; ================================================================================================================================

Func __PopUpMenu_OnEventFunction()
    Local $temp
    Opt("GUIOnEventMode", $OLDMODE) ; switch back to the old GUI mode
    Local $param = GUICtrlRead($DUMMY) ; get control ID
    For $i = 1 To UBound($POPUP_MENU_ONEVENT, 1) - 1
        If $POPUP_MENU_ONEVENT[$i][0] <> $param Then ContinueLoop
        $temp = StringSplit($POPUP_MENU_ONEVENT[$i][2], $POPUP_MENU_DATASEPERATOR)
        $temp[0] = "CallArgArray"
        Call($POPUP_MENU_ONEVENT[$i][1], $temp)
        ExitLoop
    Next
EndFunc   ;==>__OnEventFunction

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuGetIndexFromHotkey
; Description ...: Returns the index of the item using the given hotkey
; Syntax.........: __PopupMenuGetIndexFromHotkey ($sHotkey)
; Parameters ....: $sHotkey        - The hotkey to search for
; Return values .: Success         - The index
;                  Failure         - -1, and @ERROR is set to 1
; Author ........: Mat
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenuGetIndexFromHotkey($sHotKey)
    For $i = 1 To $POPUP_MENU_INFO[0][0]
        If $sHotKey = $POPUP_MENU_INFO[$i][0] Then Return $i
    Next
    Return SetError(1, 0, -1)
EndFunc   ;==>__PopUpMenuGetIndexFromHotkey

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __PopupMenuGetIndexFromHWnd
; Description ...: Returns the index of the item using the given handle
; Syntax.........: __PopupMenuGetIndexFromHWnd ($hWnd)
; Parameters ....: $sHotkey        - The handle to search for
; Return values .: Success         - The index
;                  Failure         - -1, and @ERROR is set to 1
; Author ........: Mat
; Modified.......:
; Remarks .......: @EXTENDED is set to the sub index, if it exists. If not it is set to -1.
; Related .......:
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __PopUpMenuGetIndexFromHWnd($hWnd)
    For $i = 1 To $POPUP_MENU_INFO[0][0]
        If $hWnd = $POPUP_MENU_INFO[$i][2] Then Return SetExtended(-1, $i)
        For $x = 3 To UBound($POPUP_MENU_INFO, 2) - 1 ; sub menus + items
            If $hWnd = $POPUP_MENU_INFO[$i][$x] Then Return SetExtended($x, $i)
        Next
    Next
    Return SetError(1, 0, 1)
EndFunc   ;==>__PopUpMenuGetIndexFromHWnd

; #INTERNAL_USE_ONLY#=============================================================================================================
; Name...........: __ArrayDelete
; Description ...: Deletes the specified element from the given array.
; Syntax.........: __ArrayDelete ($avArray, $iElement)
; Parameters ....: $avArray        - Array to modify
;                  $iElement       - Element to delete
; Return values .: Success         - New size of the array
;                  Failure         - 0, sets @error to:
;                                  > 1: $avArray is not an array
;                                  > 3: $avArray has too many dimensions (only up to 2D supported)
; Author ........: Cephas <cephas at clergy dot net>
; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef
;                  Ultima - 2D arrays supported, reworked function (no longer needs temporary array; faster when deleting from end)
; Remarks .......: If the array has one element left (or one row for 2D arrays), it will be set to "" after _ArrayDelete() is used on it.
; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush
; Link ..........;
; Example .......; Yes
; ================================================================================================================================

Func __ArrayDelete($avArray, $iElement)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    Local $iUBound = UBound($avArray, 1) - 1
    If Not $iUBound Then
        $avArray = ""
        Return 0
    EndIf
    If $iElement < 0 Then $iElement = 0
    If $iElement > $iUBound Then $iElement = $iUBound
    Switch UBound($avArray, 0)
        Case 1
            For $i = $iElement To $iUBound - 1
                $avArray[$i] = $avArray[$i + 1]
            Next
            ReDim $avArray[$iUBound]
        Case 2
            Local $iSubMax = UBound($avArray, 2) - 1
            For $i = $iElement To $iUBound - 1
                For $j = 0 To $iSubMax
                    $avArray[$i][$j] = $avArray[$i + 1][$j]
                Next
            Next
            ReDim $avArray[$iUBound][$iSubMax + 1]
        Case Else
            Return SetError(3, 0, 0)
    EndSwitch
    Return $avArray
EndFunc   ;==>__ArrayDelete
Edited by wraithdu
Link to comment
Share on other sites

Keep changing, I have absolutely no problem with anything you are suggesting, and you know what your doing anyhow! Showing the GUI will have no affect, unless someone manages to call WinMove on it, in which case they are pretty dum. So thats fine! I have never used dummy controls before... I thought they were for testing... Ah well, I'll look into that too, as it looks useful! As said, its open for you to do whatever you want with it, Add your name to the Modified part as well, or else i'll start going mad looking at code I haven't written, and trying to find out what I was (n't) thinking... (I notice you ran tidy on it too, I was meaning to do that, I do things slightly differently, so I should tidy it before releasing!

MrCreator, I never knew that GUIGetMsg had a sleep in it... If thats so then your right, and i'll happily put it in :D (It already has been by Wraithdu)

As to Hotkey.au3, thats coming along slowly, but i'll get there!

Mat

Edit: What is "#forceref" and what does it do? I ran a sewarch of the helpfile, and apart from it being used in several UDF's, is never mentioned...

Edited by Mat
Link to comment
Share on other sites

Code updated. Added all of wraithdu's suggestions, and one more thing... an OnShow option!!!!

Basicly, I am writing another more complex example, but I needed to update the menu. Rather than updating it every Xms, I decided it would be neat to run the function every time the menu pops up! I also added an extra parameter to SetOption, so that it would work... This I intended to do anyway, as I am always coming up with new options to tweak it.

Anyone interested in a skinned ModernMenu.au3 version? :D

Mat

Link to comment
Share on other sites

Edit: What is "#forceref" and what does it do? I ran a sewarch of the helpfile, and apart from it being used in several UDF's, is never mentioned...

#forceref is an Au3Check pre-processor command. Au3Check can check for variables that are not declared yet (like Opt("MustDeclareVars", 1)) and it can check for variables/parameters that are declared but never used in the function ('-w 5' switch). #forceref prevents Au3Check warnings in functions where you have mandated parameters, like the GuiRegisterMsg() functions, but don't necessarily need/use all the parameters inside the function.

To see what I mean, run Au3Check on my latest update with the #forceref line removed and this added at the top of the script

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

and you'll see the warnings. Basically #forceref is just a 'stop bothering me' setting.

Edited by wraithdu
Link to comment
Share on other sites

What part does not work? Does it just not show... And what example were you using... And which version (damn, I knew I should have started adding numbers :D )

I am testing on WinXP Sp3.

On another note, thankyou wraithdu, I was wondering if it had any affect on the script... :D, thankyou for your other changes too. I am adding another bug I found with OnEvent and functions with just 1 parameter. Fixed Now.

Mat

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...