先添加一个用户控件
打开 UserControl1.xaml 文件 把控件类型 UserControl 改为 : ToolSettingsHost
添加一个按钮 作为内容显示
<wpf:ToolSettingsHost x:Class="TestAddin.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:wpf="clr-namespace:Bentley.MstnPlatformNET.WPF;assembly=Bentley.MicroStation.WPF" mc:Ignorable="d" Width="300" Height="150"> <Grid> <Button Content="点击" VerticalAlignment="Center" Padding="10,5,10,5"></Button> </Grid> </wpf:ToolSettingsHost>
打开 UserControl1.xaml.cs 把UserControl1 的继承类 UserControl 也改为: ToolSettingsHost
using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Bentley.MstnPlatformNET.WPF; namespace TestAddin { /// <summary> /// UserControl1.xaml 的交互逻辑 /// </summary> public partial class UserControl1 : ToolSettingsHost { public UserControl1() { InitializeComponent(); } } }
创建控件实列
UserControl1 userControl1=new UserControl1(); userControl1.Attach(addin);
使用ToolSettingsHost 附加到 MicroStation 之后效果为
因为我的显示器分辨率缩放值为125%,1.25倍窗口(MSWindow)进行缩放, 所以实际窗口的大小为原有控件的宽高除以1.25倍;
导致控件内容(ElementHost)大小(宽,高)大于窗口(MSWindow)大小(宽,高),所以显示内容不全; 那么只要修正ElementHost 大小跟窗口大小为一致就行了;
解决方案:
修改 UserControl1.xaml.cs 内容 为:
/// <summary> /// UserControl1.xaml 的交互逻辑 /// </summary> public partial class UserControl1 : ToolSettingsHost { public UserControl1() { InitializeComponent(); } [DllImport("stdmdlbltin.dll", SetLastError = true)] public static extern int mdlNativeWindow_getToolSettingsWindow(out IntPtr windowPp); [DllImport("nativewindow.dll", SetLastError = true)] public static extern int mdlNativeWindow_setSize(IntPtr windowP, int width, int height); public override void Attach(IMatchLifetime addIn) { // AdjustWidthAndHeight(); base.Attach(addIn); // ElementHost.Width = (int)RenderSize.Width; // ElementHost.Height = (int)RenderSize.Height; ToolSettingsUtil.SetToolSettingsWindowSize(ElementHost.Width, ElementHost.Height); } /// <summary> /// 根据缩放比重新调整控件大小 /// </summary> public new void AdjustWidthAndHeight() { double dipScale = GetDipScale(); Width *= dipScale; Height *= dipScale; } /// <summary> /// 获取显示器缩放比 /// </summary> /// <returns></returns> public double GetDipScale() { Graphics g = Graphics.FromHwnd(IntPtr.Zero); double dipScale = 1; switch (g.DpiX) { case 96: dipScale = 1; break; case 120: dipScale = 1.25; break; case 144: dipScale = 1.5; break; case 168: dipScale = 1.75; break; case 192: dipScale = 2; break; } return dipScale; } }
方法1:ElementHost 跟随窗口(MSWindow)保持统一 但是不考虑原控件缩放的问题 实际会跟设定大小不一样
public override void Attach(IMatchLifetime addIn) { base.Attach(addIn); ElementHost.Width = (int)RenderSize.Width; ElementHost.Height = (int)RenderSize.Height; }
方法2:ElementHost 跟随窗口(MSWindow)保持统一,考虑原控件大小 先乘以一个缩放比 Attach 之后会自动减去之前乘以的缩放比 结果会保持原控件大小 但是检测系统显示器缩放比的方法是否 绝对可靠 有待考证
public override void Attach(IMatchLifetime addIn) { AdjustWidthAndHeight(); base.Attach(addIn); ElementHost.Width = (int)RenderSize.Width; ElementHost.Height = (int)RenderSize.Height; }
方法3:Attach之后 直接再次修改窗口(MSWindow) 的大小 保持原有大小 这里进行了 CLR函数封装
public override void Attach(IMatchLifetime addIn) { base.Attach(addIn); ToolSettingsUtil.SetToolSettingsWindowSize(ElementHost.Width, ElementHost.Height); }
// ClR 封装函数 void ToolSettingsUtil::SetToolSettingsWindowSize(int width,int height) { MSWindow* MSWPtr; mdlNativeWindow_getToolSettingsWindow(&MSWPtr); mdlNativeWindow_setSize(MSWPtr,width,height); }
方法4:同方法3,不需要封装 使用P/Invoke方式调用 但是声明 mdlNativeWindow_setSize() 编译报错,有会的希望指点一下
(由郭老师 指出问题所在 函数封装在 nativewindow.dll 中) 推荐使用此方法
public override void Attach(IMatchLifetime addIn) { base.Attach(addIn); mdlNativeWindow_getToolSettingsWindow(out IntPtr windowPp); mdlNativeWindow_setSize(windowPp, ElementHost.Width, ElementHost.Height); }
最终效果图:
编译报错,报什么错误?
stdmdlbltin.dll 找不到 mdlNativeWindow_setSize() 函数
这个函数在:nativewindow.dll,另外应该不是编译的时候报错吧,是运行的时候出的这个错误吧
郭老师 ,这种 P/Invok C++ 函数是怎么查归属dll的? 用什么方法?
这个目前没有太好的办法,我是通过dumpbin工具导出dll中的函数去查看的。
好的,谢谢郭老师!