Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 2000-02-21
8
Medium Priority
?
207 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
[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
  • 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 400 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

Independent Software Vendors: 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!

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

718 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