WPFを使ってニコニコ動画のコメントのようにデスクトップ上にメッセージを表示する試み。WPFプログラミング経験は皆無だったのだけど、わからないなりに調べたら結構できちゃうもんですね。まずは結果からどうぞ。
きちんと上から順に詰めて、隙間があればそこにメッセージを入れるようにまでした。
アニメーション
メッセージのアニメーションはWPFの機能を使ってます。メッセージを追加する部分は次のような感じになってます。Labelを生成してBeginAnimationメソッドを呼び出しています。後で登場するXAMLも併せて参考に。
Private Sub AddFlowingMessage(ByVal message As String)
Const TotalTime As Double = 3.5
Dim label = New Label
label.Content = message
label.FontSize = 80
' (MainCanvasという名前の)Canvasに追加
MainCanvas.Children.Add(label)
' Canvasに追加してUpdateLayoutしないとlabel.AcutualWidthが0.0
label.UpdateLayout()
Dim rect As New Rect( _
Me.ActualWidth, _
0.0, _
label.ActualWidth, _
label.ActualHeight)
' (GetNewMessageTopはメッセージのTop値を求める自作関数)
Canvas.SetTop(label, GetNewMessageTop(label, rect))
Dim animation = New DoubleAnimation
animation.From = Me.ActualWidth ' Windowsの右端から
animation.To = -label.ActualWidth ' Labelが隠れるまで
animation.Duration = New Duration(TimeSpan.FromSeconds(TotalTime))
' アニメーション終了時のイベントを関連付け
AddHandler animation.Completed, AddressOf Animation_Completed
' アニメーション開始
label.BeginAnimation(Canvas.LeftProperty, animation)
End Sub
Windows.Formsなんかと違う点は……。Canvasは中の要素をTopやLeft値で位置を設定できるコンテナらしい。中のLabelのTop値を変更するには Canvas.SetTop なんてのを使う。ぐへぇ。
あと、Labelの幅と高さ取得にはActualWidthとActualHeightを使う。Canvasに追加してUpdateLayoutメソッドを呼んでおかないと0.0になっちゃう。
アニメーションの終わりをイベントとして知ることができるのだけどsenderオブジェクトはClockオブジェクトらしい。何のアニメーションが終わったかどうかは、わからない感じ?
透明なウィンドウ
ウィンドウを透明にするには、こんなXAMLになる。WindowのWindowStyle、AllowsTransparency、Backgroundがポイント。AllowsTransparencyがTrueの場合、WindowStyleはNoneにしないとエラーになった。
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
Topmost="True" WindowState="Maximized">
<Grid>
<Canvas x:Name="MainCanvas">
<Button Click="Button_Click" Width="75" Height="30" Content="Click" />
</Canvas>
</Grid>
</Window>
Buttonはデバッグ用です。非矩形にする方法は青柳さんのBlogからのリンクが参考になるかも。試してませんが。
枠付きの文字
さて、上の例ではLabelを使っていたけど、文字に枠が付いていないから文字とバックの境界がわかり辛い。ニコニコ動画でも文字に外枠が付いている。これについてはMSDNライブラリの方法 : 中抜きの文字列を作成するがそのまんま参考になる。サンプルをダウンロードしてoutlinetextcontrol.csの内容をそのまんま頂けばOK。テキストからGeometryオブジェクトに変換すれば良いらしい。ClearTypeでなくなるのが少し難点。
WPFでスレッド
メッセージを追加するメソッドはサブスレッドから呼ばれることを想定している。UIの操作をする場合UIのメインスレッドからしなくてはいけない。テスト用にとサブスレッドからUI操作するコードを書いたら怒られた。きちんとチェックしてあるんですねー。スレッドについては、Dispatcher を使用して応答性の高いアプリケーションを構築するが参考になります。