【VBA×WindowsAPI】GetClassName関数の使い方

GetClassName関数

GetClassName関数は指定したウィンドウのクラス名を取得するための関数です。

ウィンドウクラス名はウィンドウを区別するための名称で、アプリケーションによって違う名称が付けられています。これによりウィンドウクラス名を見るだけで”どのアプリケーションから生成されているウィンドウなのか”を判断することができます。

VBAでよく利用されるアプリケーションのウィンドウクラス名は下記のようになっています。

アプリケーション ウィンドウクラス名
Excel XLMAIN
PowerPoint PPTFrameClass
Word OpusApp
メモ帳 Notepad
エクスプローラー CabinetWClass
UserForm ThunderDFrame

VBAではウィンドウクラス名は主にFindWindow関数を利用されるケースが多く、指定のアプリケーションのみのウィンドウを探索する際などに使われます。そんなときに「このアプリケーションのクラス名って何だろう?」という疑問を解消してくれるのがこのGetClassName関数というわけです。

アプリケーションというと少し違いますがUserFormは上表のとおり「ThunderDFrame」というウィンドウクラス名となります。これはExcelやPowerPoint、 Access等どのアプリケーションのVBAで作成しても同じウィンドウクラス名となってしまいます。

UserFormがどのアプリケーションで作成されたウィンドウなのかを知りたい場合は、GetParent関数を使ってUserFormの親ウィンドウを取得し、その親ウィンドウに対してGetClassName関数を適用することでどのアプリケーションから作成されたUserFormなのかを判定することが可能になります。

 

使用方法

GetClassName関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。

使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。

 icon-code  64bit  

Declare PtrSafe Function GetClassName Lib “user32” Alias “GetClassNameA” _
(ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

icon-code  32bit  

Declare Function GetClassName Lib “user32” Alias “GetClassNameA” _
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。

 
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。

Private Declare PtrSafe Function~ :モジュール内でのみ呼び出し有効
Public Declare PtrSafe Function~ :モジュール外で呼び出し有効

 
 

構文

GetClassName関数の構文は下記のように書きます。

icon-code GetClassName関数 

lRet = GetClassName(hWnd, lpClassName, nMaxCount)

引数

 hWnd     (64bit:LongPtr型 / 32bit:Long型)

ウィンドウクラス名を取得したいウィンドウのハンドルを入力します。
ウィンドウハンドルを取得するための関数としてFindWindow関数GetActiveWindow関数GetNextWindow関数GetParent関数など様々なものがあります。
 

 lpClassName    (String型) 

取得したクラス名を格納するための空の固定長文字列を入力します。
一般的にString型は可変長文字列として扱われることが多いため、固定長文字列はあまり聞き馴染みのない言葉かもしれませんが、可変長と固定長の違いは文字通り文字列のサイズ(文字の入るサイズ)が決まっているか決まっていないかです。

String型の文字列を固定長文字列として扱うには「Dim 〇 As String * 7」のように記載して宣します。この宣言文の場合、変数には最大7文字までの文字列しか入りませんし、7文字より少ない文字列を入れたとしても足りない分は空文字で7文字になるように補完されます。

つまりこの引数にはクラス名がすべて収まるくらいの大きさを持った固定長文字列を宣言してそのまま入力するだけです。文字列の長さが短いと取得したクラス名が途切れてしまう可能性があるので大きめにとっておく必要があります。(100文字分くらいあれば基本的にはすべて取得できます)
  

 nMaxCount   (Long型) 

取得するウィンドウクラス名の最大文字数を入力します。
第2引数と同じく小さく設定しすぎると取得したクラス名が途切れてしまう可能性があるので、確実に取得するには大きめに設定しておく必要があります。VBAではLen関数を使って固定長文字列と同じ値になるようにしておくのが一般的です。
 

戻り値

 lRet    (Long型) 

戻り値は関数が成功した場合、取得できたウィンドウクラス名の文字数が返ります。
(※文字が全角の場合は2文字分の扱いとなるので実際の文字数とは異なる場合があるので注意)
関数が失敗した場合の戻り値は0が返されます。

 

サンプルコード

以下はFindWindow関数GetClassName関数を使って、指定のウィンドウのクラス名を取得するサンプルコードです。下記コードではウィンドウのキャプション名が「コマンド プロンプト」となっているウィンドウのクラス名を取得することができます。「コマンド プロンプト」部分を書き換えることで任意のウィンドウのクラス名を調べることが可能です。

このコードで特筆すべき点は「不要なバッファ分は削除」の部分です。
GetClassName関数実行の結果、固定長文字列である「sBuf」に指定のウィンドウのクラス名が格納されました。しかし、VBEのローカルウィンドウで確認するとわかる通り「sBuf」の中にはクラス名の後ろに「・・・・」と謎の文字が続いています。この「・」はVBAではvbNullCharにあたります

最終的には、この不要なデータであるvbNullChar部分を除去する必要があります。方法は様々ですがサンプルコード記載の方法がもっとも単純で汎用性もあります。これはVBAでは馴染みのある「特定文字より左側の文字列を取得する」という処理です。最も左側にあるvbNullChar(・表示)より左側にある文字列のみをすべて取得する方法です。

GetClassName関数の戻り値は文字数なのでそれを利用するというのも手ですが、全角文字が含まれている場合には文字数の調整が必要になるので注意が必要です。

 

 icon-share-square  VBA×WindowsAPIまとめページ

その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。

 icon-share-square  参考

Microsoft公式:GetClassName 関数 (winuser.h) – Win32 apps

2023年7月16日Excel, VBA, Windows API

Posted by Lic