• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:突然ですが、DirectX9について質問させて頂きます。)

DirectX9に関するウィンドウサイズの変化問題

このQ&Aのポイント
  • DirectX9を使用してウィンドウモードとフルスクリーンモードを切り替える際、画面サイズが変化する問題が発生しています。
  • 問題の関数であるSetWindowStyleとSetClientSizeを確認すると、ウィンドウのサイズ変更時に正しい値が設定されていないことが分かりました。
  • この問題を解決するためには、ウィンドウのサイズを変更する際に正確な値を指定する必要があります。

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.4

>クライアント領域のみをキャプチャ、サイズを測定しています。 キャプチャ画像からでは、デスクトップの解像度に よっては縦横比が変わった場合、正しいウィンドウサイズの 値が取得できないと思います。 #縦長になったり、横長になったりします。 >初期状態がどうあれ、後に値が変化することは想定外ですので。 >試しに、ウィンドウモードを変更する直前にスクリーン座標を退避、 >復帰時に退避した座標を適用、といった動作も試しましたが、結果はまったく >同じでした。 サイズを変更するAPIを呼び出している以上、設定した値が おかしいのだとは思いますが、スクリーン座標を補完する事に 意味があるのでしょうか?変更するまえの位置に表示したい などの場合以外では縦横のサイズの変化には、 あまり意味が無いような気がします。 >MoveWindow( hWnd, 0, 0, 0, 0, false ); >をコメントアウトしただけでも正しく表示されません。 原点に移動し、ウィンドウサイズを0,0に指定していますが、 実際にはウィンドウは0,0にならずにシステムメニューなどの サイズで最小サイズとしてデスクトップ上に残るため、 (本当にそうなのかは微妙ですが、私の環境ではそうなりました。) このサイズをGetWindowRect、GetClientRectで取得し この時おそらく、クライアント領域の高さは0に成ると思うので その状態で、タイトルやメニューのサイズを算出しているのでは?? もし、上記のコードで設定した値0,0,0,0が、 GetWindowRectで取得された場合は、 ウィンドウ全体のサイズが800x600となり システムメニュー分の高さがクライアント領域から 引かれる可能性は無きにしも在らずですが、 本来であれば、メニューのサイズやタイトルのサイズは GetSystemMetrics関数で取得するのが最も正確な値となると思うので、 そちらを使うというのも一つの手だとは思います。 ただ、ウィンドウサイズを調べる場合は、 きちんとAPIなどで取得した値を見たほうが良いと思います。 開発環境でのキャプチャ画像などから実測すると、 実行環境での誤差が出る可能性が高いです。

ClickHere
質問者

お礼

ご回答、ありがとうございます。 どうやら、 フルスクリーンから復帰(この時点でフレームは描画されていない)⇒ ウィンドウサイズを変更(この時点で、正しく動作していない)⇒ クライアント領域の上にフレームが描画される⇒ 結果、タイトルバーの分だけサイズが小さくなる、というものの様です。 原因はよく分かりませんが、引数は関係ないことだけは確認できました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.3

机上だとわかり難かったので試してみました。 わたしの環境では試したころ、提示されたコードでは、 ウィンドウサイズは特に問題なく動作しているようで、 808x627という値が毎回設定されていました。 以下の補足をお願いします。 #少し大きくなっていますが、 #タイトルバーなどを考慮したサイズにはなっているようです。 >800x576と値がおかしくなります。 この値はどの様に確認されたのでしょうか? #わたしはデバッグウィンドウで確認しました。 また、この値は、Window領域のものでしょうか? それとも、DirectXのデバイスに与えているサイズでしょうか? DirectXにはスクリーンモードがありますので、 これを変更する場合には、デバイスの再作成が必要となりますが。。。 補足の内容からすると、 ウィンドウモード→フルスクリーンモード→ウィンドウモードの 時に値がおかしくなるということで良いでしょうか? DirectXのサイズを変更と成ると少し話が違ってくるので。。。

ClickHere
質問者

お礼

ご回答、ありがとうございます。 私は、ウィンドウキャプチャアプリケーションを使用して、 クライアント領域のみをキャプチャ、サイズを測定しています。 そのため、通常は800x600になるように計算してありますので、数値の 間違いは無いと思います。 そして、当面の問題はこのウィンドウサイズの矛盾ですね。 初期状態がどうあれ、後に値が変化することは想定外ですので。 試しに、ウィンドウモードを変更する直前にスクリーン座標を退避、 復帰時に退避した座標を適用、といった動作も試しましたが、結果はまったく 同じでした。 また、SetWindowStyle関数内6行目の MoveWindow( hWnd, 0, 0, 0, 0, false ); をコメントアウトしただけでも正しく表示されません。 SetClientSize関数内で同関数は実行されているのですが…。 気のせいか、メニューバーのサイズ分だけ、差し引かれているような気が…。 近々試してみる予定です(仮にそれで直ったところで、結局、原因は不明なままですが)。 度々ご迷惑をお掛けしますが、ご回答頂けると幸いです。

全文を見る
すると、全ての回答が全文表示されます。
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

No1です。 >ウィンドウサイズの変更を行っていませんので、 よく見たら、ウィンドウサイズは毎回変更されていますね。。。 ウィンドウモードの場合は、クライアント領域を800x600にするように ウィンドウモードに変更する際に、タイトルやメニューの高さを 考慮すれば正しく、調整されると思います。

ClickHere
質問者

お礼

ご回答、ありがとうございます。 最初の投稿へのご返答ですが、ウィンドウのサイズが…は、 クライアントサイズが…が正しい表現でしたね。御幣がありました。 #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 上記の定義も欠落していました。 ですが、タイトルバーの長さはSetClientSize関数で考慮されていると思うのですが…。 実際、アプリ起動時にこの関数を呼び出して、クライアントサイズは800x600となっていますので。 メニューバは最初から追加していないので、考慮する必要性はないと思うのですが…?

全文を見る
すると、全ての回答が全文表示されます。
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.1

起動時はフルスクリーンモードで WINDOW_WIDTH = 800 WINDOW_HEIGHT = 600 ということでしょうか? まず、基本的なところですが、 ウィンドウ領域とクライアント領域の違いを理解されていますでしょうか? また、なぜウィンドウサイズの変更が必要なのかを理解されていますか? ウィンドウ領域とは、そのウィンドウの全体の領域を指します(タイトル領域や メニュー領域ステータスバー、サイズ変更バーやボーダの領域を含んだ領域) クライアント領域とは上記の、タイトルやボーダーを含まないサイズとなります。 通常、ポップアップウィンドウはタイトルバーなどが存在しないため、 ウィンドウ領域とクライアント領域は基本的に等しくなります。 オーバーラップウィンドウは、タイトルバーやボーダーなどが、 加味されるため、ウィンドウ領域とクライアント領域が等しくなりません。 この為、「ウィンドウスタイル」を切り替える場合は、 ウィンドウサイズの変更が必要に成るわけです。 #モードだけ変更するならば、そもそもウィンドウサイズを #変更する必要はありません。 #(まぁ、ウィンドウ自体にはモードという概念はありませんが。) 提示されたプログラムでは、ウィンドウモードに変更された時しか ウィンドウサイズの変更を行っていませんので、 フルスクリーンからウィンドウモードに切り替えると、 タイトル分ずれてウィンドウサイズが変更され、 ウィンドウモードからフルスクリーンに切り替えると、 変更されたウィンドサイズがそのまま使用されることになります。

ClickHere
質問者

お礼

