После осуществления сабжа, кнопка перестала нажиматься. В новой функции обработки событий кнопки я пока ничего не делаю, а сразу вызываю старый обработчик следующим образом: push lParam push wParam push uMsg push hButton push OldButtonProc call CallWindowProcA Возможно, я должен самостоятельно обрабатывать какие-то сообщения, а не сразу вызывать стандартный обработчик? Подскажите, что я делаю не правильно.
Ошибка была в том, что я обнулял содержимое регистра eax перед выходом из своего обработчика, чего делать не следовало (видимо значение, возвращаемое функцией CallWindowProc где-то используется).
Возврат нуля означает, что все операции по нажатию кнопки (в т.ч. и перерисовка нажатого и отжатого положения) выполнены и больше ничего делать не надо. Поэтому, увидев ноль в еах, виндовс решила, что все уже сделано, суетиться не надо И пропустила стадию перерисовки кнопки. Возврат любого ненулевого значения заставит её перерисовать нажатое и отжатое состояние (т.е. "выполнить нажатие"). Это значение не обязательно должно быть от CallWindowProc. Можно например сделать or eax,-1 перед возвратом.
Я тут на днях решил поюзать MFC. Сделал карту сообщения OnLButtonClick для кнопки. Так там произошла такая же штука. Похоже что в Microsoft тоже это сделали сабкласингом.
cresta Если возвращаю -1 или любое другое значение отличное от CallWindowProc(которая возвращает 0xF), то кнопка по прежнему не перерисовывается. Или в разных версиях винды по разному?
Чтобы перерисовывалась, нужно либо вызывать CallWindowProc в теле твоего обработчика, либо там же самому руками нарисовать нажатое и отжатое состояние. И после этого можно возвращать -1. Например так (правда не кнопка, а edit, но принцип тот же) Код (Text): if(uMsg == WM_CHAR ) { CallWindowProc(lpWProcEditName, hwnd, uMsg, wParam, lParam); find_match(hwnd); //тут можно делать ещё что-нибудь return 123456789; //тут можно вернуть что угодно //в т.ч. и 0 и -1, т.к. дефолтные //действия уже сделаны по CallWindowProc }
Хм.. в том то и дело, что я вызываю CallWindowProc именно в теле своего обработчика: Код (Text): button_wndproc proc push ebp mov ebp,esp hButton equ dword ptr [ebp+08h] uMsg equ dword ptr [ebp+0Ch] wParam equ dword ptr [ebp+10h] lParam equ dword ptr [ebp+14h] mov eax,uMsg cmp uMsg,WM_MOUSEMOVE jne @default ; мой обработчик WM_MOUSEMOVE @default: push lParam push wParam push uMsg push hButton push OldButtonProc call CallWindowProcA leave or eax,-1 ; из-за этого кнопка не перерисовывается ret 16 button_wndproc endp Не работает. Кстати, команда return в C возвращает значение обязательно через eax?
А с чего это вдруг по WM_MOUSEMOVE должна перерисовываться кнопка? Кто так решил? По умолчанию кнопка перерисовывается по WM_LBUTTONDOWN и WM_LBUTTONUP. Или может ты прицепил манифест, и хочешь отловить прорисовку рамки по моменту, когда мышь зашла на кнопку? Да.
А с чего это вдруг по WM_MOUSEMOVE должна перерисовываться кнопка? Не должна, но я ведь после своего обработчика сразу вызываю стандартный. Который почему-то перестает обрабатывать WM_LBUTTONDOWN и WM_LBUTTONUP и кнопка не отрисовывается, если в eaх лежит не то, что нужно.
Вот посмотри в аттаче пример, после WM_MOUSEMOVE и возвращения из него 123456 в eax (как впрочем и -1 и любого другого значения), остальные сообщения нормально обрабатываются, и перерисовываются как нажатое, так и отжатое состояние кнопки. Чем этот пример отличается от твоего - смотри сам. Работает как с манифестом, так и без него. Обрати внимание: ни по одному из обрабатываемых сообщений не возвращается то, что получено от CallWindowProc. Тем не менее на все сообщения реагирует как положено. _2027899617__mouse_move.zip
Причина похоже в том, что значение в eax важно не для всех сообщений. Действительно, в твоем исходнике все сообщения WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSELEAVE обрабатываются корректно с произвольным значением eax. Но если добавить or eax,-1 для остальных сообщений, которые ты не обрабатываешь (после последнего вызова CallWindowProc в твоем обработчике), то получается мой случай
Естественно Оно важно для тех, которые не были упомянуты или обработаны в твоем обработчике. Если ты не обрабатываешь какие-то сообщения, то кто-то же должен их обработать Возврат нуля сигнализирует, что ты сам не обрабатывал, и CallWindowProc для их обработки тоже не вызывал. Поэтому ноль нужен. Если же ты сам рисовал вручную или вызвал для этого CallWindowProc, то необходимый минимум действий по сообщениям уже сделан, и возвращать можно что угодно.
Оно важно для тех, которые не были упомянуты или обработаны в твоем обработчике. Вот этого я и не могу понять Почему если некоторое сообщение обрабатывается в моем обработчике явно, например так: Код (Text): mov eax,uMsg .if (eax==WM_PAINT) invoke CallWindowProc,OldButtonProc,hWin,uMsg,wParam,lParam or eax,-1 ret Такой код работает, независимо, что находится в eax. В случае, если тот же WM_PAINT обрабатывается таким образом (неявно): Код (Text): .else invoke CallWindowProc,OldButtonProc,hWin,uMsg,wParam,lParam ; uMSG==WM_PAINT or eax,-1 ret То из-за этого никакие сообщения не обрабатываются и кнопка не перерисовывается. Фактически, в обоих случаях происходит вызов функции CallWindowProc с параметром uMsg==WM_PAINT. В чем разница между этими двумя вызовами? Если же ты сам рисовал вручную или вызвал для этого CallWindowProc, то необходимый минимум действий по сообщениям уже сделан, и возвращать можно что угодно. В примере выше, я вызываю CallWindowProc для сообщения WM_PAINT, изменяю eax и кнопка не отрисовывается. Хотя по идее минимум действий сделан т.к. я вызвал CallWindowProc, которая должна отослать это сообщине стандартному обработчику. Ничего не понимаю (с) Колобки
Код (Text): ; .elseif (eax==WM_PAINT) ; invoke CallWindowProc,prev_butt_proc,hWin,uMsg,wParam,lParam ; ;invoke SetWindowText,hButton,SADD("BUTTON") ; mov eax,123456 ; ret .else ;все остальные сообщения (в т.ч. WM_PAINT) invoke CallWindowProc,prev_butt_proc,hWin,uMsg,wParam,lParam .if (uMsg==WM_PAINT) mov eax,-11112222 .endif ret .endif Вот так рисует А так как ты последний раз показывал, на все подряд сообщения возвращается -1. Но не на все подряд сообщения можно возвращать произвольный результат в eax. Есть сообщения, для которых возвращаемое значение из WndProc должно быть определенным (и которое влияет на рисование кнопки). Какое из сообщений - можешь поэкспериментировать и поискать путём подбора строки .if (uMsg==WM_PAINT). Но это не WM_PAINT.