如何使用python 2.7移动Windows桌面图标?
发布时间:2020-12-20 13:47:40 所属栏目:Python 来源:网络整理
导读:我正在尝试编写一个 python例程来保存和恢复桌面图标位置.我在 Windows 7 x64上使用32位python 2.7.使用此处的信息(堆栈交换),我能够从外部进程列表视图中读取Windows用于存储此信息的图标名称和位置,但是在使用LVM_SETITEMPOSITION设置新位置(或恢复位置)时
我正在尝试编写一个
python例程来保存和恢复桌面图标位置.我在
Windows 7 x64上使用32位python 2.7.使用此处的信息(堆栈交换),我能够从外部进程列表视图中读取Windows用于存储此信息的图标名称和位置,但是在使用LVM_SETITEMPOSITION设置新位置(或恢复位置)时失败.所有图标最终都在桌面上的相同位置. ‘自动排列’和’对齐网格’已关闭.相关代码是最底层的.警告:如果您运行此代码,您的所有图标都将堆成一堆:(
import ctypes class LVITEMW(ctypes.Structure): _fields_ = [ ('mask',ctypes.c_uint32),('iItem',ctypes.c_int32),('iSubItem',('state',('stateMask',('pszText',ctypes.c_uint64),('cchTextMax',('iImage',('lParam',# On 32 bit should be c_long ('iIndent',('iGroupId',('cColumns',('puColumns',('piColFmt',ctypes.c_int64),('iGroup',] class POINT(ctypes.Structure): _fields_ = [('x',ctypes.c_int),('y',ctypes.c_int)] def icon_save_restore(savedicons=None,restore=False): import struct,commctrl,win32gui,win32con,win32api dthwnd = win32gui.FindWindow(None,'Program Manager') ukhwnd = win32gui.GetWindow(dthwnd,win32con.GW_CHILD) slvhwnd = win32gui.GetWindow(ukhwnd,win32con.GW_CHILD) pid = ctypes.create_string_buffer(4) p_pid = ctypes.addressof(pid) ctypes.windll.user32.GetWindowThreadProcessId(slvhwnd,p_pid) hProcHnd = ctypes.windll.kernel32.OpenProcess(win32con.PROCESS_ALL_ACCESS,False,struct.unpack("i",pid)[0]) pBuffertxt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd,4096,win32con.MEM_RESERVE|win32con.MEM_COMMIT,win32con.PAGE_READWRITE) copied = ctypes.create_string_buffer(4) p_copied = ctypes.addressof(copied) lvitem = LVITEMW() lvitem.mask = ctypes.c_uint32(commctrl.LVIF_TEXT) lvitem.pszText = ctypes.c_uint64(pBuffertxt) lvitem.cchTextMax = ctypes.c_int32(4096) lvitem.iSubItem = ctypes.c_int32(0) pLVI = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd,win32con.MEM_RESERVE| win32con.MEM_COMMIT,win32con.PAGE_READWRITE) win32api.SetLastError(0) ctypes.windll.kernel32.WriteProcessMemory(hProcHnd,pLVI,ctypes.addressof(lvitem),ctypes.sizeof(lvitem),p_copied) num_items = win32gui.SendMessage(slvhwnd,commctrl.LVM_GETITEMCOUNT) if restore is False: p = POINT() pBufferpnt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd,ctypes.sizeof(p),win32con.PAGE_READWRITE) icons = {} for i in xrange(num_items): # Get icon text win32gui.SendMessage(slvhwnd,commctrl.LVM_GETITEMTEXT,i,pLVI) target_bufftxt = ctypes.create_string_buffer(4096) ctypes.windll.kernel32.ReadProcessMemory(hProcHnd,pBuffertxt,ctypes.addressof(target_bufftxt),p_copied) key = target_bufftxt.value # Get icon position win32api.SendMessage(slvhwnd,commctrl.LVM_GETITEMPOSITION,pBufferpnt) p = POINT() ctypes.windll.kernel32.ReadProcessMemory(hProcHnd,pBufferpnt,ctypes.addressof(p),p_copied) icons[key] = (i,p) ctypes.windll.kernel32.VirtualFreeEx(hProcHnd,win32con.MEM_RELEASE) ctypes.windll.kernel32.VirtualFreeEx(hProcHnd,win32con.MEM_RELEASE) win32api.CloseHandle(hProcHnd) return icons else: # RESTORE ICON POSITIONS PROBLEM IS HERE SOMEWHERE!!! win32gui.SendMessage(slvhwnd,win32con.WM_SETREDRAW,0) for i in xrange(num_items): # Get icon text win32gui.SendMessage(slvhwnd,p_copied) key = target_bufftxt.value if key in savedicons.keys(): # Set icon position p = savedicons[key][1] # p is ctypes POINT p_lng = point_to_long(p) # explicitly convert to HIWORD/LOWORD and c_long # Reserve space for input variable in foreign process and get pointer to it the that memory space pBufferpnt = ctypes.windll.kernel32.VirtualAllocEx(hProcHnd,ctypes.sizeof(p_lng),win32con.PAGE_READWRITE) # Write the desired coordinates in to the space just created ret = ctypes.windll.kernel32.WriteProcessMemory(hProcHnd,ctypes.addressof(p_lng),p_copied) if ret == 0: raise WindowsError # Send the message to change the position for that item's index and the pointer to the new position ret = win32gui.SendMessage(slvhwnd,commctrl.LVM_SETITEMPOSITION,pBufferpnt) if ret == 0: raise WindowsError # Release the reserved memory for the variable (I recognize that I probably don't need to aLloc/free this within the loop) ctypes.windll.kernel32.VirtualFreeEx(hProcHnd,win32con.MEM_RELEASE) win32gui.SendMessage(slvhwnd,1,0) ctypes.windll.kernel32.VirtualFreeEx(hProcHnd,win32con.MEM_RELEASE) win32api.CloseHandle(hProcHnd) return None def point_to_long(p): ret = (p.y * 0x10000) + (p.x & 0xFFFF) return ctypes.c_long(ret) if __name__ == '__main__': mysavedicons = icon_save_restore(restore=False) icon_save_restore(mysavedicons,restore=True) 我认为可能存在以下问题:1)与32位和64位内存地址空间有关,但是我编写LVITEM结构或读取图标文本的其他组件工作正常或2)存在一些问题我正在转换坐标信息或为GETITEMPOSITION调用SendMessage.任何见解或帮助将不胜感激. 解决方法
事实证明,有一个版本使用32位地址(LVM_SETITEMPOSITION32),我希望MSDN在他们的文档中交叉引用:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb761194(v=vs.85).aspx
它直接接受POINT结构,因此无需尝试转换为HIWORD / LOWORD.在发布之前,我确实尝试使用32位移位和longlong(64位版本的long),并且使用LVM_SETITEMPOSITION不起作用.无论如何,随着变化,一切都按预期工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |