N88モードでBMP表示時にエラーが発生

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
トモカズ

N88モードでBMP表示時にエラーが発生

#1 投稿記事 by トモカズ »

[AB4]ビットマップを簡単に扱うクラス
http://www.activebasic.com/forum/viewtopic.php?t=672

を利用させていただきN88BASICモードで作成してみました。
まずは出来たようですが、OSがXPである場合(断定は出来ませんが)

(1)「ピクセル情報の取得に失敗。与えられたHBITMAPが新規DCに結合できない」と表示され、本来のウィンドゥ外(デスクトップや他のウィンドゥ等に)にBMP表示をしてしまう。
("半角/全角"キーを押したときにその現象になった時もありましたが、必ずしもそうとは言えず”いつ”発生するかは不明です。IEを起動した直後にもこの事象がありました)

(2)上記の様にエラーは表示されませんが、正常にBMPファイルが表示されない場合がある。

現在Windows2000では上記問題は発生しておりません。
XPでも複数のマシンでやってみましたが、頻繁に発生するマシンと、稀に発生するマシンがあります(?)

常駐ソフトが多いほど(?)この現象が発生するように思えます
しかし断定はできません。
推測ですが、多くの処理を行なっている最中に発生していそうな気がします。

また、使用方法が間違っているのかもしれません。

以下にソース及びBMPファイルを置いておきました。
http://homepage3.nifty.com/ae85fcmxs/re ... sample.lzh

「ピクセル情報の取得に失敗。与えられたHBITMAPが新規DCに結合できない」エラーのOK後の画面はこちらです
http://homepage3.nifty.com/ae85fcmxs/re ... mp-err.png

解決方法等、ご教授いただけないでしょうか?
よろしくお願いいたします。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#2 投稿記事 by konisi »

何度か実行しましたが、同じ状況は確認できませんでした。
コードを追ったら原因らしいものは見つかったのですが

・原因らしきもの
Bload関数を外から呼び出すと、既にビットマップを読み込んでいた場合はそれを破棄するためにWsDeleteEasyBmp関数を呼び出す
WsDeleteEasyBmp関数が呼び出されると、第二スレッド(WsEasyBmp_Static_GetPixelBitsA関数)が実行中なら強制終了する
WsEasyBmp_Static_GetPixelBitsA関数内部ではGetPixelBitsA関数を呼び出している
GetPixelBitsA関数内部でローカル変数に対してGetDCを使ってる(つまり関数内でReleaseDCをする必要がある)
途中で止まるともちろんメモリリークを起こす

・突貫工事のような解決案(こちらではそもそもバグが発見されてないので上手く動くか不明)
全ての

コード: 全て選択

TerminateThread(hSecondThread,1)

コード: 全て選択

Dim tst As DWord
Do
    GetExitCodeThread(hSecondThread,VarPtr(tst))
    If tst=STILL_ACTIVE then
        Sleep(10)
    Else
        Exit Do
    End If
Loop
に変換する(スレッドを強制終了させずに、待機する)

#この改造をしても大丈夫かどうかは淡幻星さんに聞くのが一番手っ取り早そうだと思う次第
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
トモカズ

#3 投稿記事 by トモカズ »

konisiさん、何度もすみません。ありがとうございます。

まずはご指摘の箇所の変更をしてみました。・・・が
コンパイル時に 「 "VarPtr(tst)" 無効な識別子です 」となってしまいます。

何か事前に定義が必要なのでしょうか?
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#4 投稿記事 by konisi »

すみません、ヘルプに騙されました
Win32API: GetExitCodeThread
指定したスレッドが終了しているかどうかを確認します。


--------------------------------------------------------------------------------
定義
Declare Function GetExitCodeThread Lib "kernel32" _
(hThread As HANDLE, _
ByRef lpExitCode As DWord) As Long
hThread
調査するスレッドのハンドルを指定します。
lpExitCode
DWord型変数のポインタを指定します。この変数にスレッド終了状況が格納されます。スレッドが実行されているときは STILL_ACTIVE が、終了しているときは終了コードが格納されます。
となってるのでついVarPtrと書いてしまったのですが、
よく見るとByRefで定義されてるので

コード: 全て選択

Dim tst As DWord 
Do 
    GetExitCodeThread(hSecondThread,tst) 
    If tst=STILL_ACTIVE then 
        Sleep(10) 
    Else 
        Exit Do 
    End If 
Loop
にする必要があります。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
トモカズ

#5 投稿記事 by トモカズ »

konisiさん、ホント何度もありがとうございます。

早速、修正し無事コンパイル出来ました!
今のところ、正常に動作していそうですが、なにしろ再現性が低いために色々な機種で様子を見てみたいと思います。
(前バージョンでは確かに不具合があった機種でも、今回のモノでは問題なく動作しているので大丈夫だと思います)
会社のパソコンでも(コッソリ)確かめてみます。会社のパソコンは必ずこの現象がでるので確認はし易いのです。

おかげさまで、オセロソフトがどうにかカタチになりそうです。(まだN88モードなのが残念ですが・・・)
完成したら、konisiさんに是非見てもらいたいです。
(大したソフトではありませんが)

