by 淡幻星 » 2008年6月09日(月) 07:30
konisi さんの修正案で、すでに解決しているように思われますが、
名前が出てましたので、簡単ですがコメントさせていだきます。
> #この改造をしても大丈夫かどうかは淡幻星さんに聞くのが一番手っ取り早そうだと思う次第
(コード設計上は)大丈夫なはず、です。
当方でも今現在はエラーは再現していないのですが、
クラス定義の
Sub GetPixelBits( hBmp As HBITMAP )
の部分を以下のように置き換えてください。
# 以前は似たようなエラーが起きてました。でも投稿した時点で修正しきったはずなんですが。。。
置き換えコード [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Sub GetPixelBits( hBmp As HBITMAP )
Dim hDC As HDC
Dim hMemDC As HDC
Dim hMemDC2 As HDC
Dim hBmp2 As HBITMAP
Dim w As Long
Dim h As Long
Dim n As Long
'前回のスレッドの終了を待つ。
If( hSecondThread<>NULL )Then
If( WAIT_TIMEOUT=WaitForSingleObject(hSecondThread, 0) )Then '念のためスレッド動作中かを確認。
n = 0
While FALSE=TerminateThread( hSecondThread, 1 )
'3回までリトライする。
If n<3 Then
n++
Else
MessageBox(hTargetWnd, "前回のピクセル情報の取得スレッドの停止(破棄)に失敗。", "エラー", MB_OK Or MB_ICONSTOP)
Exit While
End If
Wend
End If
CloseHandle( hSecondThread )
hSecondThread = NULL
EndIf
If nCpuSleepLevel<0 THen
'負の値が設定されたときは、ピクセル情報の取得を行わない。
Exit Function
End If
'スレッド用にビットマップを複製。hBmp→hBmp2
/*
「1つのビットマップオブジェクトを同時に複数の
デバイスコンテキストで選択することはできない.」
http://ls-al.jp/blog/archives/2006/03/post_288.html
*/
w = GetWidth()
h = GetHeight()
hDC = GetDC( hTargetWnd )
hMemDC = CreateCompatibleDC( hDC )
hMemDC2 = CreateCompatibleDC( hDC )
hBmp2 = CreateCompatibleBitmap( hDC, w, h )
If( NULL=SelectObject( hMemDC, hBmp ) )Then
'結合に失敗。
MessageBox(hTargetWnd, "ピクセル情報の取得に失敗。与えられたHBITMAPが新規DCに結合できない。", "エラー", MB_OK Or MB_ICONSTOP)
/* そのまま抜けるか、一応最後まで走らせるか・・・。迷うところ。ピクセル有無の無限待機関数の存在を考慮。
DeleteDC( hMemDC )
DeleteDC( hMemDC2 )
ReleaseDC( hTargetWnd ,hDC )
ExitSub
*/
End If
SelectObject( hMemDC2, hBmp2 )
BitBlt( hMemDC2, 0, 0, w, h, hMemDC, 0, 0, SRCCOPY )
DeleteDC( hMemDC )
DeleteDC( hMemDC2 )
ReleaseDC( hTargetWnd ,hDC )
'複製したビットマップからピクセル情報を得る@別スレッドGetPixelBitsA()を作成。
'※複製したビットマップhBmp2はスレッド側で終了時に破棄される。
SetAnyThreadParam( hBmp2 As DWord )
hSecondThread = CreateThread( ByVal NULL, NULL, AddressOf(WsEasyBmp_Static_GetPixelBitsA), VarPtr(This), NULL, VarPtr(tID) )
EndSub
その上で、画像読み込みなどの前に
SetCpuSleepLevel( -1 )
を実行して置いてください(一つのオブジェクトにつき、一回の実行でOK)。
例:
Dim objPic WsEasyBmp
objPic.SetCpuSleepLevel( -1 )
これで、画像のピクセル取得自体(今回のエラー発生箇所)を実行しなくなります。
# ピクセル取得を利用しない場合に限りますが。。。
konisi さんの修正案で、すでに解決しているように思われますが、
名前が出てましたので、簡単ですがコメントさせていだきます。
> #この改造をしても大丈夫かどうかは淡幻星さんに聞くのが一番手っ取り早そうだと思う次第
(コード設計上は)大丈夫なはず、です。
当方でも今現在はエラーは再現していないのですが、
クラス定義の
Sub GetPixelBits( hBmp As HBITMAP )
の部分を以下のように置き換えてください。
# 以前は似たようなエラーが起きてました。でも投稿した時点で修正しきったはずなんですが。。。
[hide=置き換えコード][code]
Sub GetPixelBits( hBmp As HBITMAP )
Dim hDC As HDC
Dim hMemDC As HDC
Dim hMemDC2 As HDC
Dim hBmp2 As HBITMAP
Dim w As Long
Dim h As Long
Dim n As Long
'前回のスレッドの終了を待つ。
If( hSecondThread<>NULL )Then
If( WAIT_TIMEOUT=WaitForSingleObject(hSecondThread, 0) )Then '念のためスレッド動作中かを確認。
n = 0
While FALSE=TerminateThread( hSecondThread, 1 )
'3回までリトライする。
If n<3 Then
n++
Else
MessageBox(hTargetWnd, "前回のピクセル情報の取得スレッドの停止(破棄)に失敗。", "エラー", MB_OK Or MB_ICONSTOP)
Exit While
End If
Wend
End If
CloseHandle( hSecondThread )
hSecondThread = NULL
EndIf
If nCpuSleepLevel<0 THen
'負の値が設定されたときは、ピクセル情報の取得を行わない。
Exit Function
End If
'スレッド用にビットマップを複製。hBmp→hBmp2
/*
「1つのビットマップオブジェクトを同時に複数の
デバイスコンテキストで選択することはできない.」
http://ls-al.jp/blog/archives/2006/03/post_288.html
*/
w = GetWidth()
h = GetHeight()
hDC = GetDC( hTargetWnd )
hMemDC = CreateCompatibleDC( hDC )
hMemDC2 = CreateCompatibleDC( hDC )
hBmp2 = CreateCompatibleBitmap( hDC, w, h )
If( NULL=SelectObject( hMemDC, hBmp ) )Then
'結合に失敗。
MessageBox(hTargetWnd, "ピクセル情報の取得に失敗。与えられたHBITMAPが新規DCに結合できない。", "エラー", MB_OK Or MB_ICONSTOP)
/* そのまま抜けるか、一応最後まで走らせるか・・・。迷うところ。ピクセル有無の無限待機関数の存在を考慮。
DeleteDC( hMemDC )
DeleteDC( hMemDC2 )
ReleaseDC( hTargetWnd ,hDC )
ExitSub
*/
End If
SelectObject( hMemDC2, hBmp2 )
BitBlt( hMemDC2, 0, 0, w, h, hMemDC, 0, 0, SRCCOPY )
DeleteDC( hMemDC )
DeleteDC( hMemDC2 )
ReleaseDC( hTargetWnd ,hDC )
'複製したビットマップからピクセル情報を得る@別スレッドGetPixelBitsA()を作成。
'※複製したビットマップhBmp2はスレッド側で終了時に破棄される。
SetAnyThreadParam( hBmp2 As DWord )
hSecondThread = CreateThread( ByVal NULL, NULL, AddressOf(WsEasyBmp_Static_GetPixelBitsA), VarPtr(This), NULL, VarPtr(tID) )
EndSub[/code][/hide]
その上で、画像読み込みなどの前に
SetCpuSleepLevel( -1 )
を実行して置いてください(一つのオブジェクトにつき、一回の実行でOK)。
例:
Dim objPic WsEasyBmp
objPic.SetCpuSleepLevel( -1 )
これで、画像のピクセル取得自体(今回のエラー発生箇所)を実行しなくなります。
# ピクセル取得を利用しない場合に限りますが。。。