AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Invoking directly ContextMenu of Files and Folders
Goto page Previous  1, 2, 3, 4, 5  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 01, 2009 12:04 am    Post subject: Reply with quote

HotKeyIt wrote:
Really great function, however it looks like "Copy" does not work, possibly due to absence of Explorer and marked file Sad
What you meant by not working? Copy menu item has nothing to do with explorer.
Quote:
Could we redirect the function to script, to do the job?
Sure you can do, even insert your own menu items.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 01, 2009 12:07 am    Post subject: Reply with quote

Gauss wrote:
The link for CoHelper.ahk is dead
Not just dead, it was deleted from the storage since some users had constantly annoyed by still posting questions on this library which became obsolete almost two years ago. And, this script is no longer maintained.
Back to top
View user's profile Send private message
HotKeyIt



Joined: 18 Jun 2008
Posts: 4653
Location: AHK Forum

PostPosted: Tue Dec 01, 2009 10:13 am    Post subject: Reply with quote

Sean wrote:
HotKeyIt wrote:
Really great function, however it looks like "Copy" does not work, possibly due to absence of Explorer and marked file Sad
What you meant by not working? Copy menu item has nothing to do with explorer.


Yes it just does not do anything, does it work for you Question
_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 01, 2009 7:21 pm    Post subject: Reply with quote

HotKeyIt wrote:
Yes it just does not do anything, does it work for you Question
What do you expect to happen? Open explorer or any other file manager and go to arbitrary directory and right click on empty space then select paste. What happens?
Back to top
View user's profile Send private message
HotKeyIt



Joined: 18 Jun 2008
Posts: 4653
Location: AHK Forum

PostPosted: Tue Dec 01, 2009 7:44 pm    Post subject: Reply with quote

Sean wrote:
HotKeyIt wrote:
Yes it just does not do anything, does it work for you Question
What do you expect to happen? Open explorer or any other file manager and go to arbitrary directory and right click on empty space then select paste. What happens?

When I go to explorer and right mouse click a file, select copy, then run following and select paste, it works:
Code:
#Persistent
sPath = %A_Temp%
ShellContextMenu(sPath<>"" ? sPath : 0x0011)
Return

But when I run below one, select copy, go to explorer and right mouse click on a folder or empty space, it does not work, paste is grayed out. Sad
Just tested on my second computer and it does not work as well, both XP SP3
Code:
#Persistent
sPath = %A_ProgramFiles%\Internet Explorer\iexplore.exe
ShellContextMenu(sPath<>"" ? sPath : 0x0011)
Return

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 01, 2009 9:20 pm    Post subject: Reply with quote

HotKeyIt wrote:
But when I run below one, select copy, go to explorer and right mouse click on a folder or empty space, it does not work, paste is grayed out. Sad
It works fine in my system (after changed appropriately to accord with unicode build), but, I'm using AutoHotkeyU.exe currently. Actually it's a little customized by me, but I don't think those are relevant here. So, I'm not sure if it's an issue of AHK itself or the script atm.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 01, 2009 10:04 pm    Post subject: Reply with quote

OK, I realized you might not port it to COM.ahk, right? Then, you must use OleInitialize/OleUninitialize, not CoInitialize/CoUninitialize, to make Copy work. Actually one of my customization was that always OleInitialize/OleUninitialize at the start-up/termination of AHK.
Back to top
View user's profile Send private message
HotKeyIt



Joined: 18 Jun 2008
Posts: 4653
Location: AHK Forum

PostPosted: Wed Dec 02, 2009 6:01 am    Post subject: Reply with quote

Thank you very much, it works like a charm now Smile
_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink
Back to top
View user's profile Send private message
HotKeyIt



Joined: 18 Jun 2008
Posts: 4653
Location: AHK Forum

PostPosted: Wed Dec 02, 2009 7:30 am    Post subject: Reply with quote

HotKeyIt wrote:
Thank you very much, it works like a charm now Smile


