DLLs

I just got a great answer about a Dll question.
So Heres another one .
if I have 2 dll's both have the same function names
when I load the dll's as so :

Hinst := LoadLibrary('c:\files\mikes\projects\dll\project1.dll');
if Hinst > 32 then;
   begin
    FPointer := GetProcAddress(Hinst, 'EntryPoint');
      if FPointer <> Nil then
        begin
          MyProc := proc(FPointer);
          try
            MyProc(MainMenu1);;
          except
           FreeLibrary(HInst);
           ShowMessage('Error in Calling EntryPoint in DLL');
          end;
       end;
     end;

Hinst := LoadLibrary('c:\files\mikes\projects\dll\DLL2.dll');
if Hinst > 32 then;
   begin
    FPointer := GetProcAddress(Hinst, 'EntryPoint');
      if FPointer<> Nil then
        begin
          MyProc := proc(FPointer);
          try
            MyProc(MainMenu1);
          except
           FreeLibrary(HInst1);
           ShowMessage('Error in Calling EntryPoint in DLL');
          end;
       end;


     end;
what the dlls do are they loads two menu Items. This works the two deffernt menu  do load but when I click on the first menu item(first dll that loaded) it runs the right function. when I click on the 2nd menu item(the 2nd dll that loaded) it runs the first menu item not the 2nd?

Both dll have the same function names but the function do differnt things. can anyone explain this to be because I thought if the dlls load in there own memory space the function address would be differnt even if they were name the same. well I quest I'm wrong?

--------------- Code for Dll --------------------------------------
//both dlls are the same except for the showmessage()
//which is in the  DynaClick() procedure.
uses
  Menus, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TEvent = procedure(Sender: TObject) of object;
  TSomeClass = Class
  procedure DynaClick(Sender: TObject);
end;

 var
  NewMenu : TMenuItem;
  SomeClass : TSomeClass;
  Event : TEvent;

procedure TSomeClass.DynaClick(Sender: TObject);
begin
  showMessage('Its Dll 2');
end;

procedure EntryPoint(AMenu: TMenu); export; stdcall;
var
  NoItem  : TMenuItem;
begin
   //create a event handler...
  SomeClass := TSomeClass.Create;
   //assign Event to DynaClick to be pass to the menu Onclick event...
 Event := SomeClass.DynaClick;

 NoItem := AMenu.Items[AMenu.Items.Count - 1];
 NewMenu := TMenuItem.Create(NoItem);
 NewMenu.Caption := 'DLL2 Menu';
 NewMenu.OnClick := Event;
 NoItem.Insert(NoItem.Count, NewMenu);
 SomeClass.Free;
end;

exports
   EntryPoint;

mikec459Asked:
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.

sperlingCommented:
Hmmm... Start with removing the SomeClass.Free from your EntryPoint function. That won't help, but the menuitems OnCLick will call a method of a destroyed object.

Everytime you, or VCL code, calls TMenuItem.Create, a new unique word is reserved as the "Command ID" of the menu item. This "Command ID" is passed on to Windows, and when you click an item, windows passes the command ID back to the VCL, which then again uses this ID to determine what TMenuItem.OnCLick it should call.
The problem is that the method the VCL uses to allocate these unique IDs are local to the application and the DLLs. This means that when you call TMenuItem.Create in the first DLL the menu item will allocate the first unique command ID within the DLL. And so will DLL 2, meaning you get two menu items with the same ID.

Try redesigning a bit:

Have your DLL export a function, "MenuItemClicked" or something.
Declared like this:
  procedure MenuItemClicked; export; stdcall;

Create the menuitem in the app, and pass the item to EntryPoint.

EntryPoint should set the caption, help context and so on of the TMenuItem. In addition, include this line:

  AMenuItem.Tag := INTEGER(@MenuItemClicked);


The application should set the OnClick event for all created menu items to a common procedure, e.g. DLLMenuItemClicked.

procedure TForm1.DLLMenuItemClicked(Sender : TObject);
type
  TClickProc = procedure; stdcall;
var
  ClickProc : TClickProc;
begin
  @ClickProc := POINTER(TMenuItem(Sender).Tag);
  ClickProc;
end;


This scheme should work, although I haven't tested it. Leave me a comment if you get trouble...
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
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.