GUICtrlMonthCal *関数を使用できない理由は、月/カレンダーコントロールを扱っていないためです。.NETにはそれらがありますが、この場合は代わりにDateTimePickerです。
DateTimePickersのドロップダウンにはMonthCalenderがありますが、ドロップダウンをクリックすると作成されるように見えるため、直接制御することは困難です。代わりに、プログラムが小さなテストケースを設定して値を設定するとどうなるかを調べました...これらは私が見つけたメッセージです。
<00001> 00090572 S WM_GETTEXTLENGTH
<00002> 00090572 R WM_GETTEXTLENGTH cch:12
<00003> 00090572 S WM_GETTEXT cchTextMax:26 lpszText:05E8D51C
<00004> 00090572 R WM_GETTEXT cchCopied:12 lpszText:05E8D51C ("0")
<00005> 00090572 S message:0x1002 [User-defined:WM_USER+3074] wParam:00000000 lParam:01F6A2A8
<00006> 00090572 R message:0x1002 [User-defined:WM_USER+3074] lResult:00000001
<00007> 00090572 S WM_GETTEXTLENGTH
<00008> 00090572 R WM_GETTEXTLENGTH cch:12
<00009> 00090572 S WM_GETTEXT cchTextMax:26 lpszText:05E8D51C
<00010> 00090572 R WM_GETTEXT cchCopied:12 lpszText:05E8D51C ("0")
<00011> 00090572 P WM_PAINT hdc:00000000
<00012> 00090572 S WM_ERASEBKGND hdc:54010EE3
<00013> 00090572 R WM_ERASEBKGND fErased:True
最も興味深いのはユーザー定義のメッセージです。これは、コントロールが通常、それらに固有のメッセージを取得する方法です。0x1002がデータを設定することが正しいと仮定した場合、まだ実行する必要があるのは、lParamの意味を確認することだけです。値をDateTimeオブジェクトとして設定するため、これは注意が必要な場合があります。
次に行うことは、ildasmをチェックしてSystem.Windows.Forms.DateTimePicker :: set_Valueを確認することです。これにより、.NETがどのように機能するかについて多くのことがわかります...さらに調査と更新を行います。この郵便受け。
パート2:わかりました。set_Valueの逆アセンブルは、私が言ったことを実行します... DateTimeToSysTimeを使用して、DateTimeを「システム」時間と呼ばれるものに変換します...公開されていませんが、大まかに何をしているのかを確認できます。 ILDasm ...しかし、ここでは標準のWinAPISYSTEMTIME構造を使用していると単純に想定する方が簡単です。かなりの読み物ですが、これらの構造体の1つを埋める必要があります。
次に、必要なメッセージ内のlParamがSYSTEMTIME構造体へのポインターであるというかなり安全な仮定を立てることができます...テストして投稿を更新します:)
パート3:エキサイティングなパートです...実際に機能させる。最初の問題は、SendMessageを使用してアプリケーション間でポインターを移動できないことです。そのため、他のプログラムでバッファーを作成するには、少し余分なコードが必要です。それ以外は、私が期待したとおりに機能しました。
#Include <GuiMonthCal.au3> ; $tagSYSTEMTIME is defined in here.
Local $tSI = DllStructCreate($tagSYSTEMTIME)
Local $hControl = ControlGetHandle("Date/Time Picker", "", "[NAME:ExampleDateTimePicker]")
If @error Then Exit 0 * MsgBox(16, "Error", "Demo control not found.")
; Fill the structure to current date/time using GetLocalTime
DllCall("kernel32.dll", "none", "GetLocalTime", "ptr", DllStructGetPtr($tSI))
If @error Then Exit 0 * MsgBox(16, "Error", "GetLocalTime failed.")
; Change the year
DllStructSetData($tSI, "Year", 2005)
; The struct needs to be in the process memory, so it's a bit of a workaround.
Local $tMemMap
Local $pMemory = _MemInit($hControl, DllStructGetSize($tSI), $tMemMap)
_MemWrite($tMemMap, DllStructGetPtr($tSI))
$iRet = _SendMessage($hControl, 0x1002, 0, $pMemory, 0, "wparam", "ptr")
_MemFree($tMemMap)
これを実行すると、日付部分が2005に変更されます。唯一の問題は、OnValueChangedイベントがトリガーされないことです。したがって、自動化しようとしているプログラムにそのハンドラーコードがある場合、正確に機能しない可能性があります。ユーザーが値を変更した場合になります。