アイコンのオーバーレイ

自分用tips:No.2。アイコンにoverlayを入れてみる。
サンプルはTortoiseOverlayのオーバーレイアイコン。

import os
import wx

class MainFrame(wx.Frame):
  def __init__(self):
    super(type(self), self).__init__(None, wx.ID_ANY, 'Icon Overlay')
    tree = wx.TreeCtrl(self)
    
    size = 16
    folder = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (size, size))
    overlays = ('icon/AddedIcon.ico',
                'icon/ConflictIcon.ico',
                'icon/DeletedIcon.ico',
                'icon/IgnoredIcon.ico',
                'icon/LockedIcon.ico',
                'icon/ModifiedIcon.ico',
                'icon/NormalIcon.ico',
                'icon/ReadOnlyIcon.ico',
                'icon/UnversionedIcon.ico',)
    
    imagelist = wx.ImageList(size, size)
    imagelist.Add(folder)
    tree.AssignImageList(imagelist)
    root = tree.AddRoot('root', 0)
    
    dc = wx.MemoryDC()
    dc.SetBackground(wx.WHITE_BRUSH)
    for name in overlays:
      # オーバーレイアイコン読み込み
      icon = wx.NullImage
      icon.LoadFile(name, wx.BITMAP_TYPE_ICO, 0)
      icon.Rescale(size, size)
      icon = icon.ConvertToBitmap()
      
      # ベースアイコンにオーバーレイを重ねる
      bmp = wx.EmptyBitmap(size, size)
      dc.SelectObject(bmp)
      dc.Clear()
      dc.DrawBitmap(folder, 0, 0, True)
      dc.DrawBitmap(icon, 0, 0, True)
      dc.SelectObject(wx.NullBitmap)
      
      # アイコン登録
      index = imagelist.Add(bmp)
      
      # ノード追加
      name = os.path.basename(name).replace('Icon.ico', '').lower()
      child = tree.AppendItem(root, name, index)
    
    tree.Expand(root)
    self.Show()

# main
app = wx.PySimpleApp()
app.SetTopWindow(MainFrame())
app.MainLoop()

雑感

  • wx.ImageListを使う。これはMFC/winformsとかと同じ。
  • wx.Iconは手抜きのためのもの。オーバーレイに使うにはwx.Image.LoadFile()を使わないといけない。
  • 画像処理は一旦wx.Imageを通す。
  • 合成処理はwx.DCを使ってwx.Bitmapへ出力。
  • wx.ArtProviderのアイコンがあんましカッコよくない
  • Win32APIはTreeCtrlの機能でアイコンのオーバーレイができるらしい(未確認)。ただ、wxのコードには記述が無いので使えないっぽ。

後記

wxPythonの練習がてらsubversionクライアントでも書いてみようか。しかし、まだ気合が入らない。