Win32APIをVB.NETで使用する
2017年2月16日(木)
以前、あるソフトを作っているときに、デスクトップ上の最前面に図形を描画する処理が欲しくなった。 しかし.NETのGraphicsクラスではプライマリモニタ(メインディスプレイ)への描画はできますが、セカンダリモニタ(デュアルディスプレイ時のサブディスプレイ)には描画が出来ませんでした。 google先生に聞いてみたところ、やはりGDI+ではセカンダリモニタには描画が出来ないようでしたので、代わりにWin32APIのGDIで描画することにしました。 そこで今回は、Win32APIをVB.NETで使用する方法を思い出しながら書いていきます。 ...が、もし、デスクトップの最前面に描画をするためにこのページを見に来た方がいらっしゃるとあれなので、先にオチを申し上げますと、透過処理の実現や再描画の問題があるので、描画用のフォームを作成する方が現実的だということが分かりました。 透過処理は描画範囲のデスクトップをキャプチャして、描画させる図形とキャプチャを透過合成すれば可能です。 しかし、描画範囲がゲーム画面だったりすると60fpsの早さで再描画が行われているので、こちらも60fpsで描画しなければいけない上に、そうしたとしても点滅したようにちらついてしまいました。 そうなるくらいなら、フォームを描画させる図形に変形させて常に最前面でその位置に配置すれば、CPUも食わないしちらつかないので良いと思います。 ほかの用途でもWin32APIは使うことがあるので、使用するものだけでもWin32APIラップライブラリとして登録しておくといいと思いますので、その方法を今から書いていきます。 1. クラスライブラリのプロジェクトを作成する。 まずは、APIという名前でプロジェクトを作成しましょう。 2. Class1.vbをWin32API.vbにリネームします。 3. コードを書いていきます。(クラスの外枠 + 構造体を含むメソッドの例)
Win32APIクラス
Imports System.Runtime.InteropServices Public Class Win32API <StructLayout(LayoutKind.Sequential)> Public Structure RECT Public left As Integer Public top As Integer Public right As Integer Public bottom As Integer Public Sub New(ByVal rect As Drawing.Rectangle) left = rect.Left top = rect.Top right = rect.Right bottom = rect.Bottom End Sub End Structure <DllImport("user32.dll", CharSet:=CharSet.Auto)> Public Shared Function FillRect( ByVal hdc As IntPtr, ByRef lpRect As RECT, ByVal hBrush As IntPtr) As Integer End Function End Class
解説: 上記のようにRECT構造体を使用するメソッドなどありますが、例のように構造体を定義することで問題なく使用できます。 注意点として「LayoutKind.Sequential」でメンバが宣言された順に配置されるように指定することです。 4. コードを書いていきます。(定数を含むメソッドの例)
Win32APIクラス
Public Enum ROP2 As Integer SRCCOPY = &HCC0020 SRCPAINT = &HEE0086 SRCAND = &H8800C6 SRCINVERT = &H660046 SRCERASE = &H440328 NOTSRCCOPY = &H330008 NOTSRCERASE = &H1100A6 MERGECOPY = &HC000CA MERGEPAINT = &HBB0226 PATCOPY = &HF00021 PATPAINT = &HFB0A09 PATINVERT = &H5A0049 DSTINVERT = &H550009 BLACKNESS = &H42 WHITENESS = &HFF0062 End Enum <DllImport("gdi32.dll")> Public Shared Function BitBlt( ByVal hDestDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As ROP2) As Integer End Function
解説: 列挙体ROP2の箇所は本来は定数(DWORD)ですが、ROP2列挙体をDWORDの等価であるIntergerで定義することで、候補が出てくるためプログラミングしやすくなります。 Win32APIの定数の値をググるのが面倒な時は、 http://hp.vector.co.jp/authors/VA034288/ の、WIN32API定数からアプリをダウンロードすれば簡単に検索できます。 5. 使用するAPIの記述が終わったら、APIを使用するプロジェクトで参照設定し使用します。