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

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

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

Re[5]: ウィンドウクラス


(過去ログ 119 を表示中)

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

■69532 / inTopicNo.1)  ウィンドウクラス
  
□投稿者/ C# (1回)-(2014/01/07(Tue) 01:19:46)

分類:[C#] 

Visual Studio 2010 & Windows 7

ウィンドウクラスについて質問させて下さい。

ウィンドウのハンドルを以下のように取得しています。

FindWindow("WindowsForms10.Window.8.app.0.378734a", null);

アプリケーションのクラス名(引数1)はアプリケーションをビルドし直した場合は変更される可能性がありますが、
作成したアプリを起動・終了しても変更されない、またパソコンを変更しても変更はされない認識でいます。

※ いくつかのノートパソコンで確認済みですが、正しい理解でしょうか?

その上でデスクトップ型パソコンでそのアプリを起動するとクラス名が変更されてしまうことを確認しています。
同一のアプリでPCによってクラス名が変更される場合はどのようなことが予測されますでしょうか?

ご存知の方いましたら、ご教示よろしくお願いいたします。
引用返信 編集キー/
■69535 / inTopicNo.2)  Re[1]: ウィンドウクラス
□投稿者/ とっちゃん (184回)-(2014/01/07(Tue) 10:59:54)
とっちゃん さんの Web サイト
No69532 (C# さん) に返信

> ウィンドウクラスについて質問させて下さい。
>
> ウィンドウのハンドルを以下のように取得しています。
>
> FindWindow("WindowsForms10.Window.8.app.0.378734a", null);
>
> アプリケーションのクラス名(引数1)はアプリケーションをビルドし直した場合は変更される可能性がありますが、
> 作成したアプリを起動・終了しても変更されない、またパソコンを変更しても変更はされない認識でいます。
>
> ※ いくつかのノートパソコンで確認済みですが、正しい理解でしょうか?
>
> その上でデスクトップ型パソコンでそのアプリを起動するとクラス名が変更されてしまうことを確認しています。
> 同一のアプリでPCによってクラス名が変更される場合はどのようなことが予測されますでしょうか?
>
Form クラスのウィンドウクラス名は固定されていません。
実行環境にインストールされている .NET Framework のバージョンや
実行時の動作状況などによって、先頭あるいは末尾2つが変化します。

どこが変わっているかは、ご自身で確認していると思いますが、
おそらく後続2つのいずれか(あるいは両方)が変わっていると思います。

引用返信 編集キー/
■69536 / inTopicNo.3)  Re[2]: ウィンドウクラス
□投稿者/ 魔界の仮面弁士 (486回)-(2014/01/07(Tue) 11:20:46)
No69535 (とっちゃん さん) に返信
>>FindWindow("WindowsForms10.Window.8.app.0.378734a", null);
> Form クラスのウィンドウクラス名は固定されていません。
> 実行環境にインストールされている .NET Framework のバージョンや
> 実行時の動作状況などによって、先頭あるいは末尾2つが変化します。

公式資料は見当たりませんでしたが、一説によれば
 WindowsForms10.<character sequence>.app<hash code of appdomain>
というルールだそうで。
http://www.codeproject.com/Articles/4814/A-simple-Windows-forms-properties-spy
引用返信 編集キー/
■69548 / inTopicNo.4)  Re[3]: ウィンドウクラス
□投稿者/ とっちゃん (185回)-(2014/01/07(Tue) 16:20:02)
とっちゃん さんの Web サイト
No69536 (魔界の仮面弁士 さん) に返信
> ■No69535 (とっちゃん さん) に返信
> >>FindWindow("WindowsForms10.Window.8.app.0.378734a", null);
>>Form クラスのウィンドウクラス名は固定されていません。
>>実行環境にインストールされている .NET Framework のバージョンや
>>実行時の動作状況などによって、先頭あるいは末尾2つが変化します。
>
> 公式資料は見当たりませんでしたが、一説によれば
>  WindowsForms10.<character sequence>.app<hash code of appdomain>
> というルールだそうで。
> http://www.codeproject.com/Articles/4814/A-simple-Windows-forms-properties-spy

おっと。。。実は、先のコメントを書くときに、手持ちのソースをチェックしていたりします。

手持ちのソース(NativeWindow.cs)では、
StringBuilder b = new StringBuilder(50);

