Link to home
Start Free TrialLog in
Avatar of Jaymol
Jaymol

asked on

Another App's System Menu.

I have added a new menu item to another application.  I now need to know how to handle it.  Any suggestions?
Avatar of Radler
Radler

How this was done ?
Avatar of Jaymol

ASKER

Simple....

assume you have the handle of a running application and use the following code...(Hndl=handle)

var
  SysMenu : HMenu;
begin
  SysMenu:=GetSystemMenu(Hndl, False);
  AppendMenu(SysMenu, MF_SEPARATOR,
             0, nil);
  AppendMenu(SysMenu, MF_BYCOMMAND,
             666, '&I made this...');
end;

There you go!  Now, I need to be able to handle a click on that menu option.

John.
Avatar of Jaymol

ASKER

Okay then...more points.  (But no more.)
Avatar of RBertora
following..
Jaymol;

Really, poor points =  Poor efforts

When the user click at your menu item, your form receive a WM_SYSCOMMAND, the LPARAM identifies the menu item selected.

Try to see the VCL to TMenuItem.AppendTo ( Private method ). It's a good sample to start.

T++, Radler.
Avatar of Jaymol

ASKER

Radler,

Really, bad reading = Bad answer

I'm attempting to trap the click event of a system menu on *another* application, say Microsoft Word, etc..

Not, the application I've written.

Ta,

John.
hi jaymol,

seems it is better to use insertmenuitem instead of appendmenu

the menuitem sends a message to its menu-owner, if its selected. this message you must get (hook?)

but maybe i'm wrong

meikl
Avatar of Jaymol

ASKER

That's what I'm asking
Jaymol

This is simple, when you create the menu item create a handler (user message) aswell and then trap the WM_SYSCOMMAND as radler mentioned...

add this to your private section

procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
     {this is used to define our system message for the sytem menu item we create}

then create the handler

const
 SC_RemoveTableHandler = WM_USER + 1;{this is the our system message ID}

then when you call your code...

procedure TChildFrm.FormCreate(Sender: TObject);
var
SysMenu: HMenu;
begin
 SysMenu := GetSystemMenu(Handle, False);//get the system menu handle
  AppendMenu(SysMenu, MF_BYPOSITION or MF_SEPARATOR, 0, '');//add a separator first
  AppendMenu(SysMenu, MF_BYPOSITION or MF_STRING, SC_RemoveTableHandler{your handler here}, 'Remove &Table');//add our menu item and pass the user defined message
   {this is a hack and not really recommened by windows but poses no problems}
     DeleteMenu(SysMenu, SC_CLOSE, MF_BYCOMMAND);
     DeleteMenu(SysMenu, 6, MF_BYPOSITION);
end;

then when the System recieves this message do your stuff...

procedure TChildFrm.WMSysCommand(var Msg: TWMSysCommand);
begin
 if Msg.CmdType = SC_RemoveTableHandler then begin {call the user defined system message}
{call our code here}
end
 else
inherited;{this is very important, need for the rest of the system menu work as default}
end;


Later
BoRiS
I think Meikl was the closest here. Boris you gave the obvious solution which only works for an application to work with its own system menu.

As Meikl already mention (and I second) you need to get to the message which is sent to the application with the modified system menu. Unfortunately, you cannot redirect the window procedure of a window which does not belong to your process. So the only solution I can see here is to install a global hook and listen to all message for a specific window and handle accordingly.

How to install a system hook has been widely discussed here in the last weeks.

