 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Tue Dec 01, 2009 12:04 am Post subject: |
|
|
| HotKeyIt wrote: | Really great function, however it looks like "Copy" does not work, possibly due to absence of Explorer and marked file  | 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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Tue Dec 01, 2009 12:07 am Post subject: |
|
|
| 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 |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 4653 Location: AHK Forum
|
Posted: Tue Dec 01, 2009 10:13 am Post subject: |
|
|
| Sean wrote: | | HotKeyIt wrote: | Really great function, however it looks like "Copy" does not work, possibly due to absence of Explorer and marked file  | 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  _________________ AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun  |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Tue Dec 01, 2009 7:21 pm Post subject: |
|
|
| HotKeyIt wrote: | Yes it just does not do anything, does it work for you  | 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 |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 4653 Location: AHK Forum
|
Posted: Tue Dec 01, 2009 7:44 pm Post subject: |
|
|
| Sean wrote: | | HotKeyIt wrote: | Yes it just does not do anything, does it work for you  | 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.
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  |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Tue Dec 01, 2009 9:20 pm Post subject: |
|
|
| 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.  | 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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Tue Dec 01, 2009 10:04 pm Post subject: |
|
|
| 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 |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 4653 Location: AHK Forum
|
|
| Back to top |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 4653 Location: AHK Forum
|
Posted: Wed Dec 02, 2009 7:30 am Post subject: |
|
|
| HotKeyIt wrote: | Thank you very much, it works like a charm now  |
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  |
|
| Back to top |
|
 |
fragman
Joined: 13 Oct 2009 Posts: 1199
|
Posted: Thu Dec 24, 2009 11:22 pm Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Sat Dec 26, 2009 6:39 am Post subject: |
|
|
| 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 |
|
 |
fragman
Joined: 13 Oct 2009 Posts: 1199
|
|
| Back to top |
|
 |
fragman
Joined: 13 Oct 2009 Posts: 1199
|
Posted: Tue Dec 29, 2009 4:37 pm Post subject: |
|
|
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
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 |
|
 |
Deo
Joined: 16 May 2010 Posts: 172
|
Posted: Thu Aug 26, 2010 1:55 pm Post subject: |
|
|
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 |
|
 |
sbc
Joined: 25 Aug 2009 Posts: 321
|
Posted: Wed Dec 22, 2010 3:16 am Post subject: |
|
|
| 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?
| 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 |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|