Shunnahito's Homepage

術日記

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を使用するプロジェクトで参照設定し使用します。                
inserted by FC2 system