実現したいこと
開発中のゲームプログラムのウィンドウのサイズが詳細不明な原因で変化してしまった。Windows10が記憶していると思われるウィンドウサイズの設定をリセットし、元のサイズで起動する状態に戻したい。
詳細
Windows 10でVisual Studio Community 2022を使用し、書籍「シューティングゲーム プログラミング」の付属C++プログラム(DirectX9使用)を一部改変して開発をしていた所、下記のような現象に遭遇しました。
(1) ゲーム用のウィンドウのサイズは横800x縦600とソース中で指定されているにも関わらず、何故か1000x750と思しきサイズで起動される。「1000」「750」でソース中を検索してもウィンドウサイズを制御しているような箇所は見つからず、このサイズになる理由は不明。
(2) 本プログラムにはウィンドウをAlt+Enterでフルスクリーンモードにする機能が実装されている。フルスクリーンモードにしてからウィンドウモードに戻すと、ウィンドウサイズは何故かソース中で指定されている800x600になる。1000x750になるのがバグであり、これが本来のウィンドウサイズである可能性あり(でも小さくて見づらい…)。
(3) 一度でもフルスクリーンモードにしたことのある実行ファイルは、以降は元のサイズである1000x750で起動することができなくなり、ずっと800x600で起動されるようになってしまう。
但し、実行ファイルのファイルパスが少しでも違えば、また1000x750で起動される。例えばフォルダ名や実行ファイル名を変更すればそうなる。
(4) ウィンドウが小さいと見づらいと考え、ソース中のウィンドウサイズ指定部分を800x600から1000x750に変更すると、ウィンドウサイズはその通りになるものの、ウィンドウ内のレイアウト(キャラクタや文字などがどこに配置されるか)が崩れてしまう。従ってこれだけでは解決にならない。
実行ファイルパスが変化すると元に戻ることから、エクスプローラなどのウィンドウと同じように、OSが実行ファイルパスごとに起動時のウィンドウサイズを記憶しているのではないか?と推測しました。
だとすれば、その記憶をリセットするなりして、「既に800x600で起動されるようになってしまった実行ファイルパスで、また1000x750で起動される」ようにしたいのですが、そのようなことは可能でしょうか?
本来なら、ソースにあると思われるバグを修正し、根本的解決を図りたいところなのですが、それには時間がかかりそうなので、とりあえずウィンドウサイズを元に戻すことで、開発しにくい環境から脱したいと考えました。
具体的なソースの提示もしたいところなのですが、著作権上の問題がないように該当部分だけを切り出して実行可能なものに仕立てるのはなかなか大変なので、一旦このような形で質問させて頂くことにしました。
[追記]
やはりソースを提示すべきとのご指摘を頂いたので提示します。
挙げていくとキリがなさそうですが、関係のありそうな箇所を抜粋してみました。
ゲームクラスの定義部:
C++
1// ゲーム本体のクラス 2class CGame 3{ 4protected: 5 6 // アクセラレータキー 7 HACCEL HAccel; 8 9 // ウィンドウハンドル 10 HWND HWnd; 11 12 // グラフィックス 13 CGraphics* Graphics; 14 15 // 入力 16 CInput* Input; 17 MOUSE_STATE Mouse; 18 19 // 実行ファイルのパス、アプリケーション名、ヘルプのURL 20 string ExePath, HelpURL; 21 wstring AppName; 22 23 // 速度調整 24 LARGE_INTEGER LastPerfCounter; 25 DWORD LastTickCount; 26 double Elapsed; 27 void ResetTime(); 28 29 // 一時停止 30 bool Pause, MenuPause; 31 32 // メニュー 33 bool UseMenu; 34 HMENU MenuBar; 35 36 // 終了確認 37 bool ConfirmExit; 38 39 // 画面サイズ、リフレッシュレート 40 int WindowWidth, WindowHeight, FullScreenWidth, FullScreenHeight, 41 RefreshRate; 42 bool FullScreen; 43 44 void DrawScene(); 45 46public: 47 48 // コンストラクタ,デストラクタ 49 CGame( const wchar_t* app_name, bool zbuffer, bool use_menu, bool fixed_size ); 50 ~CGame(); 51 52 // メッセージハンドラ 53 virtual LRESULT WINAPI WndProc( UINT msg, WPARAM wparam, LPARAM lparam ); 54 55 // ゲームの実行 56 void Run(); 57 58 // 各種設定 59 double FPS; 60 bool DropFrames, PauseInTheBackground; 61 62 // 移動と描画: 63 // サブクラスでオーバーライドする 64 virtual void Move() {} 65 virtual void Draw() {} 66 67 // Direct3Dリソースの管理 68 virtual void OnLostDevice() {} 69 virtual void OnResetDevice() {} 70 71 // メニュー 72 HMENU GetMenuBar() { return MenuBar; } 73 HMENU AddMenu( string text ); 74 HMENU AddSubMenu( HMENU menu, string text ); 75 void AddMenuItem( HMENU menu, string text, int id ); 76 void AddMenuSeparator( HMENU menu ); 77 void CheckMenuItem( HMENU menu, int id, bool check ); 78 79 // 各種情報の取得 80 CGraphics* GetGraphics() { return Graphics; } 81 CInput* GetInput() { return Input; } 82 const MOUSE_STATE& GetMouseState() { return Mouse; } 83 84 // 終了確認 85 void SetConfirmExit( bool ce ) { ConfirmExit = ce; } 86 87 // 画面モードの切り替え 88 void ResetScreen(); 89 void ToggleFullScreen(); 90};
ゲームクラスのコンストラクタ:
C++
1 2//============================================================== 3// <CGame>コンストラクタ 4CGame::CGame( const wchar_t* app_name, bool zbuffer, bool use_menu, bool fixed_size ) 5 : Pause( false ), MenuPause( false ), UseMenu( use_menu ), ConfirmExit( true ), 6 FPS( 60 ), DropFrames( true ), PauseInTheBackground( true ), 7 WindowWidth( 800 ), WindowHeight( 600 ), 8 FullScreenWidth( 800 ), FullScreenHeight( 600 ), 9 FullScreen( false ), RefreshRate( 60 ) 10{ 11 // アプリケーション名,実行ファイルのパス、ヘルプのURL 12 AppName = app_name; 13 ExePath = GetExePath(); 14 HelpURL = ""; 15 16 // アイコンの読み込み 17 HINSTANCE hinst = GetModuleHandle( NULL ); 18 HICON icon; 19 string icon_file = ExePath + "game.ico"; 20 if ( FileExists( icon_file ) ) 21 { 22 icon = (HICON) LoadImage( 23 hinst, CStringW( icon_file.c_str() ), 24 IMAGE_ICON, 0, 0, LR_LOADFROMFILE ); 25 } 26 else 27 { 28 icon = LoadIcon( hinst, MAKEINTRESOURCE( 1 ) ); 29 } 30 31 // ウィンドウクラスの登録: 32 // ここではダミーのメッセージハンドラを登録する 33 WNDCLASSEX wc = { 34 sizeof( WNDCLASSEX ), 35 CS_CLASSDC, 36 DummyWndProc, 37 0L, 38 0L, 39 hinst, 40 icon, 41 LoadCursor( NULL, IDC_ARROW ), 42 NULL, 43 NULL, 44 app_name, 45 NULL 46 }; 47 RegisterClassEx( &wc ); 48 49 // アクセラレータキーの設定: 50 // [ESC] : 終了 51 // [Alt]+[Enter] : 画面モード切り替え 52 // [F1] : ヘルプ 53 // [Shift]+[F1]:バージョン表示 54 ACCEL accel [] = { 55 {FVIRTKEY, VK_ESCAPE, IDC_EXIT}, 56 {FALT | FVIRTKEY, VK_RETURN, IDC_TOGGLEFULLSCREEN}, 57 {FVIRTKEY, VK_F1, IDC_HELPURL}, 58 {FSHIFT | FVIRTKEY, VK_F1, IDC_VERSION} 59 }; 60 HAccel = CreateAcceleratorTable( 61 accel, sizeof( accel ) / sizeof( ACCEL ) ); 62 63 // コマンドラインオプションの解釈 64 for ( int i = 1; i < __argc; i++ ) 65 { 66 char* s = __argv[ i ]; 67 if ( strcmp( "-w", s ) == 0 && ++i < __argc ) 68 { 69 WindowWidth = FullScreenWidth = atoi( __argv[ i ] ); 70 } 71 else 72 if ( strcmp( "-h", s ) == 0 && ++i < __argc ) 73 { 74 WindowHeight = FullScreenHeight = atoi( __argv[ i ] ); 75 } 76 else 77 if ( strcmp( "-ww", s ) == 0 && ++i < __argc ) 78 { 79 WindowWidth = atoi( __argv[ i ] ); 80 } 81 else 82 if ( strcmp( "-wh", s ) == 0 && ++i < __argc ) 83 { 84 WindowHeight = atoi( __argv[ i ] ); 85 } 86 else 87 if ( strcmp( "-fw", s ) == 0 && ++i < __argc ) 88 { 89 FullScreenWidth = atoi( __argv[ i ] ); 90 } 91 else 92 if ( strcmp( "-fh", s ) == 0 && ++i < __argc ) 93 { 94 FullScreenHeight = atoi( __argv[ i ] ); 95 } 96 if ( strcmp( "-r", s ) == 0 && ++i < __argc ) 97 { 98 RefreshRate = atoi( __argv[ i ] ); 99 } 100 if ( strcmp( "-f", s ) == 0 ) 101 { 102 FullScreen = true; 103 } 104 if ( strcmp( "-nce", s ) == 0 ) 105 { 106 ConfirmExit = false; 107 } 108 } 109 110 // ウィンドウの作成 111 long style = WS_CAPTION | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; 112 RECT r = { 0, 0, WindowWidth, WindowHeight }; 113 AdjustWindowRect( &r, style, false ); 114 115 HWnd = CreateWindow( 116 CStringW( app_name ), 117 CStringW( app_name ), 118 style, 119 0, 120 0, 121 r.right - r.left, 122 r.bottom - r.top, 123 GetDesktopWindow(), 124 NULL, 125 wc.hInstance, 126 NULL 127 ); 128 129 HWndCGameMap.insert( 130 THWndCGameMap::value_type( HWnd, this ) ); 131 132 // グラフィックスの作成 133 Graphics = new CGraphics( HWnd ); 134 if ( !Graphics ) 135 { 136 string s = 137 "このプログラムにはDirectX 9.0以上が必要です。\n" 138 "DirectXの最新版、および最新のドライバが\n" 139 "インストールされているかどうかご確認ください。\n"; 140 if ( !fixed_size ) 141 { 142 s += 143 "また、起動時のオプションで解像度を変更してみてください。\n\n" 144 "ウィンドウ時800x600、フルスクリーン1024x768の場合:\n" 145 "-w 800 -h 600 -fw 1024 -fh 768"; 146 } 147 MessageBox( HWnd, CStringW( s.c_str() ), CStringW( app_name ), MB_OK ); 148 exit( 1 ); 149 } 150 Graphics->Clear(); 151 Graphics->Present(); 152 if ( FullScreen ) ResetScreen(); 153 154 // 入力の初期化 155 Input = new CInput( HWnd ); 156 Mouse.X = Mouse.Y = 0; 157 Mouse.LButton = Mouse.MButton = Mouse.RButton = false; 158 159 // 時間 160 LastPerfCounter.QuadPart = 0; 161 LastTickCount = 0; 162 Elapsed = 0; 163 164 // メニュー 165 if ( UseMenu ) 166 { 167 MenuBar = CreateMenu(); 168 SetMenu( HWnd, MenuBar ); 169 } 170}
ウィンドウモード/フルスクリーンモード切り替えに関する箇所:
C++
1// 画面のリセット 2void CGame::ResetScreen() 3{ 4 if ( FullScreen ) 5 { 6 Graphics->SetWidth( FullScreenWidth ); 7 Graphics->SetHeight( FullScreenHeight ); 8 Graphics->SetRefreshRate( RefreshRate ); 9 } 10 else 11 { 12 Graphics->SetWidth( WindowWidth ); 13 Graphics->SetHeight( WindowHeight ); 14 Graphics->SetRefreshRate( 0 ); 15 } 16 Graphics->SetFullScreen( FullScreen ); 17 OnLostDevice(); 18 if ( Graphics->ResetDevice() ) OnResetDevice(); 19} 20 21// ウィンドウモードとフルスクリーンモードの切り替え 22void CGame::ToggleFullScreen() 23{ 24 FullScreen = !Graphics->IsFullScreen(); 25 ResetScreen(); 26} 27
よろしくお願い致します。
補足
本プログラムは、今となっては古いプログラムではありますが、上記の現象についてはバグらしき挙動であるものの、他の部分に関しては概ね正常に動作しています。

回答2件
あなたの回答
tips
プレビュー