C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[13]: アクティブウインドウが変更されたときにイベントを発生させる


(過去ログ 117 を表示中)

[トピック内 19 記事 (1 - 19 表示)]  << 0 >>

■68587 / inTopicNo.1)  アクティブウインドウが変更されたときにイベントを発生させる
  
□投稿者/ morimori (44回)-(2013/10/30(Wed) 15:57:47)

分類:[C#] 

開発環境
Windows7 Home
使用言語
2010 C# Professional

アクティブウインドウが変更されたときに処理をしたいことがあるので
アクティブウインドウの変化を監視したいのですが、
どのように変化をとらえればいいでしょうか。

自分でも調べてみたのですが、変化を監視するイベントは直接ないらしいです。
もちろんそのようなイベントを知ってらっしゃる方がいらっしゃれば教えてくださればうれしいです。
知らない方でもアクティブウインドウが切り替わったことを判別する方法をご存知の方は教えてください。

引用返信 編集キー/
■68588 / inTopicNo.2)  Re[1]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (163回)-(2013/10/30(Wed) 16:36:16)
とっちゃん さんの Web サイト
No68587 (morimori さん) に返信
> 開発環境
> Windows7 Home
> 使用言語
> 2010 C# Professional
>
Forms アプリですか?それとも、WPFアプリですか?それとも、Webアプリですか?
勝手に決めつけで、デスクトップアプリで。

Windows Forms アプリなら、System.Windows.Forms.Form.Activated/Deactivate イベントで判断できます。
WPF なら System.Windows.Window.Activated/Deactivated イベントで判断できます。

コントロールレベルでフォーカスの有無をという場合は、
System.Windows.Forms.Control.Enter/Leave イベント(場合によっては、Varidating 関連)または
System.Windows.UIElement.GotFocus/LostFocus イベント(あるいは、Varidationクラス)が使えると思います。

引用返信 編集キー/
■68589 / inTopicNo.3)  Re[2]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (45回)-(2013/10/30(Wed) 16:53:20)

情報が抜けていてすみません。
おっしゃる通りで今回探しているのはデスクトップアプリです。
ただ、今回は自身のアプリケーションのアクティブウインドウではなく、
他のアプリケーションのアクティブウインドウの切り替えを監視したいのです。
せっかく調べてくださったのに申し訳ございません。

おそらくWindowsAPIを使用することになるかと思いますが、
findWindow関数等の使い方はしっているので、
ご存知の方がいらっしゃいましたら教えてください。

引用返信 編集キー/
■68591 / inTopicNo.4)  Re[3]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (164回)-(2013/10/30(Wed) 18:32:16)
とっちゃん さんの Web サイト
No68589 (morimori さん) に返信

> 情報が抜けていてすみません。
> おっしゃる通りで今回探しているのはデスクトップアプリです。
> ただ、今回は自身のアプリケーションのアクティブウインドウではなく、
> 他のアプリケーションのアクティブウインドウの切り替えを監視したいのです。
> せっかく調べてくださったのに申し訳ございません。
>
自分のアプリではなく、別のプログラム(書き換え不可)の監視ということですか?
どのタイミングを識別したいのでしょうか?

簡単なのは、タイマー(UI系のタイマー)を使って、定期的に(0.2〜0.5秒程度)
GetForegroundWindow API を使って現在前面にあるウィンドウを取得する方法ですかね。

前回チェックしたときと違うウィンドウハンドルならアクティブが切り替わったことになります。
画面に表示されている大外のウィンドウ(一般にフレームウィンドウと呼ばれる)が取得できます。

この形であれば、.NET アプリでも実装できるので、開発コストは低く済みます。

WM_ACTIVATE メッセージ(先のウィンドウのイベントの大元)をトラップする方法もあります。
この場合はグローバルフック(.NET を使った実装はできない)を使う形になると思いますが、32/64 のプログラムで
それぞれ別々のフックプロシージャを作って、フォローする必要があると思うので、どうしても
メッセージをトラップしなければならないという場合を除いて現実的ではないと思います。

引用返信 編集キー/
■68592 / inTopicNo.5)  Re[1]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ オショウ (98回)-(2013/10/30(Wed) 20:19:10)
> アクティブウインドウが変更されたときに処理をしたいことがあるので
> アクティブウインドウの変化を監視したいのですが、
> どのように変化をとらえればいいでしょうか。

  ここの掲示板ですでに投稿されているグローバルフックを使うなら
  アクティブウィンドウの変更を監視できます。

  グローバルフックの何を使うか・・・
  ttp://hp.vector.co.jp/authors/VA016117/hook.html

  WH_CALLWNDPROCフック
  WH_CBTフック

  のどちらか・・・

  ただ、.NETだけで実装するのは無理だったと思います。

以上。参考まで
引用返信 編集キー/
■68596 / inTopicNo.6)  Re[2]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (46回)-(2013/10/31(Thu) 07:50:21)
みなさんありがとうございます。
こちらで参考にしながらやってみます。
できたらまた報告します。
引用返信 編集キー/
■68598 / inTopicNo.7)  Re[3]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (47回)-(2013/10/31(Thu) 14:09:29)
このようなソースをTimerイベントの中に入れてアクティブウインドウのスクリーンショットを取ってみました。
しかし、中には一部しか取れていなかったり画面が真っ暗だったりする画面があります。
やはりこのようなものを実装するためにはグローバルフックを利用しないとだめなのでしょうか。

        private void timerPrint_Tick(object sender, EventArgs e)
        {
            IntPtr nPtrHandle = GetForegroundWindow();
            if (intPtrNow.Equals(nPtrHandle) == false)
            {
                PrintCapture();
                intPtrNow = nPtrHandle;
            }

            //MessageBox.Show("待機テスト");
        }

        private void PrintCapture(IntPtr nPtrHandle)
        {
                RECT r;
                GetWindowRect(nPtrHandle, out r);
                Rectangle rect = new Rectangle(r.left, r.top, r.right - r.left, r.bottom - r.top);

                StringBuilder sb = new StringBuilder(100);
                Bitmap img = new Bitmap(rect.Width, rect.Height); //後で変更
                Graphics memg = Graphics.FromImage(img);
                IntPtr dc = memg.GetHdc();

                PrintWindow(nPtrHandle, dc, 0);
                memg.ReleaseHdc(dc);
                memg.Dispose();
                this.BackgroundImage = img;

                GetWindowText(nPtrHandle, sb, sb.Capacity - 4);

                string strExseption = ".jpg";
                StringBuilder sbFile = new StringBuilder();
                int nCounter = 0;
                sbFile.Append(sb.ToString());
                sbFile.Append(strExseption);

                while(File.Exists(sbFile.ToString()))
                {
                    nCounter++;
                    sbFile.Clear();
                    sbFile.Append(sb.ToString());
                    sbFile.Append(nCounter);
                    sbFile.Append(strExseption);
                }

                img.Save(sb.ToString(), System.Drawing.Imaging.ImageFormat.Png);
          }

引用返信 編集キー/
■68599 / inTopicNo.8)  Re[4]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (165回)-(2013/10/31(Thu) 15:10:07)
とっちゃん さんの Web サイト
No68598 (morimori さん) に返信

一部しか取れないというのは、どこの部分が取れてどの部分が取れないのでしょうか?
黒になってしまうウィンドウというのはどんなウィンドウでしょうか?

上記のモノには何らかの関係性がありますか?
それとも特定のウィンドウだけなのでしょうか?


引用返信 編集キー/
■68601 / inTopicNo.9)  Re[5]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (48回)-(2013/10/31(Thu) 16:01:55)
詳しく見ると、どうやら
フォームが撮られる瞬間に表示する前だったり後だったりする場合に
このような状態になることがあるように思われます。
特に特定の画面で起こるというものではなさそうです。

まだ予測の状態なので
もうすこし調べてからまた報告します。
引用返信 編集キー/
■68604 / inTopicNo.10)  Re[6]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (49回)-(2013/10/31(Thu) 16:55:02)
最初は気付かなかったのですが、
アクティブウインドウが切り替わるたびに、キャプチャを取ろうとすると
古いパソコンだとカクカクになってしまうことがあるので、
一度アクティブウインドウが閉じるまで同じウインドウはキャプチャしない
という機能もこしらえようと考えております。

