AutoHotkey Community

It is currently May 27th, 2012, 12:15 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: October 13th, 2009, 7:56 pm 
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!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 13th, 2009, 9:32 pm 
Offline

Joined: December 24th, 2008, 3:25 am
Posts: 1401
Location: :noitacoL
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 13th, 2009, 9:55 pm 
Offline

Joined: August 22nd, 2009, 11:23 pm
Posts: 294
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 :!: :!: :o

_________________
Image
"Man's quest for knowledge is an expanding series whose limit is infinity"


Last edited by txquestor on October 14th, 2009, 12:14 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2009, 5:48 pm 
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
Code:
Send {#D}

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!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2009, 5:53 pm 
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?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2009, 6:10 pm 
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!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2009, 8:26 pm 
Offline

Joined: August 22nd, 2009, 11:23 pm
Posts: 294
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

_________________
Image
"Man's quest for knowledge is an expanding series whose limit is infinity"


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 5:08 pm 
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!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 5:47 pm 
Offline
User avatar

Joined: March 19th, 2008, 12:43 am
Posts: 5480
Location: the tunnel(?=light)
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

_________________
Image
Try Quick Search for Autohotkey or see the tutorial for newbies.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 6:49 pm 
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? :)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 7:19 pm 
Offline
User avatar

Joined: March 19th, 2008, 12:43 am
Posts: 5480
Location: the tunnel(?=light)
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.

_________________
Image
Try Quick Search for Autohotkey or see the tutorial for newbies.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 8:22 pm 
Offline

Joined: October 15th, 2007, 3:10 pm
Posts: 790
Location: England
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...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 10:03 pm 
Offline
User avatar

Joined: March 19th, 2008, 12:43 am
Posts: 5480
Location: the tunnel(?=light)
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.

_________________
Image
Try Quick Search for Autohotkey or see the tutorial for newbies.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 15th, 2009, 10:03 pm 
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?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 16th, 2009, 3:32 am 
Offline

Joined: September 20th, 2006, 2:05 pm
Posts: 73
Code:
PostMessage, 0x111, 415, 0,, ahk_class Shell_TrayWnd ; WinMinimizeAll
PostMessage, 0x111, 407, 0,, ahk_class Shell_TrayWnd ; Shows the desktop


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Apollo, Leef_me, Pulover, rjgatito, XstatyK, Yahoo [Bot] and 20 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group