原因を見つけていただけるとありがたいです。
バグの内容は次のようなものです。
①画像の描画が正しく行われない。
②描画する関数の直前にOutputDebugStringA( );などを入れるだけで正しく描画される。
③直接描画に関係ないはずのコードを書き換えるだけでも、なぜか描画が行われる。
④バグ発生時の挙動は様々で、マウスの位置によって描画が行われたり行われなかったりする、何をしても描画されないなど様々です。
おそらくポインタ系のバグであるとは思うのですが、どうにも原因を見つけることができません。以下が問題のコード(原因がどこにあるか予想もつかないので全体を貼ります。できるだけ縮めてあります)ですので、どうかよろしくお願いいたします。
//////////////////////////////////////////////////
//Game.h
/////////////////////////////////////////////////
#pragma once
class Game
{
public:
Game(void);
~Game(void);
};
//////////////////////////////////////////////////
//Game.cpp
/////////////////////////////////////////////////
#include "Game.h"
#include <tchar.h>
#include "RootMain.h"
#define _CRTDBG_MAP_ALLOC
// プロトタイプ宣言
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
RootMain *rootMain;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int showCmd)
{
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
// ウィンドウクラスの情報を設定
wc.cbSize = sizeof(wc); // 構造体サイズ
wc.style = CS_HREDRAW | CS_VREDRAW; // スタイル
wc.lpfnWndProc = WndProc; // ウィンドウプロシージャ
wc.cbClsExtra = 0; // 拡張情報1
wc.cbWndExtra = 0; // 拡張情報2
wc.hInstance = hInst; // インスタンスハンドル
wc.hIcon = (HICON)LoadImage( // アイコン
NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hIconSm = wc.hIcon; // 子アイコン
wc.hCursor = (HCURSOR)LoadImage( // マウスカーソル
NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景
wc.lpszMenuName = NULL; // メニュー名
wc.lpszClassName = _T("Default Class Name");// ウィンドウクラス名
// ウィンドウクラスを登録する
if( RegisterClassEx( &wc ) == 0 ){ return 1; }
// ウィンドウを作成する
hWnd = CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
_T("Game"), // タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW, // ウィンドウの種類
CW_USEDEFAULT, // ウィンドウを表示する位置(X座標)
CW_USEDEFAULT, // ウィンドウを表示する位置(Y座標)
1000, // ウィンドウの幅
1000, // ウィンドウの高さ
NULL, // 親ウィンドウのウィンドウハンドル
NULL, // メニューハンドル
hInst, // インスタンスハンドル
NULL // その他の作成データ
);
if( hWnd == NULL ){ return 1; }
// ウィンドウを表示する
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
//ルートメインを生成
rootMain=new RootMain(hInst,hWnd);
// メッセージループ
while( 1 )
{
BOOL ret =PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
if (msg.message==VK_ESCAPE)
{
break;
}
if( msg.message==WM_QUIT||ret == -1 )
{
// アプリケーションを終了させるメッセージが来ていたら、
// あるいは GetMessage() が失敗したら( -1 が返されたら )、ループを抜ける
break;
}
else
{
// メッセージを処理する
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// アプリケーションの終了操作
//ここはウィンドウが表示されている間ループし続ける
rootMain->rootMainProcess();
//ここはウィンドウが表示されている間ループし続ける
}
//おそらくhWndがウィンドウを表している。
//_CrtDumpMemoryLeaks();
return 0;
}
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch( msg )
{
case WM_DESTROY: // ウィンドウを破棄するとき
PostQuitMessage( 0 );
return 0;
}
if(wp==VK_ESCAPE){
PostQuitMessage( 0 );
return 0;
}
// 他のメッセージは、デフォルトの処理を行う
return DefWindowProc( hWnd, msg, wp, lp );
}
//////////////////////////////////////////////////
//RootMain.h
/////////////////////////////////////////////////
#pragma once
#include < d3d9.h >
#include "NBCommon.h"
#include "PanelCreatePanel.h"
#include "MovePanel.h"
class RootMain
{
public:
RootMain(HINSTANCE,HWND);
~RootMain(void);
void rootMainProcess();
private:
PanelCreatePanel* pcp;
MovePanel* mp;
};
//////////////////////////////////////////////////
//RootMain.cpp
/////////////////////////////////////////////////
#include "RootMain.h"
#include <stdio.h>
RootMain::RootMain(HINSTANCE myHinst,HWND hWnd)
{
NBCommon::NBCommon(myHinst,hWnd);
pcp=new PanelCreatePanel();
mp=new MovePanel();
}
RootMain::~RootMain(void)
{
}
void RootMain::rootMainProcess(){
NBCommon::device->BeginScene();
NBCommon::device->Clear(0, NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_ARGB(200,200,200,200), 1.0f, 0);
//ここからメイン処理
pcp->PanelAction();
mp->PanelAction();
//ここまでメイン処理
NBCommon::device->EndScene();
NBCommon::device->Present(NULL, NULL,NULL, NULL);
}
//////////////////////////////////////////////////
//XBase.h
/////////////////////////////////////////////////
#pragma once
#include < d3d9.h >
class XBase
{
public:
HWND hWnd;
XBase(HWND);
~XBase(void);
LPDIRECT3D9 pD3d;
LPDIRECT3DDEVICE9 pDevice;
LPDIRECT3DDEVICE9 getDevice();
};
//////////////////////////////////////////////////
//XBase.cpp
/////////////////////////////////////////////////
#include "XBase.h"
XBase::XBase(HWND myHWnd)
{
hWnd=myHWnd;
}
XBase::~XBase(void)
{
}
LPDIRECT3DDEVICE9 XBase::getDevice(){
///////////////////////////////////
// Direct3Dの初期化
////////////////////////////////////
IDirect3D9* pD3D9 = NULL; // Direct3Dデバイス生成用オブジェクト
IDirect3DDevice9* pDevice3D = NULL; // Direct3Dのデバイス
// Direct3D9オブジェクトの作成
pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
// ディスプレイ情報取得
D3DDISPLAYMODE Display;
pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &Display);
D3DPRESENT_PARAMETERS D3DParam = { // スワップチェイン設定
1000,1000,Display.Format,1,D3DMULTISAMPLE_NONE,0,
D3DSWAPEFFECT_DISCARD,hWnd,TRUE,TRUE,D3DFMT_D24S8,0,0,D3DPRESENT_INTERVAL_DEFAULT
};
// HALモードで3Dデバイス作成
if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, D3DParam.hDeviceWindow,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DParam.hDeviceWindow,
D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
// REFモードで3Dデバイス作成
if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, D3DParam.hDeviceWindow,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
if (FAILED(pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, D3DParam.hDeviceWindow,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &D3DParam, &pDevice3D)))
{
// 3Dデバイス作成失敗(このグラフィックボードではDirectXが使えない)
pD3D9->Release();
}
return pDevice3D;
}
//////////////////////////////////////////////////
//NBCommon.h
/////////////////////////////////////////////////
#pragma once
#include < d3d9.h >
#include "XBase.h"
#include "PanelLibrary.h"
/**
複数のクラスで共通して使う変数をまとめたクラス。このクラスのメンバにはstatic参照できる。
*/
class NBCommon
{
public :
NBCommon(HINSTANCE myHinst,HWND myHWnd);
~NBCommon(void);
static HINSTANCE hinst;//WinAPIのHINSTANCE。
static HWND hWnd;//ウィンドウのハンドル。WinApiに与えられたもの。
static LPDIRECT3DDEVICE9 device;//DirectXのデバイス
};
//////////////////////////////////////////////////
//NBCommon.cpp
/////////////////////////////////////////////////
#include "NBCommon.h"
NBCommon::NBCommon(HINSTANCE myHinst,HWND myHWnd)
{
hinst=myHinst;
hWnd=myHWnd;
device=NULL;
XBase* xBase=new XBase(hWnd);
device=xBase->getDevice();
}
NBCommon::~NBCommon(void)
{
}
HINSTANCE NBCommon::hinst;//WinAPIのHINSTANCE。
HWND NBCommon::hWnd;//ウィンドウのハンドル。WinApiに与えられたもの。
LPDIRECT3DDEVICE9 NBCommon::device;//DirectXのデバイス
//////////////////////////////////////////////////
//XDraw.h
/////////////////////////////////////////////////
#pragma once
#include < d3d9.h >
#include "NBCommon.h"
#include < d3dx9.h >
class XDraw
{
public:
XDraw();
~XDraw(void);
LPDIRECT3DTEXTURE9 LoadTexture(char* Adress);
void drawTexture(LPDIRECT3DTEXTURE9 texture,float x,float y,float width,float height,float alpha);
LPD3DXSPRITE sprite;
HRESULT hr;
};
//////////////////////////////////////////////////
//XDraw.cpp
/////////////////////////////////////////////////
#include "XDraw.h"
#include <stdio.h>
XDraw::XDraw()
{
sprite=NULL;//スプライト。スプライトとは画面上に張り付く透明な板のこと。これにテクスチャを貼り付けて描画する。
D3DXCreateSprite(NBCommon::device,&sprite);
}
XDraw::~XDraw(void)
{
}
/**
実行ファイルのあるフォルダからの相対パスを指定して画像をロード。テクスチャ型の戻り値を返す。
*/
LPDIRECT3DTEXTURE9 XDraw::LoadTexture(char* Adress){
LPDIRECT3DTEXTURE9 texture=NULL;
D3DXCreateTextureFromFile( NBCommon::device , Adress , &texture );
return texture;
}
void XDraw::drawTexture(LPDIRECT3DTEXTURE9 texture,float x,float y,float width,float height,float alpha){
D3DXMATRIX Mat;
//テクスチャの幅と高さを取得
UINT texWidth=0;
UINT texHeight=0;
texture->GetLevelDesc(0,&desc);
texWidth=desc.Width;
texHeight=desc.Height;
//テクスチャの幅と高さを取得
///////////////////テクスチャを描画
sprite->Begin( NULL);
D3DXVECTOR3 center , position;
D3DXVECTOR2 pos2D; // 拡大
D3DXVECTOR2 scale; // 拡大
scale.x=width/texWidth;
scale.y=height/texHeight;
position.x = x;
position.y = y;
pos2D.x=position.x;
pos2D.y=position.y;
D3DXMatrixTransformation2D(&Mat,&pos2D , 0, &scale, NULL, 0, NULL);//第二項は拡大の基準。NULLだと、0,0になってしまうので、画像の左上座標を入れている。
sprite->SetTransform(&Mat);
D3DCOLOR color=D3DCOLOR_RGBA(0xff,0xff,0xff,(int)(alpha*255));
sprite->Draw( texture , NULL ,NULL , &position ,color );
sprite->End();
}
//////////////////////////////////////////////////
//PanelCreatePanel.h
/////////////////////////////////////////////////
#pragma once
#include "Panel.h"
#include <d3d9.h>
#include "XDraw.h"
class PanelCreatePanel:public Panel
{
public:
PanelCreatePanel();
~PanelCreatePanel(void);
void PanelAction();
private:
XDraw* xDraw;
LPDIRECT3DTEXTURE9 textrue;
};
//////////////////////////////////////////////////
//PanelCreatePanel.cpp
/////////////////////////////////////////////////
#include "PanelCreatePanel.h"
#include <stdio.h>
PanelCreatePanel::PanelCreatePanel()
{
xDraw=new XDraw();
textrue=xDraw->LoadTexture("xFiles/緑のテクスチャー.png");
}
PanelCreatePanel::~PanelCreatePanel(void)
{
}
void PanelCreatePanel::PanelAction(void)
{
/*ここのコメントアウトを外すと正常に画像が表示される。
char str[500];
sprintf(str,"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
OutputDebugStringA( str );
*/
//ここから描画
xDraw->drawTexture(textrue,300,100,200,200,0.3f);
//ここまで描画
}
//////////////////////////////////////////////////
//MovePanel.h
/////////////////////////////////////////////////
#pragma once
#include "Panel.h"
#include <d3d9.h>
#include "XDraw.h"
class MovePanel:public Panel
{
public:
MovePanel();
~MovePanel(void);
void PanelAction();
private:
XDraw* xDraw;
LPDIRECT3DTEXTURE9 textrue;
};
//////////////////////////////////////////////////
//MovePanel.cpp
/////////////////////////////////////////////////
#include "MovePanel.h"
#include <stdio.h>
MovePanel::MovePanel()
{
xDraw=new XDraw();
textrue=xDraw->LoadTexture("xFiles/移動パネル.png");
}
MovePanel::~MovePanel(void)
{
}
void MovePanel::PanelAction(void)
{
/*ここのコメントアウトを外すと正常に画像が表示される。
char str[500];
sprintf(str,"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
OutputDebugStringA( str );
*/
xDraw->drawTexture(textrue,100,100,200,200,0.3f);
}