またよろしくお願い致します。
コールバック関数にWM_SIZINGを記述したのですがメッセージが送られません。
環境はVisualC++2010Express、ウインドウズ7です。
コード内容は、ウインドウのサイズを変更した場合、4:3のアスペクト比を保つ様にフロントバッファへの描画領域を変更するといったものです。
チェックのためにWM_SIZE,WM_SIZINGを通るたびにキャラクターの座標が初期位置に戻るようにしたのですが、WM_SIZINGを通っていないようです。
コード内の255,256行目がWM_SIZING、
327,328行目がWM_SIZEを通った場合、キャラクターの座標をリセットする記述です。
WM_SIZE内の記述を無効にすると、ウインドウをリサイズしてもキャラクターの位置がリセットされません。
作業環境がWM_SIZINGに対応していないのではないかと思ったのですが、カーソルを当てると
「#define WM_SIZING 0x0214」と表示されるので非対応というわけではなさそうです。
お手数ですが解決策をご教授いただけたらと思います。
#define NAME "DirectX勉強中"
#define INITGUID
#include <Windows.h>
#include <d3dx9.h>
// ライブラリのリンク
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"dxguid.lib")
//開放のための関数
#define SAFE_RELEASE(x) if(x) { x->Release(); x=NULL; }// #define & 構造体の定義
#define DIDEVICE_BUFFERSIZE 100 // デバイスに設定するバッファ・サイズ
//アプリケーション情報
//HINSTANCE hInstApp; //アプリケーションのインスタンスハンドル
HWND g_hWnd = NULL; // Window Handle
LPDIRECT3D9 g_pD3D = NULL; //インターフェイスの取得のためのポインタの作成(構造体)
LPDIRECT3DDEVICE9 g_pDEV = NULL; // 描写用デバイス(インターフェイス)
//デバイス(装置、外部周辺機器)関連を管理するインターフェイス
LPDIRECT3DTEXTURE9 pTexture;//キャラクタのテクスチャハンドル
LPDIRECT3DTEXTURE9 phaikeiTexture;//背景のテクスチャハンドル
LPD3DXSPRITE pSprite;//スプライトハンドル
D3DXMATRIX m_Matrix;//キャラクタの行列
D3DXVECTOR2 m_vec2;//マトリックス自体の座標
D3DXVECTOR3 Position;//位置(x座標,y座標)キャラクタ
D3DXVECTOR3 haikeiPosition;//背景の座標
D3DDISPLAYMODE d3ddm;//画面モード
D3DPRESENT_PARAMETERS d3dpp;//インターフェイスの取得のためのポインタの作成 描画デバイスのパラメータ?
D3DVIEWPORT9 vp; //ビューポートのハンドル
BYTE diKeyState[256];//キーボード・デバイス定数の状態を設定
RECT B_B_Area;//バックバッファのサイズ
RECT PaintArea;//フロントバッファの描画領域
RECT W_Size;//ウインドウサイズ
RECT C_Size;//クライアントサイズ
D3DRECT Windowsize;//クリアメソッド用のウインドウサイズ取得レクト
//テクスチャの作成
HRESULT textureCreate()
{
HRESULT hr;//ハンドル
hr = D3DXCreateTextureFromFileEx(g_pDEV,"player.png",0,0,1,0,
D3DFMT_UNKNOWN,D3DPOOL_MANAGED,
D3DX_DEFAULT,D3DX_DEFAULT,
D3DCOLOR_XRGB(0,0,0),NULL,NULL,
&pTexture);
if(FAILED(hr))
return false;
hr = D3DXCreateTextureFromFileEx(g_pDEV,"背景2.png",
640,480,1,0, //usage
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,&Windowsize,
(D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER),
D3DCOLOR_RGBA(100,100,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);
//キャラクタ
hr = pSprite->Draw(pTexture,NULL,NULL,&Position,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;
}
//初期化処理(デバイスの設定)
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 = 640;//バックバッファサイズの指定
d3dpp.BackBufferHeight =480;//バックバッファサイズはウインドウサイズに引き伸ばされる?
d3dpp.Windowed = TRUE; // ウィンドウモード
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;//D3DSWAPEFFECT_DISCARD; // 映像信号に同期してフリップする
d3dpp.BackBufferFormat = d3ddm.Format;// カラーモードの指定
d3dpp.EnableAutoDepthStencil = TRUE; // デプスバッファ(Zバッファ)とステンシルバッファを作成
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // デプスバッファとして16bitを使う
//デバイスの作成:CreateDeviceの実行//復元用
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pDEV)))
return E_FAIL;
return S_OK;
}
//ビューポートの作成
HRESULT Viewport()//ビューポートはクライアント領域内の描画領域のこと。デバイスの描画領域とは無関係
{
HRESULT hr;//ハンドル
//ビューポートの作成
vp.X = 0;
vp.Y = 0;
vp.Width = 640;//PaintArea.right;//d3dpp.BackBufferWidth;
vp.Height =480;// PaintArea.bottom;//d3dpp.BackBufferHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
hr = g_pDEV -> SetViewport(&vp);
if(FAILED(hr))
return false;
return S_OK;
}
// DirectX Graphics の終了処理:未開放有り
void Cleanup(void)
{
SAFE_RELEASE(g_pDEV);
SAFE_RELEASE(g_pD3D);
}
//画像の移動//これでプレイヤー画像を動かす
HRESULT idou()
{
if(diKeyState[VK_RIGHT])
{
Position.x += 5.0f;
}
else if(diKeyState[VK_LEFT])
{
Position.x -= 5.0f;
}
else if(diKeyState[VK_DOWN])
{
Position.y += 5.0f;
}
else if(diKeyState[VK_UP])
{
Position.y -= 5.0f;
}
return S_OK;
}
void Action()
{
idou();
drawsprite();
}
//ウインドウのサイズ関連の調整
void AdjustmentWindow()
{
//描画領域の指定
B_B_Area.top = 0;
B_B_Area.bottom = 480;
B_B_Area.left = 0;
B_B_Area.right = 640;
//描画領域の指定
PaintArea.top = 0;
PaintArea.bottom = 480;
PaintArea.left = 0;
PaintArea.right = 640;
//クライアント領域からウインドウサイズの調整
GetWindowRect(g_hWnd,&W_Size);//ウインドウのサイズを取得
GetClientRect(g_hWnd,&C_Size);//クライアント領域のサイズを取得
//ウインドウバーの計算
int WindowsX,WindowsY,W_BarX,W_BarY,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);
}
// ウィンドウ処理(自分で処理したときは 0 を返す)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
switch(msg)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
break;
case WM_SIZING:
Position.x= 0.0f;
Position.y= 0.0f;
break;
case WM_SIZE:
if(!g_pDEV || wParam == SIZE_MINIMIZED)
{
break;
}
if(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
{
//フロントバッファの描画位置と領域を算出
int WX,WY,FBArea;
WX = LOWORD(lParam);
WY = HIWORD(lParam);
if(WX>WY)
{
//領域の高さ開始位置をリセット
PaintArea.top = 0;
//領域の高さを決定
PaintArea.bottom = WY;
//領域の幅を決定
FBArea = (WY/3)*4;//③
if(FBArea < WX)//算出されたX軸の描画範囲がウインドウよりも小さい場合
{
//領域の横開始位置を決定
PaintArea.left = (WX - FBArea)/2;
//領域の幅の開始から終点を決定
PaintArea.right = PaintArea.left + FBArea;
}
else if(FBArea > WX)//算出されたX軸の描画範囲がウインドウよりも大きい場合
{
PaintArea.left = 0;
PaintArea.right = WX;
FBArea = (WX/4)*3;
PaintArea.top = (WY - FBArea)/2;
PaintArea.bottom = PaintArea.top + FBArea;
}
}
else if(WX<WY)
{
//領域の高さ開始位置をリセット
PaintArea.left = 0;
//領域の幅を決定
PaintArea.right = WX;
//領域の高さを決定
FBArea = (WX/4)*3;//③
if(FBArea < WY)//算出されたY軸の描画範囲がウインドウよりも小さい場合
{
//領域の高さ開始位置を決定
PaintArea.top = (WY - FBArea)/2;
//領域の高さの開始から終点を決定
PaintArea.bottom = PaintArea.top + FBArea;
}
else if(FBArea > WY)//算出されたY軸の描画範囲がウインドウよりも大きい場合
{
PaintArea.top = 0;
PaintArea.bottom = WY;
FBArea = (WY/3)*4;
PaintArea.left = (WX - FBArea)/2;
PaintArea.bottom = PaintArea.right + FBArea;
}
}
//クリアメソッドの範囲設定
Windowsize.x2 = LOWORD(lParam);
Windowsize.y2 = HIWORD(lParam);
Position.x= 0.0f;
Position.y= 0.0f;
pSprite->OnLostDevice();//スプライトのロスト
g_pDEV->Reset(&d3dpp);
InvalidateRect(hWnd, &PaintArea,TRUE);//第二引数にRECTを指定し、フロントバッファの描画範囲を指定
}
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;
//hInstApp=hInst;
//ウインドウクラスの登録
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,//デスクトップ上のx、y、幅、高さ
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));
//描画関連
textureCreate();//テクスチャの作成
spriteCreate();//スプライトの作成
Viewport();//ビューポートの作成
//画像の初期位置のセット
Position.x = 0.0f;
Position.y = 0.0f;
//背景の位置のセット
haikeiPosition.x = 0.0f;
haikeiPosition.y = 0.0f;
//クリアメソッド用のサイズ
Windowsize.x1 = 0;
Windowsize.y1 = 0;
Windowsize.x2 = 640;
Windowsize.y2 = 480;
//ループ
while(msg.message!=WM_QUIT)
{
//プロシージャ
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Action();
}
}
UnregisterClass(NAME, hInst);
return TRUE;
}