WinFormsを使用しているため、WinForm DateTimePicker
コントロールは、ネイティブの共通DateTimePickerコントロールのラッパーに過ぎません。アプリケーションが入力文字列を解析できるように、派生コントロールを作成できます。これは、コントロールのDTS_APPCANPARSEスタイルを設定することによって行われます。このスタイルは、コントロールのCreateParamsプロパティをオーバーライドして設定します。
DTS_APPCANPARSEスタイルが設定されている場合、ネイティブコントロールはDTN_USERSTRING通知をコントロールに送信します。このメッセージは、コントロールのWndProc
メソッドで受信されました。
以下に示すコードの大部分は、使用されるネイティブ構造の定義です。この例で使用されている解析関数(TryParse_NMDATETIMESTRING)は、そのカルチャ設定がこの形式をサポートしているため、Thread cultureを "de-DE"に変更することによってDateTime.TryParseメソッドを "dd.MM.yyyy"の形式に再利用します。任意の構文解析ロジックを定義できます。
Imports System.Runtime.InteropServices
Imports System.Globalization
Public Class DateTimePickerCustomParse : Inherits DateTimePicker
Protected Overrides ReadOnly Property CreateParams As CreateParams
Get
Const DTS_APPCANPARSE As Int32 = &H10
Dim cp As CreateParams = MyBase.CreateParams
cp.Style = cp.Style Or DTS_APPCANPARSE
Return cp
End Get
End Property
#Region "Native Structures"
Structure NMDATETIMESTRING
Public nmhdr As NMHDR
Public pszUserString As IntPtr
Public st As SYSTEMTIME
Public dwFlags As GDT
End Structure
Public Enum GDT
GDT_ERROR = -1
GDT_VALID = 0
GDT_NONE = 1
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure SYSTEMTIME
Public wYear As Short
Public wMonth As Short
Public wDayOfWeek As Short
Public wDay As Short
Public wHour As Short
Public wMinute As Short
Public wSecond As Short
Public wMilliseconds As Short
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, Pack:=1)> _
Public Class NMHDR
Public hwndFrom As IntPtr = IntPtr.Zero
Public idFrom As Integer = 0
Public code As Integer = 0
End Class
#End Region
Private Shared Function TryParse_NMDATETIMESTRING(ByRef nmDTS As NMDATETIMESTRING) As Boolean
Dim ret As Boolean
Dim enteredDate As String = Marshal.PtrToStringUni(nmDTS.pszUserString)
Dim savedThreadCulture As CultureInfo = Threading.Thread.CurrentThread.CurrentCulture
Try
Threading.Thread.CurrentThread.CurrentCulture = New CultureInfo("de-DE")
Dim dt As DateTime
If DateTime.TryParse(enteredDate, dt) Then
nmDTS.dwFlags = GDT.GDT_VALID
nmDTS.st = DateTimeToSYSTEMTIME(dt)
ret = True
Else
nmDTS.dwFlags = GDT.GDT_ERROR
End If
Finally
Threading.Thread.CurrentThread.CurrentCulture = savedThreadCulture
End Try
Return ret
End Function
Private Shared Function DateTimeToSYSTEMTIME(dt As DateTime) As SYSTEMTIME
Dim ret As New SYSTEMTIME
ret.wYear = CShort(dt.Year)
ret.wDay = CShort(dt.Day)
ret.wMonth = CShort(dt.Month)
ret.wDayOfWeek = CShort(dt.DayOfWeek)
ret.wHour = CShort(dt.Hour)
ret.wMinute = CShort(dt.Minute)
ret.wSecond = CShort(dt.Second)
ret.wMilliseconds = CShort(dt.Millisecond)
Return ret
End Function
Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_NOTIFY As Int32 = &H4E
Const WM_REFLECT_NOTIFY As Int32 = WM_NOTIFY + &H2000
Const DTN_FIRST As Int32 = -740
Const DTN_USERSTRINGW As Int32 = (DTN_FIRST - 5)
If m.Msg = WM_REFLECT_NOTIFY OrElse m.Msg = WM_NOTIFY Then
Dim hdr As New NMHDR
Marshal.PtrToStructure(m.LParam, hdr)
If hdr.code = DTN_USERSTRINGW Then
Dim nmDTS As NMDATETIMESTRING = Marshal.PtrToStructure(Of NMDATETIMESTRING)(m.LParam)
If TryParse_NMDATETIMESTRING(nmDTS) Then
Marshal.StructureToPtr(nmDTS, m.LParam, True)
Exit Sub
End If
End If
End If
MyBase.WndProc(m)
End Sub
End Class
編集: ありDTS_APPCANPARSEスタイルを使用して約特に厄介な事があり、それはそれはコントロールを残すTab
キーの使用を排除します。これは、datetimepicker class - with dts_appcanparse style - can't tab outに記載されています。フォーカスを失うか、Enter
キーを押すと、入力されたテキストが検証のために送信されます。ただし、Enter
キーでは、DTPがキーボードを離れることなく集中しています。さらに、Tab
をコントロールに追加すると、標準のDTPのように動作します。 F2
キーを押すと、編集モードになり、テキスト全体が選択されます。上で定義した制御でこれらの問題に対処するには、以下を追加することができます。
あなたはこれで
WndProc
方法を交換する必要があります
Public Property MoveNextOnEnterKey As Boolean = True
Public Property SelectAllOnEnter As Boolean = True
Protected Overrides Sub OnEnter(e As EventArgs)
MyBase.OnEnter(e)
If SelectAllOnEnter Then SendKeys.Send("{F2}")
End Sub
Private Sub MoveNext()
Me.Parent.SelectNextControl(Me, True, True, True, True)
End Sub
:DDMMYYYY` `上` MMDDYYYY`を使用する利点が何であるかを尋ね
Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_NOTIFY As Int32 = &H4E
Const WM_REFLECT_NOTIFY As Int32 = WM_NOTIFY + &H2000
Const DTN_FIRST As Int32 = -740
Const DTN_USERSTRINGW As Int32 = (DTN_FIRST - 5)
If m.Msg = WM_REFLECT_NOTIFY OrElse m.Msg = WM_NOTIFY Then
Dim hdr As New NMHDR
Marshal.PtrToStructure(m.LParam, hdr)
If hdr.code = DTN_USERSTRINGW Then
Dim nmDTS As NMDATETIMESTRING = Marshal.PtrToStructure(Of NMDATETIMESTRING)(m.LParam)
If TryParse_NMDATETIMESTRING(nmDTS) Then
Marshal.StructureToPtr(nmDTS, m.LParam, True)
If MoveNextOnEnterKey Then
Me.BeginInvoke(New Action(AddressOf MoveNext))
End If
Exit Sub
End If
End If
End If
MyBase.WndProc(m)
End Sub
誰もがこの質問を指摘しなければなりません。 –
この「利点」は、ここでは表示された形式で日付を使用するネイティブな方法があるので、ここではかなり使用できません。 – user1697111
私は知っている、ここでは同じ日付形式を使用し、同じ "問題"があります。 –