Есть маленькая программка. По замыслу тербуется найти окно с классом "#32770" получить 2 hWnd его дочерних окон класса Edit.
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
[skip]
includelib \masm32\lib\user32.lib
[skip]
EnmProc PROTO :DWORD,:DWORD
EnmChProc PROTO :DWORD,:DWORD
.data
CommandLine dd 0
hInstance dd 0
lpfnListProc dd 0
mainclass db '#32770',0
EditClass db 'Edit',0
hMWin dd 0
hEdt1 dd 0
hEdt2 dd 0
Flg db 0
fstr db 'Окно %lx',0
buf db 60 dup (?)
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine, eax
invoke EnumWindows,ADDR EnmProc,0
mov Flg,0
invoke EnumChildWindows,hMWin,ADDR EnmChProc,0
invoke wsprintf,ADDR buf,ADDR fstr,hEdt1
invoke MessageBox,NULL,ADDR buf,NULL,MB_OK
invoke wsprintf,ADDR buf,ADDR fstr,hEdt2
invoke MessageBox,NULL,ADDR buf,NULL,MB_OK
invoke ExitProcess,eax
EnmProc proc eHandle :DWORD, y :DWORD
LOCAL clName[64] :BYTE
invoke GetClassName,eHandle,ADDR clName,64
invoke lstrcmp,ADDR clName,ADDR mainclass
or eax,eax
jnz NextWin
mov ebx,eHandle
mov hMWin,ebx ;POINT 1
jmp @F
NextWin: mov eax, eHandle
@@: ret
EnmProc endp
EnmChProc proc eHandle :DWORD, y :DWORD
LOCAL clName[64] :BYTE
invoke GetClassName,eHandle,ADDR clName,64
invoke lstrcmp,ADDR clName,ADDR EditClass
or eax,eax
jne NextWin1
lea ebx,hEdt1
xor eax,eax
mov al,Flg
add ebx,eax
mov eax,eHandle
mov [ebx],eax
add Flg,4
NextWin1: mov eax, eHandle
ret
EnmChProc endp
end start
Проблема в следующем: в w2k вызов EnumWindows отрабатывает согласно пророчеству, — в hMWin получаем hwnd окна класса #32770 (в SoftIce оно ещё обозначено как Dialog). А вот EnumChildWindows отрабатывает хз как: SoftIce показывает у окна #32770 10 дочерних, что соответствует действительности. Из них 2 Editа. EnumChildWindows находит только 1 Edit и поиск обрывается.
В Win98 программа вылетает по ошибке "Сбой при обращении к странице памяти в user32.dll". Похоже, что ей не нравится строка POINT 1. Вот только c какого перепуга
Мож кто знает как сие победить?
Здравствуйте, IMFletcher, Вы писали:
IMF>Есть маленькая программка. По замыслу тербуется найти окно с классом "#32770" получить 2 hWnd его дочерних окон класса Edit.
[skipped]
IMF>EnumChildWindows находит только 1 Edit и поиск обрывается.
EnumChildProc Function
To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE.
помоему в EnmChProc ты возвращаешь что то не то. соотв процедура отрабатывает только один раз
IMF>В Win98 программа вылетает по ошибке "Сбой при обращении к странице памяти в user32.dll". Похоже, что ей не нравится строка POINT 1. Вот только c какого перепуга Мож кто знает как сие победить?
отладчиком может попробовать
Что до ebx — то его ведь сохранять нужно, это ж не какой-нибудь ecx
Здравствуйте, kero, Вы писали:
K>Здравствуйте, IMFletcher, Вы писали:
K>Судя по коду — раненько беретесь за такие операторы, как "хз" и "c какого перепуга".
Что не так в коде? Оптимизацией по времени/размеру не занимался. Навалял за пару мин.
K>Есть хелп к MASM32, есть туторы Iczelion-а, возьмите хоть на wasm.ru.
В хелпе по masm описаны только инструкции, макросы и т.п. По поводу руководства Iczelion — курил. Да и сама программа — переделка ихнего EnumWindows. Вот только там всё загоняется в listbox посредством SendMessage, а про то как часть данных сохранить в памяти — 0. Согласитесь, для моих целей создавать окно с listboxом и получать данные из него как-то горбато.
K>И само собой: ПЕРЕЧИТАЙТЕ описания в MSDN EnumWindows, EnumChildWindows.
MSDN полного нет, пользовался win32.hlp от CBuilder 5.0.
Перечитал вдоль и поперёк. Нигде никакого упоминания про недопустимость обращения к памяти. По поводу сохранения регистров там тоже ничего нет. Явно указано, что нужно вернуть 0 или не 0.
К этому моменту уже пытался сохранить нужные данные через стек как непосредственно, так и через передачу адреса, куда нужно выплюнуть данные в lParam (и адрес в стеке, и адрес в сегменте данных), Пробовал использовать неименованный канал (CreatePipe/WriteFile/ReadFile) — под win98 всё пучком, а под винтукеем — что-то не так. При выполнении в нужные поля программа данные не заносила. При отладке посредством td32 получал стопор при записи в канал. Ощущение такое, что W2k ждёт, пока каждое записанное значение будет прочитано, иначе управление в программу не возвращается. Пробовал динамически выделять память (GlobalAlloc), передавать через lParam дескриптор выделенного блока и в Callback функции использовал GlobalLock/GlobalUnlock. Аналогично.
На данный момент сваливаю нужные данные в файл, а потом читаю из файла. Коряво, но работает и под w98, и под w2k.
K>Если же нужны примеры кода с ними — только скажите.
Говорю.
Упрощённая задача: hWnd всех найденных окон сохранены в память. Соообщения использовать нельзя, окон создавать нельзя, файлов создавать нельзя
Здравствуйте, gandalf_g, Вы писали:
_>Здравствуйте, IMFletcher, Вы писали:
IMF>>Есть маленькая программка. По замыслу тербуется найти окно с классом "#32770" получить 2 hWnd его дочерних окон класса Edit.
_>[skipped]
IMF>>EnumChildWindows находит только 1 Edit и поиск обрывается.
_>EnumChildProc Function
_>To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE.
_>помоему в EnmChProc ты возвращаешь что то не то. соотв процедура отрабатывает только один раз
Вообще-то это переделка работющего примера. Если убрать обращение к памяти (команды типа отмеченной в исходном тексте mov [ebx],eax), то окна перечисляются все. Даже в таком виде обращение к EnmChProc происходит несколько раз, до тех пор, пока не найден нужный класс.
IMF>>В Win98 программа вылетает по ошибке "Сбой при обращении к странице памяти в user32.dll". Похоже, что ей не нравится строка POINT 1. Вот только c какого перепуга Мож кто знает как сие победить?
_> отладчиком может попробовать
Отлаживать user32.dll — неблагодарное дело
. А если его не трогать, то при выполнении call EnumWindows получаем "Process terminated", который не содержит даже намёка на причину.