Здравствуйте. Есть у меня прога, довольно часто ей пользуюсь. Ну, неважно что она делает, дело вот в чем: после ее запуска появится окно (окно класса и заголовка не имеет, имеет label с текстом, первые символы текста не меняются), в этом окне нужно нажать кнопку ("OK"). Такое окно не одно будет. Есть еще проблема с другим окном, класс которого известен, а вот у кнопок на этом окне нет загаловка, то есть он равен "". Так вот, чтобы прога работала нужно понажимать на кнопки. Идея: написать программу, которая будет запускать исходную прогу и за меня нажимать на кнопки до тех пор пока не откроется главное окно. Я пробовал реализовать с помощью EnumWindowsProc, EnumChildWindows. Не получилось у меня. Если кто знает как можно решить такую задачу, поделитесь своими мыслями пожалуйста.
В первом посте я сказал, что в окне есть label с текстом (целый абзац). Найдя хэндл этого labela, я бы нашел хэндл родительского окна, на котором находится кнопка которую следует нажать. Проблема в том что не находится хэндл labela. Вот код который по идее должен находить любой элемент с загаловком, начинающимся на "xyz". Не работает с кнопками в программах, работает с загаловками проводника.
offtop информация для начинающих. в отладчиках как Builder, так Visual Studio есть окно Watches и возможность ставить BrakePoint в определенном месте кода. Если намек не понятен, то читай и делай за мной 1. Ставишь BrakePoint на EnumWindowsProc 2. Жмешь выполнить 3. Как свалится открываешь Watches и добавляешь туда строку tv (для контроля значений) 4. По шагам проходишь до if (strcmp...), контролируя значения в строке 5. Тут должно быть уже все ясно, но если не ясно, то это не лечится P.S. Комбинации клавишь и местоположения элементов не привожу т.к. в каждой среде они в разных местах. Ищите! P.P.S. Это надо было сразу попробовать и только потом постить!
To max7C4 Мне не нужна информация для начинающих. Это ничего не даст. Дело в том что, как я понимаю, EnumWindowsProc будет вызываться несколько раз операционоой системой.
ntp Да, видимо, всё таки нужна. В частности, Вам не помешает узнать о существовании MSDN. Там в свою очередь сказано, что EnumWindows перечисляет только top-level окна. Так что для каждого окна, перечисленного EnumWindows, вызывайте EnumChildWindows и проверяйте их заголовки тоже.
To l_inc: Так а я что делаю ? посмотрите мой пример еще раз, там в процедуре есть вызов EnumChildWindows.
ntp Прошу прощения. Невнимательно прочитал. Ну так Вы же возвращаете нуль в своей EnumWindowsProc... так что совет насчёт MSDN всё ещё в силе. И плюс ещё совет... не стоит вкладывать вызов EnumChildWindows в EnumWindowsProc. Все окна дочерние к дочерним и так будут перечислены, а с Вашим вызовом ещё и по много раз.
l_inc Да, действительно, что-то я затупил здесь. Дописал после msgbox'a return FALSE; a в конце процедуры поставил return true; Заработало. Спасибо Вам. А куда же мне его вкладывать ? Ведь при вызове EnumChildWindows надо знать родительский хэндл.
ntp Ну по-хорошему стоит иметь отдельную процедуру для пречисления дочерних окон. Она даже в терминах Microsoft по-другому называется: EnumChildProc. Но если не хочется, есть решения и по-корявее. Например, проверять родителя при каждом входе в EnumWindowsProc и вызывать EnumChildWindows только тогда, когда родителя нет или родителем является рабочий стол. Или при вызове EnumChildWindows передавать особый lParam, который проверять при входе в EnumWindowsProc: если это тот особый lParam, то EnumChildWindows не вызывать.
l_inc Не понял Вас. То есть для того чтобы не перебирать все элементы (окна) в системе, Вы предлагаете вставить проверку на родительское окно до вызова EnumChildWindows? Но что это будет за проверка, ведь имени класса нету - окно диалоговое. Или проверять что-то другое ? Еще созрел вопрос: Как найти хэндлы кнопок без заголовка, на форме с известным классом? Кнопок несколько.
ntp Вообще, я, вроде, указал на кривость способа... так что лучше всё-таки делать отдельную процедуру. А по вопросу... проверка - это сравнение GetAncestor(hwnd, GA_PARENT) с хэндлом рабочего стола и нулём. В случае неравенства (ни тому, ни другому), вызов EnumChildWindows не выполнять. Находите сначала хэндл формы (которую дзеннее называть окном), а потом перечисляете дочерние окна. Если класс дочернего окна - Button, то очередная кнопка найдена. Но вообще это уже вопрос из разряда самостоятельного поиска по MSDN.
1. Для GetAncestor(hwnd, GA_PARENT) мне приходится подрубать winuser.h, в котором находит ошибку, если #include <winuser.h> находится выше #include <windows.h>. Если ниже то пишет что не знает что такое GetAncestor. Не знаю что и думать. 2. Я конечно все это понимаю... быть может я неправильно сформулировал вопрос. Кнопки будут находится при перечислении в постоянном порядке или каждый раз в разном?
а еще не нужна информация для начинающих. вот сделал бы и сразу стало бы все понятно! ну или как говорится берите MSDN и идите учить матчасть!
max7C4 Что сделал бы сразу?? Свою ошибку я по глупости допустил, а не по незнанию MSDN. Вы бы лучше вместо того чтобы оффтопить и давать недальновидные советы говорили по сабжу. Хотя нет, лучше идите в свой раздел для начинающих и оффтопте там.
Возникла проблема: Как только нахожу кнопку, посылаю ей SendMessage(hwnd, BM_CLICK,0,0); Для обычных кнопок это канает, но на тех кнопках, которых мне нужно не работает. Вообще они сделаны не как стандартные, прямоугольные, а как картинка на которую нужно щелкать. Пробовал послать WM_KEYDOWN - безрезультатно. Может кто знает каким способом еще можно программно нажать на кнопку?
ntp > они сделаны не как стандартные ... каким способом еще можно программно нажать на кнопку Для начала надо определить класс окна.
To q_q Ммм... возможно вы не читали здесь все посты, но класс окна на котором расположена кнопка и класс кнопки мне известны.