連載:VB 6ユーザーのための
これならマスターできるVB 2005超入門

第12回 VB 2005でWin32 APIを利用する

羽山 博
2007/10/26
Page1 Page2 Page3 Page4

■プログラムの考え方

 フォームのデザインが終わったところで、コードを書きたくてウズウズしている人も多いと思うが、あせらず確実に進めよう。最初に、どのようにしてほかのプログラムのウィンドウのサイズを変えるのか、その考え方や流れをあらかじめ見ておこう。その方が見通しはずっとよくなるはずだ。

 ウィンドウのサイズを選択するための処理は、このプログラムのフォーム上での処理なので、従来のコードとさして変わることはない。問題は、[サイズ変更]ボタンをクリックしたときの処理だ。

 まず、ほかのウィンドウでマウスの操作をした場合でも、自分のフォームでマウス・イベントを受け取る必要がある。そのためには、ほかのウィンドウにマウス・ポインタが移動しても、マウスを「捕まえて」おかなければならない。実は、この設定は簡単。フォームのCaptureプロパティをTrueにしておくだけでよい。図4のようなイメージでとらえるといいだろう。なお、マウスを「捕まえて」おくことを「マウスをキャプチャする」という。


図4 マウスをキャプチャする
マウスをキャプチャすれば、ほかのウィンドウ上でマウス・ボタンを押しても、MouseDownイベントは自分のウィンドウで処理できる。

 次に、マウス・ボタンが押されたときのイベント・ハンドラを書く。ただし、マウスをキャプチャしても、Clickイベントを受け取ることはできないことに注意。この場合にはMouseDownイベントを受け取るので、フォームのClickイベント・ハンドラではなく、MouseDownイベント・ハンドラにコードを書く。

 ここでは、マウスの現在位置から、その位置にあるウィンドウの「ハンドル」を取得する。ハンドルとはウィンドウなどを識別するための番号のことと考えればよい。

 ただし、Win32 APIの世界では、私たちが普段「ウィンドウ」と呼んでいるもの(アプリケーションの枠全体。以下、「フレーム・ウィンドウ」と呼ぶことにする)だけでなく、画面に表示されているボタンやラベル、テキストボックスなどもすべてウィンドウとして扱われている(ウィンドウ・ハンドルを持つ)ことに注意が必要。

 従って、単にマウスの位置にあるウィンドウのハンドルを得るだけではダメで、マウスの位置にあるウィンドウから、その親ウィンドウ、さらにその親ウィンドウ……を探していき、フレーム・ウィンドウを見つける必要がある。このプログラムでは、デスクトップを親とするウィンドウ、または親のないウィンドウをフレーム・ウィンドウと見なしている(図5)


図5 マウスの位置からフレーム・ウィンドウを探す
ウィンドウの親ウィンドウを探していき、デスクトップまでたどりついたら、そのウィンドウがプログラムのフレーム・ウィンドウとなる。フレーム・ウィンドウが見つかれば、後はそのウィンドウのサイズを変更するだけだ。

 マウスの位置から、そこにあるウィンドウのハンドルを取得するには、Win32 APIであるWidnowFromPoint APIを使う。また、親ウィンドウのハンドルを取得するには、GetParent APIを、デスクトップのウィンドウ・ハンドルを取得するにはGetDesktopWindow APIを使う。つまり、自分の親ウィンドウのハンドルが、デスクトップのウィンドウ・ハンドルと同じであれば、そのウィンドウはフレーム・ウィンドウであると見なせるわけだ。

 最後は、フレーム・ウィンドウのサイズを変えてやればよい。これにはSetWindowPos APIが使える。

■Win32 APIを宣言する

 では、コードを書いていこう。Win32 APIをVB 2005で利用するには、VB 6の場合と同じように各APIの宣言が必要となる。まず、宣言の部分を見てみよう。

Public Class frmSetting

  ' 位置からウィンドウ・ハンドルを取得するAPI
  Private Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal x As Integer, ByVal y As Integer) As Integer

  ' 親ウィンドウのハンドルを取得するAPI
  Private Declare Function GetParent Lib "user32" Alias "GetParent" (ByVal hWnd As Integer) As Integer

  ' デスクトップ・ウィンドウのハンドルを取得するAPI
  Private Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" As Integer

  ' ウィンドウの位置やサイズを変えるAPI
  Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hWnd As Integer, ByVal hWndInsertAfter As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer

  ' SetWindowPos APIで使う定数
  Private Const SWP_NOMOVE = &H2
  Private iHeight, iWidth As Integer  ' ウィンドウの幅と高さ
