how to catch the mouse right button event in TMenuitem

Dear sir,

i want to write a new class TCatchMouseMenuItem which is inherited from TMenuitem. TCatchMouseMenuitem could catch the right mouse button event. please help me

thanks

Tuan Le
letuanleAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

robert_marquardtCommented:
TMenu bases on a Windows menu.
The problem is that Windows menues use their own private window and window handler function.
No easy way to penetrate.
Try to do some tricks with WM_ENTERMENULOOP, WM_EXITMENULOOP and WM_ENTERIDLE.

Menu Messages
The following messages are used with menus.
 
WM_COMMAND  
WM_CONTEXTMENU  
WM_DRAWITEM  
WM_ENTERMENULOOP  
WM_EXITMENULOOP  
WM_INITMENU  
WM_INITMENUPOPUP  
WM_MEASUREITEM  
WM_MENUCHAR  
WM_MENUSELECT  
WM_NEXTMENU  
WM_SYSCOMMAND  
0
letuanleAuthor Commented:
thanks for your answer. I wonder

 TControl = class(TComponent)
 TMenuItem = class(TComponent)

but TControl can catch rightmouse event, TMenuitem is not

i have already read the implementation of TControl and TMenuitem in menus.pas and controls.pas but i can not understand where is the code which TControl can do it

please explain me more, thank you very much

Tuan Le
0
GloomyFriarCommented:
The code looks like that:


procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;

procedure TControl.WMLButtonDown(var Message: TWMLButtonDown);
begin
  SendCancelMode(Self);
  inherited;
  if csCaptureMouse in ControlStyle then MouseCapture := True;
  if csClickEvents in ControlStyle then Include(FControlState, csClicked);
  DoMouseDown(Message, mbLeft, []);
end;

procedure TControl.DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
  Shift: TShiftState);
begin
  if not (csNoStdEvents in ControlStyle) then
    with Message do
      MouseDown(Button, KeysToShiftState(Keys) + Shift, XPos, YPos);
end;

procedure TControl.MouseDown(Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
end;

0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

DeerBearCommented:
Hi,

You could try( be very cautious ) with substituting the Window Procedure for the
menu. Yes, it's not going to be fun, but it may make your job done.

Plus, you have to keep in mind that right button mouse clicks make very
little sense in a menu system.

Maybe if you can elaborate on what you want to achieve, we may be very
well able to help you better.

HTH,

Andrew
0
Slick812Commented:
hello letuanle, this is not so easy, but you might look at the code for this EE question -

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20394288.html

this will get the right mouse click for a menu item. . . Ask questions if you need more information about this
0
letuanleAuthor Commented:
Dear GloomyFriar,

it is not easy as you think. I already override the wndproc and catch the
WM_RBUTTONDOWN event but it never goes there.

thanks,
Tuan Le
------------------------
Comment from GloomyFriar
Date: 10/30/2003 02:39AM PST  Comment    

The code looks like that:


procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;

procedure TControl.WMLButtonDown(var Message: TWMLButtonDown);
begin
  SendCancelMode(Self);
  inherited;
  if csCaptureMouse in ControlStyle then MouseCapture := True;
  if csClickEvents in ControlStyle then Include(FControlState, csClicked);
  DoMouseDown(Message, mbLeft, []);
end;

procedure TControl.DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
  Shift: TShiftState);
begin
  if not (csNoStdEvents in ControlStyle) then
    with Message do
      MouseDown(Button, KeysToShiftState(Keys) + Shift, XPos, YPos);
end;

procedure TControl.MouseDown(Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
end;


 
0
Slick812Commented:
menus are a "Separate" system object and DO NOT send ANY mouse messages to any window any where
0
Slick812Commented:
robert_marquardt has given you many of the Menu messages that are sent to the owner window for menu events or notifucations, No mouse messages in that bunch
0
Slick812Commented:
here is some code to get a Right Mouse Click form a Menu Item. This uses a WH_MOUSE  Hook to get mouse events of this process, This Hook is started whenever the Main menu is activated with the WM_ENTERMENULOOP message, and the hook is stopped on the WM_EXITMENULOOP message. You will need some method to determime which sub-menu of the Main-Menu is currently showing, that is done with the WM_INITMENUPOPUP message and saving the handle of the sub-menu in the wParam.
The HookFunc function is where the hook messages are tested, I use the MainMenu1.Items[0].Handle to test if that sub-menu is up, but you will need to change that to the sub-menu or menus handles you are interested in. The MenuItemFromPoint function will get the menu Item number for the Point position of the right mouse click, and I test it for Menu Item Zero, but you will need to change this test to one or more menu items that you need.


  private
    { Private declarations }
    hMenuUp: Integer;
    procedure EnterMenu(var Msg: TMessage); message WM_ENTERMENULOOP;
    procedure ExitMenu(var Msg: TMessage); message WM_EXITMENULOOP;
    procedure InitMenu(var Msg: TMessage); message WM_INITMENUPOPUP;


function HookFunc(Code, wParam: Integer; var MouseStrut: TMOUSEHOOKSTRUCT): Integer; stdcall;
var
MenuItem: cardinal;
begin
Result:=CallNextHookEx(hMHook, Code, wParam, Integer(@MouseStrut));
if Code < 0 then Exit;
{this test for the Right button Up and if the hMenuUp if the first sub-menu in the main menu}
if (Code = HC_ACTION) and (wParam = WM_RBUTTONUP) and
    (Form1.hMenuUp = Form1.MainMenu1.Items[0].Handle) then
      begin
   {get the menu item of the of the sub-menu clicked on}
      MenuItem := Cardinal(windows.MenuItemFromPoint(Form1.Handle, Form1.MainMenu1.Items[0].Handle, MouseStrut.pt));
      if MenuItem = 0 then // if Top Menu Item then write some numbers on the Label for a Right click on that Item
        Form1.Label1.Caption := 'WOW '+IntToStr(MouseStrut.pt.x)+'  '+IntToStr(MouseStrut.pt.y)+'  '+IntToStr(MenuItem) else
        Form1.Label1.Caption := 'Not Item zero';

      end;
end;


procedure TForm1.InitMenu(var Msg: TMessage);
var
MRect: TRect;
begin
Msg.Result := 0;
hMenuUp := Msg.WParam;
{get the handle of the sub-menu that is showing in the hMenuUp}
end;

procedure TForm1.EnterMenu(var Msg: TMessage);
begin
{start the hook when the menu is shown}
Msg.Result := 0;
if (Msg.WParam = 0) and (hMHook = 0) then
hMHook := SetWindowsHookEx(WH_MOUSE, @HookFunc, hInstance, 0);
end;

procedure TForm1.ExitMenu(var Msg: TMessage);
begin
{kill hook on menu close}
Msg.Result := 0;
if hMHook <> 0 then
if UnhookWindowsHookEx(hMHook) then
hMHook := 0;
end;

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
you might try it out. it works for me
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Slick812Commented:
seems like I forgot this

var
  Form1: TForm1;
  hMHook: Integer;

implementation

{$R *.DFM}
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.