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

GetWindowDC関数

GetWindowDC関数は指定したウィンドウのデバイスコンテキストへのハンドルを取得するための関数です。
デバイスコンテキスト(以下DC)とはMicrosoft公式を引用すると下記の通りです。

ディスプレイやプリンターといったデバイスの描画属性に関する情報を保持する Windows のデータ構造体です。 すべての描画呼び出しは、線や図形、テキストを描画するための Windows API をカプセル化するデバイスコンテキスト オブジェクトを通じて行われます。 Windows では、デバイス コンテキストがあることで、デバイスに依存しない描画が可能となっています。 デバイス コンテキストを使用して、画面やプリンター、メタファイルへの描画を行うことができます。

デバイス コンテキスト – Microsoft Learn」より

少し難しく記載されていますが簡単にいえばDCとはデバイスの描画担当者のようなものです。
私たち開発者はこのDCという”担当者”に「ウィンドウのこの位置に円を描いてほしい」「ウィンドウのこの位置のピクセルの色を教えてほしい」というような命令をすることで図形の描画やすでに描画されている情報の取得などをすることが可能になります。

DCはウィンドウのハンドルが取得できれば、そのハンドルをもとにそのウィンドウが持つDCへのハンドルも取得することができます。このウィンドウハンドルから、そのウィンドウのDCへのハンドルを取得するための関数がGetWindowDC関数です。

ウィンドウは大きく分けて、いわゆるメインの部分となる「クライアント領域」と、メニューバーやツールバー、ステータスバー、フレーム部分などの「非クライアント領域」に分かれており、複数あるDCハンドル取得用の関数のどれを使うかによって取得できる領域が異なります。

これらのうちGetWindowDC関数は非クライアント領域とクライアント領域を合わせたウィンドウ全体に対するDCハンドルを取得することができます。クライアント領域のみに対するDCハンドルはGetDC関数で取得することができます。(より詳細な設定ができるGetDCEx関数というのもあります)

領域を使い分けることでたとえば図形を描画する際に非クライアント領域まで侵食することを防いだり、描画時の座標計算などを単純化することができます。

 

使用方法

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

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

 icon-code  64bit  

Declare PtrSafe Function GetWindowDC Lib “user32” (ByVal hwnd As LongPtr) As LongPtr

icon-code  32bit  

Declare Function GetWindowDC Lib “user32” (ByVal hwnd As Long) As Long

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

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

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

 
 

構文

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

icon-code GetWindowDC関数 

hdc = GetWindowDC(hwnd)

引数

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

対象のウィンドウのハンドルを入力します。ここで入力したハンドルが示すウィンドウのDCにアクセスすることが可能になります。引数としてNULL値(0)を入力することも可能で、この場合はウィンドウのDCではなく画面全体のDCにアクセスすることが可能になります。

開発環境によって引数の型が変化するので注意が必要です。
 

戻り値

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

戻り値は関数が成功した場合、hwndが示すウィンドウ全体のDCへのハンドルです。
(※ウィンドウ全体=クライアント領域+非クライアント領域)

関数が失敗した場合の戻り値はNULL値(0)となります。
引数と同じく開発環境によって戻り値の型が変化するので注意が必要です。

本関数を実行した後は必ずReleaseDC関数を使って取得したDCを解放する必要があります。
これを行わないと不要なメモリが蓄積していきメモリリークに陥ってしまいます。

 

サンプルコード

以下はGetWindowDC関数GetDC関数のそれぞれを使ってDCにアクセスし、画面に描画されている指定座標のピクセル色を取得するサンプルコードです。指定座標のピクセルの色を取得するには同じくWindowsAPIのGetPixel関数を使います。このとき座標の基準(原点)はGetPixel関数に引数として渡すDCが持っています。つまり非クライアント領域も含むDCハンドルを取得するGetWindowDC関数は下図でいうと右側となります。(GetDC関数使用時は左側)

下記はウィンドウ名が”コマンド プロンプト”となっているウィンドウのDCハンドルを取得して x=1,y=1 地点のピクセルの色を取得するサンプルコードです。このコードの場合、GetWindowDC関数を使っているためDCはクライアント領域だけでなく非クライアント領域も含まれています。そのため、ウィンドウ名が書かれているタイトルバー部分の色が取得されます。

 
対して下記はGetWindowDC関数をGetDC関数に置き換えて、それ以外は何も変えていないサンプルコードです。こちらの場合は、対象領域がクライアント領域のみのため、コマンドプロンプトの入力エリア(デフォルトで黒色のエリア)の x=1,y=1 地点のピクセルの色が取得できます。

 

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

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

 icon-share-square  参考

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

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

Posted by Lic