Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.1 ) |
- 名前:管理人 日時:2011/12/18 16:51
DxLib_Init を呼ぶ前に SetMultiThreadFlag( TRUE ) ; を実行して描画処理を DxLib_Init を
呼んだスレッド以外でも呼べるようにした上で
ProcessMessage 以外の処理を別のスレッドで行うようにすればウインドウを掴んでいる間も
処理を続けることができます
↓こちらは画面上部で四角形が左右に動くプログラムですが、実際に四角形を動かし、描画している
スレッドと DxLib_Init や ProcessMessage を呼んでいるスレッドは別となっています
#include "DxLib.h"
int BoxX ;
int BoxXAdd ;
volatile int EndFlag ;
// ProcessMessage 以外の処理を行うスレッド
DWORD WINAPI MainThread(LPVOID)
{
// 描画先を裏画面に
SetDrawScreen( DX_SCREEN_BACK ) ;
// 四角形の情報を初期化
BoxX = 0 ;
BoxXAdd = 8 ;
// EndFlag が0の間はループ
while( EndFlag == 0 )
{
// 画面を初期化
ClearDrawScreen() ;
// 四角形を動かす処理
BoxX += BoxXAdd ;
if( BoxX < 0 || BoxX >= 640 )
BoxXAdd = -BoxXAdd ;
// 四角形の描画
DrawBox( BoxX, 24, BoxX + 64, 24 + 64, GetColor( 0,255,0 ), TRUE ) ;
// 少しCPUを休める
Sleep( 5 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
return 0 ;
}
// WinMain 関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HANDLE hand;
DWORD id;
// ウインドウモードで起動
ChangeWindowMode( TRUE );
// マルチスレッドに適したモードで起動する
SetMultiThreadFlag( TRUE ) ;
// DXライブラリを初期化
if( DxLib_Init() < 0 )
return -1 ;
// ProcessMessage 以外の処理を行うスレッドを作成
hand = CreateThread( NULL, 0, MainThread, 0, 0, &id );
// ProcessMessage ループ
while( ProcessMessage() == 0 )
{
// 少しCPUを休める
Sleep( 6 ) ;
}
// プログラムが終了したフラグを立てる
EndFlag = 1 ;
// 読み込みスレッドが終了するのを待つ
while( EndFlag == 0 )
{
Sleep( 10 ) ;
}
// DXライブラリの後始末
DxLib_End() ;
// 終了
return 0 ;
}
ただ、SetMultiThreadFlag( TRUE ) ; を使用して DxLib_Init を使用したスレッド以外でも
描画処理を行えるようにした場合は、SetMultiThreadFlag( TRUE ) ; を使用しなかった場合より
若干描画処理に掛かる CPU の負荷が高くなりますのでご注意ください
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.2 ) |
- 名前:タカトゥ 日時:2011/12/18 22:35
ありがとうございました。
無事実装できました。
ただプログラムから終了をさせようと思った場合はどうすればいいのでしょうか?
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.3 ) |
- 名前:タカトゥ(解決) 日時:2011/12/18 22:39
すみません、無事解決しました。
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.4 ) |
- 名前:タカトゥ 日時:2011/12/22 19:41
度々すみません。
ウィンドウを動かしている時にも処理が続く様にはなったのですが
ウィンドウを動かしている時に画面が乱れることがあるようです。
作成したフォントで文字を表示している時に乱れることがあるようですがまだよくわかりません。
一瞬よくわからない文字列のようなものが見えます。
普通にやる分には何の問題もないのですが念のために報告しておきます。
環境はwin7 64bit VC++2010 win7のAeroを有効にしています。
それからマルチスレッドについてはよくわからないのですが
// プログラムが終了したフラグを立てる
EndFlag = 1 ;
// 読み込みスレッドが終了するのを待つ
while( EndFlag == 0 )
{
Sleep( 10 ) ;
}
の部分はどういった意味があるのでしょうか?
また、以前報告したタスクバーで連続でクリックすると落ちる不具合も発生しました。
こちらはScreenFlip();のエラーチェックをしなければいいだけなので一応解決しました。
それから少し話がそれてしまいますが別のスレッドでマルチスレッド時は
・サウンド・画像・モデルの読み込み関数や描画や描画の設定を行う関数を複数のスレッドから同時に呼ばないこと
と有りましたが
つまり画像やモデルを表示しながら、別のスレッドで画像やモデル、音声をロードするといったことはできないということでしょうか?
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.5 ) |
- 名前:管理人 日時:2011/12/25 00:08
ウインドウを動かしている際に文字の描画がおかしくなる現象、手元でも確認できました
修正版をアップしましたので、よろしければお使いください m(_ _;m
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCCTest.exe // Dev-C++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMinGWTest.exe // MinGW 用
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』を、VCをお使いの場合は『リビルド』を、
Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
あと、EndFlag の使い方についてですが
すみません、意味の無いコードになってしまっていました
本来自分が書きたかった処理はフラグを二つ使った以下のようなものです
#include "DxLib.h"
int BoxX ;
int BoxXAdd ;
volatile int EndFlag ;
volatile int ThreadEndFlag ;
// ProcessMessage 以外の処理を行うスレッド
DWORD WINAPI MainThread(LPVOID)
{
SetFontSize( 32 ) ;
// 描画先を裏画面に
SetDrawScreen( DX_SCREEN_BACK ) ;
// 四角形の情報を初期化
BoxX = 0 ;
BoxXAdd = 8 ;
// EndFlag が0の間はループ
while( EndFlag == 0 )
{
// 画面を初期化
ClearDrawScreen() ;
// 四角形を動かす処理
BoxX += BoxXAdd ;
if( BoxX < 0 || BoxX >= 640 )
BoxXAdd = -BoxXAdd ;
// 四角形の描画
DrawBox( BoxX, 24, BoxX + 64, 24 + 64, GetColor( 0,255,0 ), TRUE ) ;
// 少しCPUを休める
Sleep( 5 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// スレッド終了フラグを1にする
ThreadEndFlag = 1 ;
return 0 ;
}
// WinMain 関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HANDLE hand;
DWORD id;
// ウインドウモードで起動
ChangeWindowMode( TRUE );
// マルチスレッドに適したモードで起動する
SetMultiThreadFlag( TRUE ) ;
// DXライブラリを初期化
if( DxLib_Init() < 0 )
return -1 ;
// ProcessMessage 以外の処理を行うスレッドを作成
hand = CreateThread( NULL, 0, MainThread, 0, 0, &id );
// ProcessMessage ループ
while( ProcessMessage() == 0 )
{
// 少しCPUを休める
Sleep( 6 ) ;
}
// プログラムが終了したことを示すフラグを立てる
EndFlag = 1 ;
// スレッド終了フラグが立つまで待つ
while( ThreadEndFlag == 0 )
{
Sleep( 10 ) ;
}
// DXライブラリの後始末
DxLib_End() ;
// 終了
return 0 ;
}
ScreenFlip がエラーを返す件については今のところ仕様とさせてください
前回は最小化されている場合は処理をしないという方法で回避したのですが、
Aeroを有効にしている状態で最小化をした場合は「最小化しました」という情報が
ソフトに伝えられる前から ScreenFlip が使用している Direct3D の機能がエラーを
返すようになってしまうため、今のところ対処のしようが無ありません・・・
> つまり画像やモデルを表示しながら、別のスレッドで画像やモデル、音声をロードするといったことはできないということでしょうか?
SetMultiThreadFlag( TRUE ) ; を DxLib_Init の前で呼んだ状態であれば
片方のスレッドで描画処理を行いながら、もう片方のスレッドで LoadGraph で
ファイルを読み込むといったことも可能です
ただ、更に別のスレッドでも LoadGraph や LoadDivGraph を呼んだりすると
正常に動作しません、グラフィックハンドルを増やす処理が別々のスレッドから
同時に行われた場合に正常に動作するように作っていないので
LoadSoundMem についても同様ですが、マルチスレッド関係は対応しようとすると
途端にエラーが発生しやすくなるので、それに対処する労力も考慮して「非対応」としています
なので、保証外なだけで現状でも気を使えば読み込みを行いながら描画、ということはできなくはありません
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.6 ) |
- 名前:タカトゥ 日時:2011/12/28 23:48
ありがとうございます。
ちなみにモデルに関しては
描画、モデルの設定のスレッドと
モデルをロードするスレッド
という感じに分けるのは問題ないでしょうか?
また、ウィンドウモードとフルスクリーンモードの切替時に落ちることがありました。
もしくは画面解像度を変更時に落ちたかもしれません。
偶然の可能性もありますが、一応報告しておきます。
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.7 ) |
- 名前:管理人 日時:2012/01/01 03:51
> ちなみにモデルに関しては
>
> 描画、モデルの設定のスレッドと
> モデルをロードするスレッド
>
> という感じに分けるのは問題ないでしょうか?
SetMultiThreadFlag( TRUE ) ; を DxLib_Init の前に実行していれば問題ありません
> また、ウィンドウモードとフルスクリーンモードの切替時に落ちることがありました。
> もしくは画面解像度を変更時に落ちたかもしれません。
> 偶然の可能性もありますが、一応報告しておきます。
ご報告ありがとうございます
落ちたプログラムでは SetChangeScreenModeGraphicsSystemResetFlag の設定を FALSE にしていましたでしょうか?
|
Re: ウィンドウをつかんでいる時にも処理を続けたい ( No.8 ) |
- 名前:タカトゥ(解決) 日時:2012/01/02 23:26
いえ、SetChangeScreenModeGraphicsSystemResetFlagは使用していません。
起こったのが1回だけなので偶然の可能性もあります。
また起きたり原因がわかったときにでも改めて報告させて頂きます。
|