Reputation: 2501
I want to implement a poor mans "Windows Fences" (by stardock software) using autohotkey.
It can be as ineffective as it can as far as programming goes. I just want to get the positions of each desktop icon upon running a ahk code snippet and using another code snippet, I'd like to put them back to where they were.
I looked at the ahk code contributions and didn't see anything like this. But again, my search terms might be a little off. Assuming no such code exists, is there a way to get the screen positions of each icon and their identifying information in autohotkey ? This will at least help me start. I am sure more questions will come.
Upvotes: 1
Views: 891
Reputation: 5548
Try the following with the function posted below :
icons := getDeskIconsPos()
chromePos := icons["Google Chrome"]
for k, pos in chromePos
{
msgbox % "Google Chrome.lnk is at X: " pos.x " Y: " pos.y
}
The function returns an object (thanks to MCL) with each item being identified by name. Under each name item is an array of all occurring instances. Each array item will have an X
and Y
containing the corresponding coordinates.
See code for THE_ITEMNAME
, THE_X_COORD
and THE_Y_COORD
.
I have used these names to clarify where the information is stored.
getDeskIconsPos() {
Critical
static MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x04, MEM_RELEASE := 0x8000
static LVM_GETITEMPOSITION := 0x00001010, LVM_SETITEMPOSITION := 0x0000100F, WM_SETREDRAW := 0x000B
ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
if !hwWindow ; #D mode
ControlGet, hwWindow, HWND,, SysListView321, A
IfWinExist ahk_id %hwWindow% ; last-found window set
WinGet, iProcessID, PID
hProcess := DllCall("OpenProcess" , "UInt", 0x438 ; PROCESS-OPERATION|READ|WRITE|QUERY_INFORMATION
, "Int", FALSE ; inherit = false
, "ptr", iProcessID)
ret := {}
if hwWindow and hProcess
{
ControlGet, list, list,Col1
VarSetCapacity(iCoord, 8)
pItemCoord := DllCall("VirtualAllocEx", "ptr", hProcess, "ptr", 0, "UInt", 8, "UInt", MEM_COMMIT, "UInt", PAGE_READWRITE)
Loop, Parse, list, `n ;Loop through items in list and get the information from the POINT structures
{
SendMessage, %LVM_GETITEMPOSITION%, % A_Index-1, %pItemCoord%
DllCall("ReadProcessMemory", "ptr", hProcess, "ptr", pItemCoord, "UInt", &iCoord, "UInt", 8, "UIntP", cbReadWritten)
;<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
THE_ITEMNAME := A_LoopField
THE_X_COORD := NumGet(iCoord,"Int")
THE_Y_COORD := Numget(iCoord, 4,"Int")
;<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(!ret.HasKey(THE_ITEMNAME))
{
ret[THE_ITEMNAME] := []
}
ret[THE_ITEMNAME].Insert({x: THE_X_COORD, y: THE_Y_COORD})
}
DllCall("VirtualFreeEx", "ptr", hProcess, "ptr", pItemCoord, "ptr", 0, "UInt", MEM_RELEASE)
}
DllCall("CloseHandle", "ptr", hProcess)
return ret
}
If you simply want to save and restore the desktop icon positions, you may try DeskIcons()
here :
http://ahkscript.org/boards/viewtopic.php?f=6&t=3529
Example usage of DeskIcons()
:
; save positions
coords := DeskIcons()
MsgBox now move the icons around yourself
; load positions
DeskIcons(coords)
Upvotes: 2
Reputation: 4065
I don't think there's an easy way to achieche this. But ImageSearch
should work quite well if performance isn't an issue (even if it is: for smaller numbers of icons, it should still perform acceptably). The only problem I see is the desktop background: If it changes, ImageSearch
will most likely fail, except for perfectly quadratic/nontransparent icons. There are three workarounds for that:
ImageSearch
. My favorite since it's easy to implement and you won't have to worry about anything.After you've found the position of the respective icon, the rest is pretty trivial: MouseClickDrag
it from its old position to the target position.
Upvotes: 0