С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
0 / 0 / 0
Регистрация: 27.01.2016
Сообщений: 4

Получить доступ к Listview сторонней программы через SendMessage

27.01.2016, 14:56. Показов 1904. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.
Проблема заключается в следующем:
в сеть включено МФУ, на котором нужно сканировать. Для этого устанавливается программка Sharp Button Manager U, в настройках которой я указываю, что при нажатии на кнопку на самом аппарате, он должен отсканировать и сохранить файл в определённой папке у меня на компе. Но при нажатии на эту кнопку он не сразу сканирует, а отправляет запрос на комп через что нужно сканировать (скрин прикрепил). Бегать после каждой страницы - это глупо. Поэтому я решил написать программку, которая будет постоянно проверять или появился такой запрос на компе, и если да, то она сама должна выбрать нужный пункт из списка (а именно Sharp Button Manager U) и нажать на кнопку ОК.
С оглашением функций, констант и определением самого окна всё понятно:

VB.NET
1
2
3
4
5
6
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function FindWindowEx& Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpClassName As String, ByVal lpWindowName As String)
 
Fhwnd = FindWindow(vbNullString, "SHARP AR-5516N")
Fhwnd2 = FindWindowEx(Fhwnd, 0, "SysListView32", vbNullString)
А как дальше через функцию SendMessage найти и выделить нужный мне пункт, какие параметры нужно использовать, не знаю.
Может кто-нибудь помочь?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.01.2016, 14:56
Ответы с готовыми решениями:

Получить логин из сторонней программы
Здравствуйте, расскажите как вытащить логин из сторонней программы? в моем случае ею является novell. Очень надо, помогите плиз.

Как получить скриншот сторонней программы?
Вобщем дело такое. Есть программа, которая работает сама по себе (назовём её 1 программой). И есть программа 2, которую пишу я и которая...

Закрытие сторонней программы через определенное время
Может кто нибудь скинуть рабочий пример таймера, который закрывает стороннее приложение?

10
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
27.01.2016, 15:05
elLoco, а разве в настройках сканера или Button Manager нет возможности выбрать программу по-умолчанию?
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
27.01.2016, 15:15
elLoco, я может быть сейчас буду не прав, это настраивается в настройках самого ButtonManager.
Вот страница из мануала:
Миниатюры
Получить доступ к Listview сторонней программы через SendMessage  
0
 Аватар для vova2112
147 / 135 / 34
Регистрация: 28.02.2014
Сообщений: 165
27.01.2016, 15:18
Наверно после того как выбрал окно надо вычислить последовательность каких нажатий клавиш на клавиатуре выделят нужный элемент в SysListView32, и попробовать отправить эту последовательность через "SendKeys":
VB.NET
1
2
3
SendKeys.Send("{Tab}")
SendKeys.Send("{DOWN}")
SendKeys.Send("{ENTER}")
Только всё это может не сработать на другой системе, где кол-во элементов у SysListView32 изменится.
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
27.01.2016, 15:28
Обратите внимание на БЛОК #2 и его описание.

Добавлено через 4 минуты
Ну а если уж не терпится попрактиковаться в программировании, то vova2112 подсказывает... определите что окно появилось и оно на переднем плане (Get/SetForegroundWindow) и отправьте последовательно нажатия клавиш... полжно получиться.

Добавлено через 4 минуты
А убедиться в правильности посылки этих команд можете простой проверхой присутствия данного окна, если оно закрытось - значит запущено сканирование.
2
0 / 0 / 0
Регистрация: 27.01.2016
Сообщений: 4
27.01.2016, 16:54  [ТС]
Я читал этот мануал. Мне не нужно сканировать через программу на компе (хотя я и такие настройки в ButtonManager пробовал), мне нужно сразу сохранить скан в pdf в определённой папке. И в ButtonManager я все нужные мне параметры выставил. Но комп всё-равно выдаёт запрос.

