MFCのデバイスコンテキストを取得して、DirectXなどで描画を行っています。
環境は、
VS2008
DirextX 9.0
MDIなんですがOnInitDialogでDirectXのデバイスを取得しています。
次にOnDrawで描画を行っています。
GetDcでコンテキストを取得し、円の描画を行っています。
MDIですので、5以上のファイルを作成すると、描画が行われなくなります。
共通デバイスコンテキストは、5以上持てないということは検索して分かったのですが、5以上のファイルに描画を成功させるためには、どうすればいいのでしょうか?
・単純に新規ファイルを作ったときに、以前に作ったファイルのデバイスコンテキストを開放また、Directxのデバイスを開放すればいい?
・DirectXのデバイスをファイルごとに作成するのではなく、共通してもてば解決できる??
・そもそも解放したりしても無理??
と考えているのですが、どうでしょうか?
助言をお願いします。
No.4ベストアンサー
- 回答日時:
補足頂きました。
言葉足らずでした。多重継承をしている訳ではありません。
DirectXと言う構造体の中にアプリ内で共有するデータをstaticメンバ変数として入れておき、全員でそれを利用しているだけです。要するにグローバル変数の様なものです。
アプリ内で共有するデータの作り方は、その人の考え方次第と言う事に成ります。
staticメンバ変数・関数の書式に馴染みが無ければ、以下を参考にすると良いです。
http://ja.wikipedia.org/wiki/%E4%BA%88%E7%B4%84% …
↓これを書き忘れていました。継承する訳ではありません。
struct DirectX
{
template<class _Tp>static BOOL ReleaseCOM(_Tp& p)
{
if(p == NULL)
return FALSE;
HRESULT hResult = p->Release();
p = NULL;
return hResult == S_OK;
}
static BOOL Init(HWND hWnd);
static BOOL UnInit();
static LPDIRECT3D9 g_pD3DPlan;//staticメンバ
static LPDIRECT3DDEVICE9 g_pDEVPlan;//staticメンバ
};
例えば、
struct DirectX
{
LPDIRECT3D9 pD3DPlan;
LPDIRECT3DDEVICE9 pDEVPlan;
};
extern DirectX g_dx;//此れを全員で使う
でも構いません。要はグローバル変数を一箇所にまとめようとしているような物です。
ただ、C++ではextern変数自体、余り使われないようです・・・。
No.3
- 回答日時:
補足頂きました。
長々と試していたのですが、
class CPlanScopeView : public CView
{
DECLARE_DYNCREATE(CPlanScopeView)
public:
LPDIRECT3D9 g_pD3DPlan; //(1)LPDIRECT3D9オブジェクト
LPDIRECT3DDEVICE9 g_pDEVPlan; //(2)IDirect3DDevice9オブジェクト
LPDIRECT3DSURFACE9 g_pBackBuffer;
・・・・
(1)(2)はそれぞれ、アプリで唯一として共有しないといけない様なので、ファイルの個数分作成しては良くない見たいです。
なので、ファイルの個数分存在してよいのはg_pBackBufferのみです。
MDIで初期化が複雑化しているので、どれを何処におくかを入念に検討した方が良いかもしれません・・・。
ファイルは幾つ開いても大丈夫でした。一応こんな感じで確認しました。Viewウィンドウではなく、Documentウィンドウの方にバックバッファを持たせた方が良いかもしれません。参考程度に。
//唯一存在するDXのデバイスなど
//DirectX.cpp
/////////////////////////////////////////////////////////
//スタティックメンバ変数
LPDIRECT3D9 DirectX::g_pD3DPlan = NULL;
LPDIRECT3DDEVICE9 DirectX::g_pDEVPlan = NULL;
//DXの初期化
BOOL DirectX::Init(HWND hWnd)
{
g_pD3DPlan = ::Direct3DCreate9(D3D_SDK_VERSION);
if(!g_pD3DPlan)return FALSE;
D3DPRESENT_PARAMETERS d3dpp = {0};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_pD3DPlan->CreateDevice(D3DADAPTER_DEFAULT ,
D3DDEVTYPE_HAL ,
hWnd ,
D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
&d3dpp,
&g_pDEVPlan );
return g_pDEVPlan != 0;
}
//DXの始末
BOOL DirectX::UnInit()
{
if(!ReleaseCOM(g_pDEVPlan))return FALSE;
if(!ReleaseCOM(g_pD3DPlan))return FALSE;
return TRUE;
}
//DirectX.cpp
/////////////////////////////////////////////////////////
//CMainFrame.cpp
CMainFrame::~CMainFrame()
{
//DXの後始末
DirectX::UnInit();
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//MFCの処理ココから
//MFCの処理ココまで
//OnCreateのラスト、ココでDXの初期化
DirectX::Init(this->GetSafeHwnd());
return 0;
}
//CMainFrame.cpp
/////////////////////////////////////////////////////////
//CMyMDIDoc.cpp
CMyMDIDoc::CMyMDIDoc() : g_pBackBuffer(NULL)//初期化
{
// TODO: この位置に1度だけ呼ばれる構築用のコードを追加してください。
}
CMyMDIDoc::~CMyMDIDoc()
{
//サーフェースの始末
DirectX::ReleaseCOM(g_pBackBuffer);
}
BOOL CMyMDIDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: この位置に再初期化処理を追加してください。
// (SDI ドキュメントはこのドキュメントを再利用します。)
//ココでサーフェースを作る
DirectX::g_pDEVPlan->CreateOffscreenPlainSurface(320, 240, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &g_pBackBuffer, NULL);
//作成に成功したら黒く塗り潰す
if(g_pBackBuffer)
{
HDC hDC = this->GetSurfaceDC();
::PatBlt(hDC, 0, 0, 320, 240, BLACKNESS);
this->ReleaseSurfaceDC(hDC);
}
return g_pBackBuffer != 0 ? TRUE : FALSE;
}
//サーフェースのDCを取る
HDC CMyMDIDoc::GetSurfaceDC()
{
HDC hDC;
g_pBackBuffer->GetDC(&hDC);
return hDC;
}
//サーフェースのDCを消す
BOOL CMyMDIDoc::ReleaseSurfaceDC(HDC hDC)
{
return g_pBackBuffer->ReleaseDC(hDC) == S_OK;
}
//CMyMDIDoc.cpp
/////////////////////////////////////////////////////////
//CMyMDIView.cpp(質問者様のCPlanScopeViewに該当するクラス)
void CMyMDIView::OnDraw(CDC* pDC)
{
CMyMDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: この場所にネイティブ データ用の描画コードを追加します。
//サーフェースのDCを取る
HDC hDC = pDoc->GetSurfaceDC();
//しくじったらメッセージでも表示する
if(hDC == NULL)
{
::MessageBox(NULL, " error ", " ", MB_OK);
}
//円を描く
::Ellipse(hDC, 0, 0, 320, 240);
//ビューに描写
::BitBlt(*pDC, 0, 0, 320, 240, hDC, 0, 0, SRCCOPY);
//サーフェースのDCを消す
pDoc->ReleaseSurfaceDC(hDC);
}
この回答への補足
たびたびすみません。
上記に詳しく記述していただいているのですが、
DirectXのクラスを作成するでいいんでしょうか?
そして、そのクラスを継承を行いな各クラスで使用するで問題ないのでしょうか?
その場合、多重継承となって、いくような気が多重継承以外では、無理ですかね。
初歩的な質問かもしれませんが宜しく御願い致します。
回答ありがとうございます。
すみません。わざわざいろいろ試していただいて。
最初に原因として、考えてた一番修正が多くあまりやりたくないものが原因とは
少しへこみます。
上記を参考にコーディングをやりなおしてみます。
また結果の報告をさせていただきます。
No.2
- 回答日時:
補足頂きました。
「g_pBackBuffer」が、個別のファイルに対するバックバッファでしょうか。
もしかして、この変数は「externやstatic」に成っていませんか?
↓こんな感じに成っていませんか
extern g_pBackBuffer = NULL;
もしそうならば、MDIチャイルドウィンドウ(ファイルを開くたびに開くウィンドウ)のクラスのメンバ変数にしなければいけません。
この回答への補足
お返事ありがとうございます。
> 「g_pBackBuffer」が、個別のファイルに対するバックバッファでしょうか。
はい。個別のバックバッファになっています。
g_pBackBufferはクラスのメンバ変数にしています。
class CPlanScopeView : public CView
{
DECLARE_DYNCREATE(CPlanScopeView)
public:
LPDIRECT3D9 g_pD3DPlan; //LPDIRECT3D9オブジェクト
LPDIRECT3DDEVICE9 g_pDEVPlan; //IDirect3DDevice9オブジェクトLPDIRECT3DSURFACE9 g_pBackBuffer;
・・・・
としています。
なので「externやstatic」にはしていませんが、ここの宣言に問題があるような
気がしてきましたが、どうでしょうか?
No.1
- 回答日時:
こんばんは。
LPDIRECT3DSURFACE9の事でしょうか。サーフェースやテクスチャは同時に幾つ存在しても構わないです。
デバイスコンテキストは描写する寸前で取って、描写が終わったら直に解放した方が良いです。
OnInitDialog()で開きっ放しにしておくのは、トラブルの元です。
void MyDlg::OnDraw(...)
{
HDC hDCSurface = NULL;
//書く直前にGetDC()する
m_pSurface->GetDC(&hDCSurface);
//円を描く
::Ellipse(hDCSurface, , ,);
//書き終わったら直閉じる
m_pSurface->ReleaseDC(hDCSurface);
}
の様にすれば良いのでは無いでしょうか。
この回答への補足
回答ありがとうございます。
早速ためしてみましたが、やはり6個目で、表示されなくなりました。。。
hr = g_pBackBuffer->GetDC(&hDC_Test);
if (!FAILED(hr)){
SelectObject(hDC_Test,g_Brush);
::Ellipse(hDC_Test,,,,);
g_pBackBuffer->ReleaseDC(hDC_Test);
}
と書いたのですが。。。
デバッグで見てみると、6個目のファイル作成時のGetDCでの戻りが
正常値が戻ってきてないです。
上記では、開きっぱなしになっていないはずですので、
他の原因があるのでしょうか?
返事が遅くなり、申し訳ありませんでした。
上記のとおり、変更すると、5個以上のでも描画できました。
ありがとうございます。
ただ、いろいろと新たな問題がでてきましたけど・・・orz
実は、追加の仕様で、画面を分割する必要性がでてきまして、
ChildFormを4分割を行ったのですが、
上記の場所で、デバイスを取得すると、MainFormに描画されるようになってしまいました。
現在、試行錯誤して、上記のやりかたで、分割でも問題なくその領域に描画で
きるように修正中です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- ルーター・ネットワーク機器 echoshow8の音声をBluetoothを介してパソコンで出力するやり方を教えて下さい。 3 2023/04/03 17:09
- Wi-Fi・無線LAN PCWi-Fiの設定方法がわからなくて困っています。 4 2022/12/28 18:30
- Android(アンドロイド) スマートフォンを盗まれた場合に備えて 3 2023/07/15 15:14
- タブレット スマホのファイルをUSB接続の異変の続き 3 2023/01/04 21:27
- プリンタ・スキャナー 印刷 キャンセル&印刷できない 2 2022/11/29 16:45
- Windows 10 新規PC導入して、うっかりマイクロソフトアカウントも新規登録してしまった時の復帰方法 3 2022/06/12 16:11
- その他(ゲーム) Steam版(PC)アーマードコア6の購入を検討しているのですが動作環境が合っているか分かりません。 4 2023/08/24 18:43
- ノートパソコン ステレオミキサーが反応しない 1 2023/06/20 23:16
- その他(コンピューター・テクノロジー) ブルースクリーンエラーの発生と解決手順 2 2022/10/09 13:05
- Bluetooth・テザリング スマホのファイルをUSB接続の異変 3 2023/01/03 22:12
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SetWindowRgn()関数について。
-
GetDC()とCreateCompatibleDC()
-
メモリデバイスコンテキストを...
-
BeginPaintの使い方
-
コンテキスト依存とは?
-
VC++のTextOutの再描画の仕方
-
エクセルで作った新しいウイン...
-
グラフの交点の求め方(Excel)
-
「アイテムは収集されました」...
-
フォントの大きさ
-
c言語でキーボードから2点の座...
-
コントロールの書式設定で、“コ...
-
ドロップダウンリストのフォン...
-
コンボボックス内の文字サイズ変更
-
UWSCで特定のChromeのタブをア...
-
PCで「使用可能な場合はグラフ...
-
Excel VBAでのMultipageの選択
-
MFCのタイマーのつかい方を教え...
-
エクセルである点からの距離で...
-
Excelの上下を固定したい
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンテキスト依存とは?
-
Win32APIにて、アイコンの情報...
-
PlgBltでの透過
-
画面がチカチカする
-
GetDC()とCreateCompatibleDC()
-
VBでFD、USBの有効・無効...
-
VC++でBitmapとText文字を表示...
-
コントロール内の文字の背景色
-
画像処理 ビットマップ ダブ...
-
BitBlt関数について教えてください
-
メモリデバイスコンテキスト&...
-
Rectangleで、リソースが解放さ...
-
画面のちらつきについて
-
Windowsプログラミング 画面描...
-
ビットマップ(表示速度とサイズ)
-
メモリデバイスコンテキストを...
-
ダブルバッファの作り方
-
TextOutについて
-
SetWindowRgn()関数について。
-
領域を塗りつぶしたい
おすすめ情報