开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