【问题标题】:Hosting of Delphi Controls in a WPF Application using Com Component not working for Delphi Buttons, checkbox , radio and date picker?使用 Com 组件在 WPF 应用程序中托管 Delphi 控件不适用于 Delphi 按钮、复选框、单选和日期选择器?
【发布时间】:2022-09-25 16:20:22
【问题描述】:

我使用 ActiveX 库创建了一个 Delphi 控件,并使用 COM 类型库将其托管在 WPF 应用程序中。 我可以看到在 WPF 中成功加载了 Label 和 Delphi 侧背景模板颜色,但它没有显示按钮、Datepicker、Checkbox 等控件。 只有标签文本和背景才能正确呈现。 如果我遗漏任何东西,有人可以帮忙吗?

这是我的示例 Delphi UI

托管到 WPF 后,它只加载如下

我正在使用 HwndHost ,下面的代码用于 WPF 托管

public class DelphiControlHost : HwndHost
{

    [DllImport(\"user32.dll\")]
    static extern IntPtr CreateWindowEx(int dwExStyle, string lpszClassName, string lpszWindowName, int style, int x, int y, int width, int height, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

    [DllImport(\"user32.dll\")]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport(\"user32.dll\")]
    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport(\"user32.dll\")]
    static extern bool DestroyWindow(IntPtr hWnd);

    int height;
    int width;
    IntPtr child;

    public DelphiControlHost(double initialWidth, double initialHeight, IntPtr hostedControl)
    {
        width = (int)initialWidth;
        height = (int)initialHeight;
        child = hostedControl;
    }

    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        
        var host = CreateWindowEx(0, \"static\", null, 0x40000000 | 0x10000000, 0, 0, height, width, 
            hwndParent.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
      
       

        SetParent(child, host);
        ShowWindow(child, 5);
        return new HandleRef(this, host);
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {
        DestroyWindow(hwnd.Handle);
    }
}

MainWindow.xaml.cs 文件

public partial class MainWindow : Window
{
    [DllImport(\"msvcr110.dll\", CallingConvention = CallingConvention.Cdecl)]
    public static extern int _fpreset();

    private ProFileUXCOMImpl service;

    public MainWindow()
    {
        _fpreset();
        InitializeComponent();
        MainWindow_OnActivated(null,null);
    }

    private void MainWindow_OnActivated(object sender, EventArgs e)
    {
        if (service != null)
            return;
        service = new ProFileUXCOMImpl();
        // var control = service.GetMainFrame(DelphiHostElement.ActualWidth, DelphiHostElement.ActualHeight);
        var control = service.GetMainFrame(600, 300);
        DelphiHostElement.Child = new DelphiControlHost(DelphiHostElement.ActualWidth, DelphiHostElement.ActualHeight, control);
    }

    private void MainCanvas_OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        service?.WindowResized();
    }
}

Delphi 端的以下代码片段

unit ProFileUXCOMU;

interface

uses
  SysUtils, ComObj, ComServ, ProFileUXCOM_TLB, Winapi.ActiveX, StdVcl,Vcl.Forms, Winapi.Windows,
  MainFormU, MainFrameU;

type

  ProFileUXCOMImpl = class(TComObject, IProFileUXCOM)
  private
    MainFrame: TMainFrame;
    MainHandle: Cardinal;
    MainPointer: Pointer;
    MainForm: TMainForm;
  protected
    function GetMainFrame(width: Double; height: Double): Pointer; stdcall;
    procedure WindowResized(width: Double; height: Double); safecall;  procedure IProFileUXCOM.WindowResized = IProFileUXCOM_WindowResized;

    procedure IProFileUXCOM_WindowResized; safecall;
  end;

implementation

function ProFileUXCOMImpl.GetMainFrame(width: Double; height: Double): Pointer; stdcall;
begin
  MainForm := TMainForm.Create(Application);
  MainForm.ClientWidth := Trunc(width);
  MainForm.ClientHeight := Trunc(height);
  MainHandle := MainForm.Frame.Handle;
  MainPointer := System.Pointer(MainHandle);
  Result := MainPointer;
end;

procedure ProFileUXCOMImpl.WindowResized(width: Double; height: Double); safecall;
begin
  MainForm.ClientWidth := Trunc(width);
  MainForm.ClientHeight := Trunc(height);
end;

procedure ProFileUXCOMImpl.IProFileUXCOM_WindowResized;
begin

end;

initialization

  TComObjectFactory.Create(ComServer, ProFileUXCOMImpl, CLASS_ProFileUXCOMImpl, \'ProFileUXCOMImpl\', \'\', ciMultiInstance, tmApartment);

end.

    标签: c# wpf delphi com hwndhost


    【解决方案1】:

    我敢打赌 WPF 应用程序不会旋转消息循环。在 Delphi 应用程序中,这通常在 Application.Run 中完成。但这是一个阻塞调用。在您的 WPF 应用程序中,您可以创建一个计时器,该计时器将定期调用 COM 对象的新导出函数,例如 WindowResized。在 Delphi 端调用 Application.ProcessMessages 的那个函数内部。

    如果您不想自己处理所有这些低级错误,可以尝试现有库:https://www.remobjects.com/hydra/

    【讨论】:

      猜你喜欢
      • 2014-09-13
      • 1970-01-01
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      相关资源
      最近更新 更多