一度とったウインドウIDを保持しておけば同じウインドウを何度も撮ることを防止することができると思いますが、
保持しているアクティブウインドウが閉じられたことを確認するにはどうすればいいでしょうか。




引用返信 編集キー/
■68606 / inTopicNo.11)  Re[7]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ みい (3回)-(2013/10/31(Thu) 17:17:18)
No68604 (morimori さん) に返信
> 最初は気付かなかったのですが、
> アクティブウインドウが切り替わるたびに、キャプチャを取ろうとすると
> 古いパソコンだとカクカクになってしまうことがあるので、
> 一度アクティブウインドウが閉じるまで同じウインドウはキャプチャしない
> という機能もこしらえようと考えております。
>
> 一度とったウインドウIDを保持しておけば同じウインドウを何度も撮ることを防止することができると思いますが、
> 保持しているアクティブウインドウが閉じられたことを確認するにはどうすればいいでしょうか。
単純なとこだとIDをリストに取っておいて、定期的にFindWindowでそのIDのウインドウがあるかどうか探す。
チェックする周期が長いと同じIDで新しいウインドウが開かないとは限らないので、
そこはウインドウタイトルも合わせてチェックするとか。
引用返信 編集キー/
■68614 / inTopicNo.12)  Re[8]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (50回)-(2013/11/01(Fri) 09:51:09)
/// <summary>
/// 描画タイトルテーブル
/// </summary>
public class PrintTable
{
/// <summary>
/// ポインタ
/// </summary>
public IntPtr ptr { set; get; }

/// <summary>
/// タイトル名
/// </summary>
public string strTitle { set; get; }
}

HashSet<PrintTable> m_listPrintPtr

このようなクラスを作り、HashSetにデータを詰めて検索しようと考えました。
しかし、このままm_listPrintPtr.Contains(ptKey)で検索しようとしても
すべてfalseで帰ってきてしまいます。

なにか工夫が必要なのでしょうか。
引用返信 編集キー/
■68615 / inTopicNo.13)  Re[7]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (168回)-(2013/11/01(Fri) 10:23:21)
とっちゃん さんの Web サイト
No68606 (みい さん) に返信
>>一度とったウインドウIDを保持しておけば同じウインドウを何度も撮ることを防止することができると思いますが、
>>保持しているアクティブウインドウが閉じられたことを確認するにはどうすればいいでしょうか。
> 単純なとこだとIDをリストに取っておいて、定期的にFindWindowでそのIDのウインドウがあるかどうか探す。
> チェックする周期が長いと同じIDで新しいウインドウが開かないとは限らないので、
> そこはウインドウタイトルも合わせてチェックするとか。

HWND がわかっている場合は、FindWindow するよりも、IsWindow でハンドルチェックするほうが高速です。
タイマーでチェックするときに、保持しているウィンドウハンドルを一通り再チェックすれば比較的ローコストで実現できると思います。

引用返信 編集キー/
■68618 / inTopicNo.14)  Re[8]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (169回)-(2013/11/01(Fri) 11:23:24)
とっちゃん さんの Web サイト
No68614 (morimori さん) に返信
> このようなクラスを作り、HashSetにデータを詰めて検索しようと考えました。
> しかし、このままm_listPrintPtr.Contains(ptKey)で検索しようとしても
> すべてfalseで帰ってきてしまいます。
>
> なにか工夫が必要なのでしょうか。

PrintTable クラスのユニーク性の基準がわからないので、どういう工夫をすればいいのかわかりません。

IntPtr ptr; は「何の」ポインタなのでしょう?

String strTitle; は、おそらく描画するタイトルなのだと思いますが、PrintTable のサマリーなどから
導き出せる答えがありません。

まぁ、ここまでの流れから、おそらくは ptr == ウィンドウハンドルと思われますが...
どこにもそれっぽいことが書かれていないので、ちょっとわかりかねます。

とりあえず。。。
HashSet<T>は T.GetHashCode(), T.Equals() の2つのメソッドを使って、オブジェクトの一意性を保ちます。
見た感じ、用意していないようなので、Object.GetHashCode(), Object.Equals()が使われていると思われます。
PrintTableは、参照型なので

var pt1 = new PrintTable;
var pt2 = new PrintTable;
pt1.ptr == pt2.ptr && pt1.strTitle == pt2.strTitle

