トップページ > 過去ログ > 記事閲覧
文字列の描画にゴミが混ざります
名前:いっち 日時: 2009/11/11 21:52

DrawStringToHandleを利用して、画面の同じ領域に何度も描画するような処理を 行っているのですが、フレーム毎に表示内容が変わりゴミが混ざります。 (例えば下記の画像1と画像2がフレーム毎に交互に表示されます。 画像1は一見正常に見えますがゴミが混じっています) 最初はメモリ周りの問題と思い、色々と試してみたのですが、 原因の追究には至りませんでした。 再現性はあるものの常に起こるわけではなく、特定の文字列(文字?)が原因とは 思うのですが、これも特定できていません。 また、フォントに"メイリオ"を使用すると発生しやすく、"MS Pゴシック"では 発生しにくいようです(無いわけではない)。 同様の事象をご存知の方や、解決方をご存知の方がいらっしゃいましたらご連絡ください。 ソース(とLog)も公開しておきますので、間違いなど指摘していただけると大変助かります。 虫の良いお願いで恐縮ですが、よろしくお願いします。 当方の主な環境は以下の通りです。 OS WindowsXP SP 3 DirectX 9.0c DXLib Ver3.00e 開発環境 VC++ 2008 Exp CPU Pen4 3.2GHz GPU Geforce 6600 GT 画像1:ttp://nukkorosu.80code.com/img/nukkorosu12092.jpg 画像2:ttp://nukkorosu.80code.com/img/nukkorosu12093.jpg ソース:ttp://gigabyteserver.com/uploader01/upload.php?counting=720&firen=winplus.jp720.zip

Page: 1 |

Re: 文字列の描画にゴミが混ざります ( No.1 )
名前:いっち 日時:2009/11/11 23:14

書き忘れましたが、Logに不審な点は特にありませんでした。 ソースはコンパイルして実行後、PgUp、PgDnキーで行を送ると、事象が再現するはずです。
Re: 文字列の描画にゴミが混ざります ( No.2 )
名前:いっち 日時:2009/11/12 00:57

ソースの主な部分を貼り付けます。 長いので所々端折ってます。 まずはMainから int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); SetGraphMode( 1024, 768, 32 ); if ( DxLib_Init() == -1 ) return -1; SetDrawScreen( DX_SCREEN_BACK ); CDXMessageWindow cMesWin( 0, 512, 0 + 768 - 1, 512 + 256 - 1 ); <-文字列の表示領域を登録 cMesWin.Visible( ); cMesWin.Add( "「さあ、もう一度押すじゃあ」"); // <-文字列を表示幅で分割してバッファに格納(下記に詳細) /*.........................................*/ // <-さらに続けて格納(省略) _TCHAR strbuff[1024]; int i = 0; int iKeyWait, iKeyWaitCount; iKeyWaitCount = iKeyWait = 15; while( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { if ( CheckHitKeyAll( ) && iKeyWaitCount > iKeyWait ) { if ( CheckHitKey( KEY_INPUT_RETURN ) ) { _stprintf( strbuff, "Line no = %04d Enterでデータを追加", i ); cMesWin.Add( strbuff ); i++; } if ( CheckHitKey( KEY_INPUT_PGDN ) )//行送り cMesWin.LineDown( ); if ( CheckHitKey( KEY_INPUT_PGUP ) )//行送り cMesWin.LineUp( ); if ( CheckHitKey( KEY_INPUT_END ) )//行送り cMesWin.LineEnd( ); if ( CheckHitKey( KEY_INPUT_HOME ) )//行送り cMesWin.LineTop( ); iKeyWaitCount = 0; } SetDrawArea( 0, 0, 1024 - 1, 768 - 1 ); ClearDrawScreen( ); cMesWin.OnShow( );// <-ここで表示領域の高さにあう行数だけバッファの内容を表示(下記に詳細) SetDrawArea( 0, 0, 1024 - 1, 768 - 1 ); ScreenFlip( ); iKeyWaitCount++; } ClearDrawScreen( ); cMesWin.OnKey( "" ); // <-DrawStringを使ってバッファの内容を全部表示。化けません ScreenFlip( ); WaitKey( ); DxLib_End( ); return 0; } // 次にバッファに格納する部分です。 // pszLineBuffがバッファです。 bool CDXMessageWindow::Add( _TCHAR *pszString ) { for ( int i = 0, j = 0, ismbc = 0; pszString[i] != 0; i += j ) { for ( j = 0; pszString[i+j] != 0; j += (ismbc + 1) ) { ismbc = (_istlead( pszString[i+j] ) ? 1 : 0); // マルチバイトチェック if ( GetDrawStringWidthToHandle( pszString + i, j + ismbc + 1 , hdxFontHandle_MB ) >= (stInnerArea.right - stInnerArea.left + 1) ) { // はみ出た ismbc = 0; break; } } if ( pszLineBuff[iLineInsertPos] != 0 ) { delete [] pszLineBuff[iLineInsertPos]; pszLineBuff[iLineInsertPos] = 0; } pszLineBuff[iLineInsertPos] = new _TCHAR[j + 1]; _tcsncpy_s( pszLineBuff[iLineInsertPos], j + 1, pszString + i, j ); iLineInsertPos = (iLineInsertPos + 1) % iLineBuffSize; // <-格納最大行数を超えると0行目に戻って再利用。配列の循環利用 iLineCount += (iLineCount < iLineBuffSize) ? 1 : 0; // <-現在の格納行数は格納最大行数を超えない } LineEnd( ); // 表示を最新行に移動 return true; } // 表示部分です。ここの出力が化けます。 // iLinePrintPosは現在表示中の行を保持します。 // Idx()は配列を循環させたときに適切な添え字を返す関数です。 // この事象は循環させる前でも発生します。 bool CDXMessageWindow::OnShow( void ) { if ( !isVisible ) return false; SetDrawArea( stClientArea.left, stClientArea.top, stClientArea.right, stClientArea.bottom ); // Item for ( int i = 0; (i < iLineVisibleMax) && (iLinePrintPos + i <iLineCount); i++ ) { if ( pszLineBuff[Idx(iLinePrintPos + i)] == 0 ) break; DrawStringToHandle( stInnerArea.left, stInnerArea.top + (i * iFontLineFeedSize_MB), pszLineBuff[Idx(iLinePrintPos + i)], iFontColor_MB, hdxFontHandle_MB, iFontColorEdge_MB ); } return true; } 以上です。 お見苦しくて申し訳ありません。
Re: 文字列の描画にゴミが混ざります ( No.3 )
名前:Will 日時:2009/11/12 13:03