Ciao, Mike
Your answer Boris was exactly what I said, but Jaymol wanna another thing :-(

Windows will be send this message to Word, of course so your program can't take it.
A way is create a Hook to Trap all WM_S... and find these associated with Words instances.

T++, Radler.
Avatar of Jaymol

ASKER

Boris, isn't that only gonna work for MY application?
Lischke

Mmmm, I have not tested this on another sysem menu, so you may be very right...

Jaymol

This will at least give you a guide line once you trap the message sent by the menu item...

Sorry everyone I jumped the gun here, I'm in a rush to get home it's 6:00pm here...

Later
BoRiS

BTW Just reject the answer if it is of no use...
Avatar of Jaymol

ASKER

Thanks Boris, but you're right.  It wasn't an answer to my question.  If this is similar to an ongoing and unanswered question, I'll delete it in a day or so.  Never mind. :-(
you should create a DLL and hook it... it's pretty easy... you'll receive a WM_COMMAND message when a menu item is clicked... then you can check out the wParam to get the menu item's ID...

..-=ViKtOr=-..
ASKER CERTIFIED SOLUTION
Avatar of DragonSlayer
DragonSlayer
Flag of Malaysia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Dragon, I can tell you why your code crashs and it is rather strange that it runs at all. First, you have declared global variables (HookSet, HookHandle etc.). These variables are only valid in the process which installed the hook and filled them. But your hook will be called in the context of the process for which a particular message is sent. You need to store the vars in a memory mapped file...

The second problem is your self defined message. This might be valid for your application alone, but not for all others. It may well be that this ID is almost used by other apps. hence you need to correctly register an own message.

Ciao, Mike
Avatar of Jaymol

ASKER

DragonSlayer: Thanks for the code.  Wonderful!!! Regarding the fact that it runs on NT but crashes on 95/98....I have quite a few components on my website, and I program in NT.  I've had a few people come back to me and tell me that they've had problems running them on 95 or 98.  What's going on???

John.
Avatar of Jaymol

ASKER

DragonSlayer : One question though....What should I use insted of MF_MOUSESELECT to identify a click?  (That detects the mouse being over it!)

Ta,

John.
Avatar of Jaymol

ASKER

Will somebody PLEASE give me a clue?
Sorry there Jaymol,

Was quite busy one whole day...
Will MF_SYSMENU work then?  Don't have time to try it out myself, sorry... the project manager's gonna kill me if I delay the project any longer :)

Cheers,
DragonSlayer
Avatar of Jaymol

ASKER

This doesn't make any difference - unless of course I've done it wrong!  I simply replaced the MF_MOUSESELECT with MF_SYSMENU, but it was still the same!  Any other suggestions?

John.
Experts, any comments?
Mike?
Never tried that out myself but according to MSDN MF_SYSMENU should always be in HiWOrd(wParam) as the hook's dealing with a system menu. I'd suggest to look for a value of $FFFF in HiWord(wParam) as this indicates that the menu has been closed and then use LoWord(wParam) to get the index of the last selected item (here indicated by the somewhat irritating term WM_NASTYAPP, irritating because WM_* denotes a Windows message not an identifier).

Ciao, Mike
Avatar of Jaymol

ASKER

Thanks Mike, I'll give it a try.
Avatar of Jaymol

ASKER

I can't get this to work.  Can anyone offer a code snippet to replace the bit that DragonSlayer left me?  It's the bit in the DLL...


if (message=WM_MENUSELECT) and (LoWord(wParam)=WM_NASTYAPP) and ((HiWord(wParam) and MF_MOUSESELECT)=MF_MOUSESELECT) then


Any ideas anyone?

John.
sorry about the mess there, John... :(

anyway, why do you wanna  replace that code?
Avatar of Jaymol

ASKER

Sorry about the delay....

I want to click on the menu item, but the code you gave me only detects the mouse being over it.

How do I resolve the problem?
Frankly speaking, i dunno :(
Avatar of Jaymol

ASKER

DragonSlayer : You didn't answer the question correctly then!
Yes, but he gave it a good effort didn't he?
Rob ;-)
FYI Jaymol, I posted that as a comment, NOT an answer.  It was YOU who accepted the comment as an answer.

PS: I do not intend to be rude, though.
Avatar of Jaymol

ASKER

Yeah, I know, but I still incorrectly gave the points.
I'm sorry you see it that way then.  But hey, cheer up a bit, will ya?
>Yeah, I know, but I still incorrectly gave the points.

Jaymol you know as well as I do that we live in a world that punishes us for stupid mistakes. You made a stupid mistake. :-(

Rob;-)