最終更新日 2024-09-25

「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 );