ModemJunki

Is it possible to create menu with no tab stops on the buttons?

3 posts in this topic

#1 ·  Posted (edited)

I'm having a hard time figuring out how to make a menu without any tab stops for the buttons.

I made a shell menu for BIOS flashing in WinPE and in it I don't want *any* buttons to be tab stopped. If I try to use GUICtrlSetStyle to remove the tab stops from all the buttons, the first button declared in the menu ends up the default (so the user could press the spacebar and the button is activated).

Melba23 posted some code like below a long time ago in this post but it seems to do the same thing as GUICtrlSetStyle does.

Any tips/help is appreciated.

_WinAPI_SetWindowLong(GUICtrlGetHandle(-1), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle(-1), $GWL_STYLE), BitNOT($WS_TABSTOP)))
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>


Opt("GUICloseOnESC", 0) ; prevent user from pressing escape key and accidentally cancelling the GUI
HotKeySet("+!{ESC}", "_doCMD") ; shift-alt-escape for a command dialogue during GUI (lab/service use)

#include <Array.au3>
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

GLobal $s_Cmd1, $s_Cmd2, $s_Cmd3, $s_Cmd4, $s_Cmd5
$s_Debug = 0
$s_dbgArray = 0

Opt("GUICloseOnESC", 0) ; prevent user from pressing escape key and accidentally cancelling the GUI
HotKeySet("+!{ESC}", "_doCMD") ; shift-alt-escape for a command dialogue during GUI (lab/service use)

$MainMenu = GUICreate("Main BIOS Menu", 600, 400, -1, -1, 0, $WS_EX_TOPMOST)
$Button1 = GUICtrlCreateButton("1", 48, 64, 75, 25)
$Label1 = GUICtrlCreateLabel("One", 136, 68, 186, 20)
$Button2 = GUICtrlCreateButton("2", 48, 110, 75, 25)
$Label2 = GUICtrlCreateLabel("Two", 136, 113, 389, 20)
$Button3 = GUICtrlCreateButton("3", 48, 172, 75, 25)
$Label3 = GUICtrlCreateLabel("Three", 136, 176, 186, 20)
$Button4 = GUICtrlCreateButton("4", 48, 218, 75, 25)
$Label4 = GUICtrlCreateLabel("Four", 136, 221, 389, 20)
$Button5 = GUICtrlCreateButton("5", 48, 272, 75, 25)
$Label5 = GUICtrlCreateLabel("Five", 136, 274, 280, 20)
$Button6 = GUICtrlCreateButton("Cancel", 475, 340, 75, 25)
$Label6 = GUICtrlCreateLabel("Click to cancel the operations", 300, 345, 175, 20)
$Label0 = GUICtrlCreateLabel("Please choose one of the following 5 options:", 171, 16, 271, 20)
$Label7 = GUICtrlCreateLabel("Which system do you want to set up? [Press or click 1, 2, 3, 4 or use 5 to flash]", 78, 312, 456, 20)
$Group1 = GUICtrlCreateGroup("IVS", 36, 44, 513, 101)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Group2 = GUICtrlCreateGroup("IAS", 36, 152, 513, 101)
GUICtrlCreateGroup("", -99, -99, 1, 1)

_WinAPI_SetWindowLong(GUICtrlGetHandle($Button1), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button1), $GWL_STYLE), BitNOT($WS_TABSTOP)))
_WinAPI_SetWindowLong(GUICtrlGetHandle($Button2), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button2), $GWL_STYLE), BitNOT($WS_TABSTOP)))
_WinAPI_SetWindowLong(GUICtrlGetHandle($Button3), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button3), $GWL_STYLE), BitNOT($WS_TABSTOP)))
_WinAPI_SetWindowLong(GUICtrlGetHandle($Button4), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button4), $GWL_STYLE), BitNOT($WS_TABSTOP)))
_WinAPI_SetWindowLong(GUICtrlGetHandle($Button5), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button5), $GWL_STYLE), BitNOT($WS_TABSTOP)))
_WinAPI_SetWindowLong(GUICtrlGetHandle($Button6), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($Button6), $GWL_STYLE), BitNOT($WS_TABSTOP)))

;~ GUICtrlSetStyle($Button1, 0)
;~ GUICtrlSetStyle($Button2, 0)
;~ GUICtrlSetStyle($Button3, 0)
;~ GUICtrlSetStyle($Button4, 0)
;~ GUICtrlSetStyle($Button5, 0)
;~ GUICtrlSetStyle($Button6, 0)
GUISetState(@SW_SHOW, $MainMenu)

