【VBA×WindowsAPI】ReleaseDC関数の使い方
ReleaseDC関数
ReleaseDC関数は取得したデバイスコンテキスト(以下DC)を解放するための関数です。
ウィンドウ内に線や図形を描画したり、指定ピクセルの色を取得したりといった”ウィンドウの描画”に関わる操作を行う際には、各ウィンドウがそれぞれ持っているDCにアクセスする必要があります。
DCにアクセスするためにはGetDC関数もしくはGetWindowDC関数を使用してDCへのハンドルを取得することで、それを引数として関連関数に渡すことで様々な描画に関する操作を行うことができます。(※DCについての説明はリンク先ページに記載しているので合わせて参照下さい)
このとき上記のようにDCを使った描画関係の処理を行った後は必ず明示的にDCを解放する必要があります。このDCの解放を行うための関数がReleaseDC関数です。
VBAでは基本的にコードがすべて終わると使用していたメモリ(変数など)は自動ですべて解放されますが、WindowsAPIであるこれら関数は”解放する”という処理を書かないとコードが終わってもメモリが解放されません。つまり、コードを実行するたびに無駄なメモリが蓄積していきメモリリークに陥ってしまうということです。
これについては「GetDC関数もしくはGetWindowDC関数を使ったら、その後にReleaseDC関数を必ず使わないといけない」という対の存在として認識しておけば問題ありません。
また、ReleaseDC関数はCreateDC関数により新たに生成したDCはReleaseDC関数で解放することが出来ません。こちらの場合はDeleteDC関数を使って解放(削除)する必要があります。
使用方法
ReleaseDC関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function ReleaseDC Lib “User32” _
(ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
Declare Function ReleaseDC Lib “user32” _
(ByVal hwnd As Long, ByVal hdc As Long) As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function ReleaseDC Lib "User32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long #Else Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
ReleaseDC関数の構文は下記のように書きます。
lRet = ReleaseDC(hwnd, hdc)
引数
hwnd (64bit:LongPtr型 / 32bit:Long型)
解放するDCを持つウィンドウのハンドルを入力します。
基本的にはGetDC関数もしくはGetWindowDC関数の引数として入力したウィンドウのハンドルと同じものを入力します。GetDC/GetWindowDC関数の引数としてNULL値(0)を入力した場合は、同じくNULL値(0)を入力します。
hdc (64bit:LongPtr型 / 32bit:Long型)
解放するDCのハンドルを入力します。
基本的にはGetDC/GetWindowDC関数で取得したハンドルと同じものを入力します。
両引数とも開発環境によって型が変化するので注意が必要です。
戻り値
lRet (Long型)
戻り値として”DCの解放が正常にできたか”が返ります。
DCが正常に解放できた場合は「1」が、解放できなかった場合は「0」が返ります。
サンプルコード
ReleaseDC関数は取得したDCを解放するだけの関数で、それだけでは特に何もできません。
よって「DCを取得するための関数」と「DCを使って何らかの描画関連処理を行うための関数」も合わせて利用するのが一般的です。たとえば「ある指定のウィンドウに対して何らかの描画関連の処理を行う」には基本的には下記コードのような流れが基本となります。
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 |
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 FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Sub main() Dim hwnd As LongPtr Dim hdc As LongPtr Dim lRet As Long 'ウィンドウ名からウィンドウハンドルを取得 hwnd = FindWindow(vbNullString, "ウィンドウ名") '取得したウィンドウのデバイスコンテキストへのハンドルを取得 hdc = GetDC(hwnd) '---------------------------------- ' ' ウィンドウに対する描画関連の処理 ' '---------------------------------- 'デバイスコンテキストを解放 lRet = ReleaseDC(hwnd, hdc) End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:ReleaseDC 関数 (winuser.h) – Win32 apps