Solved

How to get a method in a class that an API call can Callback?

Posted on 2000-02-21
8
200 Views
Last Modified: 2010-04-04
Experts,

This is what I need to accomplish.  I'm building a class that needs to pass an address of one of it's methods to a win API and in this method I will fire an event to the users of this class. Please provide example.  I can't use a public/method unit method because I'll have no idea which class invoked it, or is there a way to tell?

Thanks,
0
Comment
Question by:Johnn
  • 4
  • 3
8 Comments
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2544958
John,
  I am a little fuzzy on what exacxtly you are looking to do, but I can tell you that if you are looking to find the class which invoked the event, you should be able to use the sender parameter, since all classes derive ultimately from Tobject, you'd typecast (YourClass as Tobject).whatever... Hope this helps.


Good Luck!!

0
 
LVL 1

Author Comment

by:Johnn
ID: 2544985
Let me try to make this clearer if I can...I have a class that needs a method address to be passed to win32 API call for a callback.  I need a means to establish which instance of the class was called back so I can fire an event in that particular class.
0
 
LVL 20

Accepted Solution

by:
Madshi earned 100 total points
ID: 2545095
Johnn, that won't work this way, because class methods have an additional hidden self parameter. E.g. TNotifyEvent in reality looks like this:

procedure ([Self: TObject;] Sender: TObject);

This is indicated by the keywords "of object".

But you can nevertheless do what you want if the enumeration function has a private value you can use.

E.g. call EnumWindows like this:

function EnumWindowsProc(window: cardinal; Self: TObject);
begin
  // now in Self you have the object which called EnumWindows...
end;

procedure TSomeObject.Test;
begin
  EnumWindows(@YourStandardFunction, integer(Self));
end;

Regards, Madshi.
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 1

Author Comment

by:Johnn
ID: 2546231
Madshi, that may work for EnumWindows which allow an application defined object however other callback functions don't have such a parameter.  Any more ideas?
0
 
LVL 1

Author Comment

by:Johnn
ID: 2546240
Also, I'va managed to get the callback to call a class function via typed procedure, procedure type property, etc.  however i'm getting strange numbers for my parameters and my handle doesn't seem to be the correct one.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2546299
>> Madshi, that may work for EnumWindows which allow an application defined object however other callback functions don't have such a parameter.

Yes, that's exactly what I told you. There is no other good choice. I'm sorry... Well, of course you could put the "Self" object into a global variable, then in the callback function you can access the global variable, but that's very ugly - and won't work, if you work with threads.

>> Also, I'va managed to get the callback to call a class function via typed procedure, procedure type property, etc.  however i'm getting strange numbers for my parameters and my handle doesn't seem to be the correct one.

You can't make this work, because as soon as you use an "of object" function (that is a member of a class) as the callback pointer, the parameters are not correct. Forget it. That just CANNOT work...   :-(

BTW, about which callback function are we talking? About callback pointers in general? Or something specific?
0
 
LVL 1

Author Comment

by:Johnn
ID: 2547784
setwindowshookex, if it helps.

>>You can't make this work, because as soon as you use an "of object" function (that is a member of a class) as the callback pointer, the parameters are not correct. Forget it. That just CANNOT work...   :-(<<

The parameters contain the correct values just not the correct parameter, I suspect if I knew how to shift the data I could make it work.  So far I know that the nCode parameter contains the wParams actual value and the wParam contains lParams actual value.  I don't really need the nCode because I can jsut call CallWindowsHook as a default, it's just getting my hooks handle that is the problem :(  So I am very close to getting it to work, at least with one instance of the class during my tests.


John
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2549337
>> setwindowshookex, if it helps.

Hmm... Yes, I see, SetWindowsHookEx is really a problem. Hmm... You don't do system wide hooks, do you? Because then you would have to put the callback function in a dll.
Well, okay, let's presume, you don't want system wide hooks. Then I think your only possibility is to use a global variable like this:

var HookHandle : cardinal;
    HookSelf   : TYourObj;

function CallbackFunc(...
begin
  if ... then
    HookSelf.HookCallback(...);
end;

You have to install the hook then this way:

procedure TYourObj.InstallHook(...);
begin
  HookSelf := Self;
  HookHandle := SetWindowsHookEx(...);
end;

>> The parameters contain the correct values just not the correct parameter, I suspect if I knew how to shift the data I could make it work.  So far I know that the nCode parameter contains the wParams actual value and the wParam contains lParams actual value.  I don't really need the nCode because I can jsut call CallWindowsHook as a default, it's just getting my hooks handle that is the problem :(  So I am very close to getting it to work, at least with one instance of the class during my tests.

Yes, of course the parameters are shifted, because of the hidden self parameter. "nCode" is stored in the hidden self parameter.
So if in your handler you do something like this now:

procedure TYourObj.DirectCallbackFunc(...);
begin
  FClassVariable := ...;    
  // here you'll get problems, because Delphi now tries to resolve [Self.]FClassVariable
  // but Self is "nCode", so Delphi uses nCode as an object pointer
  // you see the problem?
  // this just can't work
end;

Regards, Madshi.
0

Featured Post

ScreenConnect 6.0 Free Trial

Discover new time-saving features in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
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…

777 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