将InternetExplorer应用程序的图标设置为ico文件[Ruby 1.9.3]

时间:2017-04-28 23:42:24

标签: ruby winapi

我创建了一个相对简单的Ruby脚本,允许用户从下拉框中选择一个项目。我这样做是通过创建一个Internet Explorer的实例,然后从ruby自动化它。

最好我想进一步使用UI并更改ICON,甚至可能更改窗口标题。

注意:我确实意识到这是“重新发明轮子”,因为有很多宝石可以帮助创建GUI。但是,遗憾的是我需要一个纯标准Ruby的解决方案。

这是我目前的代码:

# To learn how to use win32 libraries see here:
# http://phrogz.net/programmingruby/lib_windows.html
# https://ruby-doc.org/stdlib-2.2.0/libdoc/win32ole/rdoc/WIN32OLE.html
require 'win32ole'
require 'Win32API'

def combobox(sTitle, aOptions)
    ie = WIN32OLE.new('InternetExplorer.Application')

    #set various options
    ie.resizable = false
    ie.toolbar = false
    ie.registerAsDropTarget = false
    ie.statusBar = false
    ie.navigate("about:blank")
    sleep(0.1) until !ie.busy
    ie.width=450
    ie.height=190
    ie.left = ie.document.parentWindow.screen.width / 2 - 200
    ie.top = ie.document.parentWindow.screen.height / 2 - 75

    #Set window icon (C++)
    #   HANDLE icon = LoadImage(fgDisplay.Instance, "c:\\icon.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
    #   SendMessage(instance, (UINT)WM_SETICON, ICON_BIG, (LPARAM)icon);

    #icon = LoadImage(null,"my/file/name/as/string.ico",IMAGE_ICON=1,0 or 32,0 or 32,LR_DEFAULTSIZE||LR_LOADFROMFILE) #LR_DEFAULTSIZE = 0x00000040; LR_LOADFROMFILE = 0x00000010; 
    #SendMessage(HWND, WM_SETICON, ICON_BIG, icon)

    #User32 LoadImage:    https://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
    #User32 SendMessageA: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx
    #define WM_SETICON                      0x0080
    #ICON_BIG                               1
    #ICON_SMALL                             0

    #Define constants:
    _IMAGE_ICON         = 1
    _LR_LOADFROMFILE    = 0x00000040
    _LR_DEFAULTSIZE     = 0x00000010
    _WM_SETICON         = 0x0080
    _ICON_BIG           = 1
    _ICON_SMALL         = 0

    #Set icon
    icoPath = "C:\Users\jwa\Desktop\Icons\toxic.ico" #"l" --> "v"
    icon = Win32API.new("user32","LoadImage",["v","p","i","i","i","i"],"p").call(0,icoPath, _IMAGE_ICON, 0,0, _LR_DEFAULTSIZE || _LR_LOADFROMFILE)
    puts icon
    Win32API.new("user32","SendMessageA",["l","i","i","p"],"i").call(ie.hwnd,_WM_SETICON,_ICON_SMALL,icon)

    #Set window content
    s = "
    <html>
        <head>
            <title>#{sTitle}</title>
        </head>
        <script type=\"text/javascript\">window.bWait=true</script>
        <script>
        submitForm = function(){
            document.url = document.getElementById(\"entries\").selectedIndex
        }
        </script>
        <body bgColor=Silver>
            <center>
                <b>#{sTitle}<b>
                <p>
                <select id=entries size=1 style='width:250px'>
                    <option selected></option>"

                    #Add options
                    aOptions.each do |item|
                        s += "<option>#{item}</option>"
                    end

    s += "      </select>
                <p>
                <button id=but0 onclick='submitForm()'>OK</button>
            </center>
        </body>
    </html>"

    ie.document.writeLn(s)
    ie.document.body.scroll = "no"
    ie.document.body.style.borderStyle = "outset"
    ie.document.body.style.borderWidth = "3px"
    ie.document.all.entries.Focus
    ie.visible = true

    #Bring window to front
    Win32API.new("user32","BringWindowToTop",["l"],"i").call(ie.hwnd)

    #wait till url not about:blank
    begin
        until (ie.document.url!="about:blank") do 
            sleep(0.1)
        end
    rescue
        return -1
    end

    #Get id and hide ie
    id=ie.document.url
    id=id.to_i
    ie.visible = false

    #Return id-1
    return id-1

end

一般情况下,脚本可以运行,但我还没有使用自定义图标。

    #Set icon
    icoPath = "C:\Users\jwa\Desktop\Icons\toxic.ico" #"l" --> "v"
    icon = Win32API.new("user32","LoadImage",["v","p","i","i","i","i"],"p").call(0,icoPath, _IMAGE_ICON, 0,0, _LR_DEFAULTSIZE || _LR_LOADFROMFILE)
    puts icon ### ==> 0
    Win32API.new("user32","SendMessageA",["l","i","i","p"],"i").call(ie.hwnd,_WM_SETICON,_ICON_SMALL,icon) ### ==> Doesn't do anything (likely due to icon==0)

这段代码有什么明显的错误吗?

注意:同样,我很乐意为此使用类似于ffi的Gem,但不幸的是,这是不可能的。

2 个答案:

答案 0 :(得分:2)

很好的解决方案,我迟到了,但想向您展示我用于此类任务的内容。我曾经使用green_shoes来完成这些任务,但厌倦了控件的非原生外观和其他限制(例如没有网格)。

另一方面,有一个强大的自动键,具有非常好的GUI,但很难编码(肯定与Ruby相比)。

所以我尝试了autohotkey.dll,它允许你使用autohotkey代码以及Ruby的GUI。效果很好。 您需要下载并注册dll。 https://autohotkey.com/board/topic/39588-autohotkeydll/

这里是一个下拉选择的例子(还有一个真正的组合)。

require 'win32ole'

def choose_from_dropdown *list
  selections = list.join('|')
  code =  %Q{
    Gui, Add, DropDownList, r50 w200  vChoice, #{selections}
    Gui, Show, x131 y91 h67 w227, Make your choice
    Hotkey,Enter,a1,ON
    Return

    GuiClose:
    Gui, Submit, nohide
    return

    a1:
    Gui, Submit, nohide
    return
  }

  ahk = WIN32OLE.new("AutoHotkey.Script")
  ahk.AhkTextDll(code)
  choice = nil
  while ahk.ahkReady == 1 do
    sleep 1
    choice = ahk.ahkgetvar('Choice')
    if choice && choice != ""
      ahk.ahkTerminate
      return choice
    end
  end
rescue => e
  puts e.message
  puts e.backtrace
end

puts choose_from_dropdown %w{one two three}

在这样的列表中,我喜欢使用向上和向下键进行滚动并使用Enter键确认,这是我实现的,也可以使用Ok按钮等实现其他实现。

答案 1 :(得分:0)

嗯......这很尴尬。这是一个非常不错的错误...我一直忘记在Ruby \中转义字符串中的字符,所以:

#Set icon
icoPath = "C:\Users\jwa\Desktop\Icons\toxic.ico"

实际上返回"C:UsersjwaDesktopIconstoxic.ico"当然不是文件路径......我需要这样做:

#Set icon
icoPath = "C:\\Users\\jwa\\Desktop\\Icons\\toxic.ico"

糟糕。此外,似乎win32api在ruby 中使用“p”指针。因此,在seticon语句中使用win32api返回的句柄,即

Win32API.new("user32","SendMessageA",[args*],"i")

args *的最后一个参数应该是一个长"l"而不是一个指针。像这样:

Win32API.new("user32","SendMessageA",["l","i","i","l"],"i").call(ie.hwnd,_WM_SETICON,_ICON_SMALL,icon)

同样重要的是要注意,您应该同时拨打_ICON_SMALL_ICON_BIG_ICON_SMALL是窗口中的图标,_ICON_BIG是alt-tab菜单中的图标。

更改iexplorer应用程序图标的完整代码:

#Define constants:
_IMAGE_ICON         = 1
_LR_LOADFROMFILE    = 0x00000040
_LR_DEFAULTSIZE     = 0x00000010
_WM_SETICON         = 0x0080
_ICON_BIG           = 1
_ICON_SMALL         = 0

#Set icon
icoPath = "C:\\Users\\jwa\\Desktop\\Icons\\toxic.ico" #"l" --> "v"
icon = Win32API.new("user32","LoadImageA",["l","p","l","l","l","l"],"p").call(0,icoPath, _IMAGE_ICON, 0,0, _LR_DEFAULTSIZE | _LR_LOADFROMFILE | 0)
Win32API.new("user32","SendMessageA",["l","i","i","l"],"i").call(ie.hwnd,_WM_SETICON,_ICON_SMALL,icon)      # affects title bar
Win32API.new("user32","SendMessageA",["l","i","i","l"],"i").call(ie.hwnd,_WM_SETICON,_ICON_BIG,icon)        # affects alt-tab