Host a Delphi 7 application process in .net
HI!
I'm trying to host a delphi 7 vcl application in a .Net wpf application. Everything works great except modal dialogs do not behave like modal dialogs, the parent window isn't disabled. This is my code so far: class MySimpleDelphiHost : HwndHost
{
private Process _appProc;
public IntPtr hwndHost;
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
_appProc = new Process();
_appProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_appProc.StartInfo.FileName = @"MySimpleDelphiApplication.exe";
_appProc.Start();
Thre开发者_JS百科ad.Sleep(1000);
hwndHost = Win32API.FindWindow("TMainForm", null);
int oldStyle = Win32API.GetWindowLong(hwndHost, Win32API.GWL_STYLE);
Win32API.SetWindowLong(hwndHost, Win32API.GWL_STYLE, (oldStyle | Win32API.WS_CHILD) & ~Win32API.WS_BORDER);
Win32API.SetParent(hwndHost, hwndParent.Handle);
Win32API.ShowWindowAsync(hwndHost, Win32API.SW_SHOWMAXIMIZED);
return new HandleRef(this, hwndHost);
}
protected override void DestroyWindowCore(HandleRef hwnd)
{
_appProc.Kill();
}
}
If I host a none delphi application this works just fine. Any ideas?
I created a demo http://www.easy-share.com/1913154119/SimpleDelphiAppHosting.zip . Sorry for the hosting site.
FWIW have you tried setting:
Form.ModalPopupMode = pmExplicit;
Form.ModalParent = ParentForm;
Form.ShowModal;
Also you don't have to change tApplication in the Forms unit, you could do
var
OldWndProc: Pointer;
function NewWndProc(Handle: hWnd; Msg: UINT; PW: WPARAM; PL: LPARAM): LRESULT stdcall;
begin
if Msg = WM_ENABLED then
begin
doWhatever();
result := 1; // handled
end else
result := CallWindowProc(OldWndProc, Handle, Msg, PW, PL);
end;
initialization
OldWndProc := Pointer(SetWindowLong(Application.Handle, GWL_WNDPROC,
LongInt(@NewWndProc)));
I figured it out.
The VCL TApplication enumerates windows using the EnumThreadWindows function. Because the main form is the Child of my WPF application the EnumThreadWindows doesn't find my mainform.
To fix this I had to copy the Forms.pas and change TApplication.WndProc procedure. I added this code in the WM_ENABLE case
if TWMEnable(Message).Enabled then
begin
if Application.MainForm <> nil then
begin
ParentWindow := GetParent(Application.MainForm.Handle);
if ParentWindow <> 0 then
EnableWindow(ParentWindow, true);
end;
....
end else
begin
Default;
if Application.MainForm <> nil then
begin
ParentWindow := GetParent(Application.MainForm.Handle);
if ParentWindow <> 0 then
EnableWindow(ParentWindow, false);
end;
....
There maybe a better solution and I havn't tested this very well, but it seems to work.
in your code
hwndHost = Win32API.FindWindow("TMainForm", null);
make sure your forms name is not TMainForm (i suspect that) , and you said it worked on other apps so how you identified the names ,
make sure why you used TMainForm
to refer the form named TMainForm
or to refer the form named MainForm
or to refer the MainForm // (Application.mainform)
if you want to show the delphi form as a model form of c# app just put delphi form into a delphi dll and call it as a form from c# , and if you also want a stand alone delphi exe (share one form among c# and delphi appps)the call the dll fron Delphi app
but your comment
If just the parent window of the Delphi application gets disabled then that would be great.– GunnarIF
made me think like the following
IF you just want to disable the parent form of Delphi application (as you have mentioned in comment for the question )
remove the model form declaration like the above code from the project.dpr (if any)
Application.CreateForm(TForm2, Form2); // form2 is your modal dialogs
now
add unit2 to uses list //unit2 is the unit of modelform
add the following code to the event you want
procedure TForm1.Button1Click(Sender: TObject);
var
f: TForm ;
begin
F := TForm2.Create(nil);
f.ShowModal ;
end;
don't forget to make property of form2 visible to false (It is on the form2 property inspector) (only if the form is invisible the showmodel function will work)
I have posted this answer according to what you have mentioned in the comment of the question its still very hard to identify what is your problem
Yes Your code is realy working . The main form inside c# application is disabled when model dialog is showing , but the c# app(now it is just the title bar and the stuff out side the mainform)are not getting disabled , and you said it worked in other apps , so vcl is a problem i think ,
just now i checked your demo , i think it is a problem of VCL (as you said it worked in other development tools) even showmessage function does not disable the main form ;
The better answer i can predict is
use DLLs place vcl form inside the dll and call it from c# , it will work
精彩评论