Solved

Add Menuitem.

Posted on 2000-02-18
16
316 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
  • 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Suggested Solutions

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 The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

813 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now