PaulIA Posted November 29, 2006 Posted November 29, 2006 I'm not sure if this is something similar to the ListView question that I raised, but it is curious none the least, so I thought I would ask. If you run the code below, you will see that you can't press Alt+F to open the File menu. You must press and release the Alt key and then press the "F" key to open the menu. I put in a message capture to see if I could spot what is happening and compared this to the messages from a menu created using GUICtrlCreateMenu. Normally, when you press Alt+F, you get messages like: WM_SYSCOMMAND WM_INITMENU However, in the example below, I get: WM_SYSKEYDOWN WM_SYSKEYUP If I press and release the Alt key and then press the "F" key, I get: WM_SYSKEYDOWN WM_SYSKEYUP WM_SYSCOMMAND WM_INITMENU Again, this is more of a curiosity thing than anything else. It would be nice if AutoIt was compatible with controls created with CreateWindowEx, but if it's too much of a pain, I understand. I thought I would raise this up to see if this was a bug or if that's just how things need to work. -Paul CODEexpandcollapse popup#include <GUIConstants.au3> ; ================================================================================================= Global Const $MFT_SEPARATOR = 0x00000800 Global Const $MFT_STRING = 0x00000000 Global Const $MENUITEMINFO = "int;int;int;int;int;int;int;int;int;ptr;int" Global Const $MII_CBSIZE = 1 Global Const $MII_FMASK = 2 Global Const $MII_FTYPE = 3 Global Const $MII_HSUBMENU = 6 Global Const $MII_DWTYPEDATA = 10 Global Const $MIIM_ID = 0x0002 Global Const $MIIM_SUBMENU = 0x0004 Global Const $MIIM_TYPE = 0x0010 Global Const $MIIM_DATA = 0x0020 Global Const $MIIM_STRING = 0x0040 Global Const $WM_SYSKEYDOWN = 0x0104 Global Const $WM_SYSKEYUP = 0x0105 Global Const $WM_SYSCOMMAND = 0x0112 Global Const $WM_INITMENU = 0x0116 ; ================================================================================================= Global $hGUI, $hFile, $hHelp, $hMain ; Create GUI $hGUI = GUICreate("Menu Test", 400, 200) ; Create File menu $hFile = _Menu_CreateMenu() _Menu_AddMenuItem($hFile, 0, "&New" ) _Menu_AddMenuItem($hFile, 1, "&Open" ) _Menu_AddMenuItem($hFile, 2, "&Close") _Menu_AddMenuItem($hFile, 3, "&Save" ) _Menu_AddMenuItem($hFile, 4, "" ) _Menu_AddMenuItem($hFile, 5, "E&xit" ) ; Create Help menu $hHelp = _Menu_CreateMenu() _Menu_AddMenuItem($hHelp, 0, "&About") ; Create Main menu $hMain = _Menu_CreateMenu() _Menu_AddMenuItem($hMain, 0, "&File", $hFile) _Menu_AddMenuItem($hMain, 1, "&Help", $hHelp) ; Set the window menu _Menu_SetMenu($hGUI, $hMain) GUISetState() ; Set up message capture GUIRegisterMsg($WM_SYSKEYDOWN, "WM_CAPTURE") GUIRegisterMsg($WM_SYSKEYUP , "WM_CAPTURE") GUIRegisterMsg($WM_SYSCOMMAND, "WM_CAPTURE") GUIRegisterMsg($WM_INITMENU , "WM_CAPTURE") do Sleep(10) until GUIGetMsg() = $GUI_EVENT_CLOSE ; ================================================================================================= Func WM_CAPTURE($hWnd, $iMsg, $iwParam, $ilParam) Switch $iMsg case $WM_SYSKEYDOWN ConsoleWrite("WM_SYSKEYDOWN: " & Hex($iwParam) & " " & Hex($ilParam) & @CR) case $WM_SYSKEYUP ConsoleWrite("WM_SYSKEYUP .: " & Hex($iwParam) & " " & Hex($ilParam) & @CR) case $WM_SYSCOMMAND ConsoleWrite("WM_SYSCOMMAND: " & Hex($iwParam) & " " & Hex($ilParam) & @CR) case $WM_INITMENU ConsoleWrite("WM_INITMENU .: " & Hex($iwParam) & " " & Hex($ilParam) & @CR) EndSwitch Return $GUI_RUNDEFMSG EndFunc ; ================================================================================================= Func _Menu_AddMenuItem($hMenu, $iPosition, $sText, $hSubMenu=0) Local $iCmdID, $iMask, $iSize, $rMII, $pBuffer, $rBuffer $iMask = BitOR($MIIM_TYPE, $MIIM_ID, $MIIM_SUBMENU) $rMII = DllStructCreate($MENUITEMINFO) $iSize = DllStructGetSize($rMII) DllStructSetData($rMII, $MII_CBSIZE , $iSize ) DllStructSetData($rMII, $MII_FMASK , $iMask ) DllStructSetData($rMII, $MII_HSUBMENU, $hSubMenu) if $sText = "" then DllStructSetData($rMII, $MII_FTYPE, $MFT_SEPARATOR) else $iSize = StringLen($sText) $rBuffer = DllStructCreate("char[" & $iSize + 1 & "]") $pBuffer = DllStructGetPtr($rBuffer) DllStructSetData($rBuffer, 1 , $sText ) DllStructSetData($rMII , $MII_FTYPE , $MFT_STRING) DllStructSetData($rMII , $MII_DWTYPEDATA, $pBuffer ) endif _Menu_InsertMenuItem($hMenu, $iPosition, True, $rMII) EndFunc ; ================================================================================================= Func _Menu_CreateMenu() Local $aResult $aResult = DllCall("User32.dll", "hwnd", "CreateMenu") Return $aResult[0] EndFunc ; ================================================================================================= Func _Menu_InsertMenuItem($hMenu, $iItem, $bByPosition, $rMII) Local $aResult $aResult = DllCall("User32.dll", "int", "InsertMenuItem", "hwnd", $hMenu, "int", $iItem, "int", _ $bByPosition, "ptr", DllStructGetPtr($rMII)) Return ($aResult[0] <> 0) EndFunc ; ================================================================================================= Func _Menu_SetMenu($hWnd, $hMenu) Local $aResult $aResult = DllCall("User32.dll", "int", "SetMenu", "hwnd", $hWnd, "hwnd", $hMenu) Return $aResult[0] EndFunc Auto3Lib: A library of over 1200 functions for AutoIt
jpm Posted November 29, 2006 Posted November 29, 2006 You will not believe it but if you add a button it works. at least for the main menu acceleration. I will have a look. I notice you are reimplementing GUICtrlCreateMenu and GUICtrlCreateMenuItem. I don't know why. for the CreateWindowEx I don't know why you really need it as the GUICtrlCreate is using it, but I did a fix (I hope) for the crash in 3.2.1.14
jpm Posted November 30, 2006 Posted November 30, 2006 @PaulIA As an API extremist, can you help me to understand why adding the button allow the acceleration key to activate the menu. Thanks for your knowledge PS I add a file working as yours but with GUICtrlCreatMenu
PaulIA Posted November 30, 2006 Author Posted November 30, 2006 I spent some time this morning working on this. Here are some additional observations: It appears that you can create any control (including a label) and the accelerator keys will work. This is true with the script that you attached using the GUICtrlCreate methods and also using Auto3Lib to create the controls using CreateWindowEx. In a normal application, when you hold down the Alt key, you do not get any messages until you press an accelerator key. After you press the accelerator key, you then get various menu commands. The message sequence normally looks something like: WM_SYSCOMMAND WM_INITMENU WM_MENUSELECT WM_INITMENUPOPUP WM_MENUSELECT WM_ENTERIDLE In AutoIt (without a control), when you hold down the Alt key, you immediately start getting WM_SYSKEYDOWN messages. You receive these as long as you hold the Alt key down. If you press an accelerator key while holding the Alt key down, you get a WM_SYSKEYDOWN message for the accelerator. When you release the Alt key, you get a WM_SYSKEYUP message. The message sequence looks something like: WM_SYSKEYDOWN WM_SYSKEYDOWN WM_SYSKEYDOWN WM_SYSKEYDOWN WM_SYSKEYUP In AutoIt (without a control), if you press the Alt key and immediately release it, you get the following message sequence: WM_SYSKEYDOWN WM_SYSKEYUP WM_SYSCOMMAND WM_INITMENU WM_MENUSELECT WM_INITMENUPOPUP WM_MENUSELECT WM_ENTERIDLE This highlights the main menu and you can then press the accelerator key to select the menu item. As I do not have access to the source, any speculation on my part as to where the problem lies would be worthless. However, my instinct would be to start looking at the AutoIt message handlers and see if there is anything that would short circuit the generation of the WM_SYSCOMMAND. I will try to find some time to investigate further and will let you know if I find anything else. Auto3Lib: A library of over 1200 functions for AutoIt
Valik Posted November 30, 2006 Posted November 30, 2006 One thing to consider is TranslateAccelerator(). I don't think AutoIt calls it since there isn't a built-in accelerator table. But it could be that a "normal" application does use that function, which could theoretically affect the messages. I believe that even wizard-generated Windows applications use an accelerator table. It may be that TranslateAccelerator() does nothing for this particular case, but on the other hand, I think it's a variable that needs looked at so the exact impact can be determined.
jpm Posted November 30, 2006 Posted November 30, 2006 One thing to consider is TranslateAccelerator(). I don't think AutoIt calls it since there isn't a built-in accelerator table. But it could be that a "normal" application does use that function, which could theoretically affect the messages. I believe that even wizard-generated Windows applications use an accelerator table. It may be that TranslateAccelerator() does nothing for this particular case, but on the other hand, I think it's a variable that needs looked at so the exact impact can be determined.How does that relate to the fact that adding a button control make the menu selection OK?
Holger Posted December 1, 2006 Posted December 1, 2006 Reply to the first post: Absolutely normal behaviour! Just do this to see/compare it: - make a copy of the Windows tool "Soundrecorder" (sndrec32.exe) into a temp. folder - open the copy into ResourceHacker and remove all controls from the main dialog (100). - recompile it and save this - open the changed exe -> same messages from this dialog -> where is the problem? With the TranslateAccelerator() things -> good question. Maybe there is also something with "wm_command" - just a nightly idea... Greets Holger Old project:GUI/Tray menu with icons and colors Other old stuff:IconFileScanner, TriState/ThreeState GUI TreeView, GUI ContextMenu created out of a TreeView
PaulIA Posted December 1, 2006 Author Posted December 1, 2006 Reply to the first post:Absolutely normal behaviour! Just do this to see/compare it:- make a copy of the Windows tool "Soundrecorder" (sndrec32.exe) into a temp. folder- open the copy into ResourceHacker and remove all controls from the main dialog (100).- recompile it and save this- open the changed exe-> same messages from this dialog-> where is the problem? With the TranslateAccelerator() things -> good question.Maybe there is also something with "wm_command" - just a nightly idea... GreetsHolgerI'm not sure I understand what you are calling "normal behaviour". Are you saying that if I build a GUI with only a menu on it that I should not be able to select the menu unless I have a control on the GUI? Auto3Lib: A library of over 1200 functions for AutoIt
Holger Posted December 1, 2006 Posted December 1, 2006 Did you test it with my steps? Do you know an application which has only a menu so we could compare it? Greets Holger Old project:GUI/Tray menu with icons and colors Other old stuff:IconFileScanner, TriState/ThreeState GUI TreeView, GUI ContextMenu created out of a TreeView
PaulIA Posted December 1, 2006 Author Posted December 1, 2006 (edited) Did you test it with my steps? Do you know an application which has only a menu so we could compare it? Greets HolgerHere's a quick one that I built in Delphi. It only has a menu on it and I can select the menu. Edit: Used resource hacker to make sure there are NO controls except the menu and menu items. Edited December 1, 2006 by PaulIA Auto3Lib: A library of over 1200 functions for AutoIt
Holger Posted December 1, 2006 Posted December 1, 2006 Would be nice to see the source to it But only later...have to go sleep... Old project:GUI/Tray menu with icons and colors Other old stuff:IconFileScanner, TriState/ThreeState GUI TreeView, GUI ContextMenu created out of a TreeView
PaulIA Posted December 1, 2006 Author Posted December 1, 2006 Would be nice to see the source to it But only later...have to go sleep...Here you go: program Test; uses Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus; type TForm1 = class(TForm) MainMenu1: TMainMenu; File1: TMenuItem; Exit1: TMenuItem; Help1: TMenuItem; About1: TMenuItem; private public end; var Form1: TForm1; implementation {$R *.dfm} end. object Form1: TForm1 Left = 319 Top = 172 Width = 191 Height = 183 Caption = 'Menu Test' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] Menu = MainMenu1 Position = poDesktopCenter PixelsPerInch = 96 TextHeight = 13 object MainMenu1: TMainMenu Left = 42 Top = 14 object File1: TMenuItem Caption = '&File' object Exit1: TMenuItem Caption = 'E&xit' end end object Help1: TMenuItem Caption = '&Help' object About1: TMenuItem Caption = '&About' end end end end Auto3Lib: A library of over 1200 functions for AutoIt
Valik Posted December 1, 2006 Posted December 1, 2006 I would prefer something other than Delphi, something using the Windows API directly. A C program would be ideal because I don't trust that Delphi isn't doing stuff outside the norm for the Windows API.
GaryFrost Posted December 1, 2006 Posted December 1, 2006 (edited) I would prefer something other than Delphi, something using the Windows API directly. A C program would be ideal because I don't trust that Delphi isn't doing stuff outside the norm for the Windows API.You have the Dev-C++?if so there is a WinMenu example.Not sure if that will help or not.Edit: don't think that one will help, it's only using WM_COMMAND. Edited December 1, 2006 by gafrost SciTE for AutoItDirections for Submitting Standard UDFs  Don't argue with an idiot; people watching may not be able to tell the difference. Â
/dev/null Posted December 1, 2006 Posted December 1, 2006 You have the Dev-C++?if so there is a WinMenu example.Not sure if that will help or not.Edit: don't think that one will help, it's only using WM_COMMAND.however, it behaves exactly like the AU3 code of PaulIA. Press ALT, release it and then F to get the File Menu...CheersKurt __________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *
/dev/null Posted December 1, 2006 Posted December 1, 2006 (edited) however, it behaves exactly like the AU3 code of PaulIA. Press ALT, release it and then F to get the File Menu...CheersKurtif one adds TranslateMessage(&messages) to the message loop, the DEV-C++ sample works as expected. As an alternative one can install an accelerator table - see TranslateAccelerator(). I guess, "simple" Windows applications call TranslateMessage() if they have not installed an accelerator table. According to MSDN TranslateMessage() and TranslateAccelerator() should not be used together...MSDN LINKCheersKurt Edited December 1, 2006 by /dev/null __________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *
Valik Posted December 1, 2006 Posted December 1, 2006 I think TranslateMessage() was the function I was trying to think of earlier when I found TranslateAccelerator() on MSDN.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now