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
Solved

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

Posted on 2000-02-21
8
201 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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

840 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