Unterschriften auch für WinForms
Mit der Maus sieht es gruselig aus, mit dem Stift geht es bestimmt besser....
Download Beispielprojekt VS2013
Unterschriften für Winforms-Anwendungen? Es braucht dazu keine Third-Party-Tools oder teure Hardware. Alles was man dazu braucht ist eine PictureBox.
Schritt 1: Benutzersteuerelment dem Projekt hinzufügen
In diesem Beispiel nenne ich das Steuerelement: InkSignUserControl
Abbildung 1: Neues Benutzersteuerlement hinzufügen
Schritt 2: Steuerelement designen
Auf diesem Formular verwende ich folgende Steuerelemente
ein "TableLayoutPanel"
ein "Button"
und eine "PictureBox"
Abbildung 2: Design des Benutzersteuerelements
Öffnen Sie den Designer und ersetzen sie den kompletten Code mit dem Code aus Listing 1.
Abbildung 3: Designer-Code anzeigen lassen
Listing 1: "Designer-Code" des Benutzersteuerelementes "InkSignUserControl"
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class InkSignUserControl
Inherits System.Windows.Forms.UserControl
'UserControl überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Wird vom Windows Form-Designer benötigt.
Private components As System.ComponentModel.IContainer
'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.
'Das Bearbeiten ist mit dem Windows Form-Designer möglich.
'Das Bearbeiten mit dem Code-Editor ist nicht möglich.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TableLayoutPanel = New System.Windows.Forms.TableLayoutPanel()
Me.InkPanel = New System.Windows.Forms.PictureBox()
Me.CommandReset = New System.Windows.Forms.Button()
Me.TableLayoutPanel.SuspendLayout()
CType(Me.InkPanel, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'TableLayoutPanel
'
Me.TableLayoutPanel.AutoSize = True
Me.TableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.TableLayoutPanel.ColumnCount = 5
Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle())
Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle())
Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle())
Me.TableLayoutPanel.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel.Controls.Add(Me.InkPanel, 1, 1)
Me.TableLayoutPanel.Controls.Add(Me.CommandReset, 3, 2)
Me.TableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill
Me.TableLayoutPanel.Location = New System.Drawing.Point(0, 0)
Me.TableLayoutPanel.Name = "TableLayoutPanel"
Me.TableLayoutPanel.RowCount = 4
Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TableLayoutPanel.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TableLayoutPanel.Size = New System.Drawing.Size(586, 464)
Me.TableLayoutPanel.TabIndex = 2
'
'InkPanel
'
Me.InkPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.TableLayoutPanel.SetColumnSpan(Me.InkPanel, 3)
Me.InkPanel.Location = New System.Drawing.Point(23, 119)
Me.InkPanel.Name = "InkPanel"
Me.InkPanel.Size = New System.Drawing.Size(540, 180)
Me.InkPanel.TabIndex = 4
Me.InkPanel.TabStop = False
'
'CommandReset
'
Me.CommandReset.Location = New System.Drawing.Point(413, 305)
Me.CommandReset.Name = "CommandReset"
Me.CommandReset.Size = New System.Drawing.Size(150, 40)
Me.CommandReset.TabIndex = 6
Me.CommandReset.Tag = ""
Me.CommandReset.Text = "Zurücksetzen"
Me.CommandReset.UseVisualStyleBackColor = True
'
'InkSignUserControl
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.Controls.Add(Me.TableLayoutPanel)
Me.Name = "InkSignUserControl"
Me.Size = New System.Drawing.Size(586, 464)
Me.TableLayoutPanel.ResumeLayout(False)
CType(Me.InkPanel, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents TableLayoutPanel As System.Windows.Forms.TableLayoutPanel
Private WithEvents InkPanel As System.Windows.Forms.PictureBox
Private WithEvents CommandReset As System.Windows.Forms.Button
End Class
Schritt 3: "CodeBehind"
Anschliessend kopieren die den "CodeBehind" aus Listing 2.
Abbildung 4: "CodeBehind" anzeigen und durch Listing 2 ersetzen
Listing 2: "Code Behind" des Benutzersteuerelementes "InkSignUserControl"
#Region "Imports"
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Runtime.Serialization
#End Region
<Serializable> _
Public Class InkSignUserControl
#Region "Enums"
Enum ImageStateEnum
Empty
Init
Load
End Enum
#End Region
#Region "Event"
Public ValueChangedEventHandler As EventHandler(Of InkSignChangedEventArgs)
Public Custom Event ValueChanged As EventHandler(Of InkSignChangedEventArgs)
AddHandler(ByVal value As EventHandler(Of InkSignChangedEventArgs))
ValueChangedEventHandler = CType(System.Delegate.Combine(ValueChangedEventHandler, value), _
EventHandler(Of InkSignChangedEventArgs))
End AddHandler
RemoveHandler(ByVal value As EventHandler(Of InkSignChangedEventArgs))
ValueChangedEventHandler = CType(System.Delegate.Remove(ValueChangedEventHandler, value), _
EventHandler(Of InkSignChangedEventArgs))
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As InkSignChangedEventArgs)
If Not sender Is Nothing Then
End If
End RaiseEvent
End Event
Protected Overridable Sub TriggerChangeEvent()
Dim localHandler As EventHandler(Of InkSignChangedEventArgs) = ValueChangedEventHandler
If Not localHandler Is Nothing Then
localHandler(Me, New InkSignChangedEventArgs(Me))
End If
End Sub
#End Region
#Region "Members"
Private DrawingMode As Boolean = False
Private bmp As Bitmap = Nothing
Private Plist As List(Of Point)
Private PenColor As Color = Color.Black
Private NewPen As Pen
Private _ImageState As ImageStateEnum = ImageStateEnum.Empty
Public Property ImageState() As ImageStateEnum
Get
Return _ImageState
End Get
Set(ByVal value As ImageStateEnum)
If _ImageState.Equals(value) = False Then
_ImageState = value
ChangeState()
End If
End Set
End Property
Private InterruptEvents As Boolean = False
Private _Value As String = ""
Public Property Value() As String
Get
Return _Value
End Get
Set(ByVal value As String)
If _Value.Equals(value) = False Then
_Value = value
TriggerChangeEvent()
End If
End Set
End Property
#End Region
#Region "Constructors"
Public Sub New()
Dim res As Integer = 0
Try
Me.InitializeComponent()
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
#End Region
#Region "Functions"
Public _
Function ChangeState _
( _
) _
As Integer
Dim res As Integer = 0
Try
Select Case ImageState
Case ImageStateEnum.Empty
CommandReset.Visible = False
Case ImageStateEnum.Init
CommandReset.Visible = True
Case ImageStateEnum.Load
CommandReset.Visible = True
End Select
Catch ex As Exception
'* TODO: Ausnahmebehandlung
Finally
InterruptEvents = False
End Try
Return res
End Function
Public _
Function SetValue _
( _
ByVal Value As String _
) _
As Integer
Dim res As Integer = 0
Try
_Value = Value
ImageLoad()
Catch ex As Exception
res = -1
'* TODO: Ausnahmebehandlung
End Try
Return res
End Function
Public _
Function ImageReset _
( _
) _
As Integer
Dim res As Integer = 0
Try
'* Neues Hintergrundbild erstellen
bmp = New Bitmap(InkPanel.Width, InkPanel.Height)
'* Hintergrund weiss füllen
Using gr = Graphics.FromImage(bmp)
gr.FillRectangle(Brushes.White, 0, 0, InkPanel.Width, InkPanel.Height)
End Using
'* Neues Hintergrundbild ablegen
InkPanel.Image = bmp
Plist = New List(Of Point)
Me.DoubleBuffered = True
ImageState = ImageStateEnum.Init
Catch ex As Exception
res = -1
'* TODO: Ausnahmebehandlung
End Try
Return res
End Function
Public _
Function ImageSave _
( _
) _
As Integer
Dim res As Integer = 0
Try
Dim img As Image = Image.FromHbitmap(CType(InkPanel.Image, Bitmap).GetHbitmap)
Dim stm As MemoryStream = New MemoryStream
img.Save(stm, Imaging.ImageFormat.Png)
Dim fileArray() As Byte = stm.ToArray()
Value = System.Convert.ToBase64String( _
fileArray, _
0, _
fileArray.Length)
ImageState = ImageStateEnum.Load
Catch ex As Exception
res = -1
'* TODO: Ausnahmebehandlung
End Try
Return res
End Function
Public _
Function ImageLoad _
( _
) _
As Integer
Dim res As Integer = 0
Try
If _Value.Length = 0 Then
Exit Try
End If
'* Base64-String in Byte-Array umwandeln
Dim myBytes() As Byte = Nothing
myBytes = System.Convert.FromBase64String(_Value)
'* Byte-Array in Stream einlesen
Dim OutputStream As System.IO.MemoryStream = Nothing
OutputStream = New System.IO.MemoryStream(myBytes)
Dim img As Image = Image.FromStream(OutputStream)
InkPanel.Image = img
ImageState = ImageStateEnum.Load
Catch ex As Exception
res = -1
'* TODO: Ausnahmebehandlung
End Try
Return res
End Function
Private Sub ImageDraw(ByVal g As Graphics)
Try
If Plist.Count > 0 Then
Dim bs As Byte() = New Byte(Plist.Count - 1) {}
bs(0) = CByte(Drawing2D.PathPointType.Start)
For a = 1 To Plist.Count - 1
bs(a) = CByte(Drawing2D.PathPointType.Line)
g.DrawPath(NewPen, New Drawing2D.GraphicsPath(Plist.ToArray, bs))
Next
End If
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
#End Region
#Region "Controls: Events"
#Region "Events"
Private Sub InkPanel_MouseDown(sender As Object, e As MouseEventArgs) Handles InkPanel.MouseDown
Try
If ImageState = ImageStateEnum.Empty Then
ImageReset()
End If
DrawingMode = True
Plist.Add(New Point(e.X, e.Y))
NewPen = New Pen(PenColor, 3)
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
Private Sub InkPanel_MouseUp(sender As Object, e As MouseEventArgs) Handles InkPanel.MouseUp
Try
If DrawingMode = True Then
DrawingMode = False
Using gr = Graphics.FromImage(bmp)
ImageDraw(gr)
gr.Flush()
End Using
Plist.Clear()
InkPanel.Invalidate()
ImageSave()
End If
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles InkPanel.MouseMove
Try
If DrawingMode = True Then
Plist.Add(New Point(e.X, e.Y))
InkPanel.Invalidate()
End If
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
Private Sub InkPanel_MouseLeave(sender As Object, e As EventArgs) Handles InkPanel.MouseLeave
Try
'If DrawingMode = True Then
' DrawingMode = False
'End If
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
Private Sub InkPanel_Paint(sender As Object, e As PaintEventArgs) Handles InkPanel.Paint
Try
If DrawingMode = True Then
ImageDraw(e.Graphics)
End If
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
Private _
Sub CommandButton_Click _
( _
sender As Object, _
e As EventArgs _
) _
Handles _
CommandReset.Click
Dim res As Integer = 0
Try
Select Case CType(sender, Button).Name.ToLower()
Case "CommandSave".ToLower()
res = ImageSave()
Case "CommandReset".ToLower()
res = ImageReset()
Me.Value = ""
End Select
Catch ex As Exception
'* TODO: Ausnahmebehandlung
End Try
End Sub
#End Region
#End Region
End Class
<Serializable> _
Public Class InkSignChangedEventArgs
Inherits System.EventArgs
Private _UserClass As InkSignUserControl = Nothing
Public ReadOnly Property Value As String
Get
If Object.Equals(_UserClass, Nothing) Then
Return ""
End If
Return _UserClass.Value
End Get
End Property
Public _
Sub New _
( _
ByVal UserClass As InkSignUserControl _
)
_UserClass = UserClass
End Sub
End Class
<Serializable> _
Public Class InkSignItem
#Region "Members"
'* Index
Dim _Index As Integer = 0
Public Property Index() As Integer
Get
Return _Index
End Get
Set(ByVal value As Integer)
_Index = value
End Set
End Property
'* Caption
Dim _Caption As String = ""
Public Property Caption() As String
Get
Return _Caption
End Get
Set(ByVal value As String)
_Caption = value
End Set
End Property
#End Region
End Class