WPF 4.6 での修正点、透明な子ウィンドウや High DPI 改善について

Japan C# Users Group の Visual Studio 2015 リリース記念勉強会 にて、.NET Framework 4.6 で WPF に加わった修正点について発表しました。 大きな変更はなく、細かい機能追加やバグ修正程度なのですが、2つ程ピックアップして紹介しています。

Transparent Child Window support

WPF の子ウィンドウが透過できるようになります。

そもそも子ウィンドウをどういうときに使うのか… というと、Win32 相互運用シナリオや、MDI を実現したいケースでしょうか。

Win32 相互運用、つまり WPF ウィンドウ内に HwndHost (WebBrowser や WindowsForms コントロール、Win32 要素など) を表示するとき、MSDN にも記述がある通り、様々な制約があります。 特に、「HwndHost は、同じトップレベル ウィンドウの他の WPF 要素の上に表示されます。」というのが曲者で、ZIndex 等を一切無視し、HwndHost が一番上に表示されるため、その上に WPF 要素を表示することはできません。

Browser (HwndHost) は必ず全要素の上に描画されてしまう

ウィンドウ ハンドルを 1 つしか持たない WPF アプリと、それぞれの要素がウィンドウ ハンドルを持つ GDI 等の旧来のテクノロジーは、まさに水と油のような関係であり、仕組み上仕方ないことではあります。 そこで、WebBrowser や過去の資産を HwndHost 上で表示し、さらにその上に WPF 要素を表示したいとき、独立したウィンドウ ハンドルを持つ子ウィンドウはその解決方法のひとつとなります (他には、System.Windows.Controls.Primitives.Popup などが使えたり)。

(ちなみに Win32 相互運用についてはいくらかノウハウを持っているのですが、個人的にこれ以降使う気がしないので、ブログにまとめていません… もし知りたい方がいらっしゃれば @Grabacr07 に圧力をかけまくるとそのうち書き始めるかもしれません…)

また、WPF は MDI をサポートしていません。 個人的には MDI は好みではない (自宅も職場もトリプル モニター、というマルチ モニター厨なので相性が悪い) ものの、もし実装する場合は、子ウィンドウが役に立つかもしれません。

子ウィンドウを作るコードの例を示します。 一般的な WPF アプリ開発において HwndSourceParameters を使って HwndSource を自作するようなシナリオは殆どなさそうなので、見慣れないかもしれません。

サンプル コード全体は後ほどアップデートするかも。

実行して「Create child」ボタンを押すと、このような MDI 子ウィンドウっぽいものが表示されます。 .NET Framework 4.5.2 またはそれ以前をターゲットにしているアプリでは、17 行目の Background で Alpha に 128 等を指定して透過させようとしても、透明になりません (黒くなるだけ)。

MDI のようなもの (非透過)

そこで、アプリケーションのターゲット フレームワークを .NET Framework 4.6 にした上で、HwndSourceParameters のオブジェクト初期化子に以下を追加します。 また、背景を Alpha に 128 を指定して子ウィンドウのルート要素を透過させてみます。

実行すると以下のように。 子ウィンドウが透過できているのが判るかと思います。

透過した子ウィンドウ

この HwndSourceParameters.UsesPerPixelTransparency プロパティが、.NET Framework 4.6 で追加されたメンバーです。 true を指定すると、上記のように WPF 子ウィンドウが透過できるようになります。

これは、WebBrowser 等の HwndSource に対しても、透過したうえでその上に表示することができます。 よって、先述の Win32 相互運用シナリオにおける HwndHost の前後関係の問題にも寄与できるでしょう。

注意しなければならないのが、この機能を使うためには、アプリケーション マニフェストで Windows 8 向けのビルドであることを明示する必要があるということです。

app.manifest を作ると、上記のようなコードが最初から記述されているはずです。 ここで、Windows 8 のコメントを外すだけです。

余談ですが、app.manifest での指定をせずに UsesPerPixelTransparency=”True” を使用すると、Win32Exception がスローされて表示できません。

High DPI Improvements

Hight DPI 環境下におけるレイアウトの丸め処理が改善されました。

元々どんな問題があったかというと、私の MetroRadiance がモロにその影響を受けていて、こちらの記事 で指摘して頂いています。 この場合のレイアウト システムの詳細な動作については把握できていませんが、1 dip (デバイス非依存ピクセル) を指定したとき、DPI 150 % 環境下で Round(1 * 1.5) = 2 になるはずが、1 になることがあるようです。

