2011年4月2日土曜日

既存 Activity のアイコン画像(2)

Activity のアイコン画像は Activity クラス系ではなく AtivityDesigner クラス系で保持している。
これが便利でもあり不便でもあり。Activityをカスタマイズする場合、それをワークフローデザイナー上で色々触る事ができるようにするのは考えておく必要があるんだけど、その場合に重要なのは ActivityDesigner になるんだよね。こいつがワークフローデザイナー上で表示されるものを制御しているので。

そこでいい方法が思いつかなかったのもあり、デザイナー上に表示されたActivityのアイコン画像を抽出し保存、それをリソースとしてしまおうというやり方を今回はとりました。ただ原理はわかったので、そのうち動的にロードするようにするとは思いますです。

ワークフローデザイナー上にドロップした Activity は、デザイナーの Context プロパティを通してアクセスできます。ただしここでアクセスできるのは、WorkflowDesigner.Context.Items に保持されている中で、System.Activities.Presentation.View.Selection というデザイナー上で選択されている Activity、という部分だけです。まぁ実際には選択されている Activity を利用して Root 要素な Activity までアクセスすることもできるので、やればどうにかはなります。

    If designer.Context IsNot Nothing Then
        For Each child In .Context.Items
            If TypeOf child Is System.Activities.Presentation.View.Selection Then
                For Each child2 In DirectCast(child, View.Selection).SelectedObjects
                    ‘ここで Activity (ModelItem) として抽出ができた   
                Next
            End If
        Next
    End If

まずはこのような形でワークフローデザイナー(designer という名前の変数で利用)にて選択されている Activity を取得します。SelectedObjects は IEnumrable(Of ModelItem) という形で取得できるようになっています。そのようにして抽出できた Activity には View プロパティが用意され、そこを通してActivityDesigner にアクセスできるようになっています。試していないのですが単純に Activity のインスタンスを生成した場合、View プロパティに情報が設定されているのであれば動的に抽出もできそうです。

Dim targetDesigner = DirectCast(target.View, ActivityDesigner)
Dim iconBrush = targetDesigner.Icon.Drawing

Dim dv = New DrawingVisual
Using dc = dv.RenderOpen
    dc.DrawDrawing(iconBrush)
End Using

Dim outputBitmap = New RenderTargetBitmap(16, 16, 96, 96, PixelFormats.Pbgra32)
outputBitmap.Render(dv)
Dim enc = New PngBitmapEncoder
enc.Frames.Add(BitmapFrame.Create(outputBitmap))
Using Stm = System.IO.File.Create(targetDesigner.GetType.Name + ".png")
    enc.Save(Stm)
End Using

このような形で ActivityDesigner からアイコン情報を取得し、png フォーマットで保存します。png なのはアイコン情報では透過色が利用されているからで、ここで Bitmap で保存すると後で泣けます。もう一つ注意するのは、ここでは保存する際に ActivityDesigner の Type 名を利用していますが、Activity はすべてにおいて専用の ActivityDesigner を利用している訳ではなく、一部リソースのみ差し替えた状態で利用している物があります。ThrowAtivity とかそういったところでは後でファイル名を手直しする必要があります。まぁここで ActivityDesigner 名ではなく、Activity 名で保存すれば OK なのですがw

このようにして抽出し保存、その後リソースとしておけばExpress Edition であろうとも既存 Activity のアイコン画像には対応できます。

0 件のコメント:

コメントを投稿