モノクロビットマップを作り、そこに文字や絵を書き、ビットマップデータを取得しようとしています。
しかし、テスト段階でうまくいきません。
確認の段階でフォームに文字表示されません。
vb.net2003です。
win32クラスはAPIの呼び出しを定義したクラスです。
Dim PaperWidth As Integer = Me.ClientSize.Width
Dim PaperHeight As Integer = Me.ClientSize.Height
'モノクロDIBを作る
Dim bmi As win32.BITMAPINFO
With bmi.bmiHeader
.biSize = Marshal.SizeOf(bmi.bmiHeader)
.biWidth = PaperWidth
.biHeight = PaperHeight
.biPlanes = 1
.biBitCount = 8
.biCompression = win32.BI_RGB
End With
Dim adr As IntPtr
Dim hDC As IntPtr = win32.CreateCompatibleDC(IntPtr.Zero)
Dim hDIB As IntPtr = win32.CreateDIBSection(hDC, bmi, win32.DIB_RGB_COLORS, adr, IntPtr.Zero, 0)
Dim holdbmp As IntPtr = win32.SelectObject(hDC, hDIB)
'文字を書く
Dim msg As String = "test"
win32.TextOut(hDC, 0, 0, msg, Len(msg))
'確認
win32.BitBlt(Me.Handle, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, hDC, 0, 0, win32.SRCCOPY)
win32.SelectObject(hDC, holdbmp)
win32.DeleteDC(hDC)
win32.DeleteObject(hDC)
自己修正です。
.biBitCount = 1
です。
パラメータを色々変えてみた時の直し忘れです、すみません。
CreateDIBSectionを使うのならば、ColorTableも設定してください。
bmiColorsを下のように設定してみましたが
やはり何も表示しません。
With .bmiColors
.rgbRed = 255
.rgbGreen = 255
.rgbBlue = 255
End With
そりゃBITMAPINFO.bmiColorsをいくら弄ったって無駄でしょう。
API関数のSetDIBColorTableについて調べてください。
SetDIBColorTableをキーワードに検索したら、色々わかった事と、わからない事ができました。
まず確認表示のBitBlt自体が間違っていました。
うまくいかない人は「画面が黒くなる」と書いてありましたが、私の場合は何も変わらなかった。
で、BitBltの戻り値を調べたら、0になっていて、"System.ComponentModel.Win32Exception: ハンドルが無効です。"
のエラーが帰ってきてました。
で、下のように変更しました。
'確認
Dim hDst As IntPtr = win32.GetDC(PictureBox1.Handle)
res = win32.BitBlt(hDst, 0, 0, PictureBox1.Width, PictureBox1.Height, hDC, 0, 0, win32.SRCCOPY)
win32.ReleaseDC(dstObj.Handle, hDst)
これで「間違った結果」を「表示」することはできるようになりました。
ちなみにform自体に表示するのはやめて、form上のPictureBox1に表示することにしました。
文字は表示するのですが、まだ色がおかしい。
で、調べている時にわかったのですが、BITMAPINFO構造体のRGBQUADを、
'RGBQUAD構造体
<StructLayout(LayoutKind.Sequential)> _
Public Structure RGBQUAD
Dim rgbBlue As Byte '青の濃さ
Dim rgbGreen As Byte '緑の濃さ
Dim rgbRed As Byte '赤の濃さ
Dim rgbReserved As Byte '未使用(常に0)
End Structure
'BITMAPINFO構造体
<StructLayout(LayoutKind.Sequential)> _
Public Structure BITMAPINFO
Dim bmiHeader As BITMAPINFOHEADER
Dim bmiColors As RGBQUAD
End Structure
と定義していたのですが、Dim bmiColors() As RGBQUAD でなくてはならない事がわかりました。
で、今のところここまでですが、大きな進歩です。
ありがとうございます、K.J.K. さん。
解決したけど、わからない事ができました。
SetDIBColorTableで正しい色にできました。
でも、それ以前にCreateDIBSectionで正しいパラメータを与えてやれば、正しい色のDIBを作ってくれるのも(たぶん)わかりました。
ただし、
'BITMAPINFO構造体
<StructLayout(LayoutKind.Sequential)> _
Public Structure BITMAPINFO
Dim bmiHeader As BITMAPINFOHEADER
Dim bmiColors() As RGBQUAD
End Structure
で、プログラムでredimしてやるのではだめでした。
これではbmiColors()へのポインタが入ってしまうようです(たぶん、サイズが変わらないから)
'BITMAPINFO構造体
<StructLayout(LayoutKind.Sequential)> _
Public Structure BITMAPINFO
Dim bmiHeader As BITMAPINFOHEADER
Dim bmiColors0 As RGBQUAD
Dim bmiColors1 As RGBQUAD
End Structure
で、2つの色を別々に設定してやることで可能になりました。
しかし、これでは2色専用になってしまいます。
可変長の構造体の宣言はできない(調べた限り)ので、これを回避する方法は無いのでしょうか?
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)>
><MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)>
おお、できそう。
でも、アンマネージとかマーシャリングとか、わからない言葉が飛びかってます。
とりあえず、当初の問題は解決したので、「解決」押しておきます。
ありがとうございました、K.J.K. さん。
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> dim bmiColors() As RGBQUAD
としたら、
"型 BITMAPINFO はアンマネージ構造体として集成できません。有効なサイズ、またはオフセットの計算ができません。"
といわれました。
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> dim bmiColors() As Integer
なら通るんですが。
すみません、integerでも、CreateDIBSectionの所で、
"埋め込まれた配列インスタンスがレイアウトで宣言された長さと一致しないため、型を集成できませんでした。"
といわれて、やっぱりダメでした。
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconstructssample.asp
やっぱりだめです。
構造体を持つ構造体、整数配列を持つ構造体なら大丈夫みたいなんですが、構造体の配列を持つ構造体はエラーが起きます。
ちなみに、
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconstructssample.asp
は無理なので、
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/netstart/html/sdkstart.asp
を見ました。
と言っても、内容が理解しきれないのですが。
<StructLayout(LayoutKind.Sequential)> _
Public Structure myStruct
Public val As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure myStruct2
Public data As myStruct
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure myStruct3
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _
Public data As Integer()
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure myStruct4
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _
Public data As myStruct()
End Structure
Sub test()
Dim st1 As myStruct
MessageBox.Show(Marshal.SizeOf(st1))
Dim st2 As myStruct2
MessageBox.Show(Marshal.SizeOf(st2))
Dim st3 As myStruct3
Dim dt3(1) As Integer
st3.data = dt3
MessageBox.Show(Marshal.SizeOf(st3))
Dim st4 As myStruct4
Dim dt4(1) As myStruct
st4.data = dt4
MessageBox.Show(Marshal.SizeOf(st4.data(0)))
MessageBox.Show(Marshal.SizeOf(st4)) '<-ここだけダメ
End Sub
URL間違った。
http://www.microsoft.com/japan/msdn/library/ja/cpguide/html/cpconStructsSample.asp
です。
ですからmyStruct3の段階で止めて、RGBQUADを使わず、
Integerなどとして受けてしまえばいいのでは。
うーん、それが正解だったのか。
ありがとうございました。
2回目の「解決」チェックしてみよう、どうなるだろう。
ツイート | ![]() |