Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.50/16: Рейтинг темы: голосов - 16, средняя оценка - 4.50
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
1

Как узнать состояние CheckBox в чужом окне

21.09.2014, 12:47. Показов 3233. Ответов 38
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет! Подскажите, плз, как программно определить наличие галочки в чужом CheckBox
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.09.2014, 12:47
Ответы с готовыми решениями:

Как изменить состояние многих CheckBox на форме в один прием
Товарищи, наверное нубский вопрос, но если у меня есть 25 чекбоксов (0-24 соответственно), то как...

Символ под курсором в чужом окне
день добрый, спецам. сразу прошу прощения за возможно ламерский вопрос. а вопрос вот в чём - надо...

Как узнать состояние привода CD-ROM
Здравствуйте Гуру! Подскажите плз, как узнать состояние (открыт/закрыт) CD-ROM?

Как при помощи VB можно узнать состояние соединения в данный момент?
Помогите, кто может… Исходные данные: в сети (50 компов) есть почтовый сервер (под NT 4.0) c...

38
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
21.09.2014, 13:16 2
Сам чекбокс нашел? Получить можно так по хендлу
Visual Basic
1
state = SendMessage(chkHwnd, BM_GETCHECK, 0, ByVal 0&)
1
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
21.09.2014, 14:18  [ТС] 3
Хендл-то знаю, вот только может это не совсем CheckBox ?! Класс окна = WindowsForms10.BUTTON.app.0.bb8560_r16_ad1... Или BM_GETCHECK надо декларировать
У меня и с галкой и без галки ноль показывает
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
21.09.2014, 14:19 4
Цитата Сообщение от morgann55 Посмотреть сообщение
Или BM_GETCHECK надо декларировать
Естественно
0
Эксперт WindowsАвтор FAQ
17996 / 7697 / 892
Регистрация: 25.12.2011
Сообщений: 11,471
Записей в блоге: 16
21.09.2014, 15:54 5
morgann55, получается вот так:

Visual Basic
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
Option Explicit
 
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 hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
 
Const BM_GETCHECK As Long = &HF0&
 
Private Sub Command1_Click()
    Dim hwnd        As Long
    Dim hCtl        As Long
    Dim State       As Long
    Dim ButtonText  As String
    Dim WndClass    As String
 
    WndClass = "ThunderFormDC" ' класс чужого окна
    ButtonText = "myCheckBox"  ' Надпись чекбокса, если нужно идентифицировать конкретный из множества
 
    hwnd = FindWindow(WndClass, vbNullString)
    If hwnd <> 0 Then
        hCtl = FindWindowEx(hwnd, 0, "ThunderCheckBox", ButtonText)
        If hCtl <> 0 Then
            State = SendMessage(hCtl, BM_GETCHECK, 0&, ByVal 0&)
        End If
    End If
    
    MsgBox State
End Sub
Это для Чекбокса от VB6. Для VS2010 смотри какое имя класса у чекбокса и окна.
Можешь воспользоваться утилиткой ниже (не забудь запустить с теми же правами, что и подопытный).
Вложения
Тип файла: zip WinDowzer.zip (7.8 Кб, 18 просмотров)
1
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
21.09.2014, 15:56  [ТС] 6
Вроде всё на местах:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const BM_GETCHECK = &HF0
Dim RetVal&, Te2(35) As String, Ko2(35, 2) As Long
'-------------------------------------
'нашёл hwnd
Ko2(21, 0) = hwnd
'в Таймере
'.............
For i = 1 To 35
If Te2(i) = "WindowsForms10.BUTTON.app.0.bb8560_r16_ad1" Then
RetVal = SendMessage(Ko2(i, 0), BM_GETCHECK, 0, ByVal 0&): 'здесь делал Останов - хендл и BM_GETCHECK содержат значения
If RetVal <> 0 Then Stop
End If
Next i
'............
Галки ставлю - никакой реакции
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
22.09.2014, 01:29 7
Лучший ответ Сообщение было отмечено morgann55 как решение

Решение

Ты хоть проверял LastDllError?
Скинь приложение сюда. Возможно дотнетовский чекбокс не поддерживает это сообщение, тогда смотри функцию AccessibleObjectFromWindow.

Добавлено через 6 часов 25 минут
Немного исследовав .NET контролы-кнопки (спасибо insite2012), и почитав в интернете по ним информацию пришел к выводу что нельзя получить их состояние посредством BM_GETCHECK. Написал функцию для получения состояния кнопки (флажка):
Visual Basic
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
Option Explicit
 
Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, riid As Any, ByRef ppvObject As Object) As Long
Private Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function DispCallFunc Lib "oleaut32" (ByVal PPV As IUnknown, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, ByVal paCNT As Long, paTypes As Any, paValues As Any, ByRef fuReturn As Variant) As Long
 