原因は分かりませんが私のPCでも現象確認できました。 PC:DELL Vostro 1000 OS:XP Pro SP3 ただ、最初間違えてDXライブラリ Ver.2.25を使用したときには発生しませんでした。
Re: 文字列の描画にゴミが混ざります ( No.4 )
名前:いっち 日時:2009/11/12 14:05

情報ありがとうございます。 どうやら、ハード依存の現象では無さそうなのでほっとしました。 引き続き調べてみます。
Re: 文字列の描画にゴミが混ざります ( No.5 )
名前:いっち 日時:2009/11/12 18:41

検証の結果、下記のコードでも文字出力がおかしくなりました。 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { if( DxLib_Init( ) == -1 ) // DXライブラリ初期化処理 return -1; // エラーが起きたら直ちに終了 int iFontSize = 20; SetFontSize( iFontSize ); // <-問題有り // SetFontSize( DEFAULT_FONT_SIZE ); // <-問題無し // 下記文字列のうち2行をコメントにすると問題なし // ただし、フォントサイズをさらに大きくすると問題あり char szBuff[10][256] = { "亜哀愛悪握圧扱安案暗以衣位囲医依委威胃為尉異移偉意違維慰遺緯", "域育一壱逸芋引印因姻員院陰飲隠韻右宇羽雨運雲永泳英映栄営詠影", "鋭衛易疫益液駅悦越謁閲円延沿炎宴援園煙猿遠鉛塩演縁汚王凹央応", "往押欧殴桜翁奥横屋億憶虞乙卸音恩温穏下化火加可仮何花佳価果河", "科架夏家荷華菓貨渦過嫁暇禍靴寡歌箇稼課蚊我画芽賀雅餓介回灰会", "快戒改怪拐悔海界皆械絵開階解塊壊懐貝外劾害涯街慨該概垣各角拡", "革格核殻郭覚較隔閣確獲嚇穫学岳楽額掛潟括活喝渇割滑褐轄且株刈", "干刊甘汗缶完肝官冠巻看陥乾勘患貫寒喚堪換敢棺款間閑勧寛幹感漢", "慣管関歓監緩憾還館環簡観艦鑑丸含岸岩眼頑顔願企危机気岐希忌汽", "奇祈季紀軌既記起飢鬼帰基寄規喜幾揮期棋貴棄旗器輝機騎技宜偽欺", }; for ( int i = 0; i < 10; i++ ) { DrawString( 0, i*iFontSize, szBuff[i], 0x00ffffff ); } WaitKey( ); DxLib_End( ); return 0; } フォントサイズを変えて、大量の文字を出力すると起こるようです。
Re: 文字列の描画にゴミが混ざります ( No.6 )
名前:いっち 日時:2009/11/13 02:08

DxLibのソースも見てみたのですが、恥ずかしながらさっぱりわかりませんでした。 一度、管理人さんの見解をお待ちしたいと思います。 お忙しいとは思いますが、ご確認お願いします。 > 管理人さん
Re: 文字列の描画にゴミが混ざります ( No.7 )
名前:管理人 日時:2009/11/14 22:49

ご報告ありがとうございます、ソース汚くて申し訳ありません・・・ 掲載していただいたプログラムで私の環境でもバグを確認できました 修正したバージョンをアップしましたので、よろしければお使い下さい m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)
Re: 文字列の描画にゴミが混ざります ( No.8 )
名前:いっち(解決) 日時:2009/11/14 23:45

はじめまして、管理人さん。 DxLibにはいつもお世話になっています。 すばやい対応ありがとうございます。 当方の環境でも修正を確認できました。 > ソース汚くて申し訳ありません・・・ まったくそんなことないですよ。単純に私の知識不足が原因です。 今後ともよろしくお願いします。

Page: 1 |