【VBA×WindowsAPI】GetPixel関数の使い方
GetPixel関数
GetPixel関数は指定した座標のピクセルの色(RGB値)を取得するための関数です。
本関数を使用するにはデバイスコンテキスト(以下DC)にアクセスする必要があります。
DCとは簡単にいえばデバイスの描画担当者のようなものです。
私たち開発者はこのDCという”担当者”に「ウィンドウのこの位置に円を描いてほしい」「ウィンドウのこの位置のピクセルの色を教えてほしい」というような命令をすることで図形の描画やすでに描画されている情報の取得などをすることが可能になります。
WindowsAPIにはこのDCへアクセスするためのハンドルを取得するためのさまざまな関数があり、代表的なものとしてGetDC関数やGetWindowDC関数といったものがあります。
使用方法
GetPixel関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function GetPixel Lib “gdi32” _
(ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long) As Long
Declare Function GetPixel Lib “gdi32” _
(ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function GetPixel Lib "gdi32" (ByVal hdc As LongPtr, ByVal x As Long, ByVal y As Long) As Long #Else Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
GetPixel関数の構文は下記のように書きます。
lColor = GetPixel(hdc, x, y)
引数
hdc (64bit:LongPtr型 / 32bit:Long型)
DCへのハンドルを指定します。このハンドルが示すDCによって第2,3引数で指示する x, y 座標の基準となる原点位置が変化します。例えば画面全体のDCを指示した場合、画面の左上が原点となりますが、指定のウィンドウがもつDCを指示した場合、そのウィンドウの左上が原点となります。
x (Long型)
色を取得するピクセルのX座標を指定します。
y (Long型)
色を取得するピクセルのY座標を指定します。
戻り値
lColor (Long型)
戻り値は指定した座標のピクセルのRGB値です。R値、G値、B値がそれぞれ別々に取得できるわけではなくRGB関数の戻り値と同じように、RGBそれぞれの成分が合わさった値がLong型で返されます。たとえば R=255, G=255, B=255の場合は16777215 (&HFFFFFF)が返されます。
指定DCの領域外の座標が入力された場合、戻り値は「-1」が返されます。
※「-1」は定数値「CLR_INVALID (&HFFFFFFFF)」です
サンプルコード
以下はGetPixel関数を使って画面の指定座標のピクセル色を取得するサンプルコードです。
下記は画面左上を基準に右(x)方向に100px,下(y)方向に200px地点にあるピクセルの色を取得して、イミディエイトウィンドウにその結果を出力するコードです。これは画面全体をキャプチャしてその画像の指定座標にあるピクセルの色を取得しているイメージです。
画面全体のDCを取得するには、GetDC関数の引数にNULL値(0)を入力します。
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 26 27 28 29 |
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 lColor As Long Dim lRet As Long Dim lR As Long, lG As Long, lB As Long '画面全体のデバイスコンテキストへのハンドルを取得 hdc = GetDC(0) '画面のx=100,y=200地点のピクセルの色を取得 lColor = GetPixel(hdc, 100, 200) 'RGB値変換 lR = lColor Mod 256 lG = Int(lColor / 256) Mod 256 lB = Int(lColor / 256 / 256) '結果をイミディエイトウィンドウに出力 Debug.Print "カラー:" & lColor & "|R:" & lR & "|G:" & lG & "|B:" & lB 'デバイスコンテキストを解放 lRet = ReleaseDC(0, hdc) End Sub |
GetDC関数の引数にウィンドウのハンドルを渡せばそのウィンドウ内(クライアント領域内)での指定座標にあるピクセルの色を取得することができます。こちらは指定のウィンドウのみをキャプチャしてその画像の指定座標にあるピクセルの色を取得しているイメージです。
上記の画面全体の時とは違い見ているのは”指定したウィンドウのみ”なので、画面上で他のウィンドウたちに隠されていたとしても、ピクセルの色を取得することが出来ます。
(※指定ウィンドウが最小化されている場合は取得できません)
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 26 27 28 29 30 31 32 33 34 |
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 lColor As Long Dim lRet As Long Dim lR As Long, lG As Long, lB As Long 'ウィンドウ名が"コマンド プロンプト"のウィンドウハンドルを取得 Hwnd = FindWindow(vbNullString, "コマンド プロンプト") '取得したウィンドウのデバイスコンテキストへのハンドルを取得 hdc = GetDC(Hwnd) '取得したウィンドウのx=100,y=200地点のピクセルの色を取得 lColor = GetPixel(hdc, 100, 100) 'RGB値変換 lR = lColor Mod 256 lG = Int(lColor / 256) Mod 256 lB = Int(lColor / 256 / 256) '結果をイミディエイトウィンドウに出力 Debug.Print "カラー:" & lColor & "|R:" & lR & "|G:" & lG & "|B:" & lB 'デバイスコンテキストを解放 lRet = ReleaseDC(Hwnd, hdc) End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:GetPixel 関数 (wingdi.h) – Win32 apps