以前投稿させていただいたのですが、いまだに解決に至らないため再掲載させていただきました。
ダイレクトx、ビジュアルC++2010エクスプレスを使用してプログラムを書いています。
ウインドウのサイズを変更した際、画像が表示される領域を一定の比率で保つようにしたのですが、
残像が残ってしまいます。
このような状態になってしまいます。(Imgurというサイトです)
中心の画像が本来描画したい画像になります。
http://imgur.com/S6YL5he.jpg
仕組みとしては、クライアント領域内のフロントバッファ表示領域をウインドウサイズの変更に応じて変化させているのですがうまくいきません。
フロントバッファ表示領域外の画像をクリアするにはどうすればいいのでしょうか。
テストチェック用の画像はこちらに用意させていただきました。(Imgurというサイトです)
宜しくお願いします。
#define NAME "DirectX勉強中"
#define INITGUID
#include <Windows.h>
#include <d3dx9.h>
#include <dsound.h>
#include <MMSystem.h>
#include <stdio.h>
// ライブラリのリンク
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"dsound.lib")
#pragma comment(lib,"winmm.lib")
HWND g_hWnd = NULL; // Window Handle
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pDEV = NULL;
D3DXVECTOR3 Position;//位置(x座標,y座標)キャラクタ
D3DXVECTOR3 haikeiPosition;//背景の座標
BYTE diKeyState[256];
LPD3DXSPRITE pSprite = NULL;
LPDIRECT3DTEXTURE9 pTexture = NULL;
LPDIRECT3DTEXTURE9 phaikeiTexture;
LPDIRECT3DTEXTURE9 MapchipTexture;
D3DXMATRIX m_Matrix;//キャラクタの行列
D3DXVECTOR2 m_vec2;//マトリックス自体の座標
RECT B_B_Area = {0,0,0,0}; //バックバッファのサイズ
RECT PaintArea ={0,0,0,0}; //フロントバッファの描画領域
D3DDISPLAYMODE d3ddm;
D3DPRESENT_PARAMETERS d3dpp;
//***********************
D3DVIEWPORT9 vp;
#define wwx 1280
#define wwy 960
//開放のための関数
#define SAFE_RELEASE(x) if(x) { x->Release(); x=NULL; }
#define DIDEVICE_BUFFERSIZE 100
RECT W_Size;//ウインドウサイズ
RECT C_Size;//クライアントサイズ
int W_BarX,W_BarY; //ウインドウバー
//初期化処理(デバイスの設定)
HRESULT Init3DDev()
{
//インターフェイスの取得
if (NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL;
//アダプタのデータを得る(数、幅、高さ、リフレッシュレート)
if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm))) return E_FAIL;
//D3DPRESENT_PARAMETERS構造体の設定
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.BackBufferWidth = wwx;
d3dpp.BackBufferHeight =wwy;
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
//デバイスの作成:CreateDeviceの実行//復元用
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pDEV)))
return E_FAIL;
return S_OK;
}
///メモリ開放処理
// DirectX Graphics の終了処理:未開放有り
void Cleanup(void)
{
SAFE_RELEASE(g_pDEV); //デバイスの開放
SAFE_RELEASE(g_pD3D); //ダイレクトxの開放
}
//ウインドウのサイズ関連の調整
void AdjustmentWindow()
{
//描画領域の指定
B_B_Area.top = 0;
B_B_Area.bottom = wwy;
B_B_Area.left = 0;
B_B_Area.right = wwx;
//描画領域の指定
PaintArea.top = 0;
PaintArea.bottom = wwy;
PaintArea.left = 0;
PaintArea.right = wwx;
//クライアント領域からウインドウサイズの調整
GetWindowRect(g_hWnd,&W_Size);//ウインドウのサイズを取得
GetClientRect(g_hWnd,&C_Size);//クライアント領域のサイズを取得
int WindowsX,WindowsY,W_X,W_Y;
//ウインドウのサイズを計算
W_X = W_Size.right - W_Size.left;
W_Y = W_Size.bottom - W_Size.top;
//ウインドウバーのサイズを計算
W_BarX = W_X - C_Size.right;
W_BarY = W_Y - C_Size.bottom;
//正しいウインドウのサイズを計算
WindowsX = W_X + W_BarX;
WindowsY = W_Y + W_BarY;
//ウインドウのサイズを代入
SetWindowPos(g_hWnd,HWND_TOP,600,300,WindowsX,WindowsY,SWP_SHOWWINDOW);
}
//バックバッファの内容を描画する領域の計算
void WindowDraw(int a,int b,int c)//WX,WY,FBArea;
{
//フロントバッファの表示領域の算出
if(a>b)
{
//領域の高さ開始位置をリセット
PaintArea.top = 0;
//領域の高さを決定
PaintArea.bottom = b;
//領域の幅を決定
c = (b/3)*4;
if(c < a)//算出されたX軸の描画範囲がウインドウよりも小さい場合
{
//領域の横開始位置を決定
PaintArea.left = (a - c)/2;
//領域の幅の開始から終点を決定
PaintArea.right = PaintArea.left + c;
}
else if(c > b)//算出されたX軸の描画範囲がウインドウよりも大きい場合
{
PaintArea.left = 0;
PaintArea.right = a;
c = (a/4)*3;
PaintArea.top = (b - c)/2;
PaintArea.bottom = PaintArea.top + c;
}
}
else if(a<b || a == b)
{
//領域の高さ開始位置をリセット
PaintArea.left = 0;
//領域の幅を決定
PaintArea.right = a;
//領域の高さを決定
c = (a/4)*3;
if(c < b)//算出されたY軸の描画範囲がウインドウよりも小さい場合
{
//領域の高さ開始位置を決定
PaintArea.top = (b - c)/2;
//領域の高さの開始から終点を決定
PaintArea.bottom = PaintArea.top + c;
}
else if(c > b)//算出されたY軸の描画範囲がウインドウよりも大きい場合
{
PaintArea.top = 0;
PaintArea.bottom = b;
c = (b/3)*4;
PaintArea.left = (a - c)/2;
PaintArea.bottom = PaintArea.right + c;
}
}
}
//ビューポートの作成
HRESULT Viewport()
{
HRESULT hr;//ハンドル
//ビューポートの作成
vp.X = 0;
vp.Y = 0;
vp.Width = wwx;
vp.Height =wwy;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
hr = g_pDEV -> SetViewport(&vp);
if(FAILED(hr))
return false;
return S_OK;
}
//テクスチャの作成
HRESULT textureCreate()
{
HRESULT hr;//ハンドル
//背景3.png
hr = D3DXCreateTextureFromFileEx(g_pDEV,"mtkfbxI.png",
wwx,wwy,1,0,
D3DFMT_UNKNOWN,D3DPOOL_MANAGED,
D3DX_DEFAULT,D3DX_DEFAULT,
D3DCOLOR_XRGB(0,0,0),
NULL,NULL,&phaikeiTexture);
if(FAILED(hr))
return false;
return S_OK;
}
//スプライトの作成
HRESULT spriteCreate()
{
HRESULT hr;//ハンドル
hr = D3DXCreateSprite(g_pDEV,&pSprite);//1.使用するデバイス、2.受け取る変数
if(FAILED(hr))
return false;
return S_OK;
}
//スプライトの描画(キャラクタ)//描画は全てこの中で行う(画像、文字)
HRESULT drawsprite()
{
HRESULT hr;//ハンドル
D3DXMatrixTransformation2D(&m_Matrix,0,0,0,NULL,0,&m_vec2);
//塗りつぶし
g_pDEV->Clear(0,NULL,(D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER),
D3DCOLOR_RGBA(100,150,255,0),1.0f,0);
g_pDEV->BeginScene();//スプライトシーンの開始---------------------
pSprite->Begin(D3DXSPRITE_ALPHABLEND|D3DXSPRITE_DONOTSAVESTATE);
hr = pSprite->SetTransform(&m_Matrix);
//背景
hr = pSprite->Draw(phaikeiTexture,NULL,NULL,&haikeiPosition,0xffffffff);
if(FAILED(hr))
return false;
pSprite->End();//スプライトを描画して終了
g_pDEV->EndScene();//シーンを終了----------------------------------
//デバイスの情報を返す
//ここでバック、フロントバッファの範囲、描画対象のウインドウなどを指定する
return g_pDEV->Present(&B_B_Area, &PaintArea, g_hWnd, NULL);
return S_OK;
}
////////////////////////////////////////////////////////////////////
/* コールバック関数関連 */
////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
switch(msg)
{
case WM_DESTROY://ウインドウの破棄
Cleanup();
PostQuitMessage(0);
break;
case WM_SIZING://ウインドウサイズの変更中
drawsprite();
InvalidateRgn(hWnd, NULL,TRUE);
return TRUE;
case WM_SIZE://ウインドウサイズの変更後
if(!g_pDEV || wParam == SIZE_MINIMIZED)
{
break;
}
if(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
{
//フロントバッファの描画位置と領域を算出
int WX,WY,FBArea;
FBArea = 0; //初期化
WX = LOWORD(lParam); //横の取得
WY = HIWORD(lParam); //縦の取得
WindowDraw(WX,WY,FBArea);//描画領域の計算
pSprite->OnLostDevice();//スプライトのロスト
g_pDEV->Reset(&d3dpp);
InvalidateRgn(hWnd, NULL,TRUE);
}
break;
case WM_KEYDOWN://キーを押す
switch(wParam)
{ case VK_ESCAPE:
DestroyWindow(hWnd);
break;
default:
diKeyState[wParam] = 1;
}
break;
case WM_KEYUP://キーを放す
diKeyState[wParam] = 0;
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
////////////////////////////////////////////////////////////////////
/* メインコード */
////////////////////////////////////////////////////////////////////
//★ WinMain()
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
//ウインドウクラスの登録
WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0,0,hInst,NULL,NULL,NULL,NULL,NAME,NULL };
if (!RegisterClassEx(&wc)) return FALSE;
//メインウインドウ
g_hWnd= CreateWindowEx(0,NAME,NAME,WS_OVERLAPPEDWINDOW,600,300,640,480,NULL,NULL,hInst,NULL);
if (!g_hWnd) return FALSE;
// DirectX Graphics の初期化
if (FAILED(Init3DDev())) return FALSE;
// ウインドウ表示
ShowWindow(g_hWnd, SW_SHOWNORMAL);
UpdateWindow(g_hWnd);
//ウインドウサイズ等の調整
AdjustmentWindow();
ZeroMemory(&msg,sizeof(msg));
//背景の位置のセット
haikeiPosition.x = 0.0f;
haikeiPosition.y = 0.0f;
//描画関連
textureCreate();//テクスチャの作成
spriteCreate();//スプライトの作成
Viewport();//ビューポートの作成
//ループ
while(msg.message!=WM_QUIT)
{
//プロシージャ
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
drawsprite();
}
}
UnregisterClass(NAME, hInst);
return TRUE;
}