This is what I use now:
Code:
#Persistent
ShellContextMenu(A_Temp)
Return

ShellContextMenu(sPath)
{
   DllCall("ole32\OleInitialize", "Uint", 0)
   If   sPath Is Not Integer
      DllCall("shell32\SHParseDisplayName", "Uint", Unicode4Ansi(wPath,sPath), "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0)
   Else   DllCall("shell32\SHGetFolderLocation", "Uint", 0, "int", sPath, "Uint", 0, "Uint", 0, "UintP", pidl)
   DllCall("shell32\SHBindToParent", "Uint", pidl, "Uint", GUID4String(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}"), "UintP", psf, "UintP", pidlChild)
   DllCall(NumGet(NumGet(1*psf)+40), "Uint", psf, "Uint", 0, "Uint", 1, "UintP", pidlChild, "Uint", GUID4String(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}"), "Uint", 0, "UintP", pcm)
   Release(psf)
   CoTaskMemFree(pidl)

   hMenu := DllCall("CreatePopupMenu")
   DllCall(NumGet(NumGet(1*pcm)+12), "Uint", pcm, "Uint", hMenu, "Uint", 0, "Uint", 3, "Uint", 0x7FFF, "Uint", 0)   ; QueryContextMenu
   DetectHiddenWindows, On
   Process, Exist
   WinGet, hAHK, ID, ahk_pid %ErrorLevel%
   WinActivate, ahk_id %hAHK%
   Global   pcm2 := QueryInterface(pcm,IID_IContextMenu2:="{000214F4-0000-0000-C000-000000000046}")
   Global   pcm3 := QueryInterface(pcm,IID_IContextMenu3:="{BCFCE0A0-EC17-11D0-8D10-00A0C90F2719}")
   Global   WPOld:= DllCall("SetWindowLong", "Uint", hAHK, "int",-4, "int",RegisterCallback("WindowProc"))
   DllCall("GetCursorPos", "int64P", pt)
   DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x800, "Uint", 2, "Uint", 0)
   DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x002, "Uint", 1, "Uint", &sPath)
   idn := DllCall("TrackPopupMenu", "Uint", hMenu, "Uint", 0x0100, "int", pt << 32 >> 32, "int", pt >> 32, "Uint", 0, "Uint", hAHK, "Uint", 0)
   NumPut(VarSetCapacity(ici,64,0),ici), NumPut(0x4000|0x20000000,ici,4), NumPut(1,NumPut(hAHK,ici,8),12), NumPut(idn-3,NumPut(idn-3,ici,12),24), NumPut(pt,ici,56,"int64")
   DllCall(NumGet(NumGet(1*pcm)+16), "Uint", pcm, "Uint", &ici)   ; InvokeCommand
;   VarSetCapacity(sName,259), DllCall(NumGet(NumGet(1*pcm)+20), "Uint", pcm, "Uint", idn-3, "Uint", 1, "Uint", 0, "str", sName, "Uint", 260)   ; GetCommandString
   DllCall("GlobalFree", "Uint", DllCall("SetWindowLong", "Uint", hAHK, "int", -4, "int", WPOld))
   DllCall("DestroyMenu", "Uint", hMenu)
   Release(pcm3)
   Release(pcm2)
   Release(pcm)
   DllCall("ole32\OleUnInitialize", "Uint", 0)
   pcm2:=pcm3:=WPOld:=0
}
WindowProc(hWnd, nMsg, wParam, lParam)
{
   Critical
   Global   pcm2, pcm3, WPOld
   If   pcm3
   {
      If   !DllCall(NumGet(NumGet(1*pcm3)+28), "Uint", pcm3, "Uint", nMsg, "Uint", wParam, "Uint", lParam, "UintP", lResult)
         Return   lResult
   }
   Else If   pcm2
   {
      If   !DllCall(NumGet(NumGet(1*pcm2)+24), "Uint", pcm2, "Uint", nMsg, "Uint", wParam, "Uint", lParam)
         Return   0
   }
   Return   DllCall("user32.dll\CallWindowProcA", "Uint", WPOld, "Uint", hWnd, "Uint", nMsg, "Uint", wParam, "Uint", lParam)
}
VTable(ppv, idx)
{
   Return   NumGet(NumGet(1*ppv)+4*idx)
}
QueryInterface(ppv, ByRef IID)
{
   If   StrLen(IID)=38
      GUID4String(IID,IID)
   DllCall(NumGet(NumGet(1*ppv)), "Uint", ppv, "str", IID, "UintP", ppv)
   Return   ppv
}
AddRef(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+4), "Uint", ppv)
}
Release(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+8), "Uint", ppv)
}
GUID4String(ByRef CLSID, String)
{
   VarSetCapacity(CLSID, 16)
   DllCall("ole32\CLSIDFromString", "Uint", Unicode4Ansi(String,String,38), "Uint", &CLSID)
   Return   &CLSID
}
CoTaskMemAlloc(cb)
{
   Return   DllCall("ole32\CoTaskMemAlloc", "Uint", cb)
}
CoTaskMemFree(pv)
{
   Return   DllCall("ole32\CoTaskMemFree", "Uint", pv)
}
Unicode4Ansi(ByRef wString, sString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink
Back to top
View user's profile Send private message
fragman



Joined: 13 Oct 2009
Posts: 1199

PostPosted: Thu Dec 24, 2009 11:22 pm    Post subject: Reply with quote

Works nice, does anyone see a way to bring up the context menu which you get when you click on empty space in explorer?

Specifically, I would like to call the "new folder", "new text file", and "next desktop background" (win7 only?) actions. While we're at that, any proper way for calling specific items? I saw that some can be executed through COM apparently, but I suppose this doesn't work for the "empty selection" context menu?
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Dec 26, 2009 6:39 am    Post subject: Reply with quote

Don't blindly post a question. Don't you think at least have to read/scan the whole thread before posting a question to it?
Back to top
View user's profile Send private message
fragman



Joined: 13 Oct 2009
Posts: 1199

PostPosted: Sat Dec 26, 2009 10:10 am    Post subject: Reply with quote

I did, but I only found code for COHelper.ahk versions, and I don't know how to port this properly to COM.ahk.

Right now I'm trying this approach, with some more success: http://www.autohotkey.com/forum/viewtopic.php?p=319925#319925
Back to top
View user's profile Send private message
fragman



Joined: 13 Oct 2009
Posts: 1199

PostPosted: Tue Dec 29, 2009 4:37 pm    Post subject: Reply with quote

I now finally managed to execute a context menu item from the empty selection desktop context menu without showing the menu.

I really can't say I understood the whole code, I have no idea how the memory addresses of functions and structs were extracted from the winapi headers, but atleast I managed to modify the code to get it to do what I want Smile

Here's the code I used. It isn't very clean, but I wanted to share my success:
Code:
#Persistent
/*
;enable Debug view
   a_scriptPID := DllCall("GetCurrentProcessId")   ; get script's PID
   ifwinexist, DebugView on ; kill it if the debug viewer is running from an older instance
      {
      winactivate, DebugView on
      Winwaitactive, DebugView on
      winclose, DebugView on
      }
   run, %A_ScriptDir%\DebugView\Dbgview.exe /f
   winwait, DebugView on
   winactivate, DebugView on
   Winwaitactive, DebugView on
   sendinput, !E{down}{down}{down}{down}{down}{Enter}
   winwait, DebugView Filter
   winactivate, DebugView Filter
   Winwaitactive, DebugView Filter
   mouseclick, left, 125, 85
   send, [%a_scriptPID%*{Enter}
*/

/*
Executes context menu entries of shell items without showing their menus
Usage:
ShellContextMenu("Desktop",1)         ;Calls "Next Desktop background" in Win7
1st parameter can be "Desktop" for empty selection desktop menu, a path, or an idl
Leave 2nd parameter empty to show context menu and extract idn by clicking on an entry (shows up in debugview)
*/
ShellContextMenu(sPath,idn)
{
   DllCall("ole32\OleInitialize", "Uint", 0)
   if (spath="Desktop")
   {
       DllCall("shell32\SHGetDesktopFolder", "UintP", psf)
       DllCall(NumGet(NumGet(1*psf)+32), "Uint", psf, "Uint", 0, "Uint", GUID4String(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}"), "UintP", pcm)
    }
   else
   {
       If   sPath Is Not Integer
         DllCall("shell32\SHParseDisplayName", "Uint", Unicode4Ansi(wPath,sPath), "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0)
      Else   DllCall("shell32\SHGetFolderLocation", "Uint", 0, "int", sPath, "Uint", 0, "Uint", 0, "UintP", pidl)
      DllCall("shell32\SHBindToParent", "Uint", pidl, "Uint", GUID4String(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}"), "UintP", psf, "UintP", pidlChild)
      DllCall(NumGet(NumGet(1*psf)+40), "Uint", psf, "Uint", 0, "Uint", 1, "UintP", pidlChild, "Uint", GUID4String(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}"), "Uint", 0, "UintP", pcm)
    }
    Release(psf)
   CoTaskMemFree(pidl)

   hMenu := DllCall("CreatePopupMenu")
   idnMIN=1
   DllCall(NumGet(NumGet(1*pcm)+12), "Uint", pcm, "Uint", hMenu, "Uint", 0, "Uint", idnMIN, "Uint", 0x7FFF, "Uint", 0)   ; QueryContextMenu
    

   DetectHiddenWindows, On
   Process, Exist
   WinGet, hAHK, ID, ahk_pid %ErrorLevel%
   if !idn
   {
      WinActivate, ahk_id %hAHK%       
      Global   pcm2 := QueryInterface(pcm,IID_IContextMenu2:="{000214F4-0000-0000-C000-000000000046}")
      Global   pcm3 := QueryInterface(pcm,IID_IContextMenu3:="{BCFCE0A0-EC17-11D0-8D10-00A0C90F2719}")
      Global   WPOld:= DllCall("SetWindowLong", "Uint", hAHK, "int",-4, "int",RegisterCallback("WindowProc"))
      DllCall("GetCursorPos", "int64P", pt)
      DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x800, "Uint", 2, "Uint", 0)
      DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x002, "Uint", 1, "Uint", &sPath)
      idn2 := DllCall("TrackPopupMenu", "Uint", hMenu, "Uint", 0x0100, "int", pt << 32 >> 32, "int", pt >> 32, "Uint", 0, "Uint", hAHK, "Uint", 0)
    }
    else
        idn2:=idn
   NumPut(VarSetCapacity(ici,64,0),ici)
    NumPut(0x4000|0x20000000,ici,4)
    NumPut(1,NumPut(hAHK,ici,8),12)
    NumPut(idn2-idnMIN,NumPut(idn2-idnMIN,ici,12),24)
    if !idn
       NumPut(pt,ici,56,"int64")
   DllCall(NumGet(NumGet(1*pcm)+16), "Uint", pcm, "Uint", &ici)   ; InvokeCommand
   if !idn
   {
    VarSetCapacity(sName,259), DllCall(NumGet(NumGet(1*pcm)+20), "Uint", pcm, "Uint", idn2-idnMIN, "Uint", 1, "Uint", 0, "str", sName, "Uint", 260)   ; GetCommandString
    outputdebug command string: %sname% idn: %idn2%
   DllCall("GlobalFree", "Uint", DllCall("SetWindowLong", "Uint", hAHK, "int", -4, "int", WPOld))
   
   Release(pcm3)
   Release(pcm2)
   }
   DllCall("DestroyMenu", "Uint", hMenu)
   Release(pcm)
   DllCall("ole32\OleUnInitialize", "Uint", 0)
   ;pcm2:=pcm3:=WPOld:=0
}
WindowProc(hWnd, nMsg, wParam, lParam)
{
   Critical
   Global   pcm2, pcm3, WPOld
   If   pcm3
   {
      If   !DllCall(NumGet(NumGet(1*pcm3)+28), "Uint", pcm3, "Uint", nMsg, "Uint", wParam, "Uint", lParam, "UintP", lResult)
         Return   lResult
   }
   Else If   pcm2
   {
      If   !DllCall(NumGet(NumGet(1*pcm2)+24), "Uint", pcm2, "Uint", nMsg, "Uint", wParam, "Uint", lParam)
         Return   0
   }
   Return   DllCall("user32.dll\CallWindowProcA", "Uint", WPOld, "Uint", hWnd, "Uint", nMsg, "Uint", wParam, "Uint", lParam)
}
VTable(ppv, idx)
{
   Return   NumGet(NumGet(1*ppv)+4*idx)
}
QueryInterface(ppv, ByRef IID)
{
   If   StrLen(IID)=38
      GUID4String(IID,IID)
   DllCall(NumGet(NumGet(1*ppv)), "Uint", ppv, "str", IID, "UintP", ppv)
   Return   ppv
}
AddRef(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+4), "Uint", ppv)
}
Release(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+8), "Uint", ppv)
}
GUID4String(ByRef CLSID, String)
{
   VarSetCapacity(CLSID, 16)
   DllCall("ole32\CLSIDFromString", "Uint", Unicode4Ansi(String,String,38), "Uint", &CLSID)
   Return   &CLSID
}
CoTaskMemAlloc(cb)
{
   Return   DllCall("ole32\CoTaskMemAlloc", "Uint", cb)
}
CoTaskMemFree(pv)
{
   Return   DllCall("ole32\CoTaskMemFree", "Uint", pv)
}
Unicode4Ansi(ByRef wString, sString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}


Read function comment to see how to acquire idn.

I Hope this might help others, I for one had a real hard time figuring this out. Here's some good documentation on this btw: http://www.netez.com/2xExplorer/shellFAQ/bas_context.html

Two questions remain for me though:
Do I need to call OleInitialize and OleUnInitialize when I'm using COM.ahk in other parts of my script?
I tried acquiring idn of a submenu and calling above function with that (namy new->textfile). However, I don't see any result. I'm getting different idns for submenu entries, which is why I believe this should be working. I saw a post before about new context menu not being populated when called directly without context, but I don't believe this is relevant here, right? Any ideas?

Update, had a few irrelevant functions in there.
Back to top
View user's profile Send private message
Deo



Joined: 16 May 2010
Posts: 172

PostPosted: Thu Aug 26, 2010 1:55 pm    Post subject: Reply with quote

Why it may not work on folder, but files only?
I use Win 7 64bit and a code from HotKeyIt's post above
Back to top
View user's profile Send private message
sbc



Joined: 25 Aug 2009
Posts: 321

PostPosted: Wed Dec 22, 2010 3:16 am    Post subject: Reply with quote

Sean wrote:
As I said before, if the menu item appears in the main menu, not in the submenu, InvokeVerb is simpler to use.
Code:
sPath := A_ScriptFullPath ; path of the target file

SplitPath, sPath, sName, sDir
COM_Init()
psh := COM_CreateObject("Shell.Application")
COM_Invoke(psh, "NameSpace[" sDir "].ParseName[" sName "].InvokeVerb", "Copy")
COM_Release(psh)
COM_Term()
MsgBox, DONE
I've been trying to apply a filter for multiple files without success. Would you take a look at my code? Confused
Code:
Dirpath := "D:\Scripts\Test\COM"
objShell := ComObjCreate("Shell.Application")
objFolder := objShell.NameSpace(Dirpath)     
objFolderItems := objFolder.items
objFolderItems := objFolderItems.Filter(0x00040, "*.txt")   ; SHCONTF_NONFOLDERS = 64   ;this is the line which doesn't work
objFolderItems.InvokeVerbEx("Copy")
(*the code is for AHKL)
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5  Next
Page 4 of 5

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group