MelBurslan
MelBurslan

Reputation: 2501

Autohotkey: How can I get the positions of win 7 desktop icons

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

Answers (2)

Joe DF
Joe DF

Reputation: 5548

Example

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
}

Description

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.

The Function

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
}

Extra

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

MCL
MCL

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:

  1. Never change your desktop background. The easiest way but most likely not an option if you are a frequent desktop restyler.
  2. Take new screenshots of the icons every time you change the background. Very high maintenance depending on your need to change the desktop.
  3. Let the script change the desktop background to a default color before it runs 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.

References:

Upvotes: 0

Related Questions