Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

calling a Event Handler within a class

59 views
Skip to first unread message

Jens

unread,
Oct 17, 2022, 4:52:09 PM10/17/22
to
Hello,
I have a hard coded TSpeedButton on TForm.
I would like to assign it a OnClick Event Handler in a procedureal
global function (not a member of a class).
How can I do this ?

Thanks for ideas.

Frederick Virchanza Gotham

unread,
Oct 17, 2022, 5:32:55 PM10/17/22
to
Looks like you're using Embarcadero (formerly known as Borland C++).

In my dayjob I inherited a very old project that uses Embarcadero. Nowadays if I need to write a new GUI program, I use wxWidgets so that it can be built for macOS, MS-Windows and Linux.

Anyway, when I needed help with Embarcadero a few months ago, I wasn't able to find a forum online. They have a Facebook group though where you can ask questions -- if it's worth making a dummy Fb profile.

Juha Nieminen

unread,
Oct 18, 2022, 3:06:35 AM10/18/22
to
This is a generic C++ discussion forum, not a forum about that library
you are using.

That does not mean you can't ask that question here. However, it *does*
mean that you should give more details. We don't know what "TForm" or
"TSpeedButton" or any of those other things are. (And no, you can't
expect us to do the googling. It should be you who does the work to
make it as easy as possible for us to answer the question from a
C++ perspective.)

Present the problem in the form of a short piece of code and explain
what you want to achieve in a bit more detail. (If there are functions
or types that are specific to that library, explain them if necessary.)

Jens

unread,
Oct 18, 2022, 4:06:41 AM10/18/22
to
Hello,

I am a member of a church organization for peoples with
some problems.

My hobby is it, to programming applications for computers.
I master me self in Delphi (beginning with Turbo Pascal 6/7,
GNU C/C++, and finally C++ Builder 1..6 (32-Bit).

I am able to download the Community Versions of Emberracdo
Delphi, and C++ Builder in both (32, and 64-Bit for Windows).

But I have to deal with C, and Pascal code twice.
But, I can only install Delphi, or C++ Builder.
But not the same RAD Tools together - and after a year, I have
to re-new the license, and re-install all Tools again.

This implicit the installing all the RAD Tools (Components)
that I had install before I use them.
And this is a nogo.

So, I back to days, as BORLAND came with his good 32-Bit Tools
of Delphi, and C++ Builder.

My first problem, in the past few days was, that I had a problem
to "parent window" a TSplitter (a component which can be used to
move parts of GUI components vertical, or horizontal on a desktop
window form (TForm), to make more visibility of the components on
the given/underlaying TSplitter componentes.

This problem was done by me, by experiment hours of wasteing time
and stressed lost of hair.

Okay, ...

Now, I have a problem, to "set" the Event Handler of a BORLAND
C++ Builder component (TSpeedButton) - a TSpeedButton is like a
normal Windows Desktop Application Button, except, it would be
*not* appear in the tabular order of selectable items of the
applications "tabable" components (ListBox, ComboBox, Button, ...)

I said: I have to deal with Pascal, and C Code ... :
I created a .DLL project under C++ Builder 6.0, compile it, and
place it in the directory of my application .exe binary.

As code/to comunicate with the C+++ .dll code, I export functions
from the .dll library, and import it in Delphi.

All code goes done.
Till, I would create a OnClick event on a TButton/TSpeedButton.
It seems, that I must have a class that decents from a TControl,
so, the VCL manager knows, which VMT (virtual method table)
proceure, or function can be called within this (TObject) class.

I have to use: extern "C" void foo(void) { /* ... */ }

because C++ mangles functions members in C++ and fit it in space
of the VMT's of it handled TClass.
So, I can not directly call mangled C++ functions in Delphi by
simply "import" them - this came to a caos of the differnt memory
system's between Delphi, and C++ Builder.

That's why, I use pointer between Delphi, and C++ Builder.

Okay, ...

Now, the question is: is it possible, to set a event handler on
the OnClick event of a TButton object without having implicit a
TObject inherited class ?

If the answer YES, then: How can this be done in C++ Builder ?

Under Delphi, I just assign it like:

....
btn := TButton.Create(AOwner);
btn.Parent := AOwner;
btn.OnClick := btnOnClick;
....

In C++ Builder 6.0, i try the similar same procedure, but I fail
with the code:

extern "C"
__declspec(dllexport) void
__stdcall foo(int owner)
{
....
TForm *form = new TForm((HWND)owner);
....
TButton *btn = new TButton(form);
btn->Parent = form;
btn->OnClick = btnOnClick; // <-- this fails
....
}

To make more sense in this posting, I can point You to my
StackOverflow/RetroComputing article with the followin URL:

https://retrocomputing.stackexchange.com/questions/25400/how-to-embeed-c-builder-6-32-bit-tframe-into-a-delphi-7-32-bit-application

This has not directly to do with my (second) part/question about
the described problem in this post.
But it depends on in future step's.

Thanks for reading, and helping hand.
Jens

Juha Nieminen

unread,
Oct 18, 2022, 5:28:19 AM10/18/22
to
Jens <paule...@gmail.com> wrote:
> I am a member of a church organization for peoples with
> some problems.

I didn't ask for your life story. I asked for a short piece of code
and a question related to it.

David Brown

unread,
Oct 18, 2022, 5:46:10 AM10/18/22
to
In Delphi (Pascal), AFAIK class methods are treated as normal functions
with the class instance passed as the first parameter. You can assign
any function, including a freestanding function, to an "event" (that is,
a method function pointer) as long as the parameters match up. In C++,
a method function pointer is a different beast from a normal function
pointer because it can handle more complex class hierarchies than Object
Pascal supports (multiple inheritance, virtual inheritance, etc.).

Thus the assignment "btn->OnClick = btnOnClick" fails because a
pointer-to-function cannot be assigned to a pointer-to-member-function
pointer.

Far and away the simplest solution is to write a normal C++ Builder
style member function event handler for "btn->OnClick", which does
nothing but call the external function.



Bonita Montero

unread,
Oct 18, 2022, 8:21:49 AM10/18/22
to
Have a lambda wich you can cast to a normal function pointer and
access local variables of the function by declaring them as either
static or thread_local depending on if the function needs to be
thread-safe. If you have some captures with that function pointer
this approach doesn't work since you can't cast lambdas with cap-
tures to normal function pointers.

Here's an example how to do this from another context:

a#include <iostream>
#include <vector>
#include <string>
#include <climits>
#include <link.h>
#include <dlfcn.h>

using namespace std;

int main()
{
thread_local vector<string> images;
dl_iterate_phdr(
[]( dl_phdr_info* image, size_t size, void* pFn ) -> int
{
try
{
if( *image->dlpi_name )
images.emplace_back( image->dlpi_name );
else
{
Dl_info dlInfo;
if( !dladdr( (void*)image->dlpi_addr, &dlInfo ) )
return 1;
char exePath[PATH_MAX];
if( !realpath( dlInfo.dli_fname, exePath ) )
return 1;
images.emplace_back( exePath );
}
return 0;
}
catch (...)
{
return 1;
}
return 1;
}, nullptr );
for( string const &image : images )
cout << "\"" << image << "\"" << endl;
}

Manfred

unread,
Oct 18, 2022, 8:44:01 PM10/18/22
to
On 10/18/2022 10:06 AM, Jens wrote:
> Now, the question is: is it possible, to set a event handler on
> the OnClick event of a TButton object without having implicit a
> TObject inherited class ?
>
> If the answer YES, then: How can this be done in C++ Builder ?
>
> Under Delphi, I just assign it like:
>
> ....
> btn := TButton.Create(AOwner);
> btn.Parent  := AOwner;
> btn.OnClick := btnOnClick;
> ....
>
> In C++ Builder 6.0, i try the similar same procedure, but I fail
> with the code:
>
> extern "C"
> __declspec(dllexport) void
> __stdcall foo(int owner)
> {
> ....
>   TForm *form = new TForm((HWND)owner);
> ....
>   TButton *btn = new TButton(form);
>   btn->Parent  = form;
>   btn->OnClick = btnOnClick;  // <-- this fails
> ....
> }

I am not that familiar with Borland products, but from a C++ perspective
it would help if you could post the exact and complete error message -
this might show which are the types of the OnClick member, and of
btnOnClick.

You may also want to compare the following:

- declaration of the OnClick member of TButton - I guess this should be
documented by Borland - it may be an object of some class that overloads
the assignment operator; inspecting what is the expected argument type
of such operator might help
- prototype of btnOnClick

In C++ an "event" is not a built-in primitive. C++ offers all the lower
level ingredients to build an event system, so the details of events and
event handlers are specific to your implementation (Borland), and their
docs should tell how to use their events, rather than the language itself.

Jens

unread,
Oct 19, 2022, 6:58:48 AM10/19/22
to
Hello, and Thank You @all for ideas and feedback !

It seems, that the thing I would be done, does not
work without a class, and a class member.

I solved the problem, in this form:

//===
class MyDummyClass: public TObject
{
public:
void __fastcall SpeedButtonClick(System::TObject* Sender) {
ShowMessage("info speed.");
}
};
static MyDummyClass * dummyClass = NULL;

extern "C"
__declspec(dllexport) void
__stdcall create__MyCppFrame ( int ParentForm )
{
...
dummyClass = new MyDummyClass();

mySpeedButton = new TSpeedButton(myPanel);
mySpeedButton -> Parent = myPanel;
mySpeedButton -> OnClick = &(dummyClass->SpeedButtonClick);
...
}
//===

Thanks for your patient
Jens

Lynn McGuire

unread,
Oct 20, 2022, 1:26:00 AM10/20/22
to
You need to get a permanent pointer to that event handler so you can
register it. So, make it a static method.

Registering event handlers is tricky. You need to keep a vector of them
and remove them when no longer valid.

Lynn

JiiPee

unread,
Oct 20, 2022, 11:37:05 AM10/20/22
to
On 18/10/2022 12:27, Juha Nieminen wrote:
> I didn't ask for your life story.

:)
0 new messages