Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #87053 > unrolled thread

calling a Event Handler within a class

Started byJens <paule32.jk@gmail.com>
First post2022-10-17 22:51 +0200
Last post2022-10-20 00:25 -0500
Articles 11 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  calling a Event Handler within a class Jens <paule32.jk@gmail.com> - 2022-10-17 22:51 +0200
    Re: calling a Event Handler within a class Frederick Virchanza Gotham <cauldwell.thomas@gmail.com> - 2022-10-17 14:32 -0700
    Re: calling a Event Handler within a class Juha Nieminen <nospam@thanks.invalid> - 2022-10-18 07:06 +0000
      Re: calling a Event Handler within a class Jens <paule32.jk@gmail.com> - 2022-10-18 10:06 +0200
        Re: calling a Event Handler within a class Juha Nieminen <nospam@thanks.invalid> - 2022-10-18 09:27 +0000
          Re: calling a Event Handler within a class JiiPee <kerrttuPoistaTama11@gmail.com> - 2022-10-20 18:36 +0300
        Re: calling a Event Handler within a class David Brown <david.brown@hesbynett.no> - 2022-10-18 11:45 +0200
        Re: calling a Event Handler within a class Manfred <noname@add.invalid> - 2022-10-19 02:43 +0200
    Re: calling a Event Handler within a class Bonita Montero <Bonita.Montero@gmail.com> - 2022-10-18 14:21 +0200
    Re: calling a Event Handler within a class Jens <paule32.jk@gmail.com> - 2022-10-19 12:58 +0200
    Re: calling a Event Handler within a class Lynn McGuire <lynnmcguire5@gmail.com> - 2022-10-20 00:25 -0500

#87053 — calling a Event Handler within a class

FromJens <paule32.jk@gmail.com>
Date2022-10-17 22:51 +0200
Subjectcalling a Event Handler within a class
Message-ID<jr5tj7F6h7bU1@mid.individual.net>
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.

[toc] | [next] | [standalone]


#87054

FromFrederick Virchanza Gotham <cauldwell.thomas@gmail.com>
Date2022-10-17 14:32 -0700
Message-ID<01b2e8f5-1f0f-498e-9cdc-0ca075012814n@googlegroups.com>
In reply to#87053
On Monday, October 17, 2022 at 9:52:09 PM UTC+1, Jens wrote:
> 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.


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.

[toc] | [prev] | [next] | [standalone]


#87060

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-10-18 07:06 +0000
Message-ID<tilj96$ee4$1@gioia.aioe.org>
In reply to#87053
Jens <paule32.jk@gmail.com> wrote:
> 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 ?

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.)

[toc] | [prev] | [next] | [standalone]


#87061

FromJens <paule32.jk@gmail.com>
Date2022-10-18 10:06 +0200
Message-ID<jr753uFc0h4U1@mid.individual.net>
In reply to#87060
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

[toc] | [prev] | [next] | [standalone]


#87062

FromJuha Nieminen <nospam@thanks.invalid>
Date2022-10-18 09:27 +0000
Message-ID<tilrit$3nu$1@gioia.aioe.org>
In reply to#87061
Jens <paule32.jk@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.

[toc] | [prev] | [next] | [standalone]


#87100

FromJiiPee <kerrttuPoistaTama11@gmail.com>
Date2022-10-20 18:36 +0300
Message-ID<tirpui$bkli$2@dont-email.me>
In reply to#87062
On 18/10/2022 12:27, Juha Nieminen wrote:
> I didn't ask for your life story.

:)

[toc] | [prev] | [next] | [standalone]


#87063

FromDavid Brown <david.brown@hesbynett.no>
Date2022-10-18 11:45 +0200
Message-ID<tilskg$3n719$1@dont-email.me>
In reply to#87061
On 18/10/2022 10:06, Jens wrote:

> 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
> ....
> }
> 

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.


[toc] | [prev] | [next] | [standalone]


#87072

FromManfred <noname@add.invalid>
Date2022-10-19 02:43 +0200
Message-ID<tinh7v$1tfs$1@gioia.aioe.org>
In reply to#87061
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.

[toc] | [prev] | [next] | [standalone]


#87065

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-10-18 14:21 +0200
Message-ID<tim5oa$3nt3e$1@dont-email.me>
In reply to#87053
Am 17.10.2022 um 22:51 schrieb Jens:
> 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.

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;
}

[toc] | [prev] | [next] | [standalone]


#87076

FromJens <paule32.jk@gmail.com>
Date2022-10-19 12:58 +0200
Message-ID<jra3ilFq6vtU3@mid.individual.net>
In reply to#87053
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

[toc] | [prev] | [next] | [standalone]


#87084

FromLynn McGuire <lynnmcguire5@gmail.com>
Date2022-10-20 00:25 -0500
Message-ID<tiqm4n$1e6b$2@gioia.aioe.org>
In reply to#87053
On 10/17/2022 3:51 PM, Jens wrote:
> 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.

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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web