Visual Basic 6.0 中級講座
VB6対応

 

Visual Basic 中学校 > VB6 中級講座 >

4.ハンドル

 

今回のテーマはハンドルです。ハンドルを使えばVB単体ではとてもできないような面白いことがいろいろとできるようになります。楽しんで使いましょう。ただし、奥が深いことも確かです。今回はあまり深入りしないでハンドルの簡単な使用例を紹介します。

この回の要約

・Windowsは各ウィンドウを「ハンドル」と呼ばれる番号で区別している。

・ウィンドウのハンドルがわかればそのウィンドウに対してAPI等で命令することができる。

・ウィンドウのハンドルを知るにはAPIを使うことが多い。

 

1.ハンドルとは?

 

Windowsは複数のウィンドウを同時に開くことができます。こんなことは特に意識しないであたりまえのように思っている人も多いことでしょう。ウィンドウを並べて開いてファイルを移動したりすることもしばしばありますね。(ただ、「ウィンドウ」という言葉はプログラム的にはもっと深い意味があります)。

Windows自身はこれらウィンドウに番号をつけて管理しているそうです。「4番のウィンドウがクリックされた」とか、「23番のウィンドウが閉じられた」とかいった具合です。新しくウィンドウを開くとそのときあいていた番号が適当に与えられます。だから、同じウィンドウでも開くたびに番号は変わります。

この番号を知ることができれば、Windowsに変わってあなたがウィンドウを管理したり、ウィンドウに命令を出したりすることができるようになるわけです。面白そうでしょう。

この番号のことを 「ハンドル」 というのです。もう少し正確には「ウィンドウのハンドル」「ウィンドウハンドル」などといったりします。

 

2.ハンドルを知るには?

 

それではこの便利なハンドルを知るにはどうしたらよいでしょう。VBのフォームのハンドルを知るのはとても簡単です。フォームのhWndプロパティがそれです。

ためしに、MsgBox Me.hWnd と記述して実行してみてください。なぞの数字が表示されますね。これがそのフォームのハンドルというわけです。もう一度実行すると数字が変わっていることでしょう。このようにハンドルは変化します。

しかし、VBのフォームはハンドルを使わなくても自由に命令できますから、このことを知ってもそれだけではあまり役に立ちません。知りたいのは他のウィンドウのハンドルです。

他のウィンドウのハンドルを取得するにはやはりAPIを使います。ハンドルを取得するAPIはいくつかあります。代表的なものは後で紹介するとしてとりあえず簡単なAPIを使ってプログラムしてみることにしましょう。

使うAPIは WindowFromPoint です。このAPI関数は指定した座標にあるウィンドウのハンドルを取得してくれるというたいへんわかりやすい関数です。

この関数の宣言は次のようになります。

Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long

知識のある方へ:おっしゃるとおりです。この宣言はプラットフォームSDKに記載されているものとは異なります。プラットフォームSDKによればこの関数の宣言はPrivate Declare Function WindowFromPoint Lib "user32" (Pt As PointAPI) As Longとすべきです。にもかかわらずこれは実際には不都合なのです。なぜなら「VBでは構造体を値渡しできない」からなのです。

X座標とY座標を指定すればその座標にあるウィンドウのハンドルが帰ってくるわけですね。でも、ハンドルだけ知ってもつまらないので、そのウィンドウのタイトルバーの文字列を「ハンドル取得成功!」に変えてしまいましょう。ハンドルさえわかればこんなこともできるのです。

まず、ハンドルを取得する部分は次のようになります。

Dim hTargetWnd As Long

hTargetWnd = WindowFromPoint(0, 0)

たったこの2行で座標0,0にあるウィンドウのハンドルがhTargetWndに取れます。もし、0,0に有効なウィンドウがない場合は失敗しますので試すときは画面の左上に何かウィンドウを置いておいてください。

それから、ハンドルは長整数型ですのでハンドルを変数に格納する場合はその変数をAs Longで宣言してください。

次にウィンドウのタイトルバーの文字を変えてしまいます。これにはSetWindowTextというAPI関数を使います。 この関数は引数を2つとります。1つ目は「どのウィンドウか指定する」ものでここに今取得したばかりのハンドルを入れます。2つ目の引数に新たにセットしたい文字列を指定します。

