ズームインツール

VisualStudioに付属してたZOOMIN.exeがお気に入りだったんですが、最近は付属されないようで。wxの練習がてら作ってみました。

# -*- coding: utf-8 -*-

import wx

class MainFrame(wx.Frame):
    def __init__(self):
        super(MainFrame, self).__init__(None, wx.ID_ANY, 'ZoomIn : x2')
        self.SetSize((320, 240))

        # ウィンドウレイアウトの初期化
        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        self._panel1 = wx.Panel(self)
        sizer1.Add(self._panel1, 1, wx.EXPAND)
        self._scrollbar1 = wx.ScrollBar(self, style = wx.SB_VERTICAL)
        self._scrollbar1.SetScrollbar(1, 1, 7, 2);
        sizer1.Add(self._scrollbar1, 0, wx.EXPAND)
        self.Sizer = sizer1
        self.Layout()

        # イベントハンドラの設定
        self._panel1.Bind(wx.EVT_LEFT_DOWN, self._panel1_LEFT_DOWN)
        self._panel1.Bind(wx.EVT_LEFT_UP, self._panel1_LEFT_UP)
        self._panel1.Bind(wx.EVT_MOTION, self._panel1_MOTION)
        self._panel1.Bind(wx.EVT_PAINT, self._panel1_PAINT)
        self._panel1.Bind(wx.EVT_SIZE, self._panel1_SIZE)
        self._scrollbar1.Bind(wx.EVT_SCROLL, self._scrollbar1_SCROLL)

        # 初期スケール
        self._scale = 2

        # ズームインする中心座標
        self._pos = map(lambda x: x/2, self._panel1.ClientSize)
        self._pos = self._panel1.ClientToScreen(self._pos)

        # 描画用バッファ
        self._bmp = wx.EmptyBitmap(*self._panel1.ClientSize)

        self.Show()

    def _panel1_LEFT_DOWN(self, args):
        self._panel1.CaptureMouse()
        self.Cursor = wx.StockCursor(wx.CURSOR_BLANK) # マウスカーソルを非表示
        self._pos = self._panel1.ClientToScreen(args.Position);
        self.drawZoomImage(wx.ClientDC(self._panel1))
        self.drawAreaRect()

    def _panel1_LEFT_UP(self, args):
        if not self._panel1.HasCapture(): return
        self.drawAreaRect()
        self.drawZoomImage(wx.ClientDC(self._panel1))
        self.Cursor = wx.NullCursor # デフォルトのマウスカーソルに復帰
        self._panel1.ReleaseMouse()

    def _panel1_MOTION(self, args):
        if not self._panel1.HasCapture(): return
        self.drawAreaRect()
        self.drawZoomImage(wx.ClientDC(self._panel1))
        self._pos = self._panel1.ClientToScreen(args.Position);
        self.drawAreaRect()

    def _panel1_SIZE(self, args):
        self._bmp = wx.EmptyBitmap(*self._panel1.ClientSize)
        self.Refresh()
        
    def _panel1_PAINT(self, args):
        self.drawZoomImage(wx.PaintDC(self._panel1))

    def _scrollbar1_SCROLL(self, args):
        self._scale = self._scrollbar1.ThumbPosition + 1
        self.Title = self.Title.split(':')[0] + ': x{0}'.format(self._scale)
        self._panel1.Refresh()

    def drawZoomImage(self, dc):
        sx, sy = self._panel1.ClientSize
        px, py = map(lambda p, s: p - s / (self._scale * 2), self._pos, (sx,sy))
        tmp = wx.MemoryDC(self._bmp)
        tmp.Background = wx.BLACK_BRUSH
        tmp.Clear()
        tmp.Blit(0,0,sx,sy,wx.ScreenDC(),px,py)
        dc.SetUserScale(self._scale, self._scale)
        dc.Blit(0,0,sx,sy,tmp,0,0)

    def drawAreaRect(self):
        dc = wx.ScreenDC()
        dc.LogicalFunction = wx.XOR
        dc.Brush = wx.TRANSPARENT_BRUSH
        dc.Pen = wx.WHITE_PEN
        sw, sh = map(lambda x: x / self._scale, self._panel1.ClientSize)
        dc.DrawRectangle(self._pos[0]-sw/2,self._pos[1]-sh/2,sw,sh)
        
app = wx.PySimpleApp()
app.TopWindow = MainFrame()
app.MainLoop()

ソース貼るにはちょっと長いか?↓これが実行結果。

お手軽。
ropemacs最高です。補完もできる。ヘルプも呼べる。ソースジャンプもできる。言う事なし!