Re: SetDrawScreenについて ( No.1 ) |
- 名前:管理人 日時:2021/02/02 22:20
すみません、以下のような SetScreenFlipTargetWindow を使用する雑食のととさんが
現象を再現された状況に近いと思われるコードを書いて試してみたのですが、例外は発生しませんでした
( ウィンドウ2を閉じて、その直後に MakeScreen で作成したグラフィックハンドルを SetDrawScreen に渡して実行しています )
#include "DxLib.h"
char *szClassNme[ 2 ] =
{
"ウィンドウ1クラスネーム",
"ウィンドウ2クラスネーム",
} ;
// メッセージ処理用関数
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
//PostQuitMessage( 0 ) ;
break ;
default :
return(DefWindowProc( hWnd, msg, wParam, lParam ) ) ;
}
return ( 0L ) ;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow)
{
int pos, pos_add ;
LONGLONG temp_time ;
MSG msg ;
HWND hWnd[ 2 ] ;
WNDCLASS myProg ;
// ウインドウの作成
myProg.style = CS_HREDRAW | CS_VREDRAW ;
myProg.lpfnWndProc = WndProc ;
myProg.cbClsExtra = 0 ;
myProg.cbWndExtra = 0 ;
myProg.hInstance = hInstance ;
myProg.hIcon = NULL ;
myProg.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
myProg.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ) ;
myProg.lpszMenuName = NULL ;
myProg.lpszClassName = szClassNme[ 0 ] ;
if( !RegisterClass( &myProg ) )
{
return FALSE;
}
hWnd[ 0 ] = CreateWindow(
szClassNme[ 0 ],
"ウインドウ1",
WS_OVERLAPPEDWINDOW,
100, 100, 500, 500,
NULL, NULL, hInstance, NULL
) ;
ShowWindow( hWnd[ 0 ], nCmdShow ) ;
UpdateWindow( hWnd[ 0 ] ) ;
myProg.lpszClassName = szClassNme[ 1 ] ;
if( !RegisterClass( &myProg ) )
{
return FALSE;
}
hWnd[ 1 ] = CreateWindow(
szClassNme[ 1 ],
"ウインドウ2",
WS_OVERLAPPEDWINDOW,
700, 100, 500, 500,
NULL, NULL, hInstance, NULL
) ;
ShowWindow( hWnd[ 1 ], nCmdShow ) ;
UpdateWindow( hWnd[ 1 ] ) ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// VSYNC待ちをしない設定に変更
SetWaitVSyncFlag( FALSE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// MakeScreen で描画先にできる画像を作成
int Screen = MakeScreen( 640, 480 ) ;
// メッセージループ
pos = 0 ;
pos_add = 8 ;
while( ProcessMessage() == 0 )
{
if( PeekMessage( &msg, hWnd[ 0 ], 0, 0, PM_REMOVE ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if( PeekMessage( &msg, hWnd[ 1 ], 0, 0, PM_REMOVE ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 移動処理
pos += pos_add ;
if( pos > 400 || pos < 0 )
{
pos_add = -pos_add ;
}
// 描画先を裏画面に変更
SetDrawScreen( DX_SCREEN_BACK ) ;
// メインウインドウ用の描画
ClearDrawScreen() ;
DrawBox( pos, 0, pos + 64, 64, GetColor( 255,0,0 ), TRUE ) ;
SetScreenFlipTargetWindow( NULL ) ;
ScreenFlip() ;
// ウインドウ1用の描画
ClearDrawScreen() ;
DrawBox( 0, pos, 48, pos + 48, GetColor( 0,255,0 ), TRUE ) ;
SetScreenFlipTargetWindow( hWnd[ 0 ] ) ;
ScreenFlip() ;
// ウインドウ2用の描画
if( hWnd[ 1 ] != NULL )
{
ClearDrawScreen() ;
DrawBox( pos, pos, pos + 80, pos + 80, GetColor( 0, 0, 255 ), TRUE ) ;
SetScreenFlipTargetWindow( hWnd[ 1 ] ) ;
ScreenFlip() ;
// 表示直後にウィンドウを閉じる
PostMessage( hWnd[ 1 ], WM_CLOSE, 0, 0 );
hWnd[ 1 ] = NULL ;
}
// 描画先を MakeScreen で作成した画像に変更
SetDrawScreen( Screen ) ;
// 時間待ち処理
Sleep( 16 ) ;
}
// DXライブラリの後始末
DxLib_End();
return 0 ;
}
よろしければ上記のサンプルでは雑食のととさんの環境でも例外が発生しないか試してみていただけないでしょうか? m(_ _)m
|
Re: SetDrawScreenについて ( No.2 ) |
- 名前:雑食のとと 日時:2021/02/04 17:07
管理人 さま
サンプルを作ってくださりありがとうございます。
こちらでも、このサンプルでは問題は発生しませんでした。
手元で問題のプログラムとは別にコードを書いてみましたところ、
同様の例外が別関数(ScreenFlip)で発生しました。
DxLibMakeを見る限り問題になっている関数は同様のようです。
SetScreenFlipTargetWindowで無効なハンドルを設定している時に
ScreenFlipを呼び出したところ発生しました。
また、元のプログラムでの、SetDrawScreen内で例外が起こっていることについては
関数の前後に、Win32での出力を行える関数OutputDebugStringを使用して判断しています。
SetDrawScreenで発生する例についてはもうしばらく調べてみたいと思いますが、
取り急ぎ、類似の例がありましたのでご報告させていただきます。
はじめの件については追って返信させてください。
#include "DxLib.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
//PostQuitMessage( 0 ) ;
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0L);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd[2];
WNDCLASS myProg;
//ウインドウの作成
myProg.style = CS_HREDRAW | CS_VREDRAW;
myProg.lpfnWndProc = WndProc;
myProg.cbClsExtra = 0;
myProg.cbWndExtra = 0;
myProg.hInstance = hInstance;
myProg.hIcon = NULL;
myProg.hCursor = LoadCursor(NULL, IDC_ARROW);
myProg.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
myProg.lpszMenuName = NULL;
myProg.lpszClassName = "ウインドウクラス";
if (!RegisterClass(&myProg))
{
return FALSE;
}
hWnd[0] = CreateWindow(
"ウインドウクラス",
"ウインドウ1",
WS_OVERLAPPEDWINDOW,
100, 100, 500, 500,
NULL, NULL, hInstance, NULL
);
ShowWindow(hWnd[0], nCmdShow);
UpdateWindow(hWnd[0]);
DxLib::SetWindowVisibleFlag(FALSE);
DxLib::SetAlwaysRunFlag(TRUE);
DxLib::SetUseTSFFlag(FALSE);
//ウインドウモードで起動
ChangeWindowMode(TRUE);
//初期化
DxLib::DxLib_Init();
int screen = MakeScreen(640,480);
//ウインドウ消去の為に使用
int counter = 0;
while (ProcessMessage() != -1) {
//メッセージ処理
if (hWnd[0] != NULL) {
if (PeekMessage(&msg, hWnd[0], 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (counter > 1) {
DestroyWindow(hWnd[0]);
OutputDebugString(_T("Window has destroyed\n"));
hWnd[0] = NULL;
}
counter++;
}
//screenにBoxを描画
DxLib::SetDrawScreen(screen);
DxLib::DrawBox(50,50,100,100,GetColor(255,0,0),TRUE);
//裏画面にscreen内容を描画
DxLib::SetDrawScreen(DX_ORIGINAL_SCREEN_BACK);
DxLib::DrawGraph(0, 0, screen, TRUE);
//裏画面を指定のウインドウに反映
DxLib::SetScreenFlipTargetWindow(hWnd[0]);
DxLib::ScreenFlip();
Sleep(16);
}
return DxLib::DxLib_End();
}
|
Re: SetDrawScreenについて ( No.3 ) |
- 名前:管理人 日時:2021/02/05 00:07
> 手元で問題のプログラムとは別にコードを書いてみましたところ、
> 同様の例外が別関数(ScreenFlip)で発生しました。
載せていただいたプログラムを実行してみたのですが、私の手元の環境では
例外が発生しませんでした…
> SetScreenFlipTargetWindowで無効なハンドルを設定している時に
> ScreenFlipを呼び出したところ発生しました。
すみません、調べたところウィンドウハンドルが有効かを完璧に判定する方法は無いようなので
( IsWindow というウィンドウハンドルの値が有効かどうかを判定する為の API があるのですが、
ウィンドウハンドルの値は使い回されているので、仮に雑食のととさんのプログラムでウィンドウを
クローズしても、他のプロセスが新たなウィンドウを作成して、そのウィンドウに雑食のととさんの
プログラムでクローズしたウィンドウと同じウィンドウハンドルの値が割り当てられた場合、
IsWindow は雑食のととさんのプログラム内でクローズしたウィンドウハンドルの値に対して
『有効なウィンドウハンドルである』と判定する )、
SetScreenFlipTargetWindow に渡していたウィンドウハンドルが無効になった際は
SetScreenFlipTargetWindow( NULL ); を実行するようにしてください m(_ _;m
|
Re: SetDrawScreenについて ( No.4 ) |
- 名前:雑食のとと(解決) 日時:2021/02/06 23:21
管理人 さま
ご返信くださりありがとうございます。
クリティカルなサンプルコードを提供できずすみませんでした。
もしかしたら環境に依存した例外だったのかもしれないです。
自分で使う分にはSetScreenFlipTargetWindow( NULL );を適当なタイミングで呼べば十分対応できますので
解決とさせていただきます。
またどうしようもない事態になった際にはご助力くださいませ。
ありがとうございます。
|
|