が成立する状況でも

pt1.GetHashCode() == pt2.GetHashCode()
pt1.Equals(pt2) == true

は成立しません(実験してみるとわかります)。

これを成立するようにすれば、解決しますよ。


引用返信 編集キー/
■68619 / inTopicNo.15)  Re[9]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (51回)-(2013/11/01(Fri) 12:54:55)
>とっちゃんさん
回答ありがとうございます。
なるほど、ということはEqualsやGetHashCodeの
実装をPrintTable側でしなければいけないことになると思うのですが、
Equalsはおそらく
return pt1.ptr == pt2.ptr && pt1.strTitle == pt2.strTitle;
のようなものだと思いますが、GetHashCodeは
どのように実装すればいいのでしょうか。
引用返信 編集キー/
■68621 / inTopicNo.16)  Re[10]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (170回)-(2013/11/01(Fri) 13:45:15)
とっちゃん さんの Web サイト
No68619 (morimori さん) に返信
> >とっちゃんさん
> 回答ありがとうございます。
> なるほど、ということはEqualsやGetHashCodeの
> 実装をPrintTable側でしなければいけないことになると思うのですが、
> Equalsはおそらく
> return pt1.ptr == pt2.ptr && pt1.strTitle == pt2.strTitle;
> のようなものだと思いますが、GetHashCodeは
> どのように実装すればいいのでしょうか。

わかりません。内容から一意性を保つための仕組みを導出できませんので
ハッシュ値(ユニークになりやすい整数値)を導き出すをどうするべきかは判断しかねます。

No68618 で、
>>なにか工夫が必要なのでしょうか。
>
> PrintTable クラスのユニーク性の基準がわからないので、どういう工夫をすればいいのかわかりません。
>
と、書いています。


この一文がすべてを物語っています。

HashSet<T> のT や、Dictionary<K,V> の K は、ユニークかつそのコレクションで一意になるものを
指定しなければなりません(同じキーを持つ複数の値を用意できないため)。


改めて問います。



PrintTable がユニークであるために必要な情報は何ですか?

引用返信 編集キー/
■68629 / inTopicNo.17)  Re[11]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (52回)-(2013/11/01(Fri) 15:37:02)

確かに根拠もなしにユニークなハッシュ値をどう算出すればいいのか悩ましいですね。
仮に出すとしてもハッシュ値の基準を決めなければならないのでそこまでする必要があるのかという話になりますね。

そう考えるとHashSetをわざわざ使うよりも単にListを使う方が
よさそうな気がしました。

後はいったんこちらで考えてみます。
進展がありましたら報告します。

引用返信 編集キー/
■68630 / inTopicNo.18)  Re[12]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ とっちゃん (174回)-(2013/11/01(Fri) 15:50:54)
とっちゃん さんの Web サイト
No68629 (morimori さん) に返信
>
> 確かに根拠もなしにユニークなハッシュ値をどう算出すればいいのか悩ましいですね。
> 仮に出すとしてもハッシュ値の基準を決めなければならないのでそこまでする必要があるのかという話になりますね。
>
> そう考えるとHashSetをわざわざ使うよりも単にListを使う方が
> よさそうな気がしました。
>
> 後はいったんこちらで考えてみます。
> 進展がありましたら報告します。
>
あれ?PrintTable のptrってウィンドウハンドルではないんですか?

根拠になるものを明示していなかった(ポインタと書かれているだけだった)ので、あえてわからない何かというスタンスで返答書いてますが、
このスレッドの流れが変わっていないのなら、ptr は HWND だろうし、strTitle はそのウィンドウのキャプション文字列と考えられるのですが...

もし、そうなら、それを明示すればユニーク性を確保するための情報源がはっきりします。

でも、明示してこないということは、きっと違うんですよね。
スレッドには書かれていない何かがあると思いますので、あまり言及しないほうがいいのかな?

引用返信 編集キー/
■68660 / inTopicNo.19)  Re[13]: アクティブウインドウが変更されたときにイベントを発生させる
□投稿者/ morimori (53回)-(2013/11/05(Tue) 08:46:45)
いろいろ考えた末、Listで順次検索することにしました。
今回は自分が知ってる方法で収めることにします。
ご協力ありがとうございました。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -