如何通过FFI更改图标位置?

时间:2013-04-02 17:32:03

标签: ruby winapi ruby-ffi

我正在尝试使用带有FFI gem的Ruby更改Windows 7桌面中图标的位置。

到目前为止,“Managing Desktop Icons”拥有我想要的大部分内容,但它并不适合我。

该文章一度使用LVA_ALIGNLEFT,但据我所知,我需要根据“LVM_ARRANGE message”使用LVS_ALIGNLEFT

require 'ffi'

module Win32
  extend FFI::Library
  ffi_lib 'user32'
  ffi_convention :stdcall

  enum :lvm, [:LVM_GETITEMCOUNT, 4100,
              :LVM_ARRANGE, 4118,
              :LVM_SETITEMPOSITION, 4111]

  enum :parameter, [:GW_CHILD, 5,
                    :LVS_ALIGNLEFT, 2048 ]

  # Uses C Function to find the window handle(HWND) of a window with the specified text, in this case 'ProgMan'
  attach_function :findWindow, 
    :FindWindowA,[ :string, :parameter ], :int

  # Gets passed in window's child window 
  attach_function :getChildWindow,
    :GetWindow, [ :int, :parameter], :int

  # Sends a message to the passed in window  
  attach_function :sendMessage,
    :SendMessageA, [ :int, :lvm, :parameter, :long], :int
end

# Finds Windows handle for FolderView, SysListView32 which is the icon list
DesktopHandle = Win32.findWindow('ProgMan', 0)
DesktopHandle = Win32.getChildWindow(DesktopHandle, :GW_CHILD)
DesktopHandle = Win32.getChildWindow(DesktopHandle, :GW_CHILD)

# Aligns icons left?
Win32.sendMessage(DesktopHandle, :LVM_ARRANGE, :LVS_ALIGNLEFT, 0)

Win32.sendMessage(DesktopHandle, :LVM_ARRANGE, :LVS_ALIGNLEFT, 0)应该左对齐图标但不执行任何操作。

我已经使用Win32.sendMessage(DesktopHandle, :LVM_GETITEMCOUNT, 0, 0)来确保我有正确的句柄,这确实输出了相同数量的图标。

我从“LVM_* defs”中获取了大部分值。

我只是不确定为什么这不起作用。

编辑: 看起来左对齐实际上工作我只是没有意识到它在做什么,我认为使用此命令应该已将我的所有图标移动到我的屏幕的左侧,但是此命令仅更改对齐! I.E.在Microsoft单词中,当您左对齐某些内容时,或居中的内容会改变文本的方式。

现在我需要获得改变图标位置的实际部分:

for (int i=0; i<200; i++)
  SendMessage(DesktopHandle, LVM_SETITEMPOSITION, 0, MAKELPARAM(10, i));

我仍在寻找的唯一部分是如何在ruby中执行MAKELPARAM(10, I)部分,我想我可能想要使用Ruby的数组#pack,但我不肯定如何去做

更新: 事实证明我的LVM值的来源不是我需要的,而是我使用了“List-View Messages”中的值。(我更新了我的数字以便以上是好的)

我还为MAKELPARAM()找到了“Ruby Class: Object”。

def MAKELPARAM(w1,w2)
  return (w2<<16) | w1
end

这会移动我的一个图标Win32.sendMessage(DesktopHandle, :LVM_SETITEMPOSITION, 0, makeLPARAM(10, 1))

1 个答案:

答案 0 :(得分:1)

原来我在sendmessage中发送了错误的值。

计算图标数量的代码,然后将一个图标移动到某个x,y位置(这会将列表中的第一个图标移动到左上角位置,在我的情况下,我当场没有任何内容。

require 'ffi'

module Win32
  extend FFI::Library
  ffi_lib 'user32'
  ffi_convention :stdcall

  enum :lvm, [:LVM_GETITEMCOUNT, 4100,
          :LVM_DELETEALLITEMS, 4105,
          :LVM_GETNEXTITEM, 4108,
          :LVM_SETITEMPOSITION, 4111,
          :LVM_GETITEMPOSITION, 4112,
          :LVM_ARRANGE, 4118,
          :LVM_UPDATE, 4138,
          :LVM_GETITEMTEXTA, 4141,
          :LVM_SETITEMTEXTA, 4142 ]

  enum :parameter, [:GW_CHILD, 5,
                    :LVS_ALIGNLEFT, 2048 ]

  # Uses C Function to find the window handle(HWND) of a window with the specified text, in this case 'ProgMan'
  attach_function :findWindow, 
    :FindWindowA,[ :string, :parameter ], :int

  # Gets passed in window handle's child window 
  attach_function :getChildWindow,
    :GetWindow, [ :ulong, :parameter], :int

  # Sends a message to the passed in window  
  attach_function :sendMessage,
    :SendMessageA, [ :ulong, :lvm, :parameter, :long], :int

end # end of Win32

def makeLPARAM(w1, w2)
  return (w2<<16) | w1
end

# Finds Windows handle for FolderView, SysListView32 which is the icon list
DesktopHandle = Win32.findWindow('ProgMan', 0)
DesktopHandle = Win32.getChildWindow(DesktopHandle, :GW_CHILD)
DesktopHandle = Win32.getChildWindow(DesktopHandle, :GW_CHILD)

# Gets count of icons on desktop
Win32.sendMessage(DesktopHandle, :LVM_GETITEMCOUNT, 0, 0)

# Moves the first icon in the list to the top leftmost position on the screen
Win32.sendMessage(DesktopHandle, :LVM_SETITEMPOSITION, 0, makeLPARAM(10, 1))

这比我想象的要困难得多!虽然很多人没有正确的价值观,但是有人能指出一个我应该首先寻找价值观的地方吗?