 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
newbie83 Guest
|
Posted: Tue Oct 13, 2009 6:56 pm Post subject: How do select an item from the desktop context menu? |
|
|
I know that in order to invoke any context menu I need to send SHIFT+F10.
But how I make sure that it's always when the desktop is selected? And after that, how do I select a menu item by name, not by location in the menu?
Thanks! |
|
| Back to top |
|
 |
Carcophan
Joined: 24 Dec 2008 Posts: 1308 Location: :noitacoL
|
Posted: Tue Oct 13, 2009 8:32 pm Post subject: |
|
|
Sorry if I do not understand your questions fully.
| Quote: |
how I make sure that it's always when the desktop is selected
|
Windows+D will minimize all, bringing you to your desktop
After WinD you can assume that you are at your desktop, so you can send your Shift+F10
To select it by name, send the character that is underlined
'e' for refresh, 'w' for new, 'r' for properties.
Dunno if this is what you meant or not. |
|
| Back to top |
|
 |
txquestor
Joined: 22 Aug 2009 Posts: 294
|
Posted: Tue Oct 13, 2009 8:55 pm Post subject: |
|
|
To Activate a Context Menuitem use this script.
| Code: |
; ActivateContextMenuItem
; Activate the Desktop Context Menu & Select a Menuitem
; by TXQuestor
#InstallKeybdHook
SetKeyDelay, 0
+F10::
Sleep, 100
WinActivate, Program Manager
Sleep 100
;MouseMove, 50, -255, 5, R ; VERIFIED - use only if you want to click in a specific position
Sleep 100
Send {RButton} ; VERIFIED
Sleep 100
Send {Down 8} ; VERIFIED - number of arrow down to select the menuitem
Sleep 100
Send {Enter} ; VERIFIED
Return
ESC::ExitApp
|
Sometimes you need to get the menu info by this method
and then use the 'PostMessage" command to activate a menu.
http://www.autohotkey.com/docs/misc/SendMessage.html
http://www.autohotkey.com/forum/topic40112.html
This script gets any menu's Name & ID by Micha
| Code: |
; Gets all Menuiteminfo values for any type of Menu
; This version Micha added the GetMenuitemID function by my request.
; AutoHotkey Version: 1.x
; Language: English
; Platform: Win9x/NT
; Author: micha
;
; Script Function:
; Demonstrates how to retrieve infos from a context/ popup menu
;
/*
This is the struct we are using.
typedef struct tagMENUITEMINFO {
UINT cbSize;
UINT fMask;
UINT fType;
UINT fState;
UINT wID;
HMENU hSubMenu;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
ULONG_PTR dwItemData;
LPTSTR dwTypeData;
UINT cch;
HBITMAP hbmpItem;
} MENUITEMINFO, *LPMENUITEMINFO;
*/
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#Persistent
SetTimer, Demo, 500
return
Demo:
;constants
MFS_ENABLED = 0
MFS_CHECKED = 8
MFS_DEFAULT = 0x1000
MFS_DISABLED = 2
MFS_GRAYED = 1
MFS_HILITE = 0x80
;MFS_UNCHECKED = 0
;MFS_UNHILITE = 0
;Get mouse position and handle to wnd under the mouse cursor
MouseGetPos, MouseScreenX, MouseScreenY, MouseWindowUID, MouseControlID
WinGet,ControlHwnd, ID,ahk_id %MouseWindowUID%
;Get count of menu items
ContextMenCnt := GetContextMenuCount(ControlHwnd)
if ContextMenCnt < 1
{
Tooltip,
return
}
TooltipText =
;Read info for each menu item
loop, %ContextMenCnt%
{
IsEnabled := GetContextMenuState(ControlHwnd, a_index-1)
{
CurrentText =
if IsEnabled = 0
CurrentText = %CurrentText% Enabled
if (IsEnabled & MFS_CHECKED)
CurrentText = %CurrentText% Checked
if (IsEnabled & MFS_DEFAULT)
CurrentText = %CurrentText% Default
if (IsEnabled & MFS_DISABLED)
CurrentText = %CurrentText% Disabled
if (IsEnabled & MFS_GRAYED)
CurrentText = %CurrentText% Grayed
if (IsEnabled & MFS_HILITE)
CurrentText = %CurrentText% Highlight
TooltipText = %TooltipText%%a_index%:%CurrentText%`n
}
}
TextText =
loop, %ContextMenCnt%
{
StrSize := GetContextMenuText(ControlHwnd, a_index-1)
nID := GetContextMenuID(ControlHwnd, a_index-1)
TextText = %TextText%%a_index%:%StrSize%-ID=%nID%`n
}
CoordMode, Tooltip, Screen
;Tooltip, %TooltipText%---`n%TextText%, 0, 0 ; Shows Enabled/Disabled, Empty, Name, Hotkey & ID of Menuitems
Tooltip, %TextText%, 0, 0 ; ONLY shows Name, Hotkey & ID of Menuitems
return
/***************************************************************
* returns the count of menu items
***************************************************************
*/
GetContextMenuCount(hWnd)
{
WinGetClass, WindowClass, ahk_id %hWnd%
;All popups should have the window class #32768
if WindowClass <> #32768
{
return 0
}
;Retrieve menu handle from window
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
Return, menuitemcount
}
/***************************************************************
* returns the state of a menu entry
***************************************************************
*/
GetContextMenuState(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;We need to allocate a struct
VarSetCapacity(MenuItemInfo, 60, 0)
;Set Size of Struct to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Get only Flags from dllcall GetMenuItemInfo MIIM_TYPE = 1
InsertInteger(1, MenuItemInfo, 4, 4)
;GetMenuItemInfo: Handle to Menu, Index of Position, 0=Menu identifier / 1=Index
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes != 0
return -1
;Get Flag from struct
GetMenuItemInfoRes := ExtractInteger(MenuItemInfo, 12, false, 4)
/*
IsEnabled = 1
if GetMenuItemInfoRes > 0
IsEnabled = 0
return IsEnabled
*/
return GetMenuItemInfoRes
}
/***************************************************************
* returns the ID of a menu entry
***************************************************************
*/
GetContextMenuID(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;UINT GetMenuItemID( HMENU hMenu, int nPos);
InfoRes := DllCall("user32.dll\GetMenuItemID",UInt,hMenu, Uint, Position)
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes != 0
return -1
return InfoRes
}
/***************************************************************
* returns the text of a menu entry (standard windows context menus only!!!)
***************************************************************
*/
GetContextMenuText(hWnd, Position)
{
WinGetClass, WindowClass, ahk_id %hWnd%
if WindowClass <> #32768
{
return -1
}
SendMessage, 0x01E1, , , , ahk_id %hWnd%
;Errorlevel is set by SendMessage. It contains the handle to the menu
hMenu := errorlevel
;We need to allocate a struct
VarSetCapacity(MenuItemInfo, 200, 0)
;Set Size of Struct (48) to the first member
InsertInteger(48, MenuItemInfo, 0, 4)
;Retrieve string MIIM_STRING = 0x40 = 64 (/ MIIM_TYPE = 0x10 = 16)
InsertInteger(64, MenuItemInfo, 4, 4)
;Set type - Get only size of string we need to allocate
;InsertInteger(0, MenuItemInfo, 8, 4)
;GetMenuItemInfo: Handle to Menu, Index of Position, 0=Menu identifier / 1=Index
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
if InfoRes = 0
return -1
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes <> 0
return -1
;Get size of string from struct
GetMenuItemInfoRes := ExtractInteger(MenuItemInfo, 40, false, 4)
;If menu is empty return
If GetMenuItemInfoRes = 0
return "{Empty String}"
;+1 should be enough, we'll use 2
GetMenuItemInfoRes += 2
;Set capacity of string that will be filled by windows
VarSetCapacity(PopupText, GetMenuItemInfoRes, 0)
;Set Size plus 0 terminator + security ;-)
InsertInteger(GetMenuItemInfoRes, MenuItemInfo, 40, 4)
InsertInteger(&PopupText, MenuItemInfo, 36, 4)
InfoRes := DllCall("user32.dll\GetMenuItemInfo",UInt,hMenu, Uint, Position, uint, 1, "int", &MenuItemInfo)
if InfoRes = 0
return -1
InfoResError := errorlevel
LastErrorRes := DllCall("GetLastError")
if InfoResError <> 0
return -1
if LastErrorRes <> 0
return -1
return PopupText
}
; *********************************
; *********************************
; Original versions of ExtractInteger and InsertInteger provided by Chris
; - from the AutoHotkey help file - Version 1.0.37.04
; *********************************
; *********************************
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
SourceAddress := &pSource + pOffset ; Get address and apply the caller's offset.
result := 0 ; Init prior to accumulation in the loop.
Loop %pSize% ; For each byte in the integer:
{
result := result | (*SourceAddress << 8 * (A_Index - 1)) ; Build the integer from its bytes.
SourceAddress += 1 ; Move on to the next byte.
}
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index - 1, UInt, 1 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1)) ; This line is auto-merged with above at load-time.
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
; *********************************
; *********************************
PrintScreen::reload
ESC::ExitApp
|
Have Fun  _________________
"Man's quest for knowledge is an expanding series whose limit is infinity"
Last edited by txquestor on Tue Oct 13, 2009 11:14 pm; edited 2 times in total |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Wed Oct 14, 2009 4:48 pm Post subject: |
|
|
| Carcophan wrote: | | Windows+D will minimize all, bringing you to your desktop |
Thank you Carcophan txquestor. I am still struggling with this. Right now, all I am trying to do is to minimize all windows. I tried
but it didn't work. So I tried:
| Code: | Send {LWin Down}
Send {D}
Send {LWin Up} |
And it still didn't work.
What am I doing wrong?
I have Windows XP SP2 with an old keyboard that doesn't have the Windows key. Could that be the reason?
Thanks! |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Wed Oct 14, 2009 4:53 pm Post subject: |
|
|
I forgot to mention that in my attempts to minimize all windows I also tried:
| Code: | | WinActivate, Program Manager |
And it didn't work either.
I must be doing something wrong but what is it? |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Wed Oct 14, 2009 5:10 pm Post subject: |
|
|
Taking back my last statement:
| newbie83 wrote: | I forgot to mention that in my attempts to minimize all windows I also tried:
| Code: | | WinActivate, Program Manager |
And it didn't work either.
|
This works! (unlike the suggested #D) but it doesn't minimize all windows, it only deactivates them.
This is fine with me. I now need to find a way to find an empty spot on the desktop ("Program Manager") to access its context menu.
Thanks! |
|
| Back to top |
|
 |
txquestor
Joined: 22 Aug 2009 Posts: 294
|
Posted: Wed Oct 14, 2009 7:26 pm Post subject: |
|
|
You don't need a empty postion on the desktop to activate the context menu with the code I gave you above.
However, look at the code line I commented out. "MoiuseMove"
Just change the mouse position to choose the posttion you want
| Code: |
^!m::
; Minimize all windows on the desktop
MinimizeAllWindows:
WinMinimizeAll
return
|
_________________
"Man's quest for knowledge is an expanding series whose limit is infinity" |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Thu Oct 15, 2009 4:08 pm Post subject: |
|
|
| txquestor wrote: | | You don't need a empty postion on the desktop to activate the context menu with the code I gave you above. |
txquestor, thanks again but try the following complete script:
| Code: | Hotkey, F12, WINACT
return
WINACT:
WinActivate, Program Manager
Sleep 100
Sleep 100
Send {RButton}
Sleep 100
Send {Down 5} ; number of arrow down to select the menuitem
return |
When you press F12 while a file is selected in Windows Explorer, the context menu invoked is not the Desktop's one.
Can you explain this? What is the solution?
Thanks! |
|
| Back to top |
|
 |
sinkfaze
Joined: 18 Mar 2008 Posts: 5044 Location: the tunnel(?=light)
|
Posted: Thu Oct 15, 2009 4:47 pm Post subject: |
|
|
| Carcophan wrote: | | Windows+D will minimize all, bringing you to your desktop |
If I'm not mistaken Win+D brings the desktop to the top of the stack but does not minimize all windows (which explains why you can toggle back and forth with that command). Win+M is the true minimize all un-minimized windows command (and Win+Shift+M restores them). They essentially perform the same function just in different ways but some applications are known to conflict with stack order/priority, which is why I tend not to use Win+D.
So if you have no luck with Win+D, try Win+M.
| newbie83 wrote: | | I know that in order to invoke any context menu I need to send SHIFT+F10. |
Why not just use APPSKEY?
| newbie83 wrote: | When you press F12 while a file is selected in Windows Explorer, the context menu invoked is not the Desktop's one.
Can you explain this? What is the solution? |
You have to take the focus back from a specific item to the desktop in general:
| Code: | ControlFocus, , Program Manager ; sets focus to the desktop's topmost control
Send {APPSKEY}
return |
_________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Thu Oct 15, 2009 5:49 pm Post subject: |
|
|
| sinkfaze wrote: | | Why not just use APPSKEY? |
Great idea. I didn't know about it. Thank you.
| sinkfaze wrote: | You have to take the focus back from a specific item to the desktop in general:
| Code: | ControlFocus, , Program Manager ; sets focus to the desktop's topmost control
Send {APPSKEY}
return |
|
Hmmm... I tried this:
| Code: | Hotkey, F12, WINACT
return
WINACT:
ControlFocus, , Program Manager
Send {APPSKEY}
Sleep 100
Sleep 100
Send {RButton}
Sleep 100
Send {Down 5} ; number of arrow down to select the menuitem
return |
It works - but not when a file is selected in Windows Explorer. Try this. Do you see the problem?  |
|
| Back to top |
|
 |
sinkfaze
Joined: 18 Mar 2008 Posts: 5044 Location: the tunnel(?=light)
|
Posted: Thu Oct 15, 2009 6:19 pm Post subject: |
|
|
Try running only this:
| Code: | SetControlDelay, -1
Hotkey, F12, WINACT
return
WINACT:
ControlFocus, , Program Manager
Send {APPSKEY}
return |
I tested this on my machine (XP SP3) and it worked fine. _________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
OceanMachine
Joined: 15 Oct 2007 Posts: 780 Location: England
|
Posted: Thu Oct 15, 2009 7:22 pm Post subject: |
|
|
Hmm, I see what the OP is saying - sinkfaze, try running your script, but before you press F12, click to just select an icon on your desktop.
When you press F12 now, the context menu appears as if the context is for the selected icon/file, rather than the 'desktop' itself.
I wonder if there is a way to tell the "Program Manager" window to de-select any icons (similar to how just left-clicking in a blank space on the desktop would do this) prior to sending APPSKEY?
I tried looking at how I might use PostMessage to do this, but then got completely lost on MSDN
Alternatively, is there a way to just send a message to the desktop window to say 'display my context menu' or something like that? Not sure... |
|
| Back to top |
|
 |
sinkfaze
Joined: 18 Mar 2008 Posts: 5044 Location: the tunnel(?=light)
|
Posted: Thu Oct 15, 2009 9:03 pm Post subject: |
|
|
How weird, that was working fine just before I went to lunch and now it's very scattershot. Strange.
| OceanMachine wrote: | I tried looking at how I might use PostMessage to do this, but then got completely lost on MSDN
Alternatively, is there a way to just send a message to the desktop window to say 'display my context menu' or something like that? Not sure... |
I'm betting that this thread holds the key but I can't figure out how to invoke the proper desktop context menu. For instance, the below code will invoke the true Desktop Properties but not the Display Properties one expects to invoke from the Desktop window:
| Code: | sPath := "C:\Documents and Settings\sinkfaze\Desktop" ; path of the target file
SplitPath, sPath, sName, sDir
COM_Init()
psh := COM_CreateObject("Shell.Application")
COM_Invoke(psh, "NameSpace[" sDir "].ParseName[" sName "].InvokeVerb","Properties")
COM_Release(psh)
COM_Term()
return |
I'm guessing the answer lies somewhere in this post but I lack the requisite knowledge of DllCalls to know what to make of it. _________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
newbie83 Guest
|
Posted: Thu Oct 15, 2009 9:03 pm Post subject: |
|
|
| sinkfaze wrote: | Try running only this:
| Code: | SetControlDelay, -1
Hotkey, F12, WINACT
return
WINACT:
ControlFocus, , Program Manager
Send {APPSKEY}
return |
I tested this on my machine (XP SP3) and it worked fine. |
This doesn't work for me either (XP SP2 and XP SP3). Are you sure that you selected a file before pressing F12 when testing this? |
|
| Back to top |
|
 |
..:: Free Radical ::..
Joined: 20 Sep 2006 Posts: 72
|
Posted: Fri Oct 16, 2009 2:32 am Post subject: |
|
|
| Code: | PostMessage, 0x111, 415, 0,, ahk_class Shell_TrayWnd ; WinMinimizeAll
PostMessage, 0x111, 407, 0,, ahk_class Shell_TrayWnd ; Shows the desktop |
|
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|