この関数の宣言は次のようになります。

Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long

そして、文字をセットする部分のコードは次のとおりです。

Dim Ret As Long

Ret = SetWindowText (hTargetWnd, "ハンドル取得成功!")

たったのこれだけでVBの限界を超えてしまいましたね。

以上のコードの全体をもう一度載せておきます。

Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long

Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long

Private Sub Command1_Click()

Dim hTargetWnd Long

Dim Ret As Long

hTargetWnd = WindowFromPoint(0, 0)

Ret = SetWindowText(hTargetWnd, "ハンドル取得成功!")

End Sub

 

 

3.ハンドルの利用法

 

今の例では取得したハンドルをつかってタイトルバーの文字を書き換えました。このように、ハンドルは取得することが目的なのではなく取得して、それを使って何をするかが目的なのです。ハンドルさえ取得してしまえばそのウィンドウに対してはいろいろなことができるようになります。

とはいっても「何ができるの?」「どうやってやるの?」という疑問は湧いてきますね。これについては少しずつ覚えていってもらうほかはありません。いろいろなAPIの存在を知りましょう。このホームページでもハンドルを使ったプログラミングを紹介するつもりでいます。お楽しみに。

とりあえず、ハンドルを使ってできる代表的なこととそれを実現してくれる関数をいくつか簡単に説明しておきましょう。以下で説明する関数はすべてAPI関数です。

@タイトルバーの文字列を取得する。

GetWindowText関数を使います。宣言は次のとおりです。タイトルバーの文字列をつかってウィンドウを識別することができます。実際この方法でウィンドウを識別しているプログラムもあります。

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Aウィンドウの位置とサイズを変更する。

MoveWindow関数を使います。それにしてもこの機能はあまり使い道が思いつきませんね。アイディア次第ではなにかぱっとしたことができるのかもしれません。

Private Declare Function MoveWindow Lib "user32" Alias "MoveWindow" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long

Bウィンドウを閉じる。

DestroyWindow関数を使います。これは使い方がかんたんですね。お試しようにどうぞ。

Private Declare Function DestroyWindow Lib "user32" Alias "DestroyWindow" (ByVal hwnd As Long) As Long

Cキャプチャーする。

BitBlt関数を使います。これはたいへん面白い機能です。そのうち機会があればぜひ紹介したいと思っています。

Dグラフィックを描画する。

これはいろいろな関数を使います。この機能は近いうちに紹介するつもりです。これによりデスクトップにお絵かきしたりもできるわけです。(デスクトップは特殊なウィンドウの1つです)。

 

4.ハンドルの取得方法

 

ハンドルを取得する方法としてすでにWindowFromPointを紹介しました。この他にもウィンドウハンドルを取得する方法はいくつかあります。しかし、正直に言ってしますと私はその全貌をしりません。これから紹介する関数の中には使ったことのないものもまぎれています。場合に応じて使いやすそうな寛会ううを使うのがよいでしょう。

@最前面のウィンドウハンドルを取得する。

GetForegroundWindow関数を使います。使い方は簡単なのですが、使いこなすのは意外と難しいかもしれません。

Private Declare Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow" () As Long

A子ウィンドウを指定して、その親ウィンドウのハンドルを取得する。

GetParent関数を使います。すでに子ウィンドウのハンドルを取得している場合にしか使えません。親子関係を変更してしまうというSetParent関数なるものも存在しますが私は使ったことはありません。

Private Declare Function GetParent Lib "user32" Alias "GetParent" (ByVal hwnd As Long) As Long

B開いているすべてのウィンドウのハンドルを取得する。

これができればなかなかのものです。EnumWindows関数を使うのですが難易度は高めです。フックの知識がない人は使わないでください。

Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

C指定したウィンドウの次のウィンドウのハンドルを取得する。

GetNextWindow関数を使います。「次の」というのはZオーダーの順番を指しています。前のウィンドウも、後ろのウィンドウも取得できます。

Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long

 

まだまだあるのですが今回はこの辺にしておきましょう。MSDNを持っている人は自分でウィンドウハンドルを使うと何ができるのか調べてみると面白いと思います。持っていない人もマイクロソフトのサイトでAPIの情報が公開されていますから、ウィンドウハンドルの使い道を探ることができるでしょう。

それでは、今回は失礼します。