William J. Wright Ответов: 2

Как обновить datetimepicker с помощью sendmessage


Я пытаюсь написать программу, которая будет отправлять информацию сторонней программе с помощью SendMessage. До сих пор мне удавалось работать с полями со списком и текстовыми полями, но когда дело доходит до обновления элемента управления DateTimePicker, я натыкаюсь на кирпичную стену.

При использовании SendMessage в DateTimePicker он, по-видимому, вообще не изменяет дату/данные. Кто-нибудь еще сталкивался с этой проблемой?

Я действительно хочу, чтобы вы знали, что я работаю над этим уже несколько дней и гуглил все, что знаю, но так и не нашел решения. В общем, я звоню:

Что я уже пробовал:

Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByRef hwnd As Int32, ByRef wMsg As Int32, ByRef wParam As Int32, ByRef lParam As SYSTEMTIME) As Int32

    <StructLayout(LayoutKind.Sequential)> Structure SYSTEMTIME
        Public wYear As Int16
        Public wMonth As Int16
        Public wDayOfWeek As Int16
        Public wDay As Int16
        Public wHour As Int16
        Public wMinute As Int16
        Public wSecond As Int16
        Public wMilliseconds As Int16
    End Structure

    Public Const DTM_FIRST As Int32 = &H1000
    Public Const DTM_GETSYSTEMTIME As Int32 = (DTM_FIRST + 1)
    Public Const DTM_SETSYSTEMTIME As Int32 = (DTM_FIRST + 2)

    Public Shared Sub SendMessageDateToControl(ControlHandle As Integer, Message As Date)

        Dim hwnd, datehwnd As Integer
        Dim gettime As New SYSTEMTIME
        Dim changetime As New SYSTEMTIME
        changetime.wDay = Message.Day
        changetime.wMonth = Message.Month
        changetime.wYear = Message.Year
        SendMessage(ControlHandle, DTM_GETSYSTEMTIME, 0, gettime)
        SendMessage(ControlHandle, DTM_SETSYSTEMTIME, 0, changetime)

    End Sub

    Public Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
        Dim ChildrenList As New List(Of IntPtr)
        Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
        Try
            EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
        Finally
            If ListHandle.IsAllocated Then ListHandle.Free()
        End Try
        Return ChildrenList.ToArray
    End Function

    Public Shared Function GetWindowHandle(WindowCaption As String) As Integer
        Return FindWindow(Nothing, WindowCaption)
    End Function

    Private Sub GetControlInfo()

        ' Get a Window's Handle
        Dim hWnd = WindowControlHandleInfo.GetWindowHandle(TextBoxWindowName.Text)


        If (hWnd = 0) Then
            MessageBox.Show("Control Window Was Not Found", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
            Return
        End If

        ' Get all the Control Handles for the Forms Child
        Dim rtnChildWindows As IntPtr() = WindowControlHandleInfo.GetChildWindows(hWnd)

        If rtnChildWindows.Length = 0 Then Return ' No Controls were Found

        myControlInfo = New List(Of WindowControlInfo)
        Dim zOrder As Integer = 0

        ' Loop Through Each Child Window and add it to the myControlInfo
        For Each i As Integer In rtnChildWindows

            ' Get the Class Name
            Dim strClassName As String = CStr(WindowControlHandleInfo.GetClassName(i))
            ' Get the Controls Caption
            Dim ControlText As String = WindowControlHandleInfo.GetMesasgeFromControl(i)

            myControlInfo.Add(New WindowControlInfo(strClassName, zOrder, i, ControlText))
            zOrder += 1

        Next

    End Sub

    Private Sub ButtonSendDateToDateTimePicker_Click(sender As Object, e As EventArgs) Handles ButtonSendDateToDateTimePicker.Click
        WindowControlHandleInfo.SendMessageDateToControl(TextBoxHandelDateTimePicker.Text, "02/01/1991")
    End Sub


Я тоже пробовал:

    Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As String) As Int32
Public Const WM_SETTEXT As Int32 = &HC
Public Const WM_GETTEXT As Int32 = &HD
SendMessage(chwnd, WM_SETTEXT, 0, "02/01/1991")


Ни один из них не изменяет значение DateTimePicker.

2 Ответов

Рейтинг:
2

Richard MacCutchan

Public Const WM_GETTEXT As Int32 = &HD
SendMessage(chwnd, WM_SETTEXT, 0, "02/01/1991")

Предполагая, что в приведенном выше примере есть опечатка, WM_SETTEXT имеет значение x0C.


Рейтинг:
0

William J. Wright

Это опечатка. Так и должно было быть

Public Const WM_SETTEXT As Int32 = &HC

Я обновил свой первоначальный вопрос


Richard MacCutchan

Где вы устанавливаете ручку chwnd?

William J. Wright

Он фактически задается в функции в качестве параметра. Я уверен, что chwnd является правильным, потому что я могу изменить другие элементы управления в форме. Я также подтвердил дескриптор с помощью Spy++.

Richard MacCutchan

Боюсь, что это не дает никакого намека на то, что может произойти.

William J. Wright

Ричард, Спасибо тебе за помощь, это действительно ценно. Я снова обновил свой вопрос и надеюсь, что он сделает его более ясным.

Сначала я запускаю функцию GetControlInfo. Я передаю заголовок Windows в качестве параметра, который я вручную ввел в TextBoxWindowName.Текстовое поле. Это возвращает дескриптор окна, в котором расположены элементы управления.

Оттуда я получаю все дескрипторы управления, вызывая функцию GetChildWindows, передавая Гендель Windows, где расположены элементы управления. Я возвращаю эти результаты обратно в переменную rtnChildWindows. Именно здесь я храню управляющие гендели (для всех элементов управления, расположенных на форме).

Как только у меня есть все дескрипторы управления, я вызываю функцию SendMessageDateToControl, передавая дескриптор управления DateTimePicker и дату, которую я хочу отобразить.

У меня есть тонна кода, если мне нужно больше, пожалуйста, дайте мне знать!!!

Richard MacCutchan

Как определить дескриптор, который принадлежит элементу управления DateTimePicker? Вы должны быть в состоянии проверить это в небольшом примере программы, создав форму, которая содержит только DateTimePicker и запустив свой код против этого.

William J. Wright

Это делается с помощью функции GetChildWindows. Я передаю Родительский дескриптор окна в качестве параметра, чтобы получить дочерние дескрипторы управления.

Я создал две тестовые программы. Вы можете посмотреть их здесь, Если вам интересно. https://drive.google.com/drive/folders/1PbGK4yOaiyP5kM6te-J8fNY2Tf6GNiPN?usp=sharing

Вы бы запустили WindowsApp1 для имитации стороннего приложения, а затем запустили WindowsApp2 в качестве тестового приложения, над которым я работаю. Как только вы запустите WindowsApp1. Все, что вам нужно сделать, это запустить WindowsApp2. Он автоматически заполнит все дескрипторы из клиентского приложения в DatagridView WindowsApp2. Затем я использую zOrder, чтобы получить дескриптор управления и попытаться обновить данные.

Пожалуйста, не судите мой плохой код, это всего лишь тестовые приложения.

William J. Wright

Ладно, мне придется отойти от этого вопроса. Хотя я думаю, что есть ответ, я думаю, что это слишком сложно. Я собираюсь искать альтернативное решение. Спасибо Вам за тех, кто внес свой вклад.