在.net中托管Delphi 7应用程序进程

时间:2010-11-30 23:06:27

标签: .net delphi

HI!
我正在尝试在.Net wpf应用程序中托管delphi 7 vcl应用程序。 一切都很好,除了模态对话框不像模态对话框那样,父窗口没有被禁用 到目前为止,这是我的代码:

   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();
         Thread.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();         
      }
   }

如果我主持一个无delphi应用程序,这可以正常工作。有什么想法吗?

我创建了一个演示http://www.easy-share.com/1913154119/SimpleDelphiAppHosting.zip。对不起托管网站。

5 个答案:

答案 0 :(得分:2)

FWIW你试过设置:

Form.ModalPopupMode = pmExplicit;
Form.ModalParent = ParentForm;
Form.ShowModal;

此外,您不必在Forms单元中更改tApplication,您可以

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

答案 1 :(得分:1)

我明白了。
VCL TApplication使用EnumThreadWindows函数枚举窗口。因为主窗体是我的WPF应用程序的子窗口,所以EnumThreadWindows找不到我的mainform。
要解决这个问题,我必须复制Forms.pas并更改TApplication.WndProc过程。我在WM_ENABLE案例中添加了这段代码

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

可能有一个更好的解决方案,我没有对此进行过很好的测试,但似乎有效。

答案 2 :(得分:0)

代码

hwndHost = Win32API.FindWindow("TMainForm", null);

确保您的表单名称不是TMainForm(我怀疑),并且您说它可以在其他应用上工作,所以您如何识别名称,

确定您使用TMainForm的原因

引用名为 TMainForm

的表单

或引用名为 MainForm

的表单

或引用MainForm //( Application.mainform

答案 3 :(得分:0)

如果你想将delphi表单显示为c#app的模型形式,只需将delphi表单放入delphi dll并将其作为c#的表单调用,如果你还想要一个独立的delphi exe(共享一个表单) c#和delphi appps)调用dll fron Delphi app

但是你的评论

  

如果只是父窗口的话   然后Delphi应用程序被禁用   那会很棒.- GunnarIF

让我思考如下

如果您只想禁用Delphi应用程序的父窗体 (正如你在评论中提到的那样)

从project.dpr(如果有的话)

中删除模型表单声明,如上面的代码
Application.CreateForm(TForm2, Form2); // form2 is your modal dialogs

现在

将unit2添加到使用列表// unit2是modelform的单位

将以下代码添加到您想要的事件

procedure TForm1.Button1Click(Sender: TObject);
var
f: TForm  ;
begin
 F  := TForm2.Create(nil);
 f.ShowModal ;

end;

不要忘记将form2的属性显示为false(它位于form2属性检查器上)(仅当表单不可见 showmodel 函数才有效)

我根据您在问题评论中提到的内容发布了这个答案,但仍然很难确定您的问题

答案 4 :(得分:0)

是您的代码真的有效。当显示模型对话框时,c#应用程序中的主要表单被禁用,但是c#app(现在它只是标题栏和mainform外面的东西)没有被禁用,并且你说它在其他应用程序中有效,所以vcl我认为是一个问题,

刚才我检查了你的demo,我认为这是VCL的一个问题(正如你所说的在其他开发工具中工作)甚至showmessage函数也没有禁用主窗体;

我能预测的更好的答案是

使用DLL将vcl表单放在dll中并从c#调用它,它将起作用