Добавлено через 6 минут
Цитата Сообщение от vova2112 Посмотреть сообщение
Наверно после того как выбрал окно надо вычислить последовательность каких нажатий клавиш на клавиатуре выделят нужный элемент в SysListView32
с учётом возможности изменения окна запроса на разных системах просто перебирать стрелками и Табом - это не выход. Нужно получить доступ к SysListView32, найти конкретный текст и выделить нужную строку. Доступ к списку я вроде как получил, а вот с выделением строки проблема - не могу понять какие параметры нужно использовать в функции SendMessage.
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
27.01.2016, 18:26
elLoco, тогда давайте начнем с того, что функции у вас объявлены не корректно для VB.NET
такое объявление подойдет для VB6...

Вот корректное, но не совсем правильное объявление для VB.NET, но возвращающее правильноые значения:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Imports System.Runtime.InteropServices
 
Public Declare Function SendMessage Lib "user32.DLL" Alias "SendMessageA" ( _
    ByVal hwnd As Integer, _
    ByVal wMsg As Integer, _
    ByVal wParam As Integer, _
    <MarshalAs(UnmanagedType.AsAny)> ByVal lParam As Object) As Integer
 
Public Declare Function FindWindow Lib "user32.DLL" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Integer
 
Public Declare Function FindWindowEx Lib "user32.DLL" Alias "FindWindowExA" ( _
    ByVal hWnd1 As Integer, _
    ByVal hWnd2 As Integer, _
    ByVal lpsz1 As String, _
    ByVal lpsz2 As String) As Integer
0
0 / 0 / 0
Регистрация: 27.01.2016
Сообщений: 4
28.01.2016, 11:14  [ТС]
Цитата Сообщение от Yury Komar Посмотреть сообщение
elLoco, тогда давайте начнем с того, что функции у вас объявлены не корректно для VB.NET
такое объявление подойдет для VB6...
Вот корректное, но не совсем правильное объявление для VB.NET, но возвращающее правильноые значения:
мой вариант тоже рабочий, не думаю, что это принципиально. но всё-равно спасибо за корректировку. Однако что дальше?
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
28.01.2016, 11:19
elLoco, ваш вариант SendMessage был неверен, и в каких-то моментах мог вас подвести.
Что дальше? Ну SendMessage посылает команды компоненту, нужно разобраться, какие именно команды вы хотите ему послать...
0
0 / 0 / 0
Регистрация: 27.01.2016
Сообщений: 4
28.01.2016, 13:32  [ТС]
Цитата Сообщение от Yury Komar Посмотреть сообщение
elLoco, ваш вариант SendMessage был неверен, и в каких-то моментах мог вас подвести.
Что дальше? Ну SendMessage посылает команды компоненту, нужно разобраться, какие именно команды вы хотите ему послать...
команд всего две:
1. выделить в списке Sharp Button Manager U.
2. нажать ОК
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4356 / 3426 / 512
Регистрация: 27.01.2014
Сообщений: 6,257
28.01.2016, 16:05
Нажать ОК - пока отложим, это мелочи...
Вот что гугл говорит по этому поводу:
Сообщения компоненту ListView


Думаю вам нужно вот это сообщение:
LVM_SETITEMSTATE

Добавлено через 1 час 41 минуту
elLoco, нашел кое какой пример, но пишут что он не работает должным образом, доработайте и должно получиться:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Public Const LVM_FIRST As Int32 = &H1000
Public Const LVM_SETITEMSTATE = (LVM_FIRST + 43)
Public Const LVIF_STATE = &H8
Public Const LVIS_SELECTED As Int32 = &H2
 
Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)
 
Private Const LVM_GETITEMSTATE = (LVM_FIRST + 44)
 
Public Structure LV_ITEM
Dim Mask As Int32
Dim iItem As Int32
Dim iSubItem As Int32
Dim State As Int32
Dim StateMask As Int32
Dim pszText As Int32
Dim cchTextMax As Int32
Dim iImage As Int32
Dim lParam As Int32
Dim iIndent As Int32
End Structure
 
