Note to the reviewer: Please sorry for my English, I don't speak it well. But all Information's should be reproduced. If you have any questions, let me know it. Thanks, Jens
Hello,
This is more a little Article to the "DELPHI" Community there on STACKOVERFLOW, to show, how I solve the Problem during the Days of my efforts, and my Question's here on StackOverflow.
Sometimes, you can faced with the Problem, that you can not get a "Control has no Parent Window" Error Message by Delphi or C++ Builder or both, when you try to use Delphi 7 Desktop Application Component's (like TForm, or TPanel) between Desktop Application Components that will be managed by the C++ Builder 6.0 under/in a Microsoft Windows 11 Developer Environment PC.
Before we start: I am not a profesional Programmer for any firm or other individual Persopn. My lovely things are to have fun by programing Computer Application's.
And as such, I don't want Donation's.
Please be fair enough, to drop a Donate with little bit Money-Value to the Site-Owner that are linked. You help others, and you together - believe me ;-)
PLEASE NOTE: ALL LINKS, AND INFORMATION THERE ARE FOR TESTS, AND EDUCATION PURPOSES. IT IS NOT ALLOWED, TO MAKE PAID SOFTWARE WITH THE DOWNLOADABLE SOFTWARE. STACKOVERFLOW, AND ME DONT MAKE NO GURANTEES: YOU USE ALL INFORMATION'S ON YOUR OWN RISK !!!
First of all, Delphi-7, and C++ Builder 6.0 was products from BORLAND, before BORLAND was sell. The goal was it, to hold the same look and feel of the Developer IDE (Integrated Development Environment) by using different programing Languages. So you could use Delphi (Pascal), Java or C++ Builder in the same manner, the only Exception was the programing Language.
You can download Delphi-7, and C++ Builder or any other Retro-Software here.
Use the following Links, to Download:
Delphi-7, and
C++ Builder 6.0.
As a little Limit: these two Software Products comes in 32-Bit CPU-Mode, only. I hope this is not a nogo for you (under Microsoft Windows 10/11 64-Bit).
If you are a real Programmer, you have to deal sometimes with different Programing Languages. And good Application's are programed with more as one High-Level Language. (First to speak about Assembly).
The fact is, if you try to use mixed Programing-Languages-Application's, you stand for the Problem, that each Language comes with her own Memory-Model. So C++ has it's own Memory-Model than Pascal (Delphi). You could compile Delphi Component Code under C++ Builder, but you can not use C++ Builder class members or simple Functions directly from Delphi.
Commonly, each C++ Compiler tends to produce mangeled Function-Name's. This means, that the Function-Name become a post-Name, that indicates the Parameter-Name for the given Parameter-Position.
E.g.: If you have the Function "void foo(void) { ... }" Then the Function-Name foo becomes the extended Name 3fooeV (pseudo-fictiv). The first Number (3) indecates the followed Symbol that comes with three characters, then the Function-Name itself, followed by the Parameter(s) Name List-Name "eV" for "void".
C++ Compilers have a second fact: They produce case sensitive function, and class names.
Other than Pascal/Delphi Compilers: The produce caseinsensitive function, and class names. This means, that you are more flexible under Delphi - you can write the function call: FOO; like: foo; or FOo; ...
In a hex viewer, you can see, that the Compiler produced UpperCase Symbols for the Function-Names, if you have a closer look.
With C++, you have to made more attention. But then, you have binary code, that is faster than it's Delphi Pedant.
To bring all Worlds (Delphi, and C++ Builder) under a common way, we can use wrapper-Function's. This are little Function's in C-Style (without the mangled String's before, and after the Function-Name. I dont want to deep go into this to get the Time short to read this Text here, and to save Ressources :-)
I expected, that you are familar with the Creation of minimal Delphi, and C++ Builder Project's. Else, I would advice you to use the Search-Engine "google.de" to close your knowledge Gap's.
Task: Create a TForm as main application, and place an other "external" TForm or TPanel, that binary data are located in a Windows 10 32-Bit .DLL file.
This sounds on the first look easier as it is. Because, you can not simply use the "mangled" Functions from the C++ Builder .DLL in a Delphi Application. You would be fall, if you try it. If you have luck, some Function calls works, and other's not - then you have a UB = undefined behaivor. Because the application don't know the Memory-Manager's that come with Delphi or BCB (Borland C++ Builder). It will not work properly, if you "damangle" the Function Names and call it, too.
The next Problem occur, whenn you simply use TForm creation Function member's that was shiped with Delphi, you come to the Point, that you initialize 2 different Thread's. And as such, 2 Application/Thread-Window's will be open. This can be confused the User (if you think so, that you have 10 or more such kind of Forms. The C++ Code make it possible, to Hide the internal Frame, and made it away from Task-Bar.
To combine the two different Worlds of Delphi, and C++ (Builder), I created a TForm application in Delphi, while in C++ Builder I created a .DLL project to demonstrate the usage, that is need to avoid "control has no parent window".
Example:
- Create a Application TForm Project in Delphi-7,
- Create a DLL Project in C++ Builder 6.0,
- Create Code, that creates a TForm in C++ Builder,
- Create Code, that calls the TForm in C++ Builder,
- Test your Application.
Code Example for Point 1:
// the following 3 procedure declaration rest in dbgFrame.dll:
procedure create__MyCppFrame(frm: Integer); stdcall;
external 'dbgFrame.dll' name 'create__MyCppFrame';
procedure destroy_MyCppFrame; stdcall;
external 'dbgFrame.dll' name 'destroy_MyCppFrame';
procedure resize__MyCppFrame(frm: Integer); stdcall;
external 'dbgFrame.dll' name 'resize__MyCppFrame';
// Event-Code
procedure TForm2.FormCreate(Sender: TObject);
begin
create__MyCppFrame(
ScrollBox29.Handle, // your TComponent Control Handle
);
end;
procedure TForm2.FormResize(Sender: TObject);
begin
resize__MyCppFrame(ScrollBox29.Handle);
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
destroy_MyCppFrame;
end;
Code Example for Point 3:
#include <vcl.h>
#include <Classes.hpp>
#include <Graphics.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
#include <ExtCtrls.hpp>
#include <Buttons.hpp>
#include <Dialogs.hpp>
#include <ComCtrls.hpp>
#include "clientForm.h"
#pragma hdrstop
#pragma package(smart_init)
// --------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
// --------------------------------------------------------------------
static TForm * myParentForm = NULL;
static TPanel * myPanel_1 = NULL;
class MyOpenFileClass: public TObject
{
public:
void __fastcall myFormActivate(System::TObject* Sender) {
ShowWindow(Application->Handle, SW_HIDE);
}
};
static MyOpenFileClass * myOpenFileClass = NULL;
extern "C"
__declspec(dllexport) void
__stdcall create__MyCppFrame( int ParentForm )
{
try {
RECT rect;
HWND parw = (HWND)ParentForm;
GetWindowRect(parw,&rect);
MapWindowPoints(HWND_DESKTOP, GetParent(parw), (LPPOINT)&rect, 2);
myParentForm = new TForm((HWND)ParentForm);
myParentForm->OnActivate = &(myOpenFileClass->myFormActivate);
myParentForm->BorderStyle = bsNone;
myParentForm->Width = rect.right;
myParentForm->Height = rect.bottom;
myPanel_1 = new TPanel(myParentForm);
myPanel_1->Parent = myParentForm;
myPanel_1->Align = alLeft;
myPanel_1->Font = new TFont();
myPanel_1->Visible = true;
myParentForm->Visible = true;
DWORD dwExStyle = GetWindowLong(Application->Handle, GWL_EXSTYLE);
dwExStyle &= ~WS_EX_APPWINDOW ;
dwExStyle |= WS_EX_TOOLWINDOW;
SetWindowLong(Application->Handle, GWL_EXSTYLE, dwExStyle);
ShowWindow (Application->Handle, SW_HIDE);
}
catch (Exception &e) {
AnsiString s1 = "Error in external module: \r\n";
AnsiString s2 = e.Message;
AnsiString s3 = s1 + s2;
ShowMessage(s3);
}
}
Note to the Reader's: I have give a effort for this Post, but I am too tired to make any changes there. So you can give me Feedback, and I try answer.
If you have other Questions that are related to this Posting, and/or StackOverflow, please don't use my E-Mail, Discuss it here.
Thank you for reading, and watching :-) Jens