Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.07.25;
Скачать: [xml.tar.bz2];

Вниз

Как программно закрыть PopupMenu и отлавливать указатель мыши   Найти похожие ветки 

 
Max_005   (2005-04-19 16:22) [0]

Как программно закрыть TPopupMenu на одном компоненте(на котором оно было открыто) и расскрыть его на другом компаненте при наведении указателя мыши на него(на другой такой же компонент? Может действительно мышиный хук организовать? как это сделать в таком случае?


 
Piter ©   (2005-04-19 16:47) [1]

Лично я ничего не понял


 
alpet ©   (2005-04-19 18:27) [2]

1. Отправить например WM_RBUTTONDOWN означенному компоненту (закроется открытое меню) затем WM_RBUTTONUP.
2.

var hhk: THandle;
function MouseProc (code: Integer;wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
begin
//
result := CallNextHookEx (hhk, Code, wParam, lParam);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
hhk := SetWindowsHookEx (WH_MOUSE, Mouseproc, 0, GetCurrentThreadId);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnhookWindowsHookEx (hhk);
end;


В обработчике надо отправлять сообщения соответствующим компонентам.


 
Max_005   (2005-04-19 21:41) [3]

Я что-то не очень понял... в FormCreate мы создали ловушку а в FormDestroy убили ее... а как мне ее отлавливать? сообщение какоенибудь или как?


 
Marser ©   (2005-04-19 22:31) [4]


> Max_005   (19.04.05 21:41) [3] [Новое
>сообщение][Ответить]
> Я что-то не очень понял... в FormCreate мы создали
> ловушку а в FormDestroy убили ее... а как мне ее
> отлавливать? сообщение какоенибудь или как?

Обрати внимание на эту строчку:

> hhk := SetWindowsHookEx (WH_MOUSE, @Mouseproc, 0,
> GetCurrentThreadId);


 
Marser ©   (2005-04-19 22:32) [5]

Это так называемая функция обратного вызова. Подробности в хелпе.


 
Max_005   (2005-04-19 22:41) [6]

у немя нету этого в справке почемуто...:(


 
Marser ©   (2005-04-19 22:46) [7]

Странно. А у меня на mouseproc выдало:
MouseProc hook procedure is an application-defined or library-defined callback function the system calls whenever an application calls the GetMessage or PeekMessage function and there is a mouse message to be processed.

LRESULT CALLBACK MouseProc(

   int nCode, // hook code
   WPARAM wParam, // message identifier
   LPARAM lParam  // mouse coordinates
  );


Parameters

nCode

Specifies a code the hook procedure uses to determine how to process the message. This parameter can be one of the following values:

Value Meaning
HC_ACTION The wParam and lParam parameters contain information about a mouse message.
HC_NOREMOVE The wParam and lParam parameters contain information about a mouse message, and the mouse message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)


If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx.

wParam

Specifies the identifier of the mouse message.

lParam

Points to a MOUSEHOOKSTRUCT structure.



Return Values

To enable the system to process the message, the return value must be zero. To discard the message, the return value must be a nonzero value.

Remarks

The hook procedure must not install a JournalPlaybackProc callback function.
An application installs the hook procedure by specifying the WH_MOUSE hook type and the address of the hook procedure in a call to the SetWindowsHookEx function.
MouseProc is a placeholder for the application-defined or library-defined function name.

See Also

CallNextHookEx, GetMessage, JournalPlaybackProc, MOUSEHOOKSTRUCT, PeekMessage, SetWindowsHookEx


 
Max_005   (2005-04-19 23:10) [8]

что-то я не разберусь никак... давайте разберем простой пример, чтобы я хоть немного понял: на форме 3-и кнопки, к каждой кнопке привязан свой popup. при нажатии по любой кнопке правой кнопкой мышки расскрывается ее popup. так вот при расскрывшемся меню если навести на другую кнопку как сделать чтобы открылся popup той кнопки, а предыдущей кнопки закрылся? сделал как написал alpet ©   (19.04.05 18:27) [2] но это не работает...


 
Piter ©   (2005-04-20 01:06) [9]

Ты лучше объясни - зачем это надо, чтобы PopUp убиралось при наведении на что либо? В чем удобство???


 
Max_005   (2005-04-20 01:14) [10]

Piter посмотри(в конце): http://delphimaster.net/view/5-1113813834/


 
mgcr ©   (2005-04-20 10:40) [11]

Желающим странного отрубать голову.


 
Grief ©   (2005-04-20 13:07) [12]

Блин, садюга... если на вин апи - просто в while do begin end - главном цикле - отлавливай положение мыши GetCursorPos и сравнивай с координатами кнопки


 
Max_005   (2005-04-20 13:15) [13]

Grief я уже тоже об этом подумывал... а система из за этого не сильно загружаться будет?


 
Max_005   (2005-04-20 13:15) [14]

Удалено модератором


 
Max_005   (2005-04-20 13:15) [15]

Удалено модератором


 
Max_005   (2005-04-20 13:16) [16]

Удалено модератором


 
Max_005   (2005-04-20 13:16) [17]

Удалено модератором


 
Max_005   (2005-04-20 13:18) [18]

Ой извените за много сообщений... у меня все время ошибка выдавалась... а потом сразу СТОЛЬКО сообщений


 
alpet ©   (2005-04-20 13:52) [19]

После вызова TrackPopupMenuEx (а оно вызывается) основной поток будет ждать пока меню не закроется. Так что цикла организовать не удастся (если только не создавать отдельный поток, что уже черезмерно). Так же и сообщения WM_MouseMove не доходят до формы, пока открыто это меню, но они прекрасно ловятся поставленной ловушкой.

Что касается вопроса "Как?"
Вот ориентировочный код, как сделать чтобы меню выскакивало не всегда думай сам.


var hhk: THandle;

function MouseProc (code: Integer;wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
begin
// all operations
form1.OnHookEvent;
result := CallNextHookEx (hhk, Code, wParam, lParam);
end;

var popHandle: THandle; // лучше поместить в TForm1

procedure  TForm1.OnHookEvent; // создать процедуру вручную
var h: THandle;
   p: TPoint;
   btns: array [1..3] of TButton;
   n: Integer;
begin
btns [1] := button1;
btns [2] := button2;
btns [3] := button3;
p := mouse.CursorPos; // screen coord of mouse cursor
h := WindowFromPoint (p); // контрол под курсором мыша
for n := 1 to 3 do
if (h = btns [n].handle) and (popHandle <> h) and
       (popHandle <> 0) then
 begin
  PostMessage (h, WM_RBUTTONDOWN, MK_RBUTTON, p.X + p.Y shl 16);
  PostMessage (h, WM_RBUTTONUP, MK_RBUTTON, p.X + p.Y shl 16);
  popHandle := h;
  btns [n].SetFocus;
  PostMessage (h, WM_CONTEXTMENU, h, p.x + p.y shl 16);
  break;
 end;
end;


 
Max_005   (2005-04-22 21:49) [20]

Что-то не работает...:( Приведу весь код программы:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   PopupMenu1: TPopupMenu;
   PopupMenu2: TPopupMenu;
   PopupMenu3: TPopupMenu;
   N11: TMenuItem;
   N21: TMenuItem;
   N31: TMenuItem;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure OnHookEvent;
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 hhk: THandle;
 popHandle: THandle;

implementation

{$R *.dfm}

function MouseProc (code: Integer;wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
begin
// all operations
Form1.OnHookEvent;
Result := CallNextHookEx (hhk, Code, wParam, lParam);
end;

procedure TForm1.OnHookEvent; // создать процедуру вручную
var h: THandle;
  p: TPoint;
  btns: array [1..3] of TButton;
  n: Integer;
begin
btns [1] := Button1;
btns [2] := Button2;
btns [3] := Button3;
p := mouse.CursorPos; // screen coord of mouse cursor
h := WindowFromPoint (p); // контрол под курсором мыша
for n := 1 to 3 do
if (h = btns [n].handle) and (popHandle <> h) and
      (popHandle <> 0) then
begin
 PostMessage (h, WM_RBUTTONDOWN, MK_RBUTTON, p.X + p.Y shl 16);
 PostMessage (h, WM_RBUTTONUP, MK_RBUTTON, p.X + p.Y shl 16);
 popHandle := h;
 btns [n].SetFocus;
 PostMessage (h, WM_CONTEXTMENU, h, p.x + p.y shl 16);
 break;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
hhk := SetWindowsHookEx (WH_MOUSE, @Mouseproc, 0, GetCurrentThreadId);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
UnhookWindowsHookEx (hhk);
end;

end.


 
Piter ©   (2005-04-22 23:41) [21]

Max_005   (22.04.05 21:49) [20]
Что-то не работает...:(


что значит что-то не работает?


 
Max_005   (2005-04-23 00:17) [22]

ну... не работает... не переключается popup


 
Max_005   (2005-04-23 11:28) [23]

???


 
Piter ©   (2005-04-23 13:49) [24]

Max_005   (23.04.05 0:17) [22]

а ты понимаешь, что делает твой код построчно?


 
Max_005   (2005-04-23 17:39) [25]

неа...


 
Piter ©   (2005-04-23 17:56) [26]

Max_005   (23.04.05 17:39) [25]
неа...


а тебе не приходило в голову разобраться?

Или ты всерьез решил, что так люди и программируют, используя код других людей?


 
Max_005   (2005-04-23 19:14) [27]

Да не, не обижайся! Я просто не понимаю эти хуки, а в книге нету их... Вот я и думал что ктонибудь поможет


 
Piter ©   (2005-04-23 20:25) [28]

Max_005   (23.04.05 19:14) [27]
Да не, не обижайся!


ты мне? Да я не обижаюсь вовсе, мне то что...

Я просто не понимаю эти хуки

ну так разберись

Вот я и думал что ктонибудь поможет

помочь разобраться и написать за тебя исходный код - разные вещи


 
Max_005   (2005-04-23 22:56) [29]

Так почему же всетаки не переключается меню? см. Max_005   (22.04.05 21:49) [20]


 
Piter ©   (2005-04-23 23:56) [30]

Max_005   (23.04.05 22:56) [29]
Так почему же всетаки не переключается меню?


ок, начнем заново, будем учить рекурсию.

Итак, смотри пост [24]


 
Max_005   (2005-04-24 16:57) [31]

Понятно...


 
Димастый   (2005-05-28 22:27) [32]

Вот код который 100% работает у меня с Button:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   PopupMenu1: TPopupMenu;
   PopupMenu2: TPopupMenu;
   PopupMenu3: TPopupMenu;
   N11: TMenuItem;
   N21: TMenuItem;
   N31: TMenuItem;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure PopupMenu1Popup(Sender: TObject);
   procedure PopupMenu2Popup(Sender: TObject);
   procedure PopupMenu3Popup(Sender: TObject);
 private
   procedure OnHookEvent(MouseEvent: WPARAM; Struct: PMouseHookStruct);
 end;

var
 Form1: TForm1;
 HookHandle: THandle;
 CurrentPopupComponent: TComponent;

implementation

{$R *.dfm}

const Magic = $6534; // Random number

function MouseProc(Code: Integer; WParam: WPARAM; Struct: PMouseHookStruct): integer; stdcall;
begin
if Code >= 0 then Form1.OnHookEvent(WParam, Struct);
Result := CallNextHookEx(HookHandle, Code, WParam, LPARAM(Struct));
end;

procedure TForm1.OnHookEvent(MouseEvent: WPARAM; Struct: PMouseHookStruct);
var i: integer;
  MouseWinHandle: THandle;
begin
if (MouseEvent <> WM_MOUSEMOVE) and (Struct <> nil) and (Struct.dwExtraInfo <> Magic) then
  CurrentPopupComponent := nil;
//if (MouseEvent = WM_MOUSEMOVE) then
//  begin
//  if
//  end;
if CurrentPopupComponent = nil then exit;
MouseWinHandle := WindowFromPoint(Struct.pt);
for i := 0 to ComponentCount - 1 do
  if (CurrentPopupComponent <> Components[i]) and (Components[i] is TButton)
     and (TButton(Components[i]).Handle = MouseWinHandle) then
    with TButton(Components[i]), Struct.pt do begin
      CurrentPopupComponent := nil;
      PostMessage (MouseWinHandle, WM_RBUTTONDOWN, MK_RBUTTON, Struct.pt.X + Struct.pt.Y shl 16);
      PostMessage (MouseWinHandle, WM_RBUTTONUP, MK_RBUTTON, Struct.pt.X + Struct.pt.Y shl 16);
      PostMessage (MouseWinHandle, WM_CONTEXTMENU, MouseWinHandle, Struct.pt.X + Struct.pt.Y shl 16);
      //mouse_event(MOUSEEVENTF_RIGHTDOWN, X, Y, 0, Magic);
      //mouse_event(MOUSEEVENTF_RIGHTUP,   X, Y, 0, Magic);
      break;
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
HookHandle := SetWindowsHookEx(WH_MOUSE, @Mouseproc, 0, GetCurrentThreadId);
for i := 0 to ComponentCount - 1 do
  if Components[i] is TButton then
    TButton(Components[i]).PopupMenu := PopupMenu1;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
UnhookWindowsHookEx(HookHandle);
end;

procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
CurrentPopupComponent := TPopupMenu(Sender).PopupComponent;
if TPopupMenu(Sender).PopupComponent is TWinControl then
  TWinControl(TPopupMenu(Sender).PopupComponent).SetFocus;
end;

procedure TForm1.PopupMenu2Popup(Sender: TObject);
begin
CurrentPopupComponent := TPopupMenu(Sender).PopupComponent;
if TPopupMenu(Sender).PopupComponent is TWinControl then
  TWinControl(TPopupMenu(Sender).PopupComponent).SetFocus;
end;

procedure TForm1.PopupMenu3Popup(Sender: TObject);
begin
CurrentPopupComponent := TPopupMenu(Sender).PopupComponent;
if TPopupMenu(Sender).PopupComponent is TWinControl then
  TWinControl(TPopupMenu(Sender).PopupComponent).SetFocus;
end;

end.

Создал тут компонент свой, наследник TCustomControl. При нажатии левой кнопки мыши расскрывается PopupMenu внизу компонента. Вот попробовал применить этот на тот компонент хук(чтобы так же расскрывалось меню на другом таком же компоненте), не работает почему-то...:( В PostMessage поменял WM_RBUTTONDOWN, MK_RBUTTON на WM_LBUTTONDOWN, MK_LBUTTON. Т.е. по идее должно работать... ПРобовал и mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, Magic); mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, Magic); тоже не работает...:( Начал как бы тестировать код, т.е. чтобы в какой-то момент чтонибудь произошло... Вот я заметил что после строк

if (MouseEvent <> WM_MOUSEMOVE) and (Struct <> nil) and (Struct.dwExtraInfo <> Magic) then
CurrentPopupComponent := nil;
if CurrentPopupComponent = nil then exit;

Ничего не происходит... Помогите ктонибудь!


 
Cobalt ©   (2005-05-28 22:55) [33]

2 Димастый   (28.05.05 22:27) [32]

А у меня этот код делает вот что:
раскрывает меню по правой кнопке, и при перемещении мышки от одной кнопки к другой раскрывает меню у новой кнопки.

Процитирую Piter ©   (23.04.05 23:56) [30] :)
ок, начнем заново, будем учить рекурсию.
Итак, смотри пост [24]


 
Димастый   (2005-05-28 23:02) [34]

Да немного да понимаю что делает код... Подскажите где хоть ошибка?


 
Cobalt ©   (2005-05-29 01:59) [35]

Да, кстати, совсем упустил - в чём ошибка-то?
Из поста Димастый   (28.05.05 22:27) [32]
совершенно непонятно - в чём проблема?


 
Димастый   (2005-05-29 03:12) [36]

Cobalt ошибка какая-то в том, что этот код с кнопкой работает, а с моим компонентом нет...


 
Димастый   (2005-05-29 12:41) [37]

Удалено модератором
Примечание: В своей ветке свои вопросы.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.07.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.011 c
3-1118813802
evg00
2005-06-15 09:36
2005.07.25
Проблема с отчетом для БД


14-1120045134
Gorlum
2005-06-29 15:38
2005.07.25
Программировнаие для Windows Сe


9-1113163688
Ford
2005-04-11 00:08
2005.07.25
Движок средствами Delphi через Glsene.


1-1120470318
Ольга
2005-07-04 13:45
2005.07.25
Обрезание текста в MEMO


4-1117269872
zeroo
2005-05-28 12:44
2005.07.25
Kak sdelat TABSTOP?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский