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。对不起托管网站。
答案 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#调用它,它将起作用