While 1
    $nMsg = GUIGetMsg()
    Select
        Case $nMsg = $GUI_EVENT_CLOSE Or $nMsg = $Button6
            GUISetState(@SW_HIDE, $MainMenu)
            MsgBox(4096, "Cancel", "Operation cancelled. Please remove the media and click OK to reboot.")
            Exit
        Case $nMsg = $Button1 Or _IsPressed("31") Or _IsPressed("61") ; is the button, keyboard number, or keypad number pressed?
            _doRun(@ScriptDir & "\" & $s_Cmd1)
        Case $nMsg = $Button2 Or _IsPressed("32") Or _IsPressed("62")
            _doRun(@ScriptDir & "\" & $s_Cmd2)
        Case $nMsg = $Button3 Or _IsPressed("33") Or _IsPressed("63")
            _doRun(@ScriptDir & "\" & $s_Cmd3)
        Case $nMsg = $Button4 Or _IsPressed("34") Or _IsPressed("64")
            _doRun(@ScriptDir & "\" & $s_Cmd4)
        Case $nMsg = $Button5 Or _IsPressed("35") Or _IsPressed("65")
            _doRun(@ScriptDir & "\" & $s_Cmd5)
    EndSelect
WEnd

;~ ;=============================================================================
;~ ;==================================Functions==================================
;~ ;=============================================================================

;~ ;=============================================================================
;~ ; Run function for batch or executable files, hides main menu when running
;~ ;=============================================================================
Func _doRun($RunFile)
    GUISetState(@SW_HIDE, $MainMenu)
    RunWait(@ComSpec & " /c " & $RunFile)
    GUISetState(@SW_SHOW, $MainMenu)
EndFunc   ;==>_doRun

; --------------------------------------------------
; Run a command prompt for lab/field troubleshooting
; --------------------------------------------------
Func _doCMD()
    HotKeySet("+!{ESC}") ; deactivate hotkey to prvent spawning multiple cmd boxes with it
    GUISetState(@SW_HIDE, $MainMenu) ; hide the GUI
    RunWait(@ComSpec & " /c " & "cmd.exe", "", @SW_SHOW)
    GUISetState(@SW_SHOW, $MainMenu) ; bring the GUI back up
    HotKeySet("+!{ESC}", "_doCMD") ; reset the hotkey shift-alt-escape for a command dialogue (emergency use)
EndFunc   ;==>_doCMD

 

Edited by ModemJunki

Share this post


Link to post
Share on other sites



#2 ·  Posted

ModemJunki,

Either the _WinAPI_SetWindowLong or GUICtrlSetStyle code works for me to remove the TAB_STOP style:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <Misc.au3>

Opt("GUICloseOnESC", 0) ; prevent user from pressing escape key and accidentally cancelling the GUI
HotKeySet("+!{ESC}", "_doCMD") ; shift-alt-escape for a command dialogue during GUI (lab/service use)

Global $aButton[6]
Global $aButtonData[6][2] = [["", ""], [1, "One"], [2, "Two"], [3, "Three"], [4, "Four"], [5, "Five"]]
Global $aCommand[6] = ["", "Command1", "Command2", "Command3", "Command4", "Command5"]

Local $hDLL = DllOpen("user32.dll")

$MainMenu = GUICreate("Main BIOS Menu", 600, 400, -1, -1, 0, $WS_EX_TOPMOST)

For $i = 1 To 5
    $aButton[$i] = GUICtrlCreateButton($aButtonData[$i][0], 48, 5 + (40 * $i), 75, 25)
    GUICtrlCreateLabel($aButtonData[$i][1], 136, 8 + (60 * $i), 186, 20)
    ;_WinAPI_SetWindowLong(GUICtrlGetHandle($aButton[$i]), $GWL_STYLE, BitAND(_WinAPI_GetWindowLong(GUICtrlGetHandle($aButton[$i]), $GWL_STYLE), BitNOT($WS_TABSTOP)))
    GUICtrlSetStyle($aButton[$i], 0)
Next
$Button6 = GUICtrlCreateButton("Cancel", 475, 340, 75, 25)
GUICtrlCreateLabel("Click to cancel the operations", 300, 345, 175, 20)
GUICtrlCreateLabel("Please choose one of the following 5 options:", 171, 16, 271, 20)
GUICtrlCreateLabel("Which system do you want to set up? [Press or click 1, 2, 3, 4 or use 5 to flash]", 78, 312, 456, 20)
$Group1 = GUICtrlCreateGroup("IVS", 36, 44, 513, 101)
$Group2 = GUICtrlCreateGroup("IAS", 36, 152, 513, 101)
GUICtrlCreateGroup("", -99, -99, 1, 1)

GUISetState(@SW_SHOW, $MainMenu)

While 1
    $nMsg = GUIGetMsg()
    Select
        Case $nMsg = $GUI_EVENT_CLOSE Or $nMsg = $Button6
            GUISetState(@SW_HIDE, $MainMenu)
            MsgBox(4096, "Cancel", "Operation cancelled. Please remove the media and click OK to reboot.")
            DllClose($hDLL)
            Exit
        Case Else
            For $i = 1 To 5
                $sKeyCode1 = String(30 + $i)
                $sKeyCode2 = String(60 + $i)
                If $nMsg = $aButton[$i] Or _IsPressed($sKeyCode1, $hDLL) Or _IsPressed($sKeyCode2, $hDLL) Then ; is the button, keyboard number, or keypad number pressed?
                    _doRun(@ScriptDir & "\" & $aCommand[$i])
                    ExitLoop
                EndIf
            Next
    EndSelect
WEnd

;~ ;=============================================================================
;~ ;==================================Functions==================================
;~ ;=============================================================================

;~ ;=============================================================================
;~ ; Run function for batch or executable files, hides main menu when running
;~ ;=============================================================================
Func _doRun($RunFile)
    GUISetState(@SW_HIDE, $MainMenu)
    RunWait(@ComSpec & " /c " & $RunFile)
    GUISetState(@SW_SHOW, $MainMenu)
EndFunc   ;==>_doRun

; --------------------------------------------------
; Run a command prompt for lab/field troubleshooting
; --------------------------------------------------
Func _doCMD()
    HotKeySet("+!{ESC}") ; deactivate hotkey to prvent spawning multiple cmd boxes with it
    GUISetState(@SW_HIDE, $MainMenu) ; hide the GUI
    RunWait(@ComSpec & " /c " & "cmd.exe", "", @SW_SHOW)
    GUISetState(@SW_SHOW, $MainMenu) ; bring the GUI back up
    HotKeySet("+!{ESC}", "_doCMD") ; reset the hotkey shift-alt-escape for a command dialogue (emergency use)
EndFunc   ;==>_doCMD

I also took the opportunity to tidy up the code a bit - you will need to polish up the button location algorithm, but I am sure you can see the benefit of using loops when you have multiple controls in a grid.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#3 ·  Posted

Melba23,

The end result is that a button is still in focus (e.g., Cancel button is defaulted as tab stop). Its the safest option for cancel to be in focus but I would prefer that no button is focused as the spacebar activates the focused button. It seems this "nothing-in-focus" may not actually be possible in this way.

I suppose the workaround can either be to create a button with zero size (e.g., GUICtrlCreateButton("", 0, 0 , 0 ,0)) for the default focus or to have Cancel popup an "Are you sure you want to cancel this operation?" with an OK/Cancel dialogue. (After typing this I think perhaps both might be a good idea.)

Thanks for the assistance - the tip about using a loop for the controls looks like it will make maintaining this much easier.

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

  • Similar Content

    • nacerbaaziz
      By nacerbaaziz
      hello guys
      how are you؟
      I hope to be fine.
      I have a question  please
      how do I get the menu item that was pressed without that contains a variable؟
      For example I have a menu  of Favorites and I want the script recognizes the existing path in the pressed item
      i'll repeat to tell the item does not contain a variable
      Is there any solution
      if you want to explain more I could write an example of what I want.
      Greetings to all,
      thanks in advance
    • czardas
      By czardas
      The following code is intended to illustrate a method of adding recent files to the File menu, once files have been opened or saved. This is not a UDF, nor a universal solution which fits all requirements. It is just the solution I made for myself and I thought it worth sharing. I haven't noticed much about this subject. The example only emulates opening and saving files: nothing is actually written to disk. I have not included any code for opening or saving files - only the File menu and Title bar are updated. The code is intended to illustrate the logic I used. Perhaps you can improve on it or get some ideas from this example.
      #include <GUIConstants.au3> #include <MsgBoxConstants.au3> Example() #Region ; core functions Func UpdateRecentFiles(ByRef $aRecentFiles, $ahMenu, $sNewPath, $iMenuInsertPos) Local $iMaxFiles = UBound($aRecentFiles) -1 For $i = 1 To $aRecentFiles[0][0] ; check to see if the path was accessed recently If $aRecentFiles[$i][0] = $sNewPath Then ; file is already in the list For $j = $i To 2 Step -1 $aRecentFiles[$j][0] = $aRecentFiles[$j -1][0] ; push items down the list Next $aRecentFiles[1][0] = $sNewPath For $j = 1 To $aRecentFiles[0][0] ; update all recent file menu items GUICtrlSetData($aRecentFiles[$j][1], $aRecentFiles[$j][0]) ; overwrite existing control data Next Return ; the list has simply been reordered EndIf Next ; if we are here, then the file was not found in the recent files list For $i = $iMaxFiles To 2 Step -1 $aRecentFiles[$i][0] = $aRecentFiles[$i -1][0] ; push all existing items down the list Next If $aRecentFiles[0][0] < $iMaxFiles Then $aRecentFiles[0][0] += 1 ; increment the number of recent files in the list $aRecentFiles[$aRecentFiles[0][0]][1] = GUICtrlCreateMenuItem($sNewPath, $ahMenu[0], $aRecentFiles[0][0] + $iMenuInsertPos) ; create a new control ; add a second spacer to the menu after the first recent item appears (one time action) If $aRecentFiles[0][0] = 1 Then $aRecentFiles[0][1] = GUICtrlCreateMenuItem('', $ahMenu[0], $aRecentFiles[0][0] + $iMenuInsertPos +1) ; add divider after adding the first recent item EndIf $aRecentFiles[1][0] = $sNewPath ; add the new path to the files list For $i = 1 To $aRecentFiles[0][0] ; update all recent file menu items GUICtrlSetData($aRecentFiles[$i][1], $aRecentFiles[$i][0]) ; overwrite existing control data Next EndFunc ;==> UpdateRecentFiles Func ClearRecentFiles(ByRef $aRecentFiles, $idDummyInactive) For $i = 0 To $aRecentFiles[0][0] GUICtrlDelete($aRecentFiles[$i][1]) ; delete menu items $aRecentFiles[$i][1] = $idDummyInactive ; render all control IDs inactivate Next $aRecentFiles[0][0] = 0 ; there are now zero files in the list EndFunc ;==> ClearRecentFiles Func DeleteRecentItem(ByRef $aRecentFiles, $iItem, $idDummyInactive) For $i = $iItem To $aRecentFiles[0][0] -1 $aRecentFiles[$i][0] = $aRecentFiles[$i +1][0] GUICtrlSetData($aRecentFiles[$i][1], $aRecentFiles[$i][0]) Next GUICtrlDelete($aRecentFiles[$aRecentFiles[0][0]][1]) $aRecentFiles[$aRecentFiles[0][0]][1] = $idDummyInactive $aRecentFiles[0][0] -= 1 If $aRecentFiles[0][0] = 0 Then GUICtrlDelete($aRecentFiles[0][1]) $aRecentFiles[0][1] = $idDummyInactive EndIf EndFunc ;==> DeleteRecentItem #EndRegion ;==> core functions #Region ; example code Func Example() Local $sGUITitle = "New Project", $hGUI = GUICreate($sGUITitle, 500, 200) ; create GUI Local _ ; declare menu arrays $ahMenu[2] = [" File "," Options"], _ ; 1D array assigned to menus $ahMenuItem = GetMenuItems() ; 2D array assigned to menu item controls For $i = 0 To UBound($ahMenu) -1 $ahMenu[$i] = GUICtrlCreateMenu($ahMenu[$i]) ; create menu For $j = 1 To $ahMenuItem[0][$i] ; add menu item controls $ahMenuItem[$j][$i] = GUICtrlCreateMenuItem($ahMenuItem[$j][$i], $ahMenu[$i]) Next Next Local $iMenuInsertPos = 4 ; this is the menuentry position for the most recent file GUICtrlCreateMenuItem('', $ahMenu[0], $iMenuInsertPos) ; create dividor Local $aRecentFiles[9][2] = [[0]], _ ; zero previously stored items - assuming that the recent files list is empty at startup $idDummyInactive = GUICtrlCreateDummy() ; never send messages to $idDummyInactive For $i = 0 To 8 ; [IMPORTANT] Windows assigned a unique control ID to $idDummyInactive $aRecentFiles[$i][1] = $idDummyInactive ; temporarily set all (recent files list) controls to never receive messages Next GUISetState(@SW_SHOW) Local $msg, $sFilePath While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE, $ahMenuItem[5][0] ExitLoop Case $ahMenuItem[1][0] ; File ==> New New() WinSetTitle($hGUI , WinGetTitle($hGUI), $sGUITitle) Case $ahMenuItem[2][0] ; File ==> Open $sFilePath = Open() If Not @error Then WinSetTitle($hGUI , WinGetTitle($hGUI), $sFilePath) UpdateRecentFiles($aRecentFiles, $ahMenu, $sFilePath, $iMenuInsertPos) EndIf Case $ahMenuItem[3][0] ; File ==> Save $sFilePath = Save(WinGetTitle($hGUI)) If @error Then MsgBox($MB_OK, "Action Failed", "Unable to save file") ContinueLoop ; [use your own code logic] Else WinSetTitle($hGUI , WinGetTitle($hGUI), $sFilePath) UpdateRecentFiles($aRecentFiles, $ahMenu, $sFilePath, $iMenuInsertPos) ; update recent files here EndIf Case $ahMenuItem[4][0] ; File ==> Save As $sFilePath = SaveAs() If @error Then MsgBox($MB_OK, "Action Failed", "Unable to save file") ContinueLoop ; [use your own code logic] Else WinSetTitle($hGUI , WinGetTitle($hGUI), $sFilePath) UpdateRecentFiles($aRecentFiles, $ahMenu, $sFilePath, $iMenuInsertPos) ; update recent files here EndIf Case $ahMenuItem[1][1] ; Options ==> Clear Recent Files ClearRecentFiles($aRecentFiles, $idDummyInactive) Case $aRecentFiles[1][1], $aRecentFiles[2][1], $aRecentFiles[3][1], $aRecentFiles[4][1], $aRecentFiles[5][1], $aRecentFiles[6][1], $aRecentFiles[7][1], $aRecentFiles[8][1] For $i = 1 To $aRecentFiles[0][0] If $msg = $aRecentFiles[$i][1] Then $sFilePath = OpenRecent($aRecentFiles[$i][0]) If Not @error Then WinSetTitle($hGUI , WinGetTitle($hGUI), $sFilePath) UpdateRecentFiles($aRecentFiles, $ahMenu, $sFilePath, $iMenuInsertPos) ; update recent files here ElseIf @error = 1 Then If MsgBox(BitOR($MB_YESNO, $MB_DEFBUTTON2, $MB_TASKMODAL), "Action Failed", "Unable to locate " & $aRecentFiles[$i][0] & @CRLF & _ "Do you want to remove this item from the menu?") = 6 Then DeleteRecentItem($aRecentFiles, $i, $idDummyInactive) EndIf ExitLoop ; return to the While loop EndIf Next EndSwitch WEnd EndFunc ;==> Example Func New() ; start a new project [your code here] EndFunc ;==> New Func Open() Local $sFilePath = FileOpenDialog("Open", @DocumentsCommonDir, "All (*.*)") If @error Then Return SetError(1) ; read file [your code here] Return $sFilePath EndFunc ;== Open Func OpenRecent($sFilePath) If Not FileExists($sFilePath) Then Return SetError(1) ; unable to open recent file ; read file [your code here] Return $sFilePath EndFunc ;== OpenRecent Func Save($sFilePath) If Not FileExists($sFilePath) Then Local $sNewPath = SaveAs() If @error Then Return SetError(1) ; unable to save file Return $sNewPath EndIf ; save file [your code here] Return $sFilePath EndFunc ;==> Save Func SaveAs() Local $sFilePath = FileSaveDialog( "Save As", @DocumentsCommonDir, "All (*.*)") If @error Then Return SetError(1) ; unable to save file ; save new or existing file [your code here] Return $sFilePath EndFunc ;==> SaveAs Func GetMenuItems() Local $aMenuItem[6][2] $aMenuItem[0][0] = 5 ; number of items on the File Menu $aMenuItem[0][1] = 1 ; number of items on the Options Menu ; File Menu $aMenuItem[1][0] = "New" $aMenuItem[2][0] = "Open" $aMenuItem[3][0] = "Save" $aMenuItem[4][0] = "Save As" $aMenuItem[5][0] = "Exit" ; Options Menu $aMenuItem[1][1] = "Clear Recent Files" Return $aMenuItem EndFunc ;==> GetMenuItems #Region ; example code Run the example, open some files and check for new menu items that are added. Then try a few other menu options and check the various changes occurring in the File menu.
    • k4rl3on
      By k4rl3on
      Hi,
      i'm looking for a way to get the text of selected item from a popup menu
      here is my script, it works fine for non-Explorer.exe window (tested on SciTE on both context menu and menubar menu), but fails on displayed menu on Desktop...
      Local $hDLL, $hWinEventProc, $hHook Local $LastMenuItem[5] ;Save last menu item propieties Local $EVENT_Min = 0x0006 ;An MSAA event indicating that a pop-up menu was displayed. Local $EVENT_Max = 0x0007 ;An MSAA event indicating that a pop-up menu was closed. Local $hWinEventProc = DllCallbackRegister("_WinEventProc", "none", "hwnd;int;hwnd;long;long;int;int") If Not @error Then OnAutoItExitRegister("OnAutoItExit") Else MsgBox(16 + 262144, "Error", "DllCallbackRegister(_WinEventProc) did not succeed.") Exit EndIf $hHook = _SetWinEventHook($EVENT_Min, $EVENT_Max) If @error Then MsgBox(16 + 262144, "Error", "_SetWinEventHook() did not succeed.") Exit EndIf While True Sleep(250) ;function that get last menu item propieties _PopupMenuItem() WEnd Func _WinEventProc($hHook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime) Switch $iEvent Case 6 ConsoleWrite("(i) pop-up menu was displayed..."&@CRLF) Case 7 _SelectedMenuItem() ConsoleWrite("(i) pop-up menu was closed..."&@CRLF) EndSwitch EndFunc ;==>_WinEventProc Func _SetWinEventHook($iEventMin, $iEventMax) Local $aRet Local Const $WINEVENT_OUTOFCONTEXT = 0x0 Local Const $WINEVENT_SKIPOWNPROCESS = 0x2 $aRet = DllCall("User32.dll", "hwnd", "SetWinEventHook", _ "uint", $iEventMin, _ "uint", $iEventMax, _ "hwnd", 0, _ "ptr", DllCallbackGetPtr($hWinEventProc), _ "int", 0, _ "int", 0, _ "uint", BitOR($WINEVENT_OUTOFCONTEXT, $WINEVENT_SKIPOWNPROCESS)) If @error Then Return SetError(@error, 0, 0) Return $aRet[0] EndFunc ;==>_SetWinEventHook Func OnAutoItExit() If $hWinEventProc Then DllCallbackFree($hWinEventProc) If $hHook Then DllCall("User32.dll", "int", "UnhookWinEvent", "hwnd", $hHook) EndFunc ;==>OnAutoItExit Func _PopupMenuItem() Local $aRect, $hMenu = False, $MenuItem[9] Local $hDesktop = _WinAPI_GetDesktopWindow() Local $hChild = _WinAPI_GetWindow( $hDesktop, 5 ), $i = 0 Local $hWindow = WinGetHandle("[ACTIVE]") Local $hChild = _WinAPI_GetWindow($hDesktop, 5) Local $i = 0 While $hChild And $i < 5 If _WinAPI_GetClassName( $hChild ) = "#32768" Then $hMenu = _SendMessage( $hChild, 0x01E1 ) ExitLoop EndIf $hChild = _WinAPI_GetWindow( $hChild, 2 ) $i += 1 WEnd If $hMenu Then Local $iCount = _GUICtrlMenu_GetItemCount($hMenu), $sText For $i = 0 To $iCount - 1 If $i = _GUICtrlMenu_MenuItemFromPoint($hWindow, $hMenu) Then If _GUICtrlMenu_GetItemEnabled($hMenu, $i) Then $MenuItem[0] = $hWindow $MenuItem[1] = $hMenu $MenuItem[2] = $i $MenuItem[3] = _GUICtrlMenu_GetItemText($hMenu, $i ) $MenuItem[4] = _GUICtrlMenu_GetItemRectEx($hWindow, $hMenu, $i) If $LastMenuItem[0] <> $MenuItem[0] Or $LastMenuItem[1] <> $MenuItem[1] Or $LastMenuItem[2] <> $MenuItem[2] Then $LastMenuItem = $MenuItem ConsoleWrite("* mouse over item: "&$LastMenuItem[3]&@CRLF) EndIf EndIf ExitLoop EndIf Next EndIf EndFunc Func _SelectedMenuItem() Local $tPOINT = _WinAPI_GetMousePos() ConsoleWrite("(i) last mouse position: "&DllStructGetData($tPoint, "X")&":"&DllStructGetData($tPoint, "Y")&@CRLF) If _WinAPI_PtInRect($LastMenuItem[4], $tPOINT) Then ConsoleWrite("-> selected item: "&$LastMenuItem[3]&@CRLF) Else ConsoleWrite("(i) last menu item position Rect: "&DllStructGetData($LastMenuItem[4], "Left")&">"&DllStructGetData($LastMenuItem[4], "Right")&":"&DllStructGetData($LastMenuItem[4], "Top")&"V"&DllStructGetData($LastMenuItem[4], "Bottom")&@CRLF) EndIf EndFunc ; Functions From Include Directory Func _WinAPI_GetWindow($hWnd, $iCmd) Local $aResult = DllCall("user32.dll", "hwnd", "GetWindow", "hwnd", $hWnd, "uint", $iCmd) If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc Func _WinAPI_GetClassName($hWnd) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $aResult = DllCall("user32.dll", "int", "GetClassNameW", "hwnd", $hWnd, "wstr", "", "int", 4096) If @error Or Not $aResult[0] Then Return SetError(@error, @extended, '') Return SetExtended($aResult[0], $aResult[2]) EndFunc Func _GUICtrlMenu_GetItemCount($hMenu) Local $aResult = DllCall("user32.dll", "int", "GetMenuItemCount", "handle", $hMenu) If @error Then Return SetError(@error, @extended, -1) Return $aResult[0] EndFunc Func _SendMessage($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult") Local $aResult = DllCall("user32.dll", $sReturnType, "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wParam, $lParamType, $lParam) If @error Then Return SetError(@error, @extended, "") If $iReturn >= 0 And $iReturn <= 4 Then Return $aResult[$iReturn] Return $aResult EndFunc Func _GUICtrlMenu_GetItemRectEx($hWnd, $hMenu, $iItem) Local $tRECT = DllStructCreate("struct;long Left;long Top;long Right;long Bottom;endstruct") Local $aResult = DllCall("user32.dll", "bool", "GetMenuItemRect", "hwnd", $hWnd, "handle", $hMenu, "uint", $iItem, "struct*", $tRECT) If @error Then Return SetError(@error, @extended, 0) Return SetExtended($aResult[0], $tRECT) EndFunc Func _GUICtrlMenu_GetItemText($hMenu, $iItem, $bByPos = True) Local $iByPos = 0 If $bByPos Then $iByPos = 0x00000400 Local $aResult = DllCall("user32.dll", "int", "GetMenuStringW", "handle", $hMenu, "uint", $iItem, "wstr", "", "int", 4096, "uint", $iByPos) If @error Then Return SetError(@error, @extended, 0) Return SetExtended($aResult[0], $aResult[3]) EndFunc Func _GUICtrlMenu_GetItemInfo($hMenu, $iItem, $bByPos = True) Local $tInfo = DllStructCreate("uint Size;uint Mask;uint Type;uint State;uint ID;handle SubMenu;handle BmpChecked;handle BmpUnchecked;" & _ "ulong_ptr ItemData;ptr TypeData;uint CCH;handle BmpItem") DllStructSetData($tInfo, "Size", DllStructGetSize($tInfo)) DllStructSetData($tInfo, "Mask", 0x0000003F) Local $aResult = DllCall("user32.dll", "bool", "GetMenuItemInfo", "handle", $hMenu, "uint", $iItem, "bool", $bByPos, "struct*", $tInfo) If @error Then Return SetError(@error, @extended, 0) Return SetExtended($aResult[0], $tInfo) EndFunc Func _GUICtrlMenu_GetItemStateEx($hMenu, $iItem, $bByPos = True) Local $tInfo = _GUICtrlMenu_GetItemInfo($hMenu, $iItem, $bByPos) Return DllStructGetData($tInfo, "State") EndFunc Func _GUICtrlMenu_GetItemEnabled($hMenu, $iItem, $bByPos = True) Return BitAND(_GUICtrlMenu_GetItemStateEx($hMenu, $iItem, $bByPos), 0x00000002) = 0 EndFunc Func _GUICtrlMenu_MenuItemFromPoint($hWnd, $hMenu, $iX = -1, $iY = -1) If $iX = -1 Then $iX = _WinAPI_GetMousePosX() If $iY = -1 Then $iY = _WinAPI_GetMousePosY() Local $aResult = DllCall("user32.dll", "int", "MenuItemFromPoint", "hwnd", $hWnd, "handle", $hMenu, "int", $iX, "int", $iY) If @error Then Return SetError(@error, @extended, -1) Return $aResult[0] EndFunc Func _WinAPI_GetMousePosX($bToClient = False, $hWnd = 0) Local $tPoint = _WinAPI_GetMousePos($bToClient, $hWnd) If @error Then Return SetError(@error, @extended, 0) Return DllStructGetData($tPoint, "X") EndFunc Func _WinAPI_GetMousePosY($bToClient = False, $hWnd = 0) Local $tPoint = _WinAPI_GetMousePos($bToClient, $hWnd) If @error Then Return SetError(@error, @extended, 0) Return DllStructGetData($tPoint, "Y") EndFunc Func _WinAPI_PtInRect(ByRef $tRECT, ByRef $tPoint) Local $aResult = DllCall("user32.dll", "bool", "PtInRect", "struct*", $tRECT, "struct", $tPoint) If @error Then Return SetError(@error, @extended, False) Return $aResult[0] EndFunc Func _WinAPI_GetMousePos($bToClient = False, $hWnd = 0) Local $iMode = Opt("MouseCoordMode",1) Local $aPos = MouseGetPos() Opt("MouseCoordMode", $iMode) Local $tPoint = DllStructCreate("struct;long X;long Y;endstruct") DllStructSetData($tPoint, "X", $aPos[0]) DllStructSetData($tPoint, "Y", $aPos[1]) If $bToClient And Not _WinAPI_ScreenToClient($hWnd, $tPoint) Then Return SetError(@error + 20, @extended, 0) Return $tPoint EndFunc Func _WinAPI_ScreenToClient($hWnd, ByRef $tPoint) Local $aResult = DllCall("user32.dll", "bool", "ScreenToClient", "hwnd", $hWnd, "struct*", $tPoint) If @error Then Return SetError(@error, @extended, False) Return $aResult[0] EndFunc Func _WinAPI_GetDesktopWindow() Local $aResult = DllCall("user32.dll", "hwnd", "GetDesktopWindow") If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc Cause of the problem: _WinAPI_PtInRect fails on Explorer.exe windows because _GUICtrlMenu_GetItemRectEx returns relative rectangle bounds to the menu (i think) where always X1 = 0.
      Any suggestions to make this script works on all menus?
      Thanks
    • BlazerV60
      By BlazerV60
      Greetings people of the AutoIt community!
      I think I have discovered some possible wrong verbiage in the HelpFile.
      I'm trying to make my software detect the _IsPressed("KEY") for the RIGHT MENU button on the keyboard. 
      You all have a RIGHT MENU button on your keyboard (maybe you haven't noticed it), it's they key between the Right ALT key and the Right CTRL Key.
      However!!!!!!! In the helpfile it says the RIGHT MENU key is "A5", that is not true for me. A5 is actually the Right ALT key.
      So my question is, what is the _IsPressed HexKey for the RIGHT MENU button?
       
      #include <Misc.au3> #include <MsgBoxConstants.au3> Local $hDLL = DllOpen("user32.dll") While 1 If _IsPressed("A5", $hDLL) Then Sleep(100) msgbox(0,"Test", "Pressed!") Sleep(250) EndIf WEnd DllClose($hDLL)  
      If you try to run the above code, the msgbox will only appear if you press the Right ALT key, even though the helpfil says that A5 is the Right Menu Key hex.
       
      Thank you,
      Brian
    • Skysnake
      By Skysnake
      #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> Example() Func Example() GUICreate("My GUI") ; will create a dialog box that when displayed is centered GUICtrlCreateButton("my picture button", 10, 20, 40, 40, $BS_ICON) GUICtrlSetImage(-1, "shell32.dll", 22) GUISetState(@SW_SHOW) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example guictrlsetimage this awesome little example from the Helpfile
       
      My question is this: does a Menu created with a function like guictrlcreatemenu have any special attributes?  In stead of using guictrlcreatemenu, can I simply create a 'panel' and then run a series of picture buttons on it, behaving like a menu?
      I guess what I want to know is (a) if a menu contains any additional functionality which makes it a preferred choice over a row of buttons? (b) since we can not make a button menu, would a row of buttons work when presented to the user as a menu?
      Anything else I should know?
      Thanks