Solved

Add Menuitem.

Posted on 2000-02-18
16
318 Views
Last Modified: 2010-04-04
Hi,
How can I add a custom menuitem to OTHER program's menu, such as Notepad's FileMenu?  Examples expected.
(D2)
0
Comment
Question by:yingkit
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
16 Comments
 
LVL 8

Accepted Solution

by:
ZifNab earned 200 total points
ID: 2534623
Hi yingkit,

here is an example for Eudora Light (but can be any window)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DBTables, Grids, DBGrids, Db, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  PFindWindowStruct = ^TFindWindowStruct;
  TFindWindowStruct = record
    Caption : string;
    ClassName : string;
    WindowHandle : THandle;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


function EnumWindowsProc(hWindow : hWnd;
                         lParam  : LongInt) : Bool
{$IFDEF Win32} stdcall; {$ELSE} ; export; {$ENDIF}
var
  lpBuffer : PChar;
  WindowCaptionFound : bool;
  ClassNameFound : bool;

begin
  GetMem(lpBuffer, 255);
  Result := True;
  WindowCaptionFound := False;
  ClassNameFound := False;

  try
    if GetWindowText(hWindow, lpBuffer, 255) > 0 then
      if Pos(PFindWindowStruct(lParam).Caption, StrPas(lpBuffer)) > 0
       then WindowCaptionFound := true;
    if PFindWindowStruct(lParam).ClassName = '' then
      ClassNameFound := True else
        if GetClassName(hWindow, lpBuffer, 255) > 0 then
          if Pos(PFindWindowStruct(lParam).ClassName, StrPas(lpBuffer))
           > 0 then ClassNameFound := True;

    if (WindowCaptionFound and ClassNameFound) then begin
      PFindWindowStruct(lParam).WindowHandle := hWindow;
      Result := False;
    end;

  finally
    FreeMem(lpBuffer, sizeof(lpBuffer^));
  end;
end;

function FindAWindow(ACaption : string;
                     AClassName : string) : THandle;
var
  WindowInfo : TFindWindowStruct;

begin
  with WindowInfo do begin
    Caption := ACaption;
    ClassName := AClassName;
    WindowHandle := 0;
    EnumWindows(@EnumWindowsProc, LongInt(@WindowInfo));
    FindAWindow := WindowHandle;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TheWindowHandle : THandle;
begin
  TheWindowHandle := FindAWindow('Eudora Light', '');
  if TheWindowHandle = 0 then
    ShowMessage('Window Not Found!') else
  begin
    AppendMenu(GetMenu(TheWindowHandle),
      MF_STRING,
      $EFF0,
      'Your menu text');
  end;
end;

end.

Regards, Zif.
0
 

Author Comment

by:yingkit
ID: 2537500
Hello Zif,
The code worked quite well.  But if I don't want to create a new menu, but just want to add a menuitem under the "File" menu, how should I modify the code?
Thanks in advance.
0
 

Author Comment

by:yingkit
ID: 2537545
I've tried the function insertmenu, but I can't control the position where the menuitem appears.
If possible, could you please also tell me how can I execute an EXE file with some parameters when the added menuitem is clicked by the user?  Of course, I will offer more points for the answers.
Thanks!
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Expert Comment

by:ZifNab
ID: 2538343
Hi


InsertMenu works like this :

procedure TForm1.Button1Click(Sender: TObject);
var
  TheWindowHandle, MenuHandle : THandle;
begin
  TheWindowHandle := FindAWindow('Untitled - Notepad', '');
  if TheWindowHandle = 0 then
    ShowMessage('Window Not Found!') else
  begin
    MenuHandle := GetMenu(TheWindowHandle);
    MenuHandle := GetSubMenu(MenuHandle, 0);
    InsertMenu(MenuHandle,
      3,
      MF_STRING + MF_BYPOSITION,
      $EFF0,
      'Menu at place 4');
  end;
end;

I don't know directly how to intercept the click of the menu. I'll look into it.

Zif.
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2538372
yuck, it's not so easy as I thought... here is what I have so far... perhaps it should work when using dll. But I don't have time to test it in a dll.

const
  WM_NotePad = WM_USER + 100;


procedure MenuIsClicked;
begin
 showmessage('hello');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TheWindowHandle, MenuHandle : THandle;
  POldWndProc : Pointer;
begin
  TheWindowHandle := FindAWindow('Untitled - Notepad', '');
  if TheWindowHandle = 0 then
    ShowMessage('Window Not Found!') else
  begin
    MenuHandle := GetMenu(TheWindowHandle);
    MenuHandle := GetSubMenu(MenuHandle, 0);
    InsertMenu(MenuHandle,
      3,
      MF_STRING + MF_BYPOSITION,
      WM_NotePad,
      'Menu at place 4');
    POldWndProc := Pointer(SetWindowLong(MenuHandle, GWL_WNDPROC, LongInt(@MenuIsClicked)));
  end;
end;

Regards, zif

0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2540230
Hi,

Reading this :

Processes run in different memory spaces on Win32 and you cannot directly call a function in another memory space.

and we know that we've to create a dll if we want to get it to work :-(

0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 2542543
listening...
0
 

Author Comment

by:yingkit
ID: 2545269
Adjusted points to 200
0
 

Author Comment

by:yingkit
ID: 2545270
Is it possible to test it in a DLL for me and show me how I can make the DLL and get everything worked??
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2546880
yuck, tried it with DLL and I get an error about not a correct window handler, when using the menu handle :-(
0
 

Author Comment

by:yingkit
ID: 2557303
Actually, is it impossible to interfere other programs' menus, just like my question?  Very difficult??
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2557340
Hi, I don't know, it should be possible, because we can add a menu to it... only problem is that we don't find a way to attach a function/procedure to this menu :-(. Nevertheless, it looks like it is really hard.

Zif.
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2557347
mmm, perhaps a global messages hook can work...

Zif.
0
 

Author Comment

by:yingkit
ID: 2557362
Hook?  Can you give me some examples?  I don't really care what method is used.  I just want to have a new menuitem appeared in other program with my own procedures.
0
 

Author Comment

by:yingkit
ID: 2562325
Thanks ZifNab.
If you find a way to attach a procedure to a menuitem in the future, please post it here.  Thank you very much!
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2564120
yingkit, I'll certainly do!
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question