.NET Framework 4.6 では、このような BorderThickness や Margin のレイアウトの丸め処理が改善されており、ズバり上記のような問題が発生しなくなりました。 1 枚目が .NET Framework 4.5.2 での実行結果、2 枚目が 4.6 での実行結果です。

Bottom だけ 1px になってる。超ダサい。 すべて 2px に。キレイ。

この改善は、.NET Framework 4.6 をターゲットにしたアプリであれば、特にコードの修正等は必要なく、既定で適用されます (要はバグ修正的なノリなんですかね)。 また、.NET Framework 4.5.2 またはそれ以前をターゲットにしたアプリでも、.NET Framework 4.6 がインストールされている環境であれば、app.config に以下のようなコードを記述することで、この改善を受けることができます。

Switch.MS.Internal.DoNotApplyLayoutRoundingToMarginsAndBorderThickness (長ぇ)。

そして、High DPI に関しては、上記の改善のほかに “Multi-DPI setup” 環境下での改善も入っているようです (Per-Monitor DPI のこと?)。 ブラックアウトする問題が修正されているそうですが、そういう事象に遭遇したことがないので、よくわからず…。 調査中。

Visual Studio 2015 での新機能

WPF 開発で使える Visual Studio 2015 の新機能をちょこっと紹介。

Peek Definition と CodeLens はセッション資料にある通りです。 Live VisualTree と Live Property Explorer は、アプリ実行中に VisualTree の参照や各要素のプロパティ値の修正を可能にするものです。 Web 開発におけるブラウザーの開発者ツールのような感覚です。

実行中にガイドを表示しながら要素を選択して…

ガイドを表示しながら要素を選択(画像クリックで GIF アニメーション)

Live VisualTree で要素を選択したりデザイナー上に一発で呼びだしたり…

要素選んだりデザイナーで表示したり(画像クリックで GIF アニメーション)

Live Property Explorer で実行中にプロパティを書き替えたり。

プロパティを書き替え(画像クリックで GIF アニメーション)

すばらすぃ。 アプリのデバッグ効率が飛躍的に向上します。 まじ最強。

まとめ

という感じでした。 他にもタッチ サポートが改善されたりしているようですが、バグ修正っぽいのでスルーしています。

何か判ったことがあれば追記します。

WPF をこれから始める方へ

ぶっちゃけると宣伝です。

5 月発売の日経ソフトウエア (7 月号) から、「基礎からわかる C# デスクトップ アプリ開発」という連載が始まっています。 主に「C# は知っているが、アプリを作ったことはない」という人に向けた、WPF アプリ開発の入門連載です。 全 6 回を予定しており、私と @tanaka_733 さんと隔月で担当しています。

日経ソフトウエア
新連載
基礎からわかる C# デスクトップアプリ開発

発売済みの連載第 1 回は私が担当しました。 初回ということで、WPF 概要と、簡単なデモアプリ作成を通じた特徴の解説になります。

  • WPF とは
  • Visual Studio で WPF プロジェクト作成
  • XAML と分離コード (コード ビハインド)
  • WPF の特徴
    • グラフィックス
    • レイアウト
    • コントロールとカスタマイズ

Visual Studio Community 2013 がリリースされ、従来の Professional 相当の開発環境が使えるようになりました。 この連載では、Visual Studio Comunit 2013 を使って、無料でできる範囲の WPF アプリ開発について解説していきます。

本っっっ当に初心者向けの内容です。 Visual Studio のインストール方法から解説しているレベルです (それは編集さんが書き足して下さったものですが)。

これから WPF 始めたい (Windows デスクトップ アプリを作ってみたい) という方、特に「何から始めればいいかわからない」という方は読んでみて頂けると嬉しいです。

MVA

そのほか、これから WPF や XAML を始めるとき、役に立つリソースを紹介します。

Microsoft Virtual Academy (MVA) というオンライン トレーニング サイトがあります。 Microsoft が提供するもので、全コース無償で受講することができます。

Thumb コントロールで Photoshop のナビゲーターを再現する

@kurosawa0626 さんが Photoshop のナビゲーター的なものを作りたい、という話をしていて、過去に似たようなものを作ったことがあったので共有してみます。 記事内のコードは WPF で書いたものですが、WinRT でも一部を除いてほぼ同じようなコードで書けるはずです。

2015/04/12 追記:
@okazuki さんが、WinRT でやる場合の補足記事を書いてくださいました。
http://okazuki.hatenablog.com/entry/2015/04/11/195941

目標

今回は、Thumb コントロールを活用し、Photoshop のナビゲーターと同等のものを作ります。 ScrollViewer に表示されているコンテンツについて、以下を実現しましょう。

  • サムネイルの表示
  • Viewport (赤枠部分) の表示
  • 赤枠のドラッグで Viewport の位置変更