Win32 APIの宣言
自分で宣言するのは大変なので、既存の宣言から必要なものをコピー&ペーストすればよい。ただし、データ型などをVB 2005に合わせて変更する必要がある。

 どのようなWin32 APIが利用できるかは、以前のMSDNライブラリの「Win32およびCOM開発」から見ることができる。また、すべてのWin32 APIの宣言がテキスト・ファイルにまとめられており、KB178020からダウンロードできる。ただし、この内容はVB 5用であるため、データ型などの書き換えが必要になる。また、情報が古いので、掲載されていないWin32 APIもあることに注意。

 ダウンロードしたファイルはテキスト・ファイルを「Program Files\Ork97\Document\vba」というフォルダに自動的にインストールするプログラムとなっている。プログラムを実行すると、そのフォルダの下に「Win32API.txt」というテキスト・ファイルが作られるので、その中から必要な宣言を探し出して、コピー&ペーストすればよい。

 Win32 APIの宣言方法は一般的な関数とほぼ同じだが、Libの後に、そのAPIが含まれるライブラリ・ファイル名を指定する。また、実際のAPIの名前とは異なる関数名を付けたい場合には、「Alias」に続けて実際のAPIの名前を指定するとよい。

 先ほども述べたように、VB 2005でこれらの宣言を利用するには、引数や戻り値のデータ型を変更する必要がある。VB 6以前のLong型はVB 2005ではInteger型になっているので、古い宣言の中に書かれている「Long」はすべて「Integer」に書き直す必要がある。上記のリストはすでに書き直したものである(ここからは、ほかのデータ型の場合の話なので、サンプル・プログラムのコードを先に見たい方は、次ページの「マウスをキャプチャするまでのコードを書く」まで読み飛ばしていただいても差し支えない)。

 このプログラムで利用しているWin32 APIの引数はすべて整数なので、以上で宣言は終わりだが、文字列を扱うときには、以下のようにして、文字列を格納できる長さのオブジェクトを作成しておく必要がある。

 今回のプログラムでは使わないが、ユーザー名を取得するために利用できるGetUserName APIを例として見ておこう。

Public Class Form1

  ' ユーザー名を取得するAPI
  Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    ' 25文字まで格納できる文字列オブジェクトを作成しておく
    Dim strUserName As New String(" "c, 25)
    Dim ret As Integer

    ret = GetUserName(strUserName, 25) ' ユーザー名を取得する
    MessageBox.Show(strUserName)
  End Sub
End Class
文字列を引数として取るWin32 APIの利用
文字列を格納するのに必要な長さの文字列オブジェクトを作成しておく。Windowsのユーザー名は最大でも20文字なので、余裕をみて25文字分としている。なお、VB 6までの「Dim strUserName As String * 25」というコードはエラーになる。

 また、複数のデータ型の引数を受け取ることができる場合には、「As Any」というデータ型が指定されている。この場合は、受け取る引数の違いによって、宣言を分けておけばよい。例えば、SystemParametersInfoというAPIにはさまざまな引数が指定できるので、VB 6までで利用する場合の宣言は以下のようになっている。

' VB 6用の宣言
Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByVal lpvParam As Any, ByVal fuWinIni As Long) As Long

 第3引数である「lpvParam」には、処理の方法を表す「uAction」という第1引数の値によって、文字列や整数、整数の配列、真偽値(Boolean型)、そのほかの異なる型のデータを与える必要がある。As Anyと宣言されていたのはそのためだ。

 VB 2005では、As Anyが使えないので、例えば、整数の配列と真偽値を指定する必要があるなら、以下のように引数が異なる2つの宣言を記述しておき、使い分ければよい。

' SystemParametersInfo APIの第3引数で整数配列を扱う場合
Declare Function SystemParametersInfoI Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Integer, ByVal uParam As Integer, ByVal lpvParam As Integer(), ByVal fuWinIni As Integer) As Integer

' SystemParametersInfo APIの第3引数で真偽値を扱う場合
Declare Function SystemParametersInfoB Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Integer, ByVal uParam As Integer, ByVal lpvParam As Boolean, ByVal fuWinIni As Integer) As Integer

 このように宣言しておけば、整数の配列を指定する場合には、「SystemParametersInfoI」を利用することができ、真偽値を指定する場合であれば、「SystemParametersInfoB」を利用することができる。

 Win32 APIを利用するに当たっての注意事項はほかにもあるが、サンプル・プログラムそのものからかなり外れてしまったので、話を元に戻そう。詳細な注意事項について知りたい方は、VB 2005のヘルプを参照したり、「Win32 API」といったキーワードでMSDNライブラリなどを検索したりすれば情報が得られる。必要に応じて目を通しておくといいだろう。


 INDEX
  VB 6ユーザーのためのこれならマスターできるVB 2005超入門
  第12回 VB 2005でWin32 APIを利用する
    1.サンプル・プログラム18 − ウィンドウのサイズを変更するプログラム
  2.プログラムの考え方とWin32 APIの宣言
    3.マウスのャプチャとウィンドウのリサイズ
    4.フレーム・ウィンドウのハンドル取得
 
インデックス・ページヘ  「これならマスターできるVB 2005超入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH