• ベストアンサー

MFC DirectXのデバイスの再設定

MFCのMDIで、DirectXおよびWinAPIを仕様して領域に描画を行うものを作っています。 環境ですが、 VS2008 DirectX9.0 です。 子ウィンドウは4分割しており、(0,0)と(1,0)が描画領域で、(0,1)(1,1)はフォームです。 そこで、以前は各子ウィンドウごとに、デバイスを取得し、描画をおこなっていたのですが、ファイルを5個以上作成すると、WinAPIで描画されるものが表示されなくなりました。 それは、デバイスコンテキストは、5個以上もてないことが発覚したためとわかったので、デバイスは親で持つことにし、共通化することになりました。 しかし、それでは、親ウィンドウで取得しているため、描画のウィンドウサイズなどが異なるため、意図した領域にかけておりません。 そこで、各領域に再設定を行いたいのですが、どうすればよいのでしょうか? 対策として、下記のように考えたのですが、検討違いでしょうか? ・デバイスの画面の設定をResetなどをつかって、リセットし、描画領域の再設定を行う。(Resetだと、再度デバイスの取得を行うと思っているのですが、これだとファイルごとにもっているのと変わらないような気がします。) ・CreateOffscreenPlainSurface等でオフスクリーン サーフェイスを作成し、描画する。(描画の座標情報等の微調整がいるような気がします。) ・単純に再設定できるから再設定を行う。 アドバイスを御願い致します。

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

  • ベストアンサー
回答No.2

 こんばんは。  以前の方で御礼頂きました。相当難航している様で・・・。  一番手っ取り早いのは、#No1さんが説明されている通り、GetDC()/ReleaseDC()でもって、サーフェースからMDIウィンドウに描写してしまう事です。  pDev->BeginScene();  //処理  pDev->EndScene();  を使用すると、MDIドキュメントごとぶっ潰されてしまいます・・・。どうやら、MDIでDirect3Dを使用するのはそう容易では無いみたいです。  で、調べまわしていたのですが、漸くサイトを発見できました。  「SetViewportメソッドで分割」(但し事例がSDI、実験失敗)  http://www.shader.jp/xoops/html/masafumi/directx9/3dtips/d3d12.htm  「Presentメソッドの第3パラメータにウィンドウハンドルを渡す」(此方で実験成功)  http://monsho.hp.infoseek.co.jp/dx/dx77.html  非常に強引ですが・・・、前回の続編的に書けば、 ///////////////////////////////////////////////////////////////////////////// // CMyMDIView クラスの描画 void CMyMDIView::OnDraw(CDC* pDC) { CMyMDIDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: この場所にネイティブ データ用の描画コードを追加します。 //スプライトの作成 LPD3DXSPRITE pSprite = NULL; ::D3DXCreateSprite(DirectX::g_pDEVPlan, &pSprite); //シーン開始 DirectX::g_pDEVPlan->BeginScene(); DirectX::g_pDEVPlan->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0); //スプライトにテクスチャを貼って描写 pSprite->Begin(D3DXSPRITE_ALPHABLEND); pSprite->Draw(pDoc->GetTexture(), NULL, NULL, NULL, D3DCOLOR_ARGB(255, 255, 255, 255)); pSprite->End(); //シーン終了 DirectX::g_pDEVPlan->EndScene(); //第3パラメータにMDIビューのハンドルを入れる DirectX::g_pDEVPlan->Present(NULL, NULL, this->GetSafeHwnd(), NULL); //スプライトの開放(本来は何処か別の場所に作成して常駐させて置く) DirectX::ReleaseCOM(pSprite); }

その他の回答 (1)

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

>それは、デバイスコンテキストは、5個以上もてないことが発覚したためと >わかったので、デバイスは親で持つことにし、共通化することになりました。 DCを親で持つ必要はありません。 GetDCは、子ウィンドウごとで構いません。 但し「描画が終ったらReleaseDCですぐに解放する」と言う処理が必要です。 つまり、描画ルーチンは   HDC hDC; /* ここだけにしかスコープを持たないauto変数にする。publicにしない */   if ((hDC = GetDC(hWnd) != NULL) { /* 座標系はhWndで指定したウィンドゥの座標系になる */     描画処理; /* ファイル1つに対する描画はすべてここで行う */     if (ReleaseDC(hWnd,hDC) != 1) {       alert("DCの解放に失敗!");     }   } と言う事になります。 描画が終ったのにReleaseDCしないままだと「6回目のGetDCで失敗する」と言う事になります。 GetDCとReleaseDCがペアになっている限り、GetDCは何万回繰り返しても大丈夫です。 >しかし、それでは、親ウィンドウで取得しているため、描画のウィンドウサイズなどが異なるため、意図した領域にかけておりません。 親ウィンドゥでGetDCすると、座標系は親ウィンドゥになるので、座標(0,0)は「親ウィンドゥのクライアント描画領域の原点」になります。 なので「子ウィンドウの特定の座標が、親ウィンドゥのクライアント座標のどこに相当するかを求める必要」があります。 つまり「子のクライアント座標を親のクライアント座標に変換する必要」があるのです。 「子ウィンドゥのクライアント座標を、親ウィンドゥのクライアント座標に変換する」には、ClientToScreenとScreenToClientを使います(双方のウィンドウが同じスクリーンにある事が条件) 子ウィンドゥのクライアント座標系から、親ウィンドゥのクライアント座標系に変換するには   POINT Po;   Po.x = 子ウィンドゥのX座標;   Po.y = 子ウィンドゥのY座標;   ClientToScreen(Child_hWnd,&Po); /* 子の座標をスクリーン座標に */   ScreenToClient(Parent_hWnd,&Po); /* スクリーン座標を親の座標に */ で行います。これでPOINT構造体のx、yに、子の座標から親の座標に変換した座標が入ります。 >対策として、下記のように考えたのですが、検討違いでしょうか? 見当違い(「検討違い」ではなく「見当違い」が正しい) 「描画の直前にGetDCし、GetDCしたらすぐに描画を行い、描画が終ったらすぐにReleaseDCする」と言うのが正しい処理。 GetDCしたデバイスコンテキストのハンドルは、保持したままにしない事。 もし、ユーザーが「画面のプロパティを変更」したりすると、保持したままのデバイスコンテキストは、無効なハンドルになってしまうでしょう。 つまり、質問者さんのように「親ウィンドゥのデバイスコンテキストのハンドルをGetDCしたまま、ずっと保持して使い回す」と、ユーザーが「画面のプロパティを変更」した瞬間、それ以降、何も描画されなくなる可能性があります(画面のプロパティの変更を検知したらReleaseDCしてGetDCし直しても良いが、それだったら、描画処理の直前にGetDCして、描画終了してからReleaseDCすれば良い筈)

関連するQ&A

  • MFC デバイスコンテキストについて

    MFCのデバイスコンテキストを取得して、DirectXなどで描画を行っています。 環境は、 VS2008 DirextX 9.0 MDIなんですがOnInitDialogでDirectXのデバイスを取得しています。 次にOnDrawで描画を行っています。 GetDcでコンテキストを取得し、円の描画を行っています。 MDIですので、5以上のファイルを作成すると、描画が行われなくなります。 共通デバイスコンテキストは、5以上持てないということは検索して分かったのですが、5以上のファイルに描画を成功させるためには、どうすればいいのでしょうか? ・単純に新規ファイルを作ったときに、以前に作ったファイルのデバイスコンテキストを開放また、Directxのデバイスを開放すればいい? ・DirectXのデバイスをファイルごとに作成するのではなく、共通してもてば解決できる?? ・そもそも解放したりしても無理?? と考えているのですが、どうでしょうか? 助言をお願いします。

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    VC2005についてです ピクチャーコントロールのデバイスコンテキストを取得するためには どうすればよいでしょうか? MDIGetActive()->GetDC()->TextOutA(20,50,"文字列です"); この様にすれば、アクティブになった 子ウィンドウデバイスコンテキストを取得することができますが、 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 よろしくお願いします。

  • C++/CLIとMFC

    よろしくお願いします。 環境はVisual C++ 2005です。 ご存知の方がいらっしゃいましたらご教授ください。 一つのプロジェクトで作成した親Formに対して、 もう一つのプロジェクトで作成した子ウィンドウをプラグインさせ、MDIを作ろうとしているのですが [CLR]->[Windowsフォームアプリケーション]で作成したプロジェクトのFormに対して MFCで作成した子ウィンドウをプラグインさせることは可能なのでしょうか? C++/CLIでMDIを作る時は MDIの親となるFormのIsMdiContainerプロパティをtrueに設定し、 MDIの子となるFormのMdiParentプロパティをMDIの親Formの インスタンスに設定する必要があると思うのですが、 子の部分をMFCを使って作成した場合どのようにすれば 親子関係が作れるのかわからず質問させていただきました。 よろしくお願いします。

  • DirectX for VB のリファレンス

    DirectXのオフスクリーンサーフェスを、RESファイルのBitmapから作成したいのですが、方法がわかりません。誰か教えて下さい。 また、DirectX7SDKのヘルプは英語なので、使いにくくて困っています。リファレンスが充実しているような解説書はないでしょうか。

  • DirectX:描画されません・・・ヒント下さい・・・

    VCでC++を使ってDirectXを使ったプログラムを書いてます。 そういう仕事しているわけではなく、素人です。 DirectXは色々とややこしくて、何がなんだかさっぱりです。 とりあえず、Win32APIを使って、ウィンドウを表示し、DirectXを使って、ボタンを押すことで、ウィンドウモードとフルスクリーンモードを切り替えることの出来るプログラムは作れました。 しかし、3Dのモデルが表示されません。 何が駄目なのかが、さっぱりです。 こういう場合、何に原因があることが多いのでしょうか?? DirectX経験者の方、どうか、教えてください。お願いします。 以下に現在の状況を列挙します。 足りなければ、ご指摘ください。 ソースは見せることはできるのですが、かなり、スパゲティーなので・・・・。 DirectX:November 2008 目標:Xファイルからじゃなく座標を自分で指定して立方体を描画したい 出来ていると思われること ・Win32APIを使ったウィンドウの作成 ・Direct3Dオブジェクトの作成Direct3DCreate9⇒  D3DDeviceオブジェクトのプレゼンテーションパラメータの設定 ・カメラとライトの設定 ・あと、DirectXのメソッドで背景色だけは変えられます。 経験者の方がた、よろしくお願いします!!

  • VisualC++におけるメインウィンドウの領域に子ウィンドウを配置する際に発生する問題

    メインウインドウの領域に子ウインドウを作成し、その子ウインドウの領域にオブジェクトを表示しようとしています。 そこで、子ウインドのプロシージャに描画するソースを書いているのですが、子ウインドウの描画領域には何も表示されず、親ウインドウの描画領域に表示されてしまいます。 どうすれば子ウインドウの領域に描画することができるのでしょうか? 説明の至らない点もあると思いますが、わかる方いらっしゃいましたら宜しくお願い致します。

  • MFC MDIでステータスバーの追加。

    Vd++6.0 MFC。 MDIにてプログラムを作成しているのですが、 親ウィンドウにはステータスバーがついているのですが、 子ウィンドウにはついていません。 子ウィンドウごとにそれぞれのステータスを表示しようと思っているのですが、 ステータスバーを作成する方法がわかりません。 そなたか、ご存知の方宜しくお願い致します。 足りない部分は補足させていただきます。

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    VC2005についてです ピクチャーコントロールのデバイスコンテキストを操作するためには どうすればよいでしょうか? void CMainFrame::OnButton() { // ここに処理を書く CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; CButton *pButton =  (CButton*)pFrame->m_wndDialogBar.GetDlgItem(IDC_BUTTON1); pButton->SetWindowText("button"); MDIGetActive()->GetDC()->TextOutA(0,0,"文字列です"); } この様にすれば、アクティブになった 子ウィンドウデバイスコンテキストを取得することができますが、 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 MDIGetActive()->GetDlgItem(IDC_PICTURE1)->GetDC()->TextOutA(0,0,"文字列です"); この方法では、エラーがでます。 よろしくお願いします。

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    すみません、解決しませんでした・・・ C2005についてです ピクチャーコントロールのデバイスコンテキストを操作するためには どうすればよいでしょうか? void CMainFrame::OnButton() { CMDIChildWnd *mc; mc=MDIGetActive(); CStatic* pStatic=(CStatic*)mc->GetDlgItem(IDC_PICTURE1); CClientDC myPictDC(pStatic); myPictDC.TextOutA(0,0,"aiueo"); } この様にすれば、文字が出力されますが、 モニターの画面上の左上 (0,0)の位置に 出力されてしまいます。 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 ピクチャーコントロールの上に描画するためには どうすればよいでしょう? よろしくお願いします。

  • D3DXCreateTextureFromFileInMemory関数について

    DirectXのSDK内に テクスチャ作成を行う D3DXCreateTextureFromFileInMemory関数がありますが、 この引数pSrcDataについて ([in] テクスチャの作成に使うメモリ内のファイルへのポインタ。) HBITMAPクラスのhBitmapハンドルを渡す事は可能でしょうか? (行いたいことは、DirectXの描画範囲にライブ画像のような 画像描画領域を作成したいです。) ご教授の程、宜しくお願いします。

専門家に質問してみよう