Private Declare Function SendMessage Lib "user32.dll" _
Alias "SendMessageW" ( _
ByVal hwnd As IntPtr, _
ByVal wMsg As Int32, _
ByVal wParam As Int32, _
ByRef lParam As LV_ITEM _
) As Int32
 
Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button7.Click
Dim h As IntPtr = IntPtr.op_Explicit(&H350818)
 
Dim i As Integer = SendMessage(h, LVM_GETITEMCOUNT,
IntPtr.Zero, IntPtr.Zero) ' this works with different sendmessage
declaration
 
Dim li As LV_ITEM
With li
.Mask = LVIF_STATE
' To select item
.State = LVIS_SELECTED
' To deselect item
' .state = 0
.StateMask = LVIS_SELECTED
End With
SendMessage(h, LVM_SETITEMSTATE, 1, li)
End Sub
Добавлено через 11 минут
А вот этот код заверяют как РАБОЧИЙ.
Разберите его и подгоните под себя. Думаю его можно укоротить.
Он выделяет по индексу, но получить индекс можно получив список всех элементов списка и отправить тот индекс, что соответствует нужному тексту (вобщем думаю такой инфы будет достаточно "ЗА ГЛАЗА"):
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
Imports System.Runtime.InteropServices
Imports System.Text
 
Public Class Form1
    Private Const LVM_FIRST As UInteger = &H1000
    Private Const LVM_GETITEMCOUNT As UInteger = (LVM_FIRST + 4)
    Private Const LVM_SETITEM As UInteger = (LVM_FIRST + 6)
    Private Const LVM_SETITEMSTATE As UInteger = (LVM_FIRST + 43)
    Private Const LVIS_SELECTED As UInteger = &H2
    Private Const LVIF_STATE As UInteger = &H8
 
 
    Private Const MEM_COMMIT As UInteger = &H1000
    Private Const MEM_RELEASE As UInteger = &H8000
    Private Const PAGE_READWRITE As UInteger = &H4
 
    Private Const PROCESS_VM_READ As UInteger = &H10
    Private Const PROCESS_VM_WRITE As UInteger = &H20
    Private Const PROCESS_VM_OPERATION As UInteger = &H8
 
    <DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean
    End Function
    <DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
    End Function
    <DllImport("user32.dll", SetLastError:=True)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
    End Function
    <DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
    End Function
    <DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEM, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("user32.dll", SetLastError:=True)> Private Shared Function GetWindowThreadProcessId(<InAttribute()> ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
    End Function
    <DllImport("user32.dll", SetLastError:=True)> Private Shared Function FindWindowExW(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, <InAttribute(), MarshalAs(UnmanagedType.LPTStr)> ByVal lpszClass As String, <InAttribute(), MarshalAs(UnmanagedType.LPTStr)> ByVal lpszWindow As String) As IntPtr
    End Function
 
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Public Structure LV_ITEM
        Public mask As UInteger
        Public iItem As Integer
        Public iSubItem As Integer
        Public state As UInteger
        Public stateMask As UInteger
        Public pszText As IntPtr
        Public cchTextMax As Integer
        Public iImage As Integer
        Public lParam As IntPtr
        Public iIndent As Integer
        Public iGroupId As Integer
        Public cColumns As Integer
        Public puColumns As IntPtr
        Public piColFmt As IntPtr
        Public iGroup As Integer
    End Structure
 
 
    Private Sub Button_SelectItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_SelectItem.Click
        SelectItem(1, True) 'Sets the 2nd item in the listview to the Selected state if 2 items exist in the listview
    End Sub
 
    Private Sub Button_UnSelectItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_UnSelectItem.Click
        SelectItem(1, False) 'Sets the 2nd item in the listview to the Un-Selected state if 2 items exist in the listview
    End Sub
 
    Private Sub SelectItem(ByVal iIndex As Integer, ByVal selState As Boolean)
 
        Dim hLstVw As IntPtr = GetListViewHandle() 'Get the listview`s handle
 
        If Not hLstVw.Equals(IntPtr.Zero) Then 'Check if the listview handle was found
 
            Dim itemCount As Integer = SendMessage(hLstVw, LVM_GETITEMCOUNT, 0, IntPtr.Zero)
            If itemCount < iIndex Then Exit Sub 'If the item index to be set is higher than the listview`s item count then exit the sub now
 
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(hLstVw, procId) 'Get the listview`s process Id
 
            'Open the process id and set access rights to read and write to the process`s memory
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
 
            Dim lvi As New LV_ITEM 'Create a new LV_ITEM structure set to select or unselect the item depending on the selState parameter
            lvi.mask = LVIF_STATE
            lvi.stateMask = LVIS_SELECTED
            If selState Then
                lvi.state = &HF
            Else
                lvi.state = 0
            End If
 
            'Reserve space in the processes memory and write the new LV_ITEM structure`s data to it
            Dim LvItemPtr As IntPtr = VirtualAllocEx(hProc, IntPtr.Zero, Marshal.SizeOf(lvi), MEM_COMMIT, PAGE_READWRITE)
            WriteProcessMemory(hProc, LvItemPtr, lvi, Marshal.SizeOf(lvi), 0)
 
            SendMessage(hLstVw, LVM_SETITEMSTATE, iIndex, LvItemPtr) 'Send the message to set the items state
 
            VirtualFreeEx(hProc, LvItemPtr, 0, MEM_RELEASE) 'Release the processes memory used for the LV_ITEM structure`s data
            CloseHandle(hProc)
        Else
            MessageBox.Show("ListView handle not found.")
        End If
    End Sub
 
    'This is the function i used to get the SysListView32 handle of an explorer window
    Private Function GetListViewHandle() As IntPtr
        Dim hParent As IntPtr = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "CabinetWClass", Nothing)
        If Not hParent.Equals(IntPtr.Zero) Then
            Dim hChld_1 As IntPtr = FindWindowExW(hParent, IntPtr.Zero, "SHELLDLL_DefView", Nothing)
            If Not hChld_1.Equals(IntPtr.Zero) Then
                Dim hChld_2 As IntPtr = FindWindowExW(hChld_1, IntPtr.Zero, "DUIViewWndClassName", Nothing)
                If Not hChld_2.Equals(IntPtr.Zero) Then
                    Dim hChld_3 As IntPtr = FindWindowExW(hChld_2, IntPtr.Zero, "DirectUIHWND", Nothing)
                    If Not hChld_3.Equals(IntPtr.Zero) Then
                        Dim hChld_4 As IntPtr = FindWindowExW(hChld_3, IntPtr.Zero, "CtrlNotifySink", Nothing)
                        If Not hChld_4.Equals(IntPtr.Zero) Then
                            Dim hChld_5 As IntPtr = FindWindowExW(hChld_4, IntPtr.Zero, "SysListView32", "FolderView")
                            If Not hChld_5.Equals(IntPtr.Zero) Then
                                Return hChld_5 'Return the handle to the SysListView32
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return IntPtr.Zero
    End Function
End Class
Добавлено через 13 минут

Не по теме:

Надеюсь как закончите программку, исходник мы увидим? Уж больно интересно да может кому пригодится :)

3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.01.2016, 16:05
Помогаю со студенческими работами здесь

Поиск текста в окне сторонней программы через VBA
Добрый вечер, Подскажите, как осуществить поиск текста в окне стороннего процесса (хэндл окна этой сторонней программы известен)?...

Креш при запуске сторонней программы через Shell(WinAPI)
public static extern string Shell(IntPtr HWND, string operation, string file, string parameters, string directory, int showcmd); ...

Получить доступ к ListView диспетчера задач
Пытаюсь получить ListView диспетчера задач в свою, но как это сделать? Нахожу HWND самого ListView, а дальше что? Как получить...

Получить доступ к TextView внутри ListView
Привет, форумчане! Сначала кратко(потребуется код выложу, просто нужно понять принцип): Есть Активити на базе ЛистАктивити, в ней ЛистВью...

Как получить доступ к информации определённой ячейки ListView
Здраствуйте, скажите пожайлуста, как получит доступ к информации определённой ячейки ListView? Хочу считать информацию например из колонки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru