こんにちは。
お世話になっております。
ここの掲示板の以下のスレッドを参考にして、キーからでもウィンドウ最大化ボタンからでも仮想フルスクリーンが可能なコードを書きました。
https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=3421
https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=4179
キー入力によるフルスクリーンの切り替えは特に問題はありませんでした。
しかしウィンドウ最大化ボタンの方は、1回目のフルスクリーンの時のみ描画領域の下の方が僅かに短くなっており、その後キー入力でウィンドウモードに戻してから再び最大化ボタンを押すと問題なくフルスクリーンになります。
ちなみに短くなっている部分の幅が何となくですがウィンドウのタイトルバーぐらいのサイズに近い気もします。
以下がソースコードです。
#include "DxLib.h"
#define SCREEN_SIZE_X (640)
#define SCREEN_SIZE_Y (480)
int NowWindowSizeX ;
int NowWindowSizeY ;
int WindowPositionX ;
int WindowPositionY ;
// 初期状態では仮想フルスクリーンモードはOFF
int VirtualFullScreenMode = FALSE ;
// ウインドウのアクティブ状態が変化したら呼ばれるコールバック関数
int ActiveStateChangeCallbackFunction( int ActiveState, void *UserData )
{
// 仮想フルスクリーンモードが OFF の場合は特に何もしない
if( VirtualVirtualFullScreenMode == FALSE )
{
return 0 ;
}
// アクティブになったのかどうかで処理を分岐
if( ActiveState )
{
// アクティブになったらウインドウの表示優先順位を最前面に表示する設定に変更
SetWindowZOrder( DX_WIN_ZTYPE_TOPMOST, TRUE ) ;
}
else
{
// 非アクティブになったらウインドウの表示優先順位を標準に戻す
SetWindowZOrder( DX_WIN_ZTYPE_NORMAL, FALSE ) ;
}
return 0 ;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int DesktopSizeX ;
int DesktopSizeY ;
int GameScreen ;
int x, add ;
int AltPlusEnter ;
// デスクトップの情報を取得する
GetDefaultState( &DesktopSizeX, &DesktopSizeY, NULL ) ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// 最大化ボタン付きウインドウにする
SetWindowStyleMode( 7 ) ;
// ウインドウサイズにソフトの画面をフィットさせない設定にする
SetWindowSizeChangeEnableFlag( FALSE, FALSE ) ;
// ソフト画面のサイズはデスクトップと同じにする
SetGraphMode( DesktopSizeX, DesktopSizeY, 32 ) ;
// ウインドウのサイズはソフト画面のサイズにする
SetWindowSize( SCREEN_SIZE_X, SCREEN_SIZE_Y ) ;
// ウインドウの初期位置はデスクトップ画面の中心にする
SetWindowPosition( ( DesktopSizeX - SCREEN_SIZE_X ) / 2, ( DesktopSizeY - SCREEN_SIZE_Y ) / 2 ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 )
{
return -1 ;
}
// アクティブ状態が変化したときに呼ばれるコールバック関数の登録
SetActiveStateChangeCallBackFunction( ActiveStateChangeCallbackFunction, NULL ) ;
// ソフト画面描画用の描画対象に出来る画像を作成
GameScreen = MakeScreen( SCREEN_SIZE_X, SCREEN_SIZE_Y, FALSE ) ;
// メインループ
x = 0 ;
add = 8 ;
while( ProcessMessage() == 0 )
{
// 現在のウインドウのサイズを取得する
GetWindowSize( &NowWindowSizeX, &NowWindowSizeY ) ;
// ALT + ENTER が押されたかどうかを取得しておく
AltPlusEnter = GetInputSystemChar( TRUE ) == CTRL_CODE_CR ;
// ウインドウモードで、且つウインドウのサイズがソフト画面のサイズではなくなった場合( 最大化ボタンが押された場合 )か、
// 又は ALT + ENTER が押されたら擬似フルスクリーンモードにする
if( VirtualFullScreenMode == FALSE &&
( ( NowWindowSizeX != SCREEN_SIZE_X &&
NowWindowSizeY != SCREEN_SIZE_Y ) || AltPlusEnter ) )
{
// 擬似フルスクリーンモードかどうかのフラグを立てる
VirtualFullScreenMode = TRUE ;
// ウインドウをクライアント領域以外何も無いタイプにする
SetWindowStyleMode( 4 ) ;
// ウインドウの表示優先順位を最前面に表示する設定に変更
SetWindowZOrder( DX_WIN_ZTYPE_TOPMOST ) ;
// ウインドウの位置をデスクトップの一番左上に移動
SetWindowPosition( 0, 0 ) ;
// ウインドウサイズをデスクトップと同じにする
SetWindowSize( DesktopSizeX, DesktopSizeY ) ;
}
else
// 擬似フルスクリーンモードで、且つ ALT + ENTER が押されたらウインドウモードにする
if( VirtualFullScreenMode == TRUE && AltPlusEnter )
{
// 擬似フルスクリーンモードかどうかのフラグを倒す
VirtualFullScreenMode = FALSE ;
// 最大化ボタン付きウインドウにする
SetWindowStyleMode( 7 ) ;
// ウインドウの表示優先順位を標準に戻す
SetWindowZOrder( DX_WIN_ZTYPE_NORMAL ) ;
// ウインドウの位置を元に戻す
SetWindowPosition( WindowPositionX, WindowPositionY ) ;
// ウインドウのサイズをソフト画面と等しくする
SetWindowSize( SCREEN_SIZE_X, SCREEN_SIZE_Y ) ;
}
// ウインドウモードの場合はウインドウの座標を取得しておく
if( VirtualFullScreenMode == FALSE )
{
GetWindowPosition( &WindowPositionX, &WindowPositionY ) ;
}
// 描画先をソフト画面描画用のグラフィックハンドルにする
SetDrawScreen( GameScreen ) ;
// 画面のクリア
ClearDrawScreen() ;
// 移動
x += add ;
if( x < 0 || x > 640 ) add = -add ;
// 四角形の描画
DrawBox( x, 0, x + 64, 0 + 64, GetColor( 255,255,255 ), TRUE ) ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// 擬似フルスクリーンモードかどうかで処理を分岐
if( VirtualFullScreenMode == TRUE )
{
// 仮想フルスクリーンモードの場合
int ScalingSizeX, ScalingSizeY ;
// ゲーム画面の拡大描画のサイズを算出
ScalingSizeX = DesktopSizeY * GAME_SCREEN_SIZE_X / GAME_SCREEN_SIZE_Y ;
if( ScalingSizeX < DesktopSizeX )
{
ScalingSizeY = DesktopSizeY ;
}
else
{
ScalingSizeX = DesktopSizeX ;
ScalingSizeY = DesktopSizeX * GAME_SCREEN_SIZE_Y / GAME_SCREEN_SIZE_X ;
}
// 余りの部分を塗りつぶし
if( ScalingSizeX != DesktopSizeX || ScalingSizeY != DesktopSizeY )
{
if( ScalingSizeX < DesktopSizeX )
{
DrawBox( 0, 0, ( DesktopSizeX - ScalingSizeX ) / 2, DesktopSizeY, GetColor( 0, 0, 0 ), TRUE ) ;
DrawBox( DesktopSizeX - ( DesktopSizeX - ScalingSizeX ) / 2, 0, DesktopSizeX, DesktopSizeY, GetColor( 0, 0, 0 ), TRUE ) ;
}
else
{
DrawBox( 0, 0, DesktopSizeX, ( DesktopSizeY - ScalingSizeY ) / 2, GetColor( 0, 0, 0 ), TRUE ) ;
DrawBox( 0, DesktopSizeY - ( DesktopSizeY - ScalingSizeY ) / 2, DesktopSizeX, DesktopSizeY, GetColor( 0, 0, 0 ), TRUE ) ;
}
}
// ゲーム画面を拡大描画
SetDrawMode( DX_DRAWMODE_BILINEAR ) ;
DrawExtendGraph(
( DesktopSizeX - ScalingSizeX ) / 2,
( DesktopSizeY - ScalingSizeY ) / 2,
DesktopSizeX - ( DesktopSizeX - ScalingSizeX ) / 2,
DesktopSizeY - ( DesktopSizeY - ScalingSizeY ) / 2,
GameScreen, FALSE
) ;
}
else
{
// ウインドウモードの場合は等倍でソフト画面描画用のグラフィックハンドルを描画
DrawGraph( 0, 0, GameScreen, FALSE ) ;
}
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}