• ベストアンサー

VB BitBlt他でのエラー

ネットを見ながらVisual Basicを触り始めたのですが、下記のようなコードを実行すると「スタックを不安定にしています」といった感じのエラーが出てしまいます。 多分基本的な見落としだとは思うのですが、調べても上手い解決策が見つからず、質問させて頂いた次第です。  どうか、皆様のお知恵をお貸しください。 ・環境 Windows7 64bit - Microsoft Visual studio2017 - Visual Basic - Windowsデスクトップ - Windowsフォームアプリケーション ・やりたい事 別ソフトのウィンドウのタイトル、座標、画像を取得したい。 ・エラー 下記コードを開始(上の緑の三角)して実行すると、(1)のGetForegroundWindowは問題ないのですが、(2)のGetClientRect、(3)のGetWindowText、(4)のBitBltの部分を実行する際に、次のようなエラーが出てしまいます(3か所とも、関数名以外は同じエラーです)。 マネージド デバッグ アシスタント 'PInvokeStackImbalance' Message=マネージド デバッグ アシスタント 'PInvokeStackImbalance' : 'PInvoke 関数 'WindowsApp1!WindowsApp1.Form1::BitBlt' がスタックを不安定にしています。PInvoke シグネチャがアンマネージ ターゲット シグネチャに一致していないことが原因として考えられます。呼び出し規約、および PInvoke シグネチャのパラメーターがターゲットのアンマネージ シグネチャに一致していることを確認してください。' ・コード Imports OpenCvSharp Public Class Form1 Declare Function GetForegroundWindow Lib "user32" () As Long Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect) As Long Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long Declare Function BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long Public Const SRCCOPY = &HCC0020 'S Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click System.Threading.Thread.Sleep(1000) '指定ミリ秒待機する Dim hWnd As IntPtr = GetForegroundWindow() '(1)選択ウィンドウのハンドルを取得 'Dim winRect As New Rect 'GetClientRect(hWnd, winRect) '(2)ウィンドウ座標取得 Dim Title As String = Space(255) Dim ret As Long = GetWindowText(hWnd, Title, Len(Title)) '(3)ウィンドウのタイトルを取得 Title = Microsoft.VisualBasic.Left(ret, InStr(ret, vbNullChar) - 1) Dim img As IntPtr BitBlt(img, 0, 0, 100, 100, hWnd, 0, 0, SRCCOPY) '(4)ウィンドウの画像を取得 End Sub End Class

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

おそらく、引数の指定に問題があって、メモリを破壊していることが検出されたための現象だと思います。 特に、BitBltに関しては、hDestDCに未割当の整数を指定したり、hSrcDCに型の違うhWndを指定したりしているので、正しく動作していないことは間違いありません。 VBからWindowsAPIを呼び出すのであれば、WindowsAPIの使い方とVBの変数の型について理解する必要があります。

Mathmi
質問者

お礼

回答ありがとうございます。 なるほど、原因は恐らく引数の間違いですか。 まだ分からない事ばかり(特にポインタとかメモリとか)ですが、MSDN等のコードを丸写しするのではなく、データ型というか、引数の種類を重点的に調べながら修正していこうと思います。

Mathmi
質問者

補足

あれから色々調べて問題が解決したので、問題点を上げさせて貰います。 (本当なら質問文に補足したかったのですが、やり方がわからなかったので) ・ハンドルを格納する変数(hWnd)は、LongではなくInteger。ただし、IntPtrでもエラーは出なかった。 ・GetClientRectの第二引数lpRectはByRef渡しにする必要がある(Rectへのポインタが要求されている為?)。 後、上のコードを見直すと、titleを取り出すLenの所で、titleではなくrcに対して作業をしているミスがありました。 以上を対策すると、エラーが起こらず最後まで実行できました。 ありがとうございました。