tdk_man
asked on
Program Within A Program
Bit of a strange one this...
Is it possible at all to create a window in a Delphi program so that an external exe (not written in Delphi) can be run and it's output directed to that window?
I'm writing a Delphi app which let's you create the data for a 3D terrain for use in a DirectX programming environment. Once the terrain has been created I'd like to be able to view a 3D rendering of the scene in the Delphi app.
Rather than installing a DirectX component in Delphi and having to learn how to use it, I could write a small exe in the 3D programming language which simply accepts the terrain data from the Delphi app and will display the 3D view in say a 320x200 window.
Is there any way I could 'lock' this window to my delphi app's screen to make it look like it isn't a separate exe?
Or is there a better way (if it's possible at all).
TDK_Man
Is it possible at all to create a window in a Delphi program so that an external exe (not written in Delphi) can be run and it's output directed to that window?
I'm writing a Delphi app which let's you create the data for a 3D terrain for use in a DirectX programming environment. Once the terrain has been created I'd like to be able to view a 3D rendering of the scene in the Delphi app.
Rather than installing a DirectX component in Delphi and having to learn how to use it, I could write a small exe in the 3D programming language which simply accepts the terrain data from the Delphi app and will display the 3D view in say a 320x200 window.
Is there any way I could 'lock' this window to my delphi app's screen to make it look like it isn't a separate exe?
Or is there a better way (if it's possible at all).
TDK_Man
ASKER
Thanks for that, but I'm having problems with the
setparent(client,maincontr ol.Handle) ;
line.
The help files say it only has one parameter - the handle of the new window (Panel1).
However, the Panel1.Handle property should be a TWinControl which is incompatible with the type required by SetParent() and I can't figure out how to set the new value.
I put the code into FormShow BTW.
TDK_Man
setparent(client,maincontr
line.
The help files say it only has one parameter - the handle of the new window (Panel1).
However, the Panel1.Handle property should be a TWinControl which is incompatible with the type required by SetParent() and I can't figure out how to set the new value.
I put the code into FormShow BTW.
TDK_Man
try using Windows.SetParent instead
or :
function sp(hwnd,parent:THandle):in teger;
begin
result:=setparent(hwnd,par ent);
end;
note that there is no TForm1.sp(...)
wolf
function sp(hwnd,parent:THandle):in
begin
result:=setparent(hwnd,par
end;
note that there is no TForm1.sp(...)
wolf
ASKER
I've got it working... sort of.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Client: THandle;
implementation
{$R *.DFM}
procedure TForm1.FormShow(Sender: TObject);
begin
if winexec('c:\rotate.exe',sw _show) > 32 then
Begin
Sleep(2000);
Client:=FindWindow(nil,PCh ar('Rotate '));
Windows.SetParent(Client,P anel1.Hand le);
showwindow(client,sw_hide) ;
SetWindowLong(client,GWL_S TYLE,GetWi ndowLong( Handle, GWL_STYLE ) and not WS_CAPTION );
showwindow(client,sw_show) ;
setForegroundwindow(client );
Panel1.Invalidate;
Self.Invalidate;
Repaint;
movewindow(client,0,0,clie ntwidth,cl ientheight ,true);
RedrawWindow(client,0,0,RD W_INVALIDA TE+RDW_INT ERNALPAINT +RDW_UPDAT ENOW+RDW_A LLCHILDREN );
UpdateWindow(client);
End
Else
ShowMessage('Winexec Returns Less Than 32!');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseWindow(client);
end;
end.
But, the strange thing is that it will only work if the apps main form is only slightly larger than the TPanel itself.
As soon as you make the main form any larger, the display seems to move away from the top left corner of the Panel - as if it's anchored to the main form instead of the TPanel.
If anyone wants to check it out, the above code is just an empty form with a single TPanel on it and I've uploaded Rotate.exe that I've made for putting on the root of drive C: to http://www.matedit.com/rotate.zip.
TDK_Man
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Client: THandle;
implementation
{$R *.DFM}
procedure TForm1.FormShow(Sender: TObject);
begin
if winexec('c:\rotate.exe',sw
Begin
Sleep(2000);
Client:=FindWindow(nil,PCh
Windows.SetParent(Client,P
showwindow(client,sw_hide)
SetWindowLong(client,GWL_S
showwindow(client,sw_show)
setForegroundwindow(client
Panel1.Invalidate;
Self.Invalidate;
Repaint;
movewindow(client,0,0,clie
RedrawWindow(client,0,0,RD
UpdateWindow(client);
End
Else
ShowMessage('Winexec Returns Less Than 32!');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseWindow(client);
end;
end.
But, the strange thing is that it will only work if the apps main form is only slightly larger than the TPanel itself.
As soon as you make the main form any larger, the display seems to move away from the top left corner of the Panel - as if it's anchored to the main form instead of the TPanel.
If anyone wants to check it out, the above code is just an empty form with a single TPanel on it and I've uploaded Rotate.exe that I've made for putting on the root of drive C: to http://www.matedit.com/rotate.zip.
TDK_Man
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Slick812:
The main form of the Delphi application will contain all the options and buttons for the landscape generator and the window (TPanel) on the form will simply display a 3D view of the terrain being created.
I could save the terrain data to disk and then run a program written in the 3D language which would load the terrain data and show the landscape. However it wouldn't be very user-friendly if you had to load another program to see the results every time you changed something!
A better way would be to have the 3D exe running at the same time - accepting data from the Delphi application when data changes and updating the 3D display in real time.
Using this method, to the user, it would look like they were seeing a 3D window in the Delphi application.
As I said before, the only real alternative is something like the WDX8 or DelphiX components and having to learn how to use them from scratch.
TDK_Man
The main form of the Delphi application will contain all the options and buttons for the landscape generator and the window (TPanel) on the form will simply display a 3D view of the terrain being created.
I could save the terrain data to disk and then run a program written in the 3D language which would load the terrain data and show the landscape. However it wouldn't be very user-friendly if you had to load another program to see the results every time you changed something!
A better way would be to have the 3D exe running at the same time - accepting data from the Delphi application when data changes and updating the 3D display in real time.
Using this method, to the user, it would look like they were seeing a 3D window in the Delphi application.
As I said before, the only real alternative is something like the WDX8 or DelphiX components and having to learn how to use them from scratch.
TDK_Man
OK, I read your last comment and I agree with your statements, as far as I can understand it, , I do not really follow your thoughts or your intent to say something about code or methods, at least for the code in my comment?
In that I had hoped that your landscape program could run on your delphi programs form as a child window at the same time, , maybe with the code I gave, which seems to work with a notepad. . ., but I may have been off target, sorry about that
In that I had hoped that your landscape program could run on your delphi programs form as a child window at the same time, , maybe with the code I gave, which seems to work with a notepad. . ., but I may have been off target, sorry about that
ASKER
Sorry, I misunderstood you.
When you said "another window is not nesary (TPanel)" I thought you were suggesting that the TPanel wasn't needed and the whole Form should be used to display the 3D view. It didn't click that you were actually suggesting a 'child' window which actually is a nice idea!
My comments in the last post were based on my incorrect asssumption of what you meant. :)
"I do not really follow your thoughts or your intent to say something about code or methods"
Sorry, I don't know what you are referring to here. I haven't mentioned either.
Now I know what you are suggesting, I'll try your method and see what happens.
Thanks for the help...
TDK_Man
When you said "another window is not nesary (TPanel)" I thought you were suggesting that the TPanel wasn't needed and the whole Form should be used to display the 3D view. It didn't click that you were actually suggesting a 'child' window which actually is a nice idea!
My comments in the last post were based on my incorrect asssumption of what you meant. :)
"I do not really follow your thoughts or your intent to say something about code or methods"
Sorry, I don't know what you are referring to here. I haven't mentioned either.
Now I know what you are suggesting, I'll try your method and see what happens.
Thanks for the help...
TDK_Man
ASKER
Thanks for that Slick812 - it worked perfectly! :)
I modified my exe to create a 320x240 window without a title bar and altered the MoveWindow line to:
MoveWindow(RotateApp, Panel1.Left+1,Panel1.Top+1 , 318, 238, True);
and the exe display appears to exactly fit in the TPanel on the main form!
I'm very impressed and very thankful. You deserve the points.
TDK_Man
I modified my exe to create a 320x240 window without a title bar and altered the MoveWindow line to:
MoveWindow(RotateApp, Panel1.Left+1,Panel1.Top+1
and the exe display appears to exactly fit in the TPanel on the main form!
I'm very impressed and very thankful. You deserve the points.
TDK_Man
Do you think of something like that? (not tested)
your program is at c:\theprogram.exe
and is viewed in maincontrol (eg. a TPanel)
.....
var client : THandle;
wtitle := 'ProgramCaption';
chdir('c:\');
if winexec('theprogram.exe',S
begin
client:=FindWindow(nil,wTi
end;
if client=0 then showmessage('Can't start the application')
else begin
setparent(client,maincontr
showwindow(client,sw_hide)
SetWindowLong(client,GWL_S
showwindow(client,sw_show)
setForegroundwindow(client
maincontrol.Invalidate;
self.Invalidate;
repaint;
movewindow(client,0,0,clie
RedrawWindow(client,0,0,RD
UpdateWindow(client);
....
wolf