« WMリーダーの構造 | メイン | 続々・アラートウィンドウへフォーカスを移さない »
2005年10月19日
mixi Alert 開発日誌:: 続・アラートウィンドウへフォーカスを移さない
Tweet @jin1016をフォロー前回の対処方法(以下のソース参照)でもフォーカスが移動してしまう時がある。
Visible = true; |
移動しない時もあるのだが、いつ移動していつ移動しないのかはなぞ。
C++ BuilderでVCLを使っている以上避けられない問題なのだろうか?
と言う事で、VCLのソースを追ってみた。
でも、Object Pascal…… 変数の宣言で型が後に来るのと、if-thenやbegin-endさえ理解していれば、ある程度勘で読めるはず。
見たところ……
TCustomForm::CMShowingChangedで、表示に切り替わった時にShowWindowがコールされている。
TCustomForm::CMShowingChangedは、TWinControl::UpdateShowingが、メッセージを投げることで呼ばれる。
TWinControl::UpdateShowingは、TWinControl.UpdateControlStateで呼ばれる。
TWinControl.UpdateControlStateは、TWinControl::CMVisibleChangedで呼ばれる。
TWinControl.UpdateControlStateは、TControl::SetVisibleで値がセットされた時に呼ばれる。
TControl::SetVisibleは、Visibleプロパティに値が設定される時に呼ばれる。
実際には途中でいろいろと判定があるが、このような流れでShowWindowがコールされるようだ。
で、すぐに思いつく対処方法はーー
1. 上述の処理を自前で実装して、ShowWindowのところをSetWindowPosにする。
2. GetForegroundWindowで事前にフォーカスのあるウィンドウのハンドルを取得しておいて、自分を表示した後にSetForegroundWindowをコールして元に戻す。
ぐらい。
1. はコードを追った感じだとかなり大変。
でも、CMShowingChangedをオーバーライドすれば…… と思ったけど、privateだった。
そうだ、そうじゃなくてWndProcをオーバーライドしてCM_SHOWINGCHANGEDメッセージへの応答を書き換えれば比較的少ないコード量で対処できそう。
2. の方法に傾きかけていたけど、トリッキーなので避けたいなぁと思っていた。
が、すぐに問題は表出する。
Object Pascalがわからない。
TCustomForm::CMShowingChangedは、100行以上ある大きい関数。
そのほとんどすべてをC++に書き換えたいわけだが、raiseとかInclude()がよくわからない。
Object Pascalを勉強してもいいが……
方法2を使うことにしよう。
これであれば何があっても問答無用でフォーカスを元に戻せる。
ただ、他に機能拡張している途中なので実装はまた今度。
バージョン管理はしているので、ブランチさせてもいいが、マージが面倒。
結構長い間放置していたので、少し先になってもいいだろう。
投稿者 Takenori : 2005年10月19日 08:37
comments powered by Disqus