すみません。あつかましいとは思いますが、もう一つ質問です。(別スレッドの方がよろしいかもしれませんが)
出来ればN88モードのウィンドゥサイズが固定に出来れば良いなぁと考えておりますが可能なのでしょうか?
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#6 投稿記事 by konisi »

N88BASICプロンプトのウインドウハンドルは_PromptSys_hWndに入っているので、

コード: 全て選択

#prompt
Dim style As DWord
SetWindowPos(_PromptSys_hWnd,0,0,0,0,0,SWP_FRAMECHANGED Or SWP_NOSIZE Or SWP_NOMOVE)
style=GetWindowLong(_PromptSys_hWnd,GWL_STYLE)
style=style And Not WS_THICKFRAME
SetWindowLong(_PromptSys_hWnd,GWL_STYLE,style)
でだいたいいけると思います

システムボタンの描画位置がバグるので、これを実行した後一旦最小化→元のサイズに戻すをするほうがいいと思います。

コード: 全て選択

ShowWindow(_PromptSys_hWnd,SW_SHOWMINNOACTIVE)
ShowWindow(_PromptSys_hWnd,SW_SHOWNOACTIVATE)
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
トモカズ

#7 投稿記事 by トモカズ »

konisiさん

早速、試してみました。ありがとうございました。
完成しましたら、ご報告させていただきます。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#8 投稿記事 by イグトランス »

スレッドの終了待ちはWaitForSingleObject(hSecondThread, INFINITE)のほうが短いコードで、
しかも無駄にCPUを使わないので、他のタスクに対して優しいです。

SetWindowPosは、SetWindowLongの後に実行しないと意味がないと思います。
そうすれば、最小化→元に戻すをする必要がない気がするのですがどうでしょうか。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#9 投稿記事 by konisi »

スレッドの終了待ちはWaitForSingleObject(hSecondThread, INFINITE)のほうが短いコードで、
しかも無駄にCPUを使わないので、他のタスクに対して優しいです。
なるほど。
「シグナル状態」の意味を誤解して、対象スレッド内でSleepを使った時に関数を抜けてしまうと思ってたもので(ry

#寝ぼけ頭で適当に書くものでは無いなと反省
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ゲスト

#10 投稿記事 by ゲスト »

イグトランスさん、ありがとうございます。

TerminateThread(hSecondThread,1) の箇所を
WaitForSingleObject(hSecondThread, INFINITE)に
置き換えればよろしいのでしょうか?

また、
ウィンドゥの最小化ボタンの無効化が可能だと嬉しいのですがいかがでしょうか?

質問の連続で申しわけありません。ヘルプを見てはいるのですが中々困難です。
サンプルプログラムが乗っていてくれると助かるのですが・・・

よろしくお願いいたします。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#11 投稿記事 by konisi »

SetWindowLongの近くで

コード: 全て選択

style=style And Not WS_THICKFRAME
としているのを

コード: 全て選択

style=style And Not (WS_THICKFRAME Or WS_MINIMIZEBOX)
に変更すると、最小化ボタンは無効になります。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#12 投稿記事 by イグトランス »

ここでのWaitForSingleObjectは、DoからLoopまでの全部をこれ1行に置き換えられます。結果的に変数tstも要らなくなるはずです。そういう意味で短くなると書いたわけです。

ほんと、ヘルプに関してはわかりづらいとは思います。どうしたらいいだろうとは思うんですけどね……。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

#13 投稿記事 by 淡幻星 »

konisi さんの修正案で、すでに解決しているように思われますが、
名前が出てましたので、簡単ですがコメントさせていだきます。

> #この改造をしても大丈夫かどうかは淡幻星さんに聞くのが一番手っ取り早そうだと思う次第
(コード設計上は)大丈夫なはず、です。

当方でも今現在はエラーは再現していないのですが、
クラス定義の
Sub GetPixelBits( hBmp As HBITMAP )
の部分を以下のように置き換えてください。
# 以前は似たようなエラーが起きてました。でも投稿した時点で修正しきったはずなんですが。。。 その上で、画像読み込みなどの前に
SetCpuSleepLevel( -1 )
を実行して置いてください(一つのオブジェクトにつき、一回の実行でOK)。
例:
Dim objPic WsEasyBmp
objPic.SetCpuSleepLevel( -1 )
これで、画像のピクセル取得自体(今回のエラー発生箇所)を実行しなくなります。
# ピクセル取得を利用しない場合に限りますが。。。
トモカズ

#14 投稿記事 by トモカズ »

konisiさん、イグトランスさん、淡幻星さん
ご丁寧にありがとうございました。

konisiさんのコード、イグトランスさんのコードでそれぞれコンパイルし、現在のところ問題なく動作しております。
次は淡幻星さんのコードに修正を行い試してみたいと思います。

皆様のお陰で、どうにか完成に近づきました。

http://homepage3.nifty.com/ae85fcmxs/02 ... versi.html
(バージョン2です)

また、不明点が出てくると思います。その際は宜しくお願いいたします。
返信する