PictureBoxにマウスでフリーハンドの絵を描く様子を保存し、再生する。
昨日のコードに PictureBox を追加する。
- 「記録開始」ボタンを押すとマウス操作の記録開始。(ボタン表示は「保存」と変わる)
- 「1」〜「5」のボタンを押すと上の青いラベルに数字が挿入される。
- 下の白いキャンバス(PictureBox)で左ボタン押しつつマウスを動かすと線が描画される。
- 「保存」ボタンを押すと、操作履歴がファイルに保存される。
- 「読込」ボタンを押して保存ファイルを読み込むと(ビデオ再生の様に)文字入力/絵の描画が行われる。
「1」〜「5」のボタンは Button1〜Button5に、「表示をクリア」「記録開始」「読込」ボタンはButton100〜Button102に割り振っている(記録対象となる編集ボタンはButton6以降に後から追加できる様に!)。
Imports System.Threading Imports System.Drawing Imports System.Drawing.Drawing2D Public Structure CommandClass Public name As String Public arg As String Public Sub New(ByVal s1 As String, ByVal s2 As String) Me.name = s1 Me.arg = s2 End Sub End Structure Public Class Form1 Private status As Integer = 0 '0:定常状態 1:記録中 Private commands As Collection = New Collection() Private commandPreTime As Date Private timerDelegate As TimerCallback = New TimerCallback(AddressOf timerFunc) Private myTimer As Timer = New Timer(timerDelegate, Nothing, Timeout.Infinite, -1) Private myCount As Integer = 0 Private preX As Integer = -1 Private preY As Integer = -1 Private Function eventInvoke(ByVal cmd As String, ByVal code As String) As String If cmd = "r" Or cmd = "p" Then Label1.Text = Label1.Text & code ElseIf cmd = "t" Or cmd = "m" Then Dim xy As String() = code.Split(",") Dim x As Integer = CInt(xy(0)) Dim y As Integer = CInt(xy(1)) If preX >= 0 Then Dim g As Graphics = PictureBox1.CreateGraphics g.DrawLine(Pens.Red, preX, preY, x, y) g.Dispose() End If preX = x preY = y End If If status = 1 Then '記録中 If commands.Count > 0 Then Dim span As TimeSpan = Now() - commandPreTime commands.Add(New CommandClass("s", span.TotalSeconds)) End If commandPreTime = Now() commands.Add(New CommandClass(cmd, code)) End If eventInvoke = code End Function Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button1.Click, Button2.Click, Button3.Click, Button4.Click, Button5.Click eventInvoke("r", sender.Text) End Sub Private Sub Button100_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button100.Click If status = 0 Then commands.Clear() preX = -1 preY = -1 status = 1 Button100.Text = "保存する" Else status = 0 Dim sfd As New SaveFileDialog() sfd.FileName = "events.txt" 'sfd.InitialDirectory = "C:\" sfd.Filter = "TEXTファイル(*.txt)|*.txt|すべてのファイル(*.*)|*.*" sfd.FilterIndex = 1 '初期表示は*.txtだけ sfd.Title = "保存先のファイルを選択してください" If sfd.ShowDialog() = DialogResult.OK Then Dim stream As System.IO.Stream = sfd.OpenFile() If Not (stream Is Nothing) Then Dim sw As New System.IO.StreamWriter(stream) sw.WriteLine("# s:指定秒数SLEEPする / t:タッチパネルイベント発行 / " & _ "p:指定されたキーのPressイベントを発行 / r:指定されたキーのReleaseイベントを発行") For Each com In commands sw.WriteLine(com.name & " " & com.arg.ToString) Next sw.Close() stream.Close() End If End If Button100.Text = "記録開始" End If End Sub Private Sub Button101_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button101.Click Dim ofd As New OpenFileDialog() ofd.FileName = "events.txt" 'ofd.InitialDirectory = "C:\" ofd.Filter = "TEXTファイル(*.txt)|*.txt|すべてのファイル(*.*)|*.*" ofd.FilterIndex = 1 ofd.Title = "開くファイルを選択してください" ofd.RestoreDirectory = True If ofd.ShowDialog() = DialogResult.OK Then Dim stream As System.IO.Stream = ofd.OpenFile() If Not (stream Is Nothing) Then Dim sr As New System.IO.StreamReader(stream) Dim sarray As String() commands.Clear() preX = -1 preY = -1 While sr.Peek() > -1 Dim s As String = sr.ReadLine() If s.Length < 3 Or s.StartsWith("#") Then ' Do nothing 'Next While 'break; とか next に該当するのって何? Else sarray = s.Split(" ") commands.Add(New CommandClass(sarray(0), sarray(1))) End If End While sr.Close() stream.Close() myCount = 1 myTimer.Change(10, Timeout.Infinite) End If End If End Sub Private Sub Button102_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button102.Click Dim g As Graphics = PictureBox1.CreateGraphics() Label1.Text = "" g.Clear(PictureBox1.BackColor) g.Dispose() End Sub Delegate Function FuncDelegate(ByVal cmd As String, ByVal arg As String) Public Sub timerFunc(ByVal o As Object) While myCount <= commands.Count Dim com As CommandClass = commands(myCount) myCount = myCount + 1 If com.name = "s" Then myTimer.Change(Convert.ToInt32(com.arg * 1000), Timeout.Infinite) Exit Sub Else Invoke(New FuncDelegate(AddressOf eventInvoke), com.name, com.arg) End If End While myTimer.Change(Timeout.Infinite, Timeout.Infinite) MessageBox.Show("再生を終了しました") End Sub Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)_ Handles PictureBox1.MouseDown eventInvoke("t", e.X & "," & e.Y) End Sub Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)_ Handles PictureBox1.MouseUp eventInvoke("T", e.X & "," & e.Y) End Sub Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)_ Handles PictureBox1.MouseMove If e.Button = Windows.Forms.MouseButtons.Left Then eventInvoke("m", e.X & "," & e.Y) End If End Sub End Class