0

我正在使用 AutoIt 自动填写第 3 方 .NET 应用程序中的表单。我无法在日历控件中设置日期。

WindowsForms10.SysDateTimePick32.app.0.378734a根据 AutoIt3 Window Info Tool,该控件属于类类型。最初我只是尝试将控件的文本设置为我想要的日期,但这根本没有做任何事情。

然后我尝试使用_GUICtrlMonthCal_SetCurSel,但是(与_GUI*我尝试的所有功能一样)这也没有做任何事情(包括正确的标题,当我运行它时它没有做任何事情)。

有谁知道我将如何做这件事?

4

1 回答 1

1

您不能使用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...但是更容易假设它在这里使用标准的 WinAPI SYSTEMTIME 结构。这是一个相当多的阅读,但你需要填写其中一个结构。

然后我们可以做出相当安全的假设,即我们想要的消息中的 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 事件,因此如果您尝试自动化的程序中有任何处理程序代码,那么它可能无法完全按照如果用户更改了值,它会。

于 2011-07-06T07:48:03.823 回答