ご回答、ありがとうございます。 ウィンドウのフレームのサイズは考慮してリサイズしています(多分)。 ややこしいソースになってしまいましたが、ご指摘お願いします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • WNDPROC をクラスのメンバにもちたいです

    ツリーコントロールをクラスにラップしたいのですが、 クラス内のメンバで WNDPROC PrevProc; とすると、 error C2597: 静的でないメンバ 'TreeControlClass::PrevProc' への参照が正しくありません。 というエラーが表示されます。 どうにかできないでしょうか? クラスの外に変数宣言するしかダメでしょうか? よろしくお願いします。 Visual C++.NETで開発 #include<Commctrl.h> class TreeControlClass { private: HWND TreeWnd; WNDPROC PrevProc; public: void WindowCreate(HWND ParentWnd,RECT Rect) { DWORD Style; Style=WS_VISIBLE|WS_CHILD|WS_BORDER|TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT; int x,y,width,height; x=Rect.left; y=Rect.top; width=Rect.right-Rect.left; height=Rect.bottom-Rect.top; TreeWnd=CreateWindow(WC_TREEVIEW,"",Style,x,y,width,height,ParentWnd,NULL,NULL,NULL); PrevProc=(WNDPROC)GetWindowLong(TreeWnd,GWL_WNDPROC); SetWindowLong(TreeWnd,GWL_WNDPROC,(LONG)TreeProc); return; } void WindowDestroy() { SetWindowLong(TreeWnd,GWL_WNDPROC,(LONG)PrevProc); DestroyWindow(TreeWnd); return; } static LRESULT CALLBACK int TreeProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { default: return (CallWindowProc(PrevProc, hWnd, message, wParam, lParam)); } } };

  • VBA ユーザーフォームの×ボタン制御の不具合

    PowerPoint VBAで複数のユーザーフォームからなるVBAマクロを作成しました。 フォーム内の「次へ」「前へ」ボタンでのみ、マクロの実行制御をしているので、途中で右上の×を押されると、想定外エラーが発生します。 そこで、一番下に貼りつけたようなコードを全てのフォームに挿入することで、右上の×が表示されないようにしました。 あくまでフォームにしかコードは埋め込んでいません。 (標準モジュール、クラスには入ってません) ですが、極稀に、「フォームの右上×」ではなく、「PowerPointの右上×」が非表示になってしまう現象が発生します。 いろいろやるうちに再現はするのですが、厳密な再現手順がよくわかりません。 状況と下記ソースから、どこらへんに原因がありそうかアドバイス頂けないでしょうか? 全コードは出せない部分が多いのですが、アドバイスにあたり必要なコードがあれば、別途貼らせて頂きます。 Private Const GWL_STYLE = (-16) Private Const WS_SYSMENU = &H80000 ' ウィンドウに関する情報を返す Private Declare Function GetWindowLong Lib "USER32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long ' ウィンドウの属性を変更 Private Declare Function SetWindowLong Lib "USER32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long ' Activeなウィンドウのハンドルを取得 Private Declare Function GetActiveWindow Lib "USER32.dll" () As Long ' メニューバーを再描画 Private Declare Function DrawMenuBar Lib "USER32.dll" (ByVal hWnd As Long) As Long ' フォームアクティブ時処理 Private Sub UserForm_Activate() Dim hWnd As Long Dim Wnd_STYLE As Long hWnd = GetActiveWindow() Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE) Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU) SetWindowLong hWnd, GWL_STYLE, Wnd_STYLE DrawMenuBar hWnd End Sub

  • WindowsAPIの、ウインドウの表示非表示

    WindowsAPIのCreateWindowEx関数で作った 例えば第一引数が WS_EX_TOOLWINDOW|WS_EX_TOPMOST で第四引数が WS_SYSMENU | WS_VSCROLL | WS_SIZEBOX のウインドウを、何かのアクションがあったときいったん非表示にしてから、また何かのアクションがあった時に表示させるには、どのような物を使うのがベストなのでしょうか? プロシージャ内(HWNDはhw)で一例として(…?)試しに以下だけのものでやってみると long lStyle = GetWindowLong(hw, GWL_STYLE); lStyle = ~WS_VISIBLE; SetWindowLong(hw, GWL_STYLE, lStyle); 確かに非表示扱いにはなるようなのですが、これだけではスクリーンは再描画されず、再描画されるには人為的に別ウインドウを移動したりしないといけません。 おそらく「何かによって再描画させられれば」出来ると思うのですが それはどうすれば実現できるのでしょうか? また、これより もっと「こっちの方がいい」といった方法はありますでしょうか?

  • ウインドウの移動禁止

    最大化したウインドウをタイトルバーでドラッグして移動させるのを禁止したいのですが、うまくいきません!どなたかご教授下さい。 現在 1.OnInitDialog()内  ・ウインドウを最大化   this->ShowWindow(SW_SHOWMAXIMIZED);  ・最大化,最小化ボタン消去、サイズ変更禁止   lStyle = GetWindowLong( this->m_hWnd, GWL_STYLE );   lStyle &= ~WS_MINIMIZEBOX;   lStyle &= ~WS_MAXIMIZEBOX;   lStyle &= ~WS_SIZEBOX;   SetWindowLong( this->m_hWnd, GWL_STYLE, lStyle ); 2.WindowProc()内  ・タイトルバーでのダブルクリックを無視   if( message == WM_NCLBUTTONDBLCLK ){     return TRUE;   } しかし、ウインドウをタイトルバーでドラッグして移動を禁止する事が出来ません。 何か方法は無いのでしょうか? 環境 WindowsXP Pro SP3 VC++6.0 SP6 以上、よろしくお願いします。

  • ウィンドウスタイルの変更

    現象を文章で書きます。 まず始めに、ウィンドウスタイルにWS_BORDER | WS_CHILD | WS_VISIBLE | WS_THICKFRAME(サイズ変更境界を持つウィンドウ)を設定したボタンを作りました。 それを後の処理で style = GetWindowLongPtr(hWnd,GWL_STYLE); //ウィンドウスタイルの取得 style ^= WS_THICKFRAME; //style XOR WS_THICKFRAMESetWindowLongPtr(hWnd,GWL_STYLE,style); //新しいウィンドウスタイルを設定 としたらボタンのサイズ変更は出来なくなるのですが、 サイズ変更境界が表示されたままになります。 その状態でウィンドウを最小化、元に戻すとするとサイズ変更境界だけ消えたような変な形のボタンになります。 これがどうしてもいやなのです。 原因もわかりません。 対処法を教えてもらえないでしょうか? 環境はBorlandです。

  • 最大化時のフルスクリーン

    いつもお世話になっております。 VS2005 を使ってWindowsアプリケーションの実装を行っています。 最大化時にフルスクリーンにしたくプログラムを作成しているのですが、 WndProc内で下記のプログラムを実行し、 最大化アイコンをクリックするとバグ?が起きてしまいます。 -------------------------------------------------- case WM_SIZE:   cxClient = LOWORD(lParam);   cyClient = HIWORD(lParam);   if(wParam == SIZE_MAXIMIZED){ //最大化されたら     ShowWindow(hWnd, SW_SHOWNORMAL); //(1)ウィンドウを元のサイズに戻す     //(2)アプリケーションのウィンドウのフレームを「なし」にする     GetWindowLong(hWnd, GWL_STYLE); //ウインドウ・スタイルの取得     SetWindowLong(hWnd, GWL_STYLE, WS_POPUP); //ウインドウ・スタイルの設定     SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);     ShowWindow(hWnd, SW_MAXIMIZE); //(3)ウィンドウ最大化   } return 0; -------------------------------------------------- 実行したアプリケーションの右上の最大化ボタンを押すと、 見た感じではif文の中を繰り返し行っているような・・・ 元のサイズに戻って最大化になってを数秒繰り返して 最後にペイントして停止します。(高速なため確かではありません) 上記プログラムをどう直したらよいのでしょう。 ご教授お願いいたします。

  • こちらでマクロのコードを書いてもらったのですが、

    こちらでエクセルのコードを書いてもらい、そのコードを貼り付けてやってみたのですが、うまくいってるのでしょうか? 書いてもらったコードが (1)シートタブを右クリックし「コードの挿入」からVBEを開き、 以下のVBAコードを貼り付ける。 Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)   UserForm1.Caption = Target.Range.Text   UserForm1.PictureSizeMode = fmPictureSizeModeZoom   UserForm1.Picture = LoadPicture(Target.ScreenTip)   UserForm1.Show End Sub (2)VBEのメニューより「挿入」→「ユーザーフォーム」でフォームを作成し、 フォームを右クリックしてコードの表示を選択。 初期で入力されているコードを全て削除したのちに、以下のコードを貼り付け。 VBEを「×」で閉じる。 Option Explicit 'Windows API宣言 Private Const GWL_STYLE = (-16) Private Const WS_THICKFRAME = &H40000 Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function GetActiveWindow Lib "user32" () As Long Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long ' フォームをリサイズ可能にするための設定 Public Sub FormSetting()     Dim result As Long     Dim hwnd As Long     Dim Wnd_STYLE As Long     hwnd = GetActiveWindow()     Wnd_STYLE = GetWindowLong(hwnd, GWL_STYLE)     Wnd_STYLE = Wnd_STYLE Or WS_THICKFRAME Or &H30000     result = SetWindowLong(hwnd, GWL_STYLE, Wnd_STYLE)     result = DrawMenuBar(hwnd) End Sub Private Sub UserForm_Activate()     Call FormSetting End Sub (3)任意のセル(例えばA1セル)に任意の文字を入力し、ハイパーリンクを作成します。 セル参照の入力はリンクを挿入したセルのアドレス「A1」とし、 ヒント設定にて表示させたい画像のパスを設定します。 対応しているファイル形式は(bmp・dib・gif・jpg・wmf・emf・ico・cur)になります。 作成したリンクをクリックするとウィンドウで画像が開きます。 リサイズ可能にしているため、大きさは変更できますが、開いた時の初期サイズは (2)で作成したユーザーフォームのサイズになります。 以上になるのですが、上記のを実行して、A1をクリックしたら開きたい画像がフォトビューアーで開き、A1の下あたりに、添付画像のように別のA1と書かれたウィンドウが開きます。 本当はこのA1と書かれた所に開きたい画像が表示されてるはずなのでしょうか?

  • EDIT 作成時のちらつき防止について

    Enterキーを押下された時に画面にEDITBOXを表示し、 再度Enterキーを押下されたらEDITBOXを消す。 という処理を行っているのですが、表示する時も消す時も画面のちらつきが発生します。 このちらつきを防ぐにはどうしたらいいでしょうか? Enterキーが押されたときに、毎回、CreateWindowし、SetWindowLongでWNDPROCを設定しています。 mainWndProc関数の一部 mHwEnter = CreateWindow("EDIT", "ここに入力", WS_CHILD | WS_VISIBLE | WS_BORDER, 173, 380, 12 * 16, 16, mHwMain, NULL, hInst, NULL); mainWndProc = (WNDPROC)GetWindowLong(mHwEnter, GWL_WNDPROC); SetWindowLong(mHwEnter, GWL_WNDPROC, (LONG)WndProcEnter); 再度Enterキーが押されたとき ウインドウを破棄しています。 WndProcEnter関数の一部 SetWindowLong (mHwEnter, GWL_WNDPROC, (LONG)mainWndProc); DestroyWindow (mHwEnter); mHwEnter = NULL; EDITの表示、消去の仕方はWebで調べたのですが、間違っていたらご指摘お願いします。 また、メイン(親)画面は20FPSくらいで描画し続けています。MFCやDirectXは使用していません。 ちらつき防止のわかる方がいたら回答お願いします。

  • DirectXの画面サイズについて

    DirectXで640x480のサイズのウィンドウに、座標変換済みポリゴンを描画してみて気付いたのですが。 右端のX座標は640でウィンドウサイズと等しいのですが、最下のY座標が443とウィンドウサイズと等しくありません。 測ってみてもウィンドウサイズはちゃんと480でした。 もともとこのようなものなのでしょうか? HWND hWnd = CreateWindow( L"Title", L"Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, wc.hInstance, NULL );

  • プログラミング初心者です

    processingプログラミング作成をしています。 mouseファンクション(mouseClickedとか)やkeyファンクション(keyPressed)などのファンクションをつかったときに、クリックやkeyをたたいたら次々変わっていくみたいなプログラムを作成したいんですが、教えてください。 いまは画面を4等分にし、mouseClickedををつかったらランダムに選ばれたスペースを赤く塗り、もう一回mouseをクリックしたら、その赤く塗られたのは消えて、次のまたランダムに選ばれたスペースへと移動する。。それを何回もやるというプログラミングにしたいです。 sizeは600,600でそれぞれのrectは rect(0,0,300,300) rect(300,0,600,300) rect(0,600,300,300) rect(600,600,300,300) で区切ってます。ずっと時間かけてやってますが、これをどうやってrandomファンクションにし、それをランダムに選ばれたスペースをマウスクリックしたら赤く塗られるようにするかがもっていくかがどうしてもわかりません。 あと、もう一回クリックしたら前にクリックした場所が消えるというのもわかりません。 これが今までに書いたプログラムです。 いまはif elseをつかっています。 よろしくお願いします。 void setup() { size(600,600); strokeWeight(2); background(255); line(0,width/2,600,width/2); line(height/2,0,height/2,600); } void draw() { fill(255,0,0); } void mouseClicked() { if( mouseX <= width/2) { fill(255,0,0); rect(0,0,width/2,height/2); } else { rect(width/2,0,300,300); fill(255,0,0); } if (mouseX > height/2) { rect(0,width/2,height/2,height); fill(255,0,0); } else { rect(width/2,height/2,width,height); fill(255,0,0); } }

このQ&Aのポイント
  • 携帯アプリと繋いでいるプリンターで、ファームウェア更新後にプリンター本体に❌印がついたまま消えなくなりました。
  • ❌印がついているにもかかわらず、携帯アプリからは普通に印刷できます。
  • 電源を落としても再度入れ直しても、❌印は消えません。
回答を見る