【VBA×WindowsAPI】GetDC関数の使い方
GetDC関数
GetDC関数は指定したウィンドウのデバイスコンテキストへのハンドルを取得するための関数です。
デバイスコンテキスト(以下DC)とはMicrosoft公式を引用すると下記の通りです。
ディスプレイやプリンターといったデバイスの描画属性に関する情報を保持する Windows のデータ構造体です。 すべての描画呼び出しは、線や図形、テキストを描画するための Windows API をカプセル化するデバイスコンテキスト オブジェクトを通じて行われます。 Windows では、デバイス コンテキストがあることで、デバイスに依存しない描画が可能となっています。 デバイス コンテキストを使用して、画面やプリンター、メタファイルへの描画を行うことができます。
少し難しく記載されていますが簡単にいえばDCとはデバイスの描画担当者のようなものです。
私たち開発者はこのDCという”担当者”に「ウィンドウのこの位置に円を描いてほしい」「ウィンドウのこの位置のピクセルの色を教えてほしい」というような命令をすることで図形の描画やすでに描画されている情報の取得などをすることが可能になります。
DCはウィンドウのハンドルが取得できれば、そのハンドルをもとにそのウィンドウが持つDCへのハンドルも取得することができます。このウィンドウハンドルからそのウィンドウのDCへのハンドルを取得するための関数がGetDC関数です。
ウィンドウは大きく分けて、いわゆるメインの部分となる「クライアント領域」と、メニューバーやツールバー、ステータスバー、フレーム部分などの「非クライアント領域」に分かれており、複数あるDCハンドル取得用の関数のどれを使うかによって取得できる領域が異なります。
これらのうちGetDC関数はクライアント領域のみに対するDCハンドルを取得することができます。非クライアント領域も含めたDCハンドルはGetWindowDC関数で取得することができます。(より詳細な設定ができるGetDCEx関数というのもあります)
領域を使い分けることで、たとえば図形を描画する際に非クライアント領域まで侵食することを防いだり、描画時の座標計算などを単純化することができます。
使用方法
GetDC関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function GetDC Lib “User32” (ByVal hwnd As LongPtr) As LongPtr
Declare Function GetDC Lib “user32” (ByVal hwnd As Long) As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function GetDC Lib "User32" (ByVal hwnd As LongPtr) As LongPtr #Else Declare Function GetDC Lib “user32” (ByVal hwnd As Long) As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
GetDC関数の構文は下記のように書きます。
hdc = GetDC(hwnd)
引数
hwnd (64bit:LongPtr型 / 32bit:Long型)
対象のウィンドウのハンドルを入力します。ここで入力したハンドルが示すウィンドウのDCにアクセスすることが可能になります。引数としてNULL値(0)を入力することも可能で、この場合はウィンドウのDCではなく画面全体のDCにアクセスすることが可能になります。
開発環境によって引数の型が変化するので注意が必要です。
戻り値
hdc (64bit:LongPtr型 / 32bit:Long型)
戻り値は関数が成功した場合、hwndが示すウィンドウのクライアント領域のDCへのハンドルです。
関数が失敗した場合の戻り値はNULL値(0)となります。
引数と同じく開発環境によって戻り値の型が変化するので注意が必要です。
本関数を実行した後は必ずReleaseDC関数を使って取得したDCを解放する必要があります。
これを行わないと不要なメモリが蓄積していきメモリリークに陥ってしまいます。
サンプルコード
以下はGetDC関数を使ってDCにアクセスし、画面に描画されている指定座標のピクセル色を取得するサンプルコードです。指定座標のピクセルの色を取得するには同じくWindowsAPIのGetPixel関数を使います。このとき座標の基準(原点)はGetPixel関数に引数として渡すDCが持っています。
GetDC関数の引数がNULL(0)の場合はDCの対象が画面全体となるため、GetPixel関数で指定する座標は画面全体で見たときの座標となります。つまり今見ているモニター(画面)の左上を基準に右(x)に100px,下(y)に200px地点のピクセルの色を取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Declare PtrSafe Function GetDC Lib "User32" (ByVal hwnd As LongPtr) As LongPtr Declare PtrSafe Function ReleaseDC Lib "User32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long Declare PtrSafe Function GetPixel Lib "gdi32" (ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long) As Long Sub main() Dim hdc As LongPtr Dim color As Long Dim ret As Long '画面全体のデバイスコンテキストへのハンドルを取得 hdc = GetDC(0) '画面のx=100,y=200地点のピクセルの色を取得 color = GetPixel(hdc, 100, 200) 'デバイスコンテキストを解放 ret = ReleaseDC(0, hdc) End Sub |
対して、GetDC関数の引数にウィンドウハンドルを指定するとGetPixel関数で指定する座標はそのウィンドウ上での座標となります。つまり下記コードの場合は、コマンドプロンプトウィンドウのクライアント領域の左上を基準として右(x)に100px,下(y)に200px地点のピクセルの色が取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Declare PtrSafe Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Declare PtrSafe Function GetDC Lib "User32" (ByVal hwnd As LongPtr) As LongPtr Declare PtrSafe Function ReleaseDC Lib "User32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long Declare PtrSafe Function GetPixel Lib "gdi32" (ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long) As Long Sub main() Dim hwnd As LongPtr Dim hdc As LongPtr Dim color As Long Dim ret As Long 'ウィンドウ名が"コマンド プロンプト"のウィンドウハンドルを取得 hwnd = FindWindow(vbNullString, "コマンド プロンプト") '取得したウィンドウのデバイスコンテキストへのハンドルを取得 hdc = GetDC(hwnd) '取得したウィンドウのx=100,y=200地点のピクセルの色を取得 color = GetPixel(hdc, 100, 200) 'デバイスコンテキストを解放 ret = ReleaseDC(hwnd, hdc) End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:GetDC 関数 (winuser.h) – Win32 apps – Microsoft Learn