主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

.NET FrameworkでGUIアプリを作ってみる

                
 .NET Framework(以下.NETと略す)を使ってみたかったので、以前PyGTKで作ったスクリーンキャプチャしたりするアプリを移植してみた。.NET Framework4.0、IronPython2.7でやった。そのスクリプトとXAMLは記事の末尾に。

 この直前の記事に関係することなのだけど、どうやら.NETで使うBitmapは、不要になるたびにGDIからDeleteObject関数を呼び出してBitmapデータに使われたメモリを解放しなければならないらしい。それを知らずにスクリーンキャプチャを繰り返していたら、使用メモリが肥大し、ついにはメモリリークを起こした。しかしGDIはIronPythonから直接呼び出せるようになってはいない。以下の2つのサイトを参考に、C#でクラスを作成して、IronPythonから呼び出せるようにしてこの問題はクリアした。
http://stackoverflow.com/questions/5375943/creating-a-bitmapimage-wpf
http://www.voidspace.org.uk/ironpython/winforms/part10.shtml

import datetime

import clr
clr.AddReference("System")
clr.AddReference("System.Xml")
clr.AddReference("System.Drawing")
clr.AddReference("IronPython.Wpf")
clr.AddReference("WPFToolkit.Extended")
clr.AddReference("GDItool")

import gc
import wpf
from System.Drawing import Bitmap, Graphics, Point, Size, GraphicsUnit, Rectangle
from System.Drawing.Imaging import *
from System import TimeSpan, IntPtr
from System.IO import StringReader
from System.Xml import XmlReader
from System.Windows import Window, Application, Int32Rect
from System.Windows.Markup import XamlReader
from System.Windows.Threading import *
from System.Windows.Input import *
from System.Windows.Media import Color
from System.Windows.Media.Imaging import BitmapImage, BitmapSizeOptions
from System.Windows.Interop import Imaging
from System.Diagnostics import PerformanceCounter

import Xceed.Wpf.Toolkit
from UnmanagedCode import GDI32, User32

class Main(Window):
def __init__(self):
wpf.LoadComponent(self, 'a01.xaml')

self.pb = self.FindName('image')
self.cpu_usage = self.FindName('cpu_usage')
self.stack00 = self.FindName('stack00')
self.spin_x = self.FindName('spin_x')
self.spin_x.ValueChanged += self.change_axis
self.spin_y = self.FindName('spin_y')
self.spin_y.ValueChanged += self.change_axis
self.spin_w = self.FindName('spin_w')
self.spin_w.ValueChanged += self.change_axis
self.spin_h = self.FindName('spin_h')
self.spin_h.ValueChanged += self.change_axis
self.spin_h = self.FindName('fps_spin')
self.spin_h.ValueChanged += self.change_fps

self.radio1 = self.FindName('radioButton1')
self.radio1.Click += self.change_color_radio
self.radio2 = self.FindName('radioButton2')
self.radio2.Click += self.change_color_radio
self.radio3 = self.FindName('radioButton3')
self.radio3.Click += self.change_color_radio

self.button_play = self.FindName('button_play')
self.button_play.Click += self.play
self.button_pause = self.FindName('button_pause')
self.button_pause.Click += self.pause
self.button_capture = self.FindName('button_capture')
self.button_capture.Click += self.capture

self.performance = PerformanceCounter()
self.performance.CategoryName = "Processor"
self.performance.CounterName = "% Processor Time"
self.performance.InstanceName = "_Total"

self.timer1 = DispatcherTimer()
self.timer1.Interval = TimeSpan(0, 0, 1.0)
self.timer1.Tick += self.tick_on
self.timer1.Start()

self.timer2 = DispatcherTimer()
self.timer2.Interval = TimeSpan(0, 0, 1.0)
self.timer2.Tick += self.tick_cpu
self.timer2.Start()

self.x = 100
self.y = 100
self.width = 400
self.height = 300
self.pb.Width = self.width
self.pb.Height = self.height
self.Width = self.width + 170
self.Height = self.height
self.stack00.Width = self.Width
self.stack00.Height = self.Height

self.imageAttributes = ImageAttributes()
colorMatrix = ColorMatrix(((1, 0, 0, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1),))
self.imageAttributes.SetColorMatrix(
colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap)

def tick_on(self, target, args):
gc.collect()
bmp = Bitmap(self.width, self.height)
g = Graphics.FromImage(bmp)
g.CopyFromScreen(self.x, self.y, 0, 0, Size(self.width, self.height))
self.bmp = bmp.Clone()
if self.radio1.IsChecked == False:
g.DrawImage(bmp,
Rectangle(0, 0, self.width, self.height), # destination rectangle
0, 0, # upper-left corner of source rectangle
self.width, # width of source rectangle
self.height, # height of source rectangle
GraphicsUnit.Pixel,
self.imageAttributes)
g.Dispose()
self.screen_bmp = bmp
im = bmp.GetHbitmap()
source = Imaging.CreateBitmapSourceFromHBitmap(im,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions())

self.pb.Source = source
GDI32.DeleteObject(im)

def change_color_radio(self, target, args):
if self.radio1.IsChecked == True:
colorMatrix = ColorMatrix(((1, 0, 0, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1),))
elif self.radio2.IsChecked == True:
colorMatrix = ColorMatrix(((0, 0, 0, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1),))
elif self.radio3.IsChecked == True:
colorMatrix = ColorMatrix(((1, 0, 0, 0, 0),
(0, 0, 0, 0, 0),
(0, 0, 1, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1),))
self.imageAttributes.SetColorMatrix(colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap)

gc.collect()
bmp = self.bmp.Clone()
g = Graphics.FromImage(bmp)
if self.radio1.IsChecked == False:
g.DrawImage(bmp,
Rectangle(0, 0, self.width, self.height), # destination rectangle
0, 0, # upper-left corner of source rectangle
self.width, # width of source rectangle
self.height, # height of source rectangle
GraphicsUnit.Pixel,
self.imageAttributes)
g.Dispose()
self.screen_bmp = bmp
im = bmp.GetHbitmap()
source = Imaging.CreateBitmapSourceFromHBitmap(im,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions())

self.pb.Source = source
GDI32.DeleteObject(im)

def tick_cpu(self, target, args):
num = int(self.performance.NextValue())
self.cpu_usage.Content = str(num) + "%"

def change_axis(self, target, args):
name = target.Name
if name == "spin_x":
self.x = target.Value
elif name == "spin_y":
self.y = target.Value
elif name == "spin_w":
self.width = target.Value
elif name == "spin_h":
self.height = target.Value
self.pb.Width = self.width
self.pb.Height = self.height
self.Width = self.width + 170
self.Height = self.height
self.stack00.Width = self.Width
self.stack00.Height = self.Height

def change_fps(self, target, args):
value = 1.0 / target.Value
self.timer1.Interval = TimeSpan(0, 0, value)

def play(self, target, args):
self.timer1.Start()

def pause(self, target, args):
self.timer1.Stop()

def capture(self, target, args):
filename = "cap_%s.png" %(datetime.datetime.now().strftime("%Y%m%dT%H%M%S"))
self.screen_bmp.Save(filename)

def treat_color(self):
pass

def main():
Application().Run(Main())


if __name__ == "__main__":
main()


<?xml version="1.0" encoding="utf-8"?>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Makestomy - Color Design Helper"
Width="524"
Left="0"
Height="500"
WindowState="Normal">
<StackPanel
Name="stack00"
Orientation="Horizontal"
Width="510"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="356">
<StackPanel
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="172"
Height="301">
<StackPanel
Orientation="Horizontal"
Height="42"
Width="159">
<xctk:IntegerUpDown
Name="spin_x"
FormatString="N0"
Value="100"
Minimum="100"
Increment="5"
Maximum="32000"
Width="75"
Height="23" />
<xctk:IntegerUpDown
Name="spin_y"
FormatString="N0"
Value="100"
Minimum="100"
Increment="5"
Maximum="32000"
Width="75"
Height="23" />
</StackPanel>
<StackPanel
Orientation="Horizontal"
Height="42"
Width="159">
<xctk:IntegerUpDown
Name="spin_w"
FormatString="N0"
Value="400"
Minimum="100"
Increment="5"
Maximum="32000"
Width="75"
Height="23" />
<xctk:IntegerUpDown
Name="spin_h"
FormatString="N0"
Value="300"
Minimum="100"
Increment="5"
Maximum="32000"
Width="75"
Height="23" />
</StackPanel>
<StackPanel
Orientation="Horizontal"
Height="42"
Width="159">
<RadioButton
Height="20"
Name="radioButton1"
GroupName="radio"
Content="C"
IsChecked="True"
Width="35" />
<RadioButton
Height="20"
Name="radioButton2"
GroupName="radio"
Width="35"
Content="P" />
<RadioButton
Height="20"
Name="radioButton3"
GroupName="radio"
Width="35"
Content="D" />
</StackPanel>
<StackPanel
Orientation="Horizontal"
Height="42"
Width="159"
VerticalAlignment="Top">
<Button
Height="23"
Width="50"
Content="Play"
Name="button_play"/>
<Button
Height="23"
Width="50"
Name="button_pause"
Content="Pause" />
<Button
Height="23"
Width="50"
Name="button_capture"
Content="Capture" />
</StackPanel>
<StackPanel
Orientation="Horizontal"
Height="41"
Width="155">
<Label
Content="Refresh Rate"
Height="24"
Width="77" />
<xctk:IntegerUpDown
Name="fps_spin"
FormatString="N0"
Value="1"
Minimum="1"
Increment="1"
Maximum="60"
Width="75"
Height="23" />
</StackPanel>
<StackPanel
Height="31"
Width="155"
Orientation="Horizontal">
<Label
Content="CPU Usage"
Height="26"
Width="75" />
<Label
Name="cpu_usage"
Width="70"
Height="24"
Content="10%" />
</StackPanel>
</StackPanel>
<Image
Name="image"
Width="222"
Height="224"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</StackPanel>
</Window>
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。