所以我试图学习如何在directX中制作一个精灵并下载一个示例文件,但是这个例子中有一个我无法克服的错误,必须知道如何修复,每当附加到窗口的精灵是移出屏幕并返回到屏幕上移出的精灵部分,直到我松开鼠标左键才重新绘制。我阅读了RenderFrame()
函数中的所有内容,希望找到一些改变但没有成功的设置。
Here是问题的示例动画(由于某些奇怪的原因,我找不到任何因我的视频没有502错误的文件共享服务。)
以下是源代码:
// main.cpp : Defines the entry point for the application.
//
#include <windows.h>
#include "C:\Program Files\Microsoft DirectX SDK (August 2008)\Include\D3dx9core.h"
#include "C:\Documents and Settings\Death\My Documents\Downloads\DXSprite\DXSprite\resource.h"
//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HWND g_hWnd = NULL;
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
ID3DXSprite * g_pD3DXSprite = NULL;
LPDIRECT3DTEXTURE9 g_pTexture = NULL;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT InitializeD3D ( );
void RenderFrame ( );
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
WNDCLASSEX winClass;
MSG uMsg;
HRESULT hr;
memset(&uMsg,0,sizeof(uMsg));
winClass.lpszClassName = "MY_WINDOWS_CLASS";
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc = WindowProc;
winClass.hInstance = hInstance;
winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDC_DXSPRITE);
winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDC_DXSPRITE);
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
if( !RegisterClassEx(&winClass) )
return E_FAIL;
g_hWnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
"Direct3D 9 - ID3DXSprite Example",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL );
if( g_hWnd == NULL )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
UpdateWindow( g_hWnd );
//----------------------------------------------------------------
// Create the DirectX device
//----------------------------------------------------------------
if (FAILED( InitializeD3D()))
return 0;
//----------------------------------------------------------------
// CREATE THE ID3DXSprite
//----------------------------------------------------------------
// Create the ID3DXSprite interface object
hr = D3DXCreateSprite(g_pD3DDevice, &g_pD3DXSprite );
if( FAILED(hr) )
return hr;
//----------------------------------------------------------------
// LOAD THE TEXTURE FOR THE SPRITE
//----------------------------------------------------------------
// --------------------------------------------------------
// Load the texture. I decided to use the extended
// version of the texture loading function just to show what
// it would look like.
// The texture was created with Photoshop with a transparent
// background to start with. Then line cross hairs were added.
//
// Note - If you don't use a texture image that has a power of
// 2 size for the width or height then the image may not load
// properly. This image is 256x256.
//
D3DXCreateTextureFromFileEx(
g_pD3DDevice,
"C:\\Documents and Settings\\Death\\My Documents\\Downloads\\DXSprite\\DXSprite\\sarah.jpg", // Our texture image!
D3DX_DEFAULT, // width
D3DX_DEFAULT, // height
D3DX_DEFAULT, // MIP levels
0, // usage
D3DFMT_DXT1, // texture format
D3DPOOL_MANAGED, // mem pool
D3DX_DEFAULT, // filter
D3DX_DEFAULT, // MIP filter
0, // transparent color key
NULL, // image info struct
NULL, // palette
&g_pTexture); // the returned texture, if success
if ( FAILED(hr) )
return hr;
// ---------
// Main Loop
// ---------
while( uMsg.message != WM_QUIT )
{
RenderFrame();
if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &uMsg );
DispatchMessage( &uMsg );
}
}
// -------------------------
// Release directx resources
// -------------------------
if (g_pD3DXSprite)
{
g_pD3DXSprite->Release();
g_pD3DXSprite = NULL;
}
if (g_pTexture)
{
g_pTexture->Release();
g_pTexture = NULL;
}
if (g_pD3DDevice)
{
g_pD3DDevice->Release();
g_pD3DDevice = NULL;
}
UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );
return (int)uMsg.wParam;
}
//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;
case WM_CLOSE:
{
PostQuitMessage(0);
}
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc( hWnd, msg, wParam, lParam );
}
break;
}
return 0;
}
//-----------------------------------------------------------------------------
// Name: InitializeD3D()
// Desc: Create DirectX interface objects
// Initialize the view matrix.
// Setup render states that will not need changing throughout
// the life of the application.
//-----------------------------------------------------------------------------
HRESULT InitializeD3D( )
{
HRESULT hr;
// Create a direct 3D interface object
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
if( g_pD3D == NULL )
{
// TO DO: Respond to failure of Direct3DCreate9
return E_FAIL;
}
D3DDISPLAYMODE d3ddm;
if( FAILED( hr = g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
{
// TO DO: Respond to failure of GetAdapterDisplayMode
return hr;
}
//
if( FAILED( hr = g_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
d3ddm.Format, D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
if( hr == D3DERR_NOTAVAILABLE )
// POTENTIAL PROBLEM: We need at least a 16-bit z-buffer!
return hr;
}
//
// Do we support hardware vertex processing? If so, use it.
// If not, downgrade to software.
//
D3DCAPS9 d3dCaps;
if( FAILED( hr = g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, &d3dCaps ) ) )
{
// TO DO: Respond to failure of GetDeviceCaps
return hr;
}
DWORD dwBehaviorFlags = 0;
if( d3dCaps.VertexProcessingCaps != 0 )
dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
//
// Everything checks out - create a simple, windowed device.
//
D3DPRESENT_PARAMETERS d3dpp;
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.Windowed = TRUE;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Attempt to create a HAL device, end app on failure just to keep things
// simple. In other words we are not trying to create a REF device if the
// HAL fails.
if( FAILED( hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
dwBehaviorFlags, &d3dpp, &g_pD3DDevice ) ) )
{
// Should respond to failure of creating the hardware device.
return hr;
}
// If we get here everything worked!
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RenderFrame()
// Desc: Draw the image to the framebuffer.
//-----------------------------------------------------------------------------
void RenderFrame( )
{
if (!g_pD3DDevice && !g_pD3DXSprite && !g_pTexture)
return;
// Clear the frame & depth buffer ready for drawing (Black color)
g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0 );
g_pD3DDevice->BeginScene();
{
//-------------------------
// Render the sprite
//
D3DXVECTOR3 vecPos = D3DXVECTOR3(0,0,0);
if (g_pD3DXSprite && g_pTexture)
{
g_pD3DXSprite->Begin( D3DXSPRITE_ALPHABLEND );
g_pD3DXSprite->Draw(g_pTexture, NULL, NULL, &vecPos, 0xffffffff);
g_pD3DXSprite->End();
}
}
g_pD3DDevice->EndScene();
// Frame buffer to Front buffer
g_pD3DDevice->Present( NULL, NULL, NULL, NULL );
}
答案 0 :(得分:1)
This answer也是您问题的答案。通过使用此代码(#include <ctime>
)输出循环中的当前时间,您可以在拖动窗口时验证消息循环未运行:
// ---------
// Main Loop
// ---------
while( uMsg.message != WM_QUIT )
{
std::time_t time = std::time(0);
OutputDebugStringA(ctime(&time));
// ...
以下是答案:
Windows上会发生许多模态操作。 Win32模态操作指的是通过启动自己的事件处理循环将应用程序置于“模式”直到模式完成的函数。常见的应用程序模式包括拖放操作,移动/大小操作,在应用程序可以继续之前弹出需要输入的对话框。
所以发生的事情是:你的消息循环没有被运行。您的窗口收到了传递给DefWindowProc的WM_LBUTTONDOWN消息。 DefWindowProc确定用户正在尝试以交互方式调整窗口大小或移动窗口并输入大小/移动模态函数。此功能在消息处理循环中查看鼠标消息,以便它可以拦截它们以提供交互式大小调整体验,并且仅在调整大小操作完成时退出 - 通常是通过用户释放保持按钮或按下escape。 / p>
您收到通知 - DefWindowProc在进入和退出模态事件处理循环时发送WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE消息。
要继续生成“空闲”消息,通常在调用模态函数之前创建一个计时器(SetTimer) - 或者当收到DefWindowProc正在进入模态函数的消息时 - 模态循环将继续调度WM_TIMER消息...并从定时器消息处理程序调用idle proc。当模态函数返回时销毁计时器。
原始答案:
我看到一些显示此行为的DX应用程序和一些不显示此行为的DX应用程序。不仅仅是精灵,而且从屏幕外拖出的整个矩形都是黑色的。这意味着它是一个窗口重绘问题。
尝试在WindowProc中拦截WM_MOVING并调用RedrawWindow
答案 1 :(得分:0)
当你用DirectX / OpenGL / GDI +覆盖Win32窗口时,你忽略了GDI绘画。从屏幕拖出一个窗口会将WM_PAINT和WM_ERASEBKGND消息发送到离开屏幕的窗口区域。 WM_ERASEBKGND会覆盖ID3DXSprite,将区域清除为窗口类的hbrBackground成员。
修复: 将WNDCLASS(EX)中的hbrBackground设置为 GetStockObject(NULL_BRUSH)。可以这么说,空刷是一个'空'刷子。它会导致WM_ERASEBKGND消息被忽略,从而阻止精灵被删除。
<强>代码:强>
winClass.lpszClassName = "MY_WINDOWS_CLASS";
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc = WindowProc;
winClass.hInstance = hInstance;
winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDC_DXSPRITE);
winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDC_DXSPRITE);
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
其他一切都保持不变。 :)