We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now

x

DLLs

mikec459
mikec459 asked
on
Medium Priority
496 Views
Last Modified: 2010-04-04
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;

Comment
Watch Question

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

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.