pythonwinapipywin32

Getting Desktop Icon's positions with pywin32 (Python)


I've been trying to get the X and Y of the icons on the desktop screen however none of the solutions I've tried seem to give the desired outcome "Icon: {Name} (X,Y)" or something along those lines.

Code I've tried

I've tried this code however it only seems to give attributes of the file rather than anything relating to X,Y coords

import win32com.client

shell = win32com.client.Dispatch("Shell.Application")
desktop_folder = shell.NameSpace(0)
desktop_items = shell.NameSpace(0).Items()

# Loop through all desktop icons and perform some action
for i in range(desktop_items.Count): 
    item = desktop_items.Item(i)
    
    recieved = desktop_folder.GetDetailsOf(item, SOME_INDEX) # E.g. 0 gives the Name of the file

I've also tried looking at ways of changing this code to implement LVM_GETITEMPOSITION which I presume is what I need to get these coords. However (most likely due to my lack of knowledge in interfacing with win32) I can't seem to get that working and the best I got was a bunch of zeros.

And finally I also looked at other stackoverflow articles though they were mostly in other (programming) languages (in which I didn't know how to convert from) or took me to another article which then took me to another one until I was back full circle..

Stackoverflow articles I've looked at:

How to move desktop icons with python? (Got working however didn't know how to change bytes strings into coordinates)

How to move desktop icons using winapi on C? (Moves icons not gets pos)

How to get the windows desktop icons position in python? (redirected me to nothing useful)

LVM_GETITEMPOSITION (No accepted answer)

and many more which I won't list out


Solution

  • [SO]: How to move desktop icons with python? (@CristiFati's answer) (mentioned in the question) contains all the needed pieces (including what you weren't able to figure out: folder_view.GetItemPosition(item)): 2 separate scripts that one has to (somehow) combine.

    Note: As specified in my other answer, the 1st PyWin32 official version containing IFolderView functionality is v307.

    code00.py:

    #!/usr/bin/env python
    
    import sys
    
    import pythoncom
    import win32com.client as wcomcli
    from win32com.shell import shell, shellcon
    
    
    SWC_DESKTOP = 0x08
    SWFO_NEEDDISPATCH = 0x01
    
    CLSID_ShellWindows = "{9BA05972-F6A8-11CF-A442-00A0C90A8F39}"
    IID_IFolderView = "{CDE725B0-CCC9-4519-917E-325D72FAB4CE}"
    
    
    def main(*argv):
        shell_windows = wcomcli.Dispatch(CLSID_ShellWindows)
        hwnd = 0
        dispatch = shell_windows.FindWindowSW(
            wcomcli.VARIANT(pythoncom.VT_I4, shellcon.CSIDL_DESKTOP),
            wcomcli.VARIANT(pythoncom.VT_EMPTY, None),
            SWC_DESKTOP, hwnd, SWFO_NEEDDISPATCH,
        )
        service_provider = dispatch._oleobj_.QueryInterface(pythoncom.IID_IServiceProvider)
        browser = service_provider.QueryService(shell.SID_STopLevelBrowser, shell.IID_IShellBrowser)
        shell_view = browser.QueryActiveShellView()
        folder_view = shell_view.QueryInterface(IID_IFolderView)
        items_len = folder_view.ItemCount(shellcon.SVGIO_ALLVIEW)
        desktop_folder = shell.SHGetDesktopFolder()
        print(f"Found {items_len} items\n")
        for i in range(items_len):
            item = folder_view.Item(i)
            print(f"Item {i:2d}\n"
                  #f"  Id: {item}\n"
                  f"  Name: {desktop_folder.GetDisplayNameOf([item], shellcon.SHGDN_NORMAL)}\n"
                  f"  Position: {folder_view.GetItemPosition(item)}"
            )
    
    
    if __name__ == "__main__":
        print(
            "Python {:s} {:03d}bit on {:s}\n".format(
                " ".join(elem.strip() for elem in sys.version.split("\n")),
                64 if sys.maxsize > 0x100000000 else 32,
                sys.platform,
            )
        )
        rc = main(*sys.argv[1:])
        print("\nDone.\n")
        sys.exit(rc)
    

    Output:

    img00