Private Const IID_IAccessible       As String = "{618736e0-3c3d-11cf-810c-00aa00389b71}"
Private Const OBJID_CLIENT          As Long = -4
Private Const CC_STDCALL            As Long = 4
Private Const STATE_SYSTEM_CHECKED  As Long = &H10
 
' Ïîëó÷èòü ñîñòîÿíèå ôëàæêà .NET - êîíòðîëà
Private Function GetCheckState(ByVal hwnd As Long) As Long
    Dim iid(15)     As Byte
    Dim IAccessible As IUnknown
    
    IIDFromString StrPtr(IID_IAccessible), iid(0)
    
    AccessibleObjectFromWindow hwnd, OBJID_CLIENT, iid(0), IAccessible
     
    If IAccessibleGet_accState(IAccessible, 0) And STATE_SYSTEM_CHECKED Then
        GetCheckState = vbChecked
    Else
        GetCheckState = vbUnchecked
    End If
    
End Function
 
Private Function IAccessibleGet_accState(obj As IUnknown, VarID As Variant) As Variant
    Dim types() As Integer, param() As Long
    ReDim types(1): ReDim param(1)
    types(0) = vbVariant: types(1) = vbLong
    param(0) = VarPtr(VarID): param(1) = VarPtr(IAccessibleGet_accState): IAccessibleGet_accState = param(1)
    Call DispCallFunc(obj, 56, CC_STDCALL, vbLong, 2, types(0), param(0), 0)
End Function
2
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
22.09.2014, 05:21  [ТС] 8
Я уже нашёл решение через графику, но решил опробовать ЧудоТехники: скопировал только Декларацию, нажал F5 и Редактор тут же сломался Окно проги стало открываться где-то под ПанельюЗадач и я вижу только ЕГО тень когда кликаю значок на ПанелиЗадач Чего бы это могло такое произойти и как теперь с этим бороться??
Может у кого было подобное...
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
22.09.2014, 08:43 9
morgann55, ты мой пример пробовал?
0
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
22.09.2014, 19:29  [ТС] 10
Цитата Сообщение от The trick Посмотреть сообщение
morgann55, ты мой пример пробовал?
Ну конечно ЕГО Что же я ещё мог копировать...
Редактор-то мне переустанавливать??
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
22.09.2014, 19:34 11
morgann55, я не понимаю тебя
0
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
22.09.2014, 20:39  [ТС] 12
Я взял вот это
Visual Basic
1
2
3
4
5
6
7
8
Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, riid As Any, ByRef ppvObject As Object) As Long
Private Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function DispCallFunc Lib "oleaut32" (ByVal PPV As IUnknown, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, ByVal paCNT As Long, paTypes As Any, paValues As Any, ByRef fuReturn As Variant) As Long
 
Private Const IID_IAccessible       As String = "{618736e0-3c3d-11cf-810c-00aa00389b71}"
Private Const OBJID_CLIENT          As Long = -4
Private Const CC_STDCALL            As Long = 4
Private Const STATE_SYSTEM_CHECKED  As Long = &H10
вставил в Декларации своей проги и сразу проверил примет ли прога эти строки - нажал F5 и Редактор слетел... Форма1 оказывается где-то ниже ПанелиЗадач... Остановил, удалил эти строки - тоже самое, перезагрузился полностью - без изменений...
Так надеюсь понятно
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
22.09.2014, 21:37 13
Вот посмотрите проект и приложение скомпилированное. Нужно зажать кнопку на окне и перетащить на чекбокс.
Вложения
Тип файла: rar morgann55.rar (6.5 Кб, 25 просмотров)
1
1365 / 207 / 37
Регистрация: 09.02.2012
Сообщений: 745
23.09.2014, 00:02  [ТС] 14
The trick, твоя функция отлично работает! Спасибо!!
А с Редактором я сам лопухнулся: у меня было самое большое разрешение и Форма стояла внизу экрана (чтоб видеть и ЧужоеПриложение и Реакцию моей проги), а потом я переключил разрешение обратно на маленькое и Форма оказалась ниже экрана (ведь её Top был больше ВысотыЭкрана)
Всё, вопрос исчерпан.
0
185 / 183 / 31
Регистрация: 11.10.2016
Сообщений: 599
05.01.2022, 15:46 15
The trick, а подскажите, пожалуйста, как адаптировать ваш код для 64-битных систем. Я пробовал так:
декларация
Visual Basic
1
2
3
Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hwnd As LongPtr, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
Declare PtrSafe Function IIDFromString Lib "ole32" (ByVal lpsz As LongPtr, lpiid As Any) As Long
Declare PtrSafe Function DispCallFunc Lib "OleAut32.dll" (ByVal pvInstance As LongPtr, ByVal oVft As LongPtr, ByVal cc As Integer, ByVal vtReturn As Integer, ByVal cActuals As Long, ByRef prgvt As Integer, ByRef prgpvarg As LongPtr, ByRef pvargResult As Variant) As Long
и сам код:
Visual Basic
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
Private Function GetCheckState(ByVal hwnd As LongPtr) As Long
Const OBJID_CLIENT = -4&
Const STATE_SYSTEM_CHECKED = &H10
Dim iid(15)     As Byte
Dim IAccessible As IUnknown, IID_IAccessible$
    
    IID_IAccessible = "{618736e0-3c3d-11cf-810c-00aa00389b71}"
    IIDFromString StrPtr(IID_IAccessible), iid(0)
    
    AccessibleObjectFromWindow hwnd, OBJID_CLIENT, iid(0), IAccessible
     
    If IAccessibleGet_accState(IAccessible, 0) And STATE_SYSTEM_CHECKED Then
        GetCheckState = True
    Else
        GetCheckState = False
    End If
    
End Function
 
Private Function IAccessibleGet_accState(obj As IUnknown, VarID As Variant) As Variant
    Dim types() As Integer, param() As LongPtr, VarRtn As Variant
    ReDim types(1): ReDim param(1)
    types(0) = vbVariant: types(1) = vbLong
    param(0) = VarPtr(VarID): param(1) = VarPtr(IAccessibleGet_accState): IAccessibleGet_accState = param(1)
    Call DispCallFunc(ObjPtr(obj), 56, CC_STDCALL, vbLong, 2, types(0), param(0), VarRtn)
    IAccessibleGet_accState = VarRtn
End Function
Видимо, что-то где-то упустил или намудрил с типами данных. Может, objptr не нужен, может еще что.
IIDFromString работает и возвращает какие-то символы в массиве iid, а вот дальше - всё по нулям
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
05.01.2022, 15:52 16
Что возвращает AccessibleObjectFromWindow?
0
185 / 183 / 31
Регистрация: 11.10.2016
Сообщений: 599
05.01.2022, 16:17 17
до вызова AccessibleObjectFromWindow переменная IAccessible - неопределена, после вызова - окно Locals показывает <No Variables>

Добавлено через 10 минут
AccessibleObjectFromWindow, вроде, тоже корректно отрабатывает, Err.LastDLLError возвращает ноль, а IAccessible, видимо, на что-то указывает, т.е. она не Is Nothing, как было ранее.
0
Модератор
9726 / 3687 / 871
Регистрация: 22.02.2013
Сообщений: 5,532
Записей в блоге: 78
05.01.2022, 16:47 18
_shark, у меня пока нет времени вникать, но вижу что тут во-первых, types(1) = vbLong нужно заменить на ptr-тип, к примеру vbString; во-вторых, смещение 56 нужно увеличить в 2 раза т.к. размер указателя на 64 битах = 8 байтам. Также нужно тестировать все возвращаемые значения.
0
185 / 183 / 31
Регистрация: 11.10.2016
Сообщений: 599
05.01.2022, 16:55 19
ок, спасибо, буду ковырять дальше. Просто подумал, что вам за прошедшее время, возможно, приходилось использовать такой участок кода в своих программах на новых 64-битных системах, ну и, чем черт не шутит, где-нибудь в закромах остался нужный мне код и корректные декларации
0
10 / 6 / 0
Регистрация: 06.11.2017
Сообщений: 21
11.01.2022, 15:54 20
_shark, а обычными BM_GETCHECK сообщениями не работает? Зачем эти усложнения с COM?
0
11.01.2022, 15:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.01.2022, 15:54
Помогаю со студенческими работами здесь

Узнать текст ToolTip-a контрола в чужом приложении ?
Чужое приложение (CorelDRAW), в нём есть до десятка контролов класса - &quot;Edit&quot;, причем...

Как узнать позицию курсора в текстовом окне?
Подскажите пожалуйста кто знает, как узнать позицию курсора в текстовом окне. Заранее благодарна...

Как узнать текущее положение курсора в текстовом окне ???
Смотрите сабж.. нужно позарез ))

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru