Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Обработка WM_LBUTTONDOWN


Автор: Dmitry_177 23.11.2006, 22:57
Как мне обрабатывать сообщение WM_LBUTTONDOWN по нажатию на кнопке? Т.е. нужно определить на какой кнопке была нажата левая кнопка мыши, попробовал так:
Код

function WindowProc(Window: HWnd; Message: Word; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
...
WM_LBUTTONDOWN: begin
                       if Window = hButton then MessageBox(0, '1', '1', 0);
                     end;

не работает, где hButton это хендл кнопки

Автор: Sunvas 23.11.2006, 23:43
Цитата(Dmitry_177 @  23.11.2006,  22:57 Найти цитируемый пост)
Как мне обрабатывать сообщение WM_LBUTTONDOWN по нажатию на кнопке?

Создать наследника и в нем ловить это сообщение.

Цитата(Dmitry_177 @  23.11.2006,  22:57 Найти цитируемый пост)
Т.е. нужно определить на какой кнопке была нажата левая кнопка мыши

А не проще ли воспользовать событием onmouseup/onmousedow? Там в переменной Button храниться такая инфа.

Автор: Dmitry_177 23.11.2006, 23:59
Я на одном API делаю, без VCL

Автор: ArtemRubtsov 24.11.2006, 04:50
можно координаты компонентов брать на форме и исходя из этого сделать вывод где была нажата кнопка

но лучше всего создать обработчика onmousedown для кнопки

Если есть кнопка (пусть даже созданная при старте приложения) значит у нее есть onmousedown по умолчанию, просто нужно его описать и будет счастье
а еще у кнопки есть OnClick    :)

Автор: bems 24.11.2006, 08:53
обрабатывай не WM_LBUTTONDOWN, а WM_COMMAND. В lParam будет хэндл кнопки

Автор: Dmitry_177 24.11.2006, 10:12
Почитал про WM_COMMAND, там про клавиши ускорителя, что это? И про пункты меню...

Автор: bems 24.11.2006, 10:32
Цитата(Dmitry_177 @  24.11.2006,  10:12 Найти цитируемый пост)
клавиши ускорителя, что это? 
гарячие комбинации

а еще там про контролы, например кнопки

Добавлено @ 10:38 
если HIWORD(wParam)>1 то это точно контрол. 
Но можно просто сравнить HWND(lParam) с хэндлом кнопки и если совпадает - вызвать твой обработчик

Автор: Dmitry_177 24.11.2006, 10:53
А если нужно еще WM_LBUTTONUP обрабатывать?

Добавлено @ 10:58 
А еще попробовал я WM_COMMAND обрабатывать, у меня почему-то он срабатывает на двойном щелчке мыши а не на одном..

Автор: bems 24.11.2006, 11:14
вот так вроде должно устроить  smile 
Код

program Hellow;
uses
  windows,
  messages;

const sClassName='HellowWndClassName';
      sWndName='Hellow';

var wnd,hwndButton:HWND;OriginalBtnProc:pointer;

 function BtnProc(wnd:HWND;uMsg:DWORD;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
 begin
 case uMsg of
  WM_LBUTTONDOWN:SetWindowText(wnd,':)');
    WM_LBUTTONUP:SetWindowText(wnd,'Click me');
 end;
 result:=CallWindowProc(OriginalBtnProc,wnd,uMsg,wParam,lParam);
 end;

 function SubclassButton:pointer;
 begin
 result:=pointer(SetWindowLong(hwndButton,GWL_WNDPROC,integer(@BtnProc)));
 end;

 procedure UnsubclassButton;
 begin
 SetWindowLong(hwndButton,GWL_WNDPROC,integer(OriginalBtnProc));
 end;

 procedure WMCommand(hwndControl:HWND);
 begin
 if hwndControl=hwndButton
    then MessageBox(wnd,'Hellow, world!','Clicked',MB_OK);
 end;

 function WndProc(wnd:HWND;uMsg:DWORD;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
 begin
 result:=DefWindowProc(wnd,uMsg,wParam,lParam);
 case uMsg of
    WM_CLOSE:begin
             UnsubclassButton;
             PostQuitMessage(0);
             end;
  WM_COMMAND:WMCommand(HWND(lParam));
 end;
 end;

 function CreateWnd:HWND;
 var clss:WNDCLASS;
 begin
 clss.style:=CS_CLASSDC;
 clss.lpfnWndProc:=@WndProc;
 clss.cbClsExtra:=0;
 clss.cbWndExtra:=0;
 clss.hInstance:=hInstance;
 clss.hIcon:=0;
 clss.hCursor:=LoadCursor(0,IDC_ARROW);
 clss.hbrBackground:=GetStockObject(GRAY_BRUSH);
 clss.lpszMenuName:=nil;
 clss.lpszClassName:=sClassName;
 RegisterClass(clss);
 result:=CreateWindow(sClassName,sWndName,WS_OVERLAPPEDWINDOW or WS_VISIBLE,
                      integer(CW_USEDEFAULT),integer(CW_USEDEFAULT),200,200,0,0,hInstance,nil);
 hwndButton:=CreateWindow('BUTTON','Click me',
                          WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON or BS_CENTER or BS_TEXT or BS_VCENTER,
                      50,50,100,50,result,0,hInstance,nil);
 end;

var msg:TMSG;
begin
wnd:=CreateWnd;
OriginalBtnProc:=SubclassButton;
while GetMessage(msg,0,0,0) do
 begin
 TranslateMessage(msg);
 DispatchMessage(msg);
 end;
end.

Автор: Dmitry_177 24.11.2006, 11:27
Я так и сделал с WM_COMMAND...

Да, мне именно нажатие и отпускание обрабатывать нужно...

Автор: bems 24.11.2006, 11:38
отредактировал сообщение, теперь вроде то что надо

Добавлено @ 11:43 
WM_COMMAND можно и выкинуть  smile 

Автор: Dmitry_177 24.11.2006, 12:09
Спасибо большое!

Автор: BUGOR 24.11.2006, 13:08
Тебе координаты мыши в момент клика известны? Известны. Тогда юзай WindowFromPoint, он вернёт нэндл объекта над которым находится курсор.

Автор: bems 24.11.2006, 13:51
В родительском окне координаты не известны - WM_LBUTTONDOWN приходит кнопке, а не родителю.
Если пользоваться GetCursorPos то нужно знать хотя бы момент нажатия

Автор: Dmitry_177 24.11.2006, 13:58
Кстати насчет WindowFromPoint, она определяет хендл любого окна, даже чужого? А есть какаянибудь типа этой функции, которая определяет хендл только в моем приложении, а если в точке находится чужое окно, то например вернет 0?

Автор: bems 24.11.2006, 14:33
вот
Код

function MyWindowFromPoint(Point:TPoint):HWND;
var PID:DWORD;
begin
result:=WindowFromPoint(Point);
GetWindowThreadProcessID(result,@PID);
if PID<>GetCurrentProcessID
   then result:=0;
end;

Автор: Dmitry_177 24.11.2006, 14:38
Спасибо еще раз большое!!!

Автор: Dmitry_177 30.11.2006, 02:45
В главной процедуре обрабатываю сообщение WM_NCHITTEST,
Код

     WM_NCHITTEST: begin
                     if Window = hWindow then
                       if GetAsyncKeyState(VK_LBUTTON) < 0 then
                         Result := HTCAPTION;
                   end;

И не доходит сообщение WM_LBUTTONDOWN до кнопки, сделав его обработку сабклассингом... Что делать?

Автор: bems 30.11.2006, 09:16
вероятно это потому что ты не вызываешь DefWindowProc. В каких случаях вызывать, а в каких - нет, зависит от того, какого ты хочешь добиться эффекта. Например если ты не хочешь, чтобы окно перетаскивалось за кнопку, то Result := HTCAPTION делай только если курсор не на кнопке, а в противном случае result:=DefWindowProc(...

не очень понятно, как должно по твоему себя вести окно...

Автор: bems 30.11.2006, 16:25
если начинаешь строить из себя заголовок окна, то смотри WM_NCLBUTTONDOWN и WM_ENTERSIZEMOVE

Автор: Dmitry_177 30.11.2006, 19:21
Дело в том что сообщение WM_LBUTTONDOWN вообще не доходит до кнопки, т.е. она не нажимается...

Автор: bems 1.12.2006, 00:04
Цитата(Dmitry_177 @  30.11.2006,  02:45 Найти цитируемый пост)
 if Window = hWindow then
                       if GetAsyncKeyState(VK_LBUTTON) < 0 then
                         Result := HTCAPTION;

что такое Window и hWindow? если Result := HTCAPTION может произойти и при нажатии на кнопку, то этого и следует ожидать - вместь нажатия окно начнет перетаскиваться. А если по остальному коду выходит, что кнопка исключена в этой ситуации, то нужно предусмотреть для нее вызов DefWindowProc

Автор: Dmitry_177 1.12.2006, 04:03
Window: HWND это первый парамент WindowProc, а hWindow это хендл главного окна

Автор: bems 1.12.2006, 11:52
не воспроизводится. Может проблема в чем-то другом? дай больше кода

Автор: Dmitry_177 3.12.2006, 18:14
Я разобрался что было не так.. Я сабклассинг делал чуть-чуть неправильно...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)