「hmPy・IronPython」のその他の例題 WPFの利用

  • 概要

    .NETのプログラミングにあまり触れていない方は、

    WPFの利用にはXMLが必須

    と思っているかもしれませんが、そのようなことはありません。

    WPFはFormと同様の感覚で、普通に利用することが可能です。

    Win32 APIをラップしたに過ぎないFormとは異なり、
    WPFのGUI要素は、原則的にはFrameworkElementというクラスの派生です。

    この特性により通常のWindowsアプリでは有りえないような、
    GUIの「組み合わせ」「入れ子」「変形」「修飾」を統一的手段で簡単に実現可能です。
    (例えば、ボタンの中にメニューを配置し、そのメニューの中にムービーを配置、
    といったGUIの常識とかけ離れた入れ子構造でも、何一つ問題ありません)

    WPFの使用

    以下のようなファイルをwpf.pyとして作成してみましょう。
    文字コードはcp932(sjis)です。

    # coding: cp932
    
    import clr
    clr.AddReferenceByPartialName("System.Windows")
    clr.AddReferenceByPartialName("WindowsBase")
    clr.AddReferenceByPartialName("PresentationCore")
    clr.AddReferenceByPartialName("PresentationFrameWork")
    
    import System
    import System.Windows
    import System.Windows.Media
    import System.Windows.Media.Imaging
    import System.Windows.Controls
    import System.Windows.Shapes
    import System.Windows.Documents
    from System import *
    from System.Windows import *
    from System.Windows.Media import *
    from System.Windows.Media.Imaging import *
    from System.Windows.Controls import *
    from System.Windows.Shapes import *
    from System.Windows.Documents import *
    
    class MyWindow(System.Windows.Window):
      def SetForm(self):
        self.Title = r"秀丸マクロ hmPyによるWPF"
        self.Width = 96 * 10
        self.Height = 96 * 5
        self.FontSize = 22
    
      def SetFont(self):
        self.FontFamily = FontFamily("MS明朝")
    
      def SetButton(self):
        ef = System.Windows.Media.Effects.DropShadowEffect()
        ef.BlurRadius = 5
        ef.ShadowDepth = 1
        self.btnTest = Button()
        self.btnTest.Content = "秀丸"
        self.btnTest.Padding = System.Windows.Thickness(2)
        self.btnTest.Foreground = System.Windows.Media.Brushes.White
        self.btnTest.Background = System.Windows.Media.Brushes.Black
        self.btnTest.Effect = ef
        self.btnTest2 = Button()
        self.btnTest2.Content = "WPF"
        self.btnTest2.Padding = System.Windows.Thickness(2)
        self.btnTest2.Foreground = System.Windows.Media.Brushes.White
        self.btnTest2.Background = System.Windows.Media.Brushes.Black
        self.btnTest2.Effect = ef
    
      def SetFormCanvas(self):
        c = Canvas()
        c.Children.Add(self.btnTest)
        Canvas.SetLeft(self.btnTest, 30.0)
        Canvas.SetTop(self.btnTest, 30.0)
        c.Children.Add(self.btnTest2)
        Canvas.SetLeft(self.btnTest2, 30.0)
        Canvas.SetTop(self.btnTest2, 80.0)
        c.Children.Add(self.tbArea)
        Canvas.SetLeft(self.tbArea, 30)
        Canvas.SetTop(self.tbArea, 120)
        c.Children.Add(self.bzpath)
        Canvas.SetLeft(self.tbEdit1, 550)
        Canvas.SetTop(self.tbEdit1, 80)
        c.Children.Add(self.tbEdit1)
        Canvas.SetLeft(self.tbEdit2, 600)
        Canvas.SetTop(self.tbEdit2, 80)
        c.Children.Add(self.tbEdit2)
        Canvas.SetLeft(self.tbEdit3, 550)
        Canvas.SetTop(self.tbEdit3, 150)
        c.Children.Add(self.tbEdit3)
        self.Content = c
    
      def SetBackGround(self):
        myLinearGradientBrush = LinearGradientBrush()
        myLinearGradientBrush.GradientStops.Add(GradientStop(Color.FromArgb(222, 212, 255, 204), 0.0))
        myLinearGradientBrush.GradientStops.Add(GradientStop(Color.FromArgb(232, 212 - 100, 247 - 100, 255 - 100), 1.0))
        myRectangle = System.Windows.Shapes.Rectangle()
        myRectangle.Width = 100
        myRectangle.Height = 100
        self.Background = myLinearGradientBrush
    
      def SetTextBlock(self):
        self.tbArea = TextBlock()
        self.tbArea.TextWrapping = TextWrapping.Wrap
        text = r"WPF in 秀丸マクロ"
    
        hl = Hyperlink(Run(text))
        hl.Click += self.hl_Click
        self.tbArea.Inlines.Add(hl)
    
    
      def SetBackgroundImage(self):
        # パターンの繰り返し
        uri = Uri("test.bmp", UriKind.RelativeOrAbsolute)
        brush = ImageBrush(BitmapImage(uri))
        brush.TileMode = TileMode.Tile
        brush.Viewport = Rect(0, 0, 0.2, 0.2)
    
      # ベジェ曲線
      def SetBezierSegment(self):
        bezier = BezierSegment()
        bezier.Point1 = Point(160, 210)
        bezier.Point2 = Point(260, 410)
        bezier.Point3 = Point(410, 310)
        figure = PathFigure()
        figure.StartPoint = Point(30, 310)
        figure.Segments.Add(bezier)
        geometry = PathGeometry()
        geometry.Figures.Add(figure)
        self.bzpath = Path()
        self.bzpath.Data = geometry
        self.bzpath.Stroke = Brushes.Black
    
      def SetRotateInputBox(self):
        transform = RotateTransform(-30)
        self.tbEdit1 = TextBox()
        self.tbEdit1.Text = "入力エディット1"
        self.tbEdit1.RenderTransform = transform
        self.tbEdit2 = TextBox()
        self.tbEdit2.Text = "入力エディット2"
        self.tbEdit2.RenderTransform = transform
    
      def SetSkewInputBox(self):
        transform = SkewTransform(40, 10) # 基点を軸に、水平方向に 40 度、垂直方向に 10 度、長方形が曲がっていることを確認してください。
        self.tbEdit3 = TextBox()
        self.tbEdit3.Text = "3次元入力域。複数行OK"
        self.tbEdit3.AcceptsReturn = True
        self.tbEdit3.RenderTransform = transform
    
      def __init__(self):
        self.SetForm()
        self.SetFont()
        self.SetButton()
        self.SetTextBlock()
        self.SetBezierSegment()
        self.SetRotateInputBox()
        self.SetSkewInputBox()
        self.SetBackGround()
        self.SetFormCanvas()
    
      def OnSourceInitialized(self, e):
        pass
    
      def hl_Click(self, o, e):
        System.Diagnostics.Process.Start(r"http://秀丸.net/?page=nobu_tool_hm_ironpython_wpf")
    
    
    # ウィンドウを開いている間に、秀丸の方を先に閉じられると、不正終了してしまう。
    try:
        win = MyWindow()
        win.ShowDialog()
    except Exception as e:
        if win:
            win.Close()
    finally:
        if win:
            win.Close()
    

    呼び出しマクロ

    #PY = loaddll( hidemarudir + "\\hmPy.dll");
    
    #_ = dllfuncw( #PY, "DoFile", currentmacrodirectory + "\\wpf.py" );
    
    freedll( #PY );