[C#/WPF] Windowクラスのイベント全部、発生時にログ取ってみる
もくじ
やりたいこと
WPFを作っていてよく思うのが、ウインドウを起動したときにどのイベントが、どういう順番で、 発生しているのか、ということだった。
一度、全部のイベントでログを吐くようにしてみて、発生する順番をはっきりさせたい。
やったこと
試しに、Windowクラスの全イベントにログを仕込んで見ようと思った。
本当は、
Type type = typeof(MainWindow);
var methodInfos = type.GetEvents();
LogOnDesktop.WriteLogToDesktopLogFile("-----------------------イベント
foreach (var mi in methodInfos)
{
//mi.AddEventHandler(this, ログを吐くメソッド・・・);
}
みたいな感じで、全イベントにログを仕込むようにしたかったのだが、AddEventHandler()
の第二引数にどういうものを渡せばそれが実現できるのかが全然わからなかったので、いったんやめて、泥臭い方法で実現した。
具体的にやったこと
コード
下記のようなコードを作った。
using System;
using System.IO;
using System.Windows;
namespace WpfApp48
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// すべてのイベント発生時に、自分のイベントの名前を出力するよう登録
SourceInitialized += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("SourceInitialized"); });
DpiChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DpiChanged"); });
Activated += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Activated"); });
Deactivated += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Deactivated"); });
StateChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StateChanged"); });
LocationChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LocationChanged"); });
Closing += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Closing"); });
Closed += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Closed"); });
ContentRendered += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ContentRendered"); });
PreviewMouseDoubleClick += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseDoubleClick"); });
MouseDoubleClick += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseDoubleClick"); });
TargetUpdated += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TargetUpdated"); });
SourceUpdated += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("SourceUpdated"); });
DataContextChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DataContextChanged"); });
RequestBringIntoView += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("RequestBringIntoView"); });
SizeChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("SizeChanged"); });
Initialized += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Initialized"); });
Loaded += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Loaded"); });
Unloaded += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Unloaded"); });
ToolTipOpening += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ToolTipOpening"); });
ToolTipClosing += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ToolTipClosing"); });
ContextMenuOpening += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ContextMenuOpening"); });
ContextMenuClosing += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ContextMenuClosing"); });
PreviewMouseDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseDown"); });
MouseDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseDown"); });
PreviewMouseUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseUp"); });
MouseUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseUp"); });
PreviewMouseLeftButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseLeftButtonDown"); });
MouseLeftButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseLeftButtonDown"); });
PreviewMouseLeftButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseLeftButtonUp"); });
MouseLeftButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseLeftButtonUp"); });
PreviewMouseRightButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseRightButtonDown"); });
MouseRightButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseRightButtonDown"); });
PreviewMouseRightButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseRightButtonUp"); });
MouseRightButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseRightButtonUp"); });
PreviewMouseMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseMove"); });
MouseMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseMove"); });
PreviewMouseWheel += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewMouseWheel"); });
MouseWheel += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseWheel"); });
MouseEnter += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseEnter"); });
MouseLeave += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("MouseLeave"); });
GotMouseCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GotMouseCapture"); });
LostMouseCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LostMouseCapture"); });
QueryCursor += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("QueryCursor"); });
PreviewStylusDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusDown"); });
StylusDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusDown"); });
PreviewStylusUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusUp"); });
StylusUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusUp"); });
PreviewStylusMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusMove"); });
StylusMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusMove"); });
PreviewStylusInAirMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusInAirMove"); });
StylusInAirMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusInAirMove"); });
StylusEnter += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusEnter"); });
StylusLeave += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusLeave"); });
PreviewStylusInRange += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusInRange"); });
StylusInRange += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusInRange"); });
PreviewStylusOutOfRange += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusOutOfRange"); });
StylusOutOfRange += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusOutOfRange"); });
PreviewStylusSystemGesture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusSystemGesture"); });
StylusSystemGesture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusSystemGesture"); });
GotStylusCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GotStylusCapture"); });
LostStylusCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LostStylusCapture"); });
StylusButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusButtonDown"); });
StylusButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("StylusButtonUp"); });
PreviewStylusButtonDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusButtonDown"); });
PreviewStylusButtonUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewStylusButtonUp"); });
PreviewKeyDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewKeyDown"); });
KeyDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("KeyDown"); });
PreviewKeyUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewKeyUp"); });
KeyUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("KeyUp"); });
PreviewGotKeyboardFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewGotKeyboardFocus"); });
GotKeyboardFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GotKeyboardFocus"); });
PreviewLostKeyboardFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewLostKeyboardFocus"); });
LostKeyboardFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LostKeyboardFocus"); });
PreviewTextInput += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewTextInput"); });
TextInput += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TextInput"); });
PreviewQueryContinueDrag += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewQueryContinueDrag"); });
QueryContinueDrag += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("QueryContinueDrag"); });
PreviewGiveFeedback += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewGiveFeedback"); });
GiveFeedback += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GiveFeedback"); });
PreviewDragEnter += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewDragEnter"); });
DragEnter += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DragEnter"); });
PreviewDragOver += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewDragOver"); });
DragOver += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DragOver"); });
PreviewDragLeave += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewDragLeave"); });
DragLeave += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DragLeave"); });
PreviewDrop += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewDrop"); });
Drop += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("Drop"); });
PreviewTouchDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewTouchDown"); });
TouchDown += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TouchDown"); });
PreviewTouchMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewTouchMove"); });
TouchMove += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TouchMove"); });
PreviewTouchUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("PreviewTouchUp"); });
TouchUp += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TouchUp"); });
GotTouchCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GotTouchCapture"); });
LostTouchCapture += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LostTouchCapture"); });
TouchEnter += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TouchEnter"); });
TouchLeave += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("TouchLeave"); });
IsMouseDirectlyOverChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsMouseDirectlyOverChanged"); });
IsKeyboardFocusWithinChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsKeyboardFocusWithinChanged"); });
IsMouseCapturedChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsMouseCapturedChanged"); });
IsMouseCaptureWithinChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsMouseCaptureWithinChanged"); });
IsStylusDirectlyOverChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsStylusDirectlyOverChanged"); });
IsStylusCapturedChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsStylusCapturedChanged"); });
IsStylusCaptureWithinChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsStylusCaptureWithinChanged"); });
IsKeyboardFocusedChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsKeyboardFocusedChanged"); });
LayoutUpdated += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LayoutUpdated"); });
GotFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("GotFocus"); });
LostFocus += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("LostFocus"); });
IsEnabledChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsEnabledChanged"); });
IsHitTestVisibleChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsHitTestVisibleChanged"); });
IsVisibleChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("IsVisibleChanged"); });
FocusableChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("FocusableChanged"); });
ManipulationStarting += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationStarting"); });
ManipulationStarted += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationStarted"); });
ManipulationDelta += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationDelta"); });
ManipulationInertiaStarting += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationInertiaStarting"); });
ManipulationBoundaryFeedback += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationBoundaryFeedback"); });
ManipulationCompleted += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationCompleted"); });
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// すべてのイベントの名前を表示
Type type = typeof(MainWindow);
var methodInfos = type.GetEvents();
LogOnDesktop.WriteLogToDesktopLogFile("-----------------------イベントの一覧--------------------------");
foreach (var mi in methodInfos)
{
LogOnDesktop.WriteLogToDesktopLogFile(mi.Name);
// 本当はここでイベント登録までやりたかったが、できなかった...
// ※第二引数のイベントの型を動的に変える方法がわからなかった。
//mi.AddEventHandler(this, a);
}
}
}
// ログをデスクトップに残すためのクラス
static class LogOnDesktop
{
public static void WriteLogToDesktopLogFile(string line)
{
var logPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\log.log";
File.AppendAllText(logPath, DateTime.Now.ToString("hh:mm:ss.fff") + " " + line);
File.AppendAllText(logPath, Environment.NewLine);
}
}
}
※一番下にあるLogOnDesktopクラスは、単にデスクトップにログを吐くだけのクラス。
コードをつくるときにやったこと
まず、上のコード中にもある下記ロジックで、Windowクラスが持つイベントを全部文字で吐き出させた。
// すべてのイベントの名前を表示
Type type = typeof(MainWindow);
var methodInfos = type.GetEvents();
LogOnDesktop.WriteLogToDesktopLogFile("-----------------------イベントの一覧
foreach (var mi in methodInfos)
{
LogOnDesktop.WriteLogToDesktopLogFile(mi.Name);
}
次に、それをEXCELに貼り付けて、ログを吐くイベントを全部に登録できるコードが簡単にできるよううまいこと?やった。
↓こんな感じ
それで出来たコードをMainWindowのコンストラクタに貼り付けてできあがり。
結果
このアプリを起動し、その後ただ×ボタンを押して閉じる、という操作をすると、下記のようなイベントが出ていた。
11:01:48.115 IsVisibleChanged
11:01:48.214 SizeChanged
11:01:48.222 LayoutUpdated
11:01:48.231 SourceInitialized
11:01:48.737 Activated
11:01:48.787 PreviewGotKeyboardFocus
11:01:48.796 IsKeyboardFocusWithinChanged
11:01:48.809 IsKeyboardFocusedChanged
11:01:48.847 GotKeyboardFocus
11:01:48.886 LayoutUpdated
11:01:48.895 Loaded
11:01:48.922 ContentRendered
11:01:48.936 LayoutUpdated
11:01:49.120 LayoutUpdated
11:01:49.135 LayoutUpdated
11:01:49.223 LayoutUpdated
11:01:49.240 LayoutUpdated
11:01:49.267 LayoutUpdated
11:01:49.278 LayoutUpdated
11:01:49.287 LayoutUpdated
11:01:49.297 LayoutUpdated
11:01:49.307 LayoutUpdated
11:01:51.175 Closing
11:01:51.181 IsVisibleChanged
11:01:51.204 Deactivated
11:01:51.262 IsKeyboardFocusWithinChanged
11:01:51.271 IsKeyboardFocusedChanged
11:01:51.278 LostKeyboardFocus
11:01:51.294 Closed
これで、Windowが起動したときに、どういう順番でイベントが来ているかがわかった。
あとWindowの上でマウスを移動したりクリックしたりすると、またイベントが来てる様を見ることができる。(Spy++と見比べても面白そう?)
考察
Initializedイベントが来てない?
↓
下記のようにコードを変えると、来るようになった。
(来るようになったというか、元から来てたけどすでに来た後にハンドラ登録してたからログできてなかった)
public MainWindow()
{
// ★★イベント登録を、InitializeComponent()より先に持ってくる
SourceInitialized += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("SourceInitialized"); });
DpiChanged += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("DpiChanged"); });
・
・
ManipulationCompleted += ((obj, ev) => { LogOnDesktop.WriteLogToDesktopLogFile("ManipulationCompleted"); });
InitializeComponent();
}
・
・
これを、面倒だがWindow上に配置したいろんなコントロールに書いてやれば、ルーティングイベントの流れの勉強ができそうな気がする。
Discussion