↓ みたいなやつ

Photoshop

最終的に完成したコードは、gist で公開しています。 WPF アプリケーションを作成し、MainWindow.xaml と MainWindow.xaml.cs を組み込めば実行できます。

Continue reading

Microsoft MVP for .NET を受賞しました

2015 年 4 月期で Microsoft MVP Award を再受賞しました。 技術専門分野は .NET になります (2015 年 1 月から、.NET 言語系技術専門分野 (Visual C#, Visual Basic, Visual F#) が .NET に統合されました)。

まさに KanColleViewer な 1 年という感じでした。 おかげさまでダウンロード数はまもなく 300 万といったところで、大きな反響を頂いたと共に、単なる開発技術以上の学び (リポジトリ管理とか、アプリのリリース関連作業とか!) を得ることができました。 本当にありがとうございました。


これまでは、めとべやという勉強会を通じ、KanColleViewer を題材として XAML や WPF の魅力を伝える活動が中心でした。 それは今後も続けていきます (新しいネタ作りたいところではありますが!)。 Windows 10 も今夏リリースとのことで、XAML Platform の動向はしっかり追っていきたいですね。

そして現在、謎社に転職し、今は Unity 方面から C# を攻めています。 Unity UI (uGUI) 上で動作する WPF ライクな拡張機能等も開発しており、これまでの経験を活かしつつ C# の魅力を共有していければと思っています。

引き続き、今後ともよろしくお願いいたします。

Unity のための C# 勉強会 セッション資料

Unity のための C# 勉強会にて UniRx + Reactive Property のお話をさせて頂いたので、資料を公開します。

実は一晩で作った資料なのでいろいろ雑っぽい いろいろ準備不足すぎて大変アレでしたが… 会場には Rx に触れられたことのない方も多くいらっしゃったようで、Rx (UniRx) がどんなものか、触りだけでも知って頂ければ幸いです。

資料内にも書きましたが、ガッツリ勉強するなら以下のスライドは必読ですよ!

Reactive Programming by UniRx for Asynchronous & Event Processing (@neuecc)
未来のプログラミング技術をUnityで ~UniRx~ (@toRisouP)

特に @toRisouP 先生の資料は、Rx のとっつきにくさを資料の解りやすさで解消するアプローチを取られていて、本当に素晴らしいです。 一方私は、セッション中のライブコーディングで実際にお見せして親しんでもらおうというアプローチ、をとろうとするのですが (資料読むだけセッションって性に合わなくて…)。 もうちょっと手際よくやらないとダメですね。反省。

VSTU 勉強会で LT しました

日本 Android の会 Unity 部、Visual Studio Tools for Unity 勉強会にて LT させて頂きました。

タイトルを考えたのは @neuecc であり、私ではありません、断じて。 別に Boo に親を殺されたわけでもないし、特段恨みもありません!

が、流石に Boo.Lang.dll は必要ないので、VSTU による .csproj の自動生成処理をフックして削除する方法についてご紹介しました。 要は LINQ to XML で好きに弄ればいいということです!

ライブ コーディングした SATSUGAI 用コードは以下になります。

この方法を使えば、Q&A でも話題に上がった #define の追加や unsafe 関連の設定もできる、はず、です (実際にやったことはありませんが、いずれも .csproj に書かれる設定なので)。

うまく活用し、快適な C# + Visual Studio ライフを送って下さい!

Visual Studio 2015 Preview で XAML デザイナーが動作しないとき

Visual Studio 2015 Preview がリリースされた当初から、WPF プロジェクトで XAML デザイナーが正常に動作しない現象をいくつか確認しています。

パッケージの更新、依存関係、または競合の検証に失敗しました。

パッケージの更新、依存関係、~~~

WPF プロジェクトで発生するのを確認。

同じコンピューター上で新しく Windows Universal app のプロジェクトを作成し、開発者ライセンスを取得したところ解決しました。

Manifest module does not contain assembly manifest or module is corrupted.

SS150209050024KD

WPF プロジェクトで発生するのを確認。

.csproj 内で以下が記述されていれば、それが原因のようです。 この行を削除したところ解決しました。

この部分は、Windows デスクトップ アプリからトースト通知等の WinRT の API を叩くために、手動で追加することが多いです。 追加前後で、Reference Manager に以下のような違いが現れます。

追加前

追加後

実際にプロジェクト内で WinRT の API を使用しているかどうかに関わらず、とにかく TargetPlatformVersion が記述されているだけで XAML デザイナーがエラーを吐きます (少なくとも私の環境では。情報求む)。

XAML デザイナーを正常動作させるために .csproj から TargetPlatformVersion の行を消してしまうと、今度は WinRT への参照ができなくなります (ビルド エラーになるはず)。 現時点では、XAML デザイナーが必要なプロジェクトと WinRT の API を叩くプロジェクトは、別アセンブリにする等の対処が必要ですね。

ちなみに、Windows 10 Technical Preview + Visual Studio 2015 CTP 5 で TargetPlatformVersion を 10.0 にしてみたところ、これまたエラーで XAML デザイナーは正常動作せず。

2014 年総括

毎年恒例のチラ裏反省会です (遅刻気味)。

仕事

初めて転職しました。 昨年の振り返りでも書いていましたが、かなり残念だった現状を変えるための答えとして。 C#er としての力を発揮できるベストな環境に Join できたと思っています。

とはいえ、Unity に振り回されっぱなしだったのが反省点です。 来年は攻勢に出ます。

個人活動

おかげ様で、Microsoft MVP for Visual C# を受賞しました (1 月から Visual C# ではなく .NET になりますが…)。

後述のアプリ開発もそうですが、個人的にフォーカスしてる分野がクライアント アプリ開発技術なので、同じくクライアント アプリ開発技術をメインに扱っているめとべや勉強会には大変お世話になりました。

勉強会の運営って難しいですね。
ある程度ジャンルやテーマを絞った方が、参加者の方々が持ち帰れるものもより濃いものになる… という個人的な考えがあるので、アプリ開発者向け勉強会とか主催してみたりしましたが、どうだったでしょうか、うーん。 (もちろんノージャンルでいろいろ扱ってくださる勉強会も楽しいですし、新しい発見もあって大変勉強になりますが!)

そして、今年はほぼ東京だけで活動していたので、来年は旅行したい!県外の勉強会にもいろいろ出てみたいですね。 とても楽しかっためとべや大阪で味をしめたわけではありません。

アプリ

何か作ったかと言えば、艦これツール「提督業も忙しい!」のダウンロード数が予想以上に伸びて、そちらをぼちぼち。 昨年末に公開してからまる 1 年ですが、ダウンロード数 270 万くらいです。 ご利用頂きありがとうございます。

実際にユーザーさんの反応などたくさん頂いたので、技術的な部分だけでなく、アプリの公開方法とか告知方法とか含め、かなり勉強になりました。 あとメンタルも鍛えられました。

そして単に作るだけでなくて、技術情報の共有もそれなりにやったつもり、です。 特に Windows 8(.1) 時代のデスクトップ アプリの事例として、外観のカスタマイズとかいろいろ。 作って、公開して、技術情報を共有するサイクルを今後も続けていければいいなー、と。

そして、WPF 向けライブラリも公開してはいるのですが、あまり保守できてるとは言えず、こちらは反省。 Windows のデスクトップ自体は復権 (?) の兆しですし、Windows 10 や WPF の強化も含めて見守りつつ、ぱわーあっぷさせたい。。 あと @od_10z さんと「Windows Phone アプリを 1 本作る」約束をしていたのが未だ果たせていないので、これも来年 (ごめんなさいごめんなさいごめんなさい)。

ブログ

夏頃から完全に失速しました。。。

仕事が Unity になり、まず勉強から入ったので、なかなか共有するネタができず。 加えて、アクセス数に WordPress (ClearDB) が耐えられていないのか何なのか、下書きしてる途中に 503 吐かれてウボァーな事案も何回かあり、はてなブログかどこかに移行したい…

来年は月 3 記事くらいのペースは維持したいですね! (言うだけならタダ)

提督業

2013/12/31 -> 2014/12/31

ケッコンカッコカリ 26 人 (ごく普通の提督)。
イベントは今のところすべて踏破してます。

更に、12/31 時点で実装されている艦は古鷹改二を除きすべてコンプしています。 その古鷹もいま Lv.61 なので、年明けて早いうちに久々に図鑑コンプできそうですネ。

最近は艦これに費やす時間がめっきり減ってしまっていますが、余った資源を演習遠征 x 2 に回すことでレベル上げだけは継続しています。 出撃する暇がないとき、資源を貯める必要がないときに回すと結構オイシイ遠征です。

というか、ほぼ図鑑コンプ状態のいま、惰性のレベル上げ以外にやることがないじゃない、という。 そして AL/MI ほどの大規模イベントも踏破できるだけの艦が揃っているので、焦ってレベル上げる必要もなく。

KanColleViewer 更新の催促だけは頻繁に頂くようになったので、やることと言えばそっちですね…はい。

2015 年へ

なんといっても Unity マンになったので、そちらでの成果をご期待ください。 もともとクライアント サイドの開発を得意としていたので、これまでの経験をうまくシナジーさせられたらいいな、と。 (もちろんサーバー側もやりますけどね!)

そして Unity に限らず、勉強会登壇をはじめとした情報発信に関わることは、自分のスキル向上に直結する活動として、来年もしっかり続けていきます。

ということで、2014 年、お世話になった方々本当にありがとうございました。来年もよろしくお願い致します。

Room metro #28 XAML Day

XAML Advent Calendar、今年も始まりました!
http://qiita.com/advent-calendar/2014/xaml

さっそく 1 日目担当ということで、この辺のライブラリ作成 で得たコントロール作成周りのネタを放出します。

…が、なんと Room metro #28 XAML Day にてすべて話してきてしまったので、今回はその資料を公開! ということで。。。

[slideshare id=42207950&doc=roadtouilibrary-141201043432-conversion-gate02]

セッション中、半分くらいの時間はスライドではなく実際に Visual Studio を動かしてコードを書くデモを行っていたので、スライドだけ見ると物足りないかも… (これでも、デモしたコーディングや操作の手順はなるべくスライドに記載しました)。

以下、重要な部分等の抜粋などなど。

UI の再利用のために

以前からこのブログでも何度も書いているのですが、最近の Windows Desktop アプリでは、標準 Chrome を使用せずモダンな外観になっているものが多くなっています。 標準コントロールの組み合わせだけで作るのではなく、Style や Template、そしてコントロールを自作するというシチュエーションも増えてきているのではないでしょうか。

そこで、せっかく自作するのであればライブラリとして再利用できる形にまとめることを意識しよう、ということで、今回のセッションではコントロールの自作に焦点を絞り、その方法の選択や注意点などをまとめています。

コントロールの選択、自作するのか否か

WPF や WinRT、その他 Toolkit 等で提供されていない UI (外観や操作) を実現する手段は複数考えられます。

  • Style / ControlTemplate の変更
  • Trigger + Action / Behavior の使用
  • 新たなコントロールの作成

セッションではかなり後半 (スライド 47 ページ目) になってしまいましたが、実現したいコントロールの価値命題が何なのかをハッキリさせることが重要です。 そして、XAML Platform におけるコントロールの価値命題とはその原理や振る舞いであり、外観は含まれません (なぜなら、Style や Template といった仕組みによって、見た目はいくらでも変更できるからです)。

よって、今から作ろうとしているコントロールがどういう振る舞いをするのかを考えましょう。 マウスのクリックによる On/Off を表現したいのであれば、大抵は ToggleButton の外観を変更するだけで何とかなります。 同様に、何らかの項目を並べて表示したいのであれば、ItemsControl (またはその派生型) を使いましょう (去年の XAML Advent Calendar 参照)。

このように、もし既存コントロールの振る舞いと同じで、見た目だけが異なるものが欲しい場合、それは Style や Template で実現できます。

既存コントロールにない振る舞いを求められる場合は、新たにコントロールを作成することになります。 スライドでは NumericUpDown を例にしています (WinForms にはあって WPF にないコントロールの鉄板ネタですね)。

再利用可能なコントロール

新たなコントロールを作ることになったとして、UserControl 型から派生して作成する方法と、Control 型から派生して作成する方法 (= Custom Control) があります。

それぞれの特徴はスライドの通りです。

  • User Control
    • UserControl 型から派生
    • Window や Page と同じ感覚で作れる
    • 複雑なカスタマイズはできない
  • Custom Control
    • Control 型から派生 (WPF や WinRT が提供するコントロールと同じ実装方法)
    • ロジックと外観を分離させた作り
    • 複雑なカスタマイズもサポートできる

ライブラリにするのであれば、再利用時に複雑なカスタマイズが可能な Custom Control で作った方がよい場合が多いです。 カスタマイズを阻害しないために、ロジックと外観をしっかり分離させることが重要です (スライド 32-33 ページ目)。


XAML Advent Calendar 2014、明日は @KatsuYuzu さんです。 よろしくお願いします!

近況のご報告

Twitter 等でお気付きの方も多くいらっしゃるかと思いますが…
7 月末日で株式会社日立ソリューションズを退職し、今月から株式会社グラニで働いています。

日立には 4 年と 4 ヶ月ほどお世話になりました。
転職の理由はです。

これから暫くは、ある時はネイティブ エンジニア (Unity)、ある時はツール エンジニア (WPF, etc…) として邁進します。
今後ともよろしくお願い致します。