0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Autodesk Inventor API Hacking (WPFのWindowを表示)

Last updated at Posted at 2019-12-27

#0. はじめに
Freeradicalの中の人、yamarahです。
いつまでもWinFormsではつらいので、WPFを使おうという話しです。
WPF自体については解説しません。Formの代わりにWPFのWindowを表示するには、どうすれば良いのかを説明します。

#1. ProjectにWPFを追加するための準備
Visual Studio → ソリューション エクスプローラーで右クリック → 追加新しい項目で'WPF'が無い場合があります。
AddWPF.PNG
上の画像にはWPFがありますが、もし見当たらない場合は、ProjectでUseWPFtrueにします。
これで、新しい項目の追加WPFが表示されるはずです。
また、実際にWPFのWindowを追加した後に、

Windows デスクトップ アプリケーションを作成するには、Microsoft.NET.Sdk.WindowsDesktop が必要です。現在の SDK では、'UseWpf' と 'UseWindowsForms' はサポートされていません。

と警告が出る場合があります。この場合は、警告に従って、Projectの1行目を

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

に変更しましょう。
これらの変更を施したProjectの冒頭部分は、このようになると思います。

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net472</TargetFramework>
    <UseWPF>true</UseWPF>
    <RootNamespace>InvAddIn</RootNamespace>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>

以前の記事(C#8.0、そして.NET Core3.0)に従って、nullableも有効にしています。
ちなみに、WindowsFormsも使う場合は、

    <UseWindowsForms>true</UseWindowsForms>

を加えます。

#2. 実際に表示する
表示するだけなら、単純に

var wpfWindow = new Window1();
wpfWindow.ShowDialog();    // modalの場合
// wpfWindow.Show();       // modelessの場合

とすれば、表示されます。しかし、これだけだと、WinFormsについて書いた以前の記事(Modeless FormのZ order)と同じ問題が発生して、WindowがInventorの後ろに隠れうる状態です。
WPFでは、WinFormsの場合と違って、modalでもInventorの後ろに回ります。
解決策は、modelessなWinFormsと同じように親子関係の設定をする必要があり、WPFでは次のようにします。

var wpfWindow = new Window1();
// Window Handleを操作するためのHelper
var helper = new System.Windows.Interop.WindowInteropHelper(wpfWindow);
// 親を設定する
helper.Owner = new System.IntPtr(InventorApplication.MainFrameHWND);
// 表示する
wpfWindow.ShowDialog();    // modalの場合
// wpfWindow.Show();       // modelessの場合

#3. Dockable Windowに表示したい
基本的には、WinFormsの場合と同じ手順でWPF Windowを表示できます。
(helperからHandleを取る前に、EnsureHandle()を呼ぶのと、VisibilityをVisbleにするのを忘れないように!!)
しかしながら、残念なことにキー入力ができません。Inventor Forum

Dockable Window with WPF controls, don't receive keyboard input

によると、Inventor 2018から発病しているbugっぽいです。現時点(Inventor 2020.2)では、直接WPF Windowを貼っても、WinFormsで包んでも、キー入力ができません。
    ↓
2020.01.09 追記
Messageをhookして、WM_GETDLGCODEに応答することで、キー入力できるようになることが分かりました。
以下は、そのサンプルコードです。

public void Activate(ApplicationAddInSite addInSiteObject, bool firstTime)
{
    InventorApplication = addInSiteObject.Application;

    // WPF Windowの初期化
    var wpfWindow = new WpfWindow();
    wpfWindow.WindowStyle = System.Windows.WindowStyle.None;
    wpfWindow.ResizeMode = System.Windows.ResizeMode.NoResize;
    wpfWindow.Visibility = System.Windows.Visibility.Visible;

    // WPF WindowのHandleを得る
    var helper = new WindowInteropHelper(wpfWindow);
    helper.EnsureHandle();
    var handle = helper.Handle;

    // Dockable Windowの作成
    var dockableWindow = InventorApplication.UserInterfaceManager.DockableWindows.Add(System.Guid.NewGuid().ToString(), "Test", "Test");
    dockableWindow.AddChild(handle);

    // Key hookをセット
    HwndSource.FromHwnd(handle).AddHook(WndProc);
}

private const UInt32 DLGC_WANTARROWS = 0x0001;
private const UInt32 DLGC_WANTTAB = 0x0002;
private const UInt32 DLGC_WANTALLKEYS = 0x0004;
private const UInt32 DLGC_HASSETSEL = 0x0008;
private const UInt32 DLGC_WANTCHARS = 0x0080;
private const UInt32 WM_GETDLGCODE = 0x0087;

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == WM_GETDLGCODE)
    {
        handled = true;
        return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTTAB | DLGC_WANTALLKEYS);
    }
    return IntPtr.Zero;
}

#99. 親の記事に戻る
Autodesk Inventor API Hacking (概略)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?