b.Append(Application.WindowsFormsVersion);
b.Append('.');
b.Append(className);
b.Append(".app.");
b.Append(domainQualifier);
b.Append('.');
String appDomain = Convert.ToString(AppDomain.CurrentDomain.GetHashCode(), 16);
b.Append(VersioningHelper.MakeVersionSafeName(appDomain, ResourceScope.Process, ResourceScope.AppDomain));

b.ToString();

となっています。

Application.WindowsFormsVersion はinternal 属性の付いたプロパティ(文字列を返す)で実装は
return "WindowsForms10";
となっています。
固定なのは、互換性の問題だそうです(ソースのコメント(超絶意訳モード)に、書き換えたやつは死刑って書いてありましたw)。

className は、デフォルトではこの部分の手前で "Window." + Convert.ToString( CreateParams.ClassStyle, 16 ); という値で作成されたものです。
CreateParams.ClassStyle はデフォルトでは、8(CS_DBLCLKS という定義値)です。

domainQualifier は、内部的にカウンタになっている値で、ウィンドウクラスの登録に失敗した場合にカウントアップするように作られています。

あとは、ヘルプを見ればわかるものなので割愛(値に意味があるわけではないので)。


さて。。。このウィンドウクラス名ですが、これで検索は全く意味をなさないということが改めて調査した結果わかりました。

実験は、
App1(2010/5/5 に作成したアプリケーション)と、App2(11月のわんくま勉強会のために作成したデモアプリ)を両方起動した状態でSpy++ でクラス名を取得しただけですが。
実行環境ではどちらのクラス名も
WindowsForms10.Window.8.app.0.2bf8098_r9_ad1
となっており、FindWindow の結果からはこれがどのプログラムであるかを特定することが不可能であることを立証してしまいました。

一応。。。実行環境を記載しておきます。
Windows 8.1 Pro 64bit版でActiveDirectoryドメイン環境です。
インストールされているVSは、2010/2012 で、アップデートは現時点で最新の状態です。
#2013が入ってないのは、もうじき新マシンに乗り換えるため

ちなみに、ほかにどこかで使われていないか?と調査したところ、VSの子ウィンドウなどいろいろなところで使われていることもわかりました。
まぁ、おまけの部分については何の意味もありませんが。。。

ということで、クラス名を特殊化するなどの特別な行為を行っていない場合
FindWindow にウィンドウクラス名を与えて検索する行為は事実上不可能であるということを追記しておきます。

じゃぁどうするか?については、なぜ検索するのかという部分がないと適切な回答を得ることは難しいのでとりあえず割愛します。

引用返信 編集キー/
■69617 / inTopicNo.5)  Re[4]: ウィンドウクラス
□投稿者/ C# (2回)-(2014/01/13(Mon) 21:09:39)
とっちゃん、魔界の仮面弁士さん

ご連絡が遅くなって申し訳ありません。

クラス名ですが、先頭・末尾以外すべての値が変わっていました。

>FindWindow にウィンドウクラス名を与えて検索する行為は事実上不可能であるということを追記しておきます。

内容理解しましたが対処方法が分かりません。検索する理由としてはアプリ1(自作)からアプリ2(既存)を
動かすことが目的です。
Findwindow関数を使用してアプリ2のクラス名を取得して、アプリ2のtoolstrip内にアプリ2の操作ボタンが
あるのですがショートカットキー(F1)に対応しているため、postmessage関数を使用してアプリ2を実行しています。
PostMessage(hWndWorkPtr, (uint)WM_KEYDOWN, (int)Keys.F1, 0);

別PCでも問題なく動作するにはどのようにしたらよろしいでしょうか?
お手数おかけ致しますが、ご教示お願い致します。
引用返信 編集キー/
■69618 / inTopicNo.6)  Re[5]: ウィンドウクラス
□投稿者/ Azulean (257回)-(2014/01/13(Mon) 22:48:49)
ウィンドウクラス名が特定に使えないのですから、

1.ウィンドウのキャプションを用いて特定する
2.プロセスから特定する

といったように、ウィンドウクラスに頼らない方法を模索することになるでしょう。
ウィンドウキャプションが十分にユニークなものであれば、クラス名は NULL(IntPtr.Zero) を渡してキャプションだけで FindWindow すればよいでしょう。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -