In the code below i wanted to display an image or some pixels by using surface and backbuffer.
It compiles correctly but gives a run-time error when reach to GetSurfaceLevel or LockRect.
The code:
#include <d3d9.h>
#include <windows.h>
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DSURFACE9 surf,back;
D3DLOCKED_RECT lock ;
IDirect3DTexture9* texture = NULL;
HRESULT InitD3D( HWND );
HRESULT InitVB();
VOID Cleanup();
VOID Render();
LRESULT WINAPI MsgProc( HWND , UINT , WPARAM , LPARAM );
//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
UNREFERENCED_PARAMETER( hInst );
// Register the window class
WNDCLASSEX wc =
{
sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
"D3D Tutorial", NULL
};
RegisterClassEx( &wc );
// Create the application's window
HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
WS_OVERLAPPEDWINDOW, 100, 100, 320, 240,
NULL, NULL, wc.hInstance, NULL );
// Initialize Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) ){
// Create the vertex buffer
if( SUCCEEDED( InitVB() ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
printf("4");
Render();
printf("5");
// Enter the message loop
MSG msg;
ZeroMemory( &msg, sizeof( msg ) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
}
UnregisterClass( "D3D Tutorial", wc.hInstance );
return 0;
}
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
// Create the D3D object.
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
d3dpp.hDeviceWindow = hWnd;
// Create the D3DDevice
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
// Device state would normally be set here
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitVB()
// Desc: Creates a vertex buffer and fills it with our vertices. The vertex
// buffer is basically just a chuck of memory that holds vertices. After
// creating it, we must Lock()/Unlock() it to fill it. For indices, D3D
// also uses index buffers. The special thing about vertex and index
// buffers is that they can be created in device memory, allowing some
// cards to process them in hardware, resulting in a dramatic
// performance gain.
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
typedef struct {char r,g,b;}st;
g_pd3dDevice->CreateTexture(320,240,0,0,D3DFMT_R8G8B8,
D3DPOOL_MANAGED,&texture,NULL);
g_pd3dDevice->CreateOffscreenPlainSurface(4,4,D3DFMT_R8G8B8
,D3DPOOL_MANAGED,&surf,NULL);
texture->GetSurfaceLevel(0,&surf);
surf->LockRect(&lock,NULL,0);
st st3[]={{0,0,255,},{0,255,0,},{255,0,0,},{127,127,127,},
{255,0,0,},{0,0,255,},{127,127,127,},{0,255,0,},
{0,255,0,},{127,127,127,},{255,0,0,},{0,0,255},
{127,127,127,},{255,0,0,},{0,255,0,},{255,0,0,},
};
void *b,*c;
b=(void *)st3;
c=(void *)lock.pBits;
memcpy(c, b, sizeof(st3));
surf->UnlockRect();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
// Clear the backbuffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 10, 10, 10 ), 1.0f, 0 );
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&back);
g_pd3dDevice->UpdateSurface(surf, NULL, back, NULL);
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
Related
On Code::Blocks 13.12, I used the wizard to create a DX9 project by starting a new project. I specified the DX folder and it doesn't complain. An auto-generated .cpp appears and it's set to GUI application, file is not set to read-only mode, and I hit compile:
||=== Build: Debug in xxxxxxxx (compiler: GNU GCC Compiler) ===|
c:\program files\codeblocks\mingw\bin..\lib\gcc\mingw32\4.7.1......\libmingw32.a(main.o):main.c:(.text.startup+0xa7)||undefined reference to `WinMain#16'|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|
Here's the full code that's auto-generated:
#include <windows.h>
#include <d3d9.h>
#define NOMINMAX
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
HRESULT InitD3D( HWND hWnd )
{
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
return S_OK;
}
VOID Cleanup()
{
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
VOID Render()
{
if( NULL == g_pd3dDevice )
return;
// Clear the backbuffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Rendering of scene objects can happen here
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
// Register the window class
WNDCLASSEX wc =
{
sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0, 0,
GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
"D3D Tutorial", NULL
};
RegisterClassEx( &wc );
// Create the application's window
HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: CreateDevice",
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
NULL, NULL, wc.hInstance, NULL );
// Initialize Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
// Enter the message loop
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
UnregisterClass( "D3D Tutorial", wc.hInstance );
return 0;
}
Before the same questions are asked before in answers where this may have been solved, here's what's been tried:
1.Restarted Code::Blocks; still gives the same error.
2.Tried GUI and console; still gives the same error.
3.Tried with a blank application; still gives the same error.
4.Tried with a Windows GUI application; still gives the same error.
I am guaranteed that the DX SDK is setup and the runtime is up-to-date and everything else of the related such. Any other suggestions to this issue?
Replace this Microsoft monstrosity:
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
with this standard C++ code:
int main()
That's it.
Your code appears to already be written for a standard main, e.g. you're using GetModuleHandle( 0 ) instead of the hInst from wWinMain.
If you want UTF-16 encoded process command line, just call GetCommandLine, and possibly CommandLineToArgvW (IIRC) to parse it. MinGW-64 does support wmain, via a special option. But with the two functions mentioned you can implement the wmain support in five to six lines of code, so it doesn't really matter, and I'd rather write the code than using an obscure option.
I'm making a simple text editor win32 application for fun. I'm having a peculiar problem with my program. It seems that my program is not returning zero when it exits. Instead, it is returning 1385929. When my main GUI window is destroyed, I use PostQuitMessage( 0 ), but it seems that is not what is being returned in my main function's message.wParam. Here is my code thus far,
#define WIDTH 500
#define HEIGHT 400
#define EDIT_ID 10
LRESULT CALLBACK windowProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
{
static HDC deviceContext = INVALID_HANDLE_VALUE;
static HWND editControl = INVALID_HANDLE_VALUE;
switch ( message )
{
case WM_CREATE :
deviceContext = GetDC( window );
if ( !deviceContext )
{
showWindowsError( "Creating Device Context", FALSE );
DestroyWindow( window );
}
editControl = CreateWindow(
"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL,
0,
0,
0,
0,
window,
( HMENU )EDIT_ID,
( HINSTANCE )GetWindowLong( window, GWL_HINSTANCE ),
NULL
);
if ( !editControl )
{
showWindowsError( "Creating Edit Control", TRUE );
DestroyWindow( window );
}
return 0;
break;
case WM_COMMAND :
switch ( wParam )
{
case WM_UNDO :
SendMessage( editControl, WM_UNDO, 0, 0 );
break;
case WM_CUT :
SendMessage( editControl, WM_CUT, 0, 0 );
break;
case WM_COPY :
SendMessage( editControl, WM_COPY, 0, 0 );
break;
case WM_PASTE :
SendMessage( editControl, WM_PASTE, 0, 0 );
break;
case WM_CLEAR :
SendMessage( editControl, WM_CLEAR, 0, 0 );
break;
default:
return DefWindowProc( window, message, wParam, lParam );
}
case WM_SIZE :
MoveWindow( editControl, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
return 0;
break;
case WM_DESTROY :
ReleaseDC( window, deviceContext );
DestroyWindow( editControl );
PostQuitMessage( 0 );
return 0;
break;
}
return DefWindowProc( window, message, wParam, lParam );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
{
WNDCLASSEX windowClass = { 0 };
HWND window = INVALID_HANDLE_VALUE;
MSG message = { 0 };
HBRUSH windowColor = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
windowClass.cbSize = sizeof( windowClass );
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
windowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
windowClass.hbrBackground = windowColor;
windowClass.lpszClassName = "TextEditorWindow";
if ( !RegisterClassEx( &windowClass ) )
{
DeleteObject( windowColor );
showWindowsError( "Registering Windows Class", TRUE );
}
window = CreateWindow(
"TextEditorWindow",
"Text Editor",
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if ( !window )
{
DeleteObject( windowColor );
showWindowsError( "Creating GUI", TRUE );
}
ShowWindow( window, SW_SHOW );
UpdateWindow( window );
do
{
TranslateMessage( &message );
DispatchMessage( &message );
} while ( GetMessage( &message, window, 0, 0 ) > 0 );
DeleteObject( windowColor );
return message.wParam;
}
Your call to GetMessage() has the 2nd parameter set to your window's HWND, which limits the messages received only to those sent to that window - see the documentation of the API function.
WM_QUIT is, on the other hand, a message sent to the thread running the message pump, without any particular window. Because of that filter, you don't receive it and message.wParam is never set to that 0.
But why does the loop end and the program shuts down anyway? Because that HWND in window gets invalid after the window is closed, therefore GetMessage() ends with an error and returns -1.
Additionally, you are currently calling TranslateMessage() and DispatchMessage() with message before it is filled with any correct data, on the first iteration. The loop should rather be like this:
while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &message );
DispatchMessage( &message );
}
My compiler codeblocks gives me the following error when I try to compile my code:
c:\blah.cpp|67|error: 'SetLayeredWindowAttributes' was not declared in this scope
I am including windows.h so I don't see why this would happen. Here is the full code:
// main.cpp : Defines the entry point for the application. //
#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"
#include <windows.h>
#include <string>
#include <stdio.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 //----------------------------------------------------------------------------- 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 ); SetLayeredWindowAttributes(GetActiveWindow(), NULL, 255, LWA_ALPHA); //---------------------------------------------------------------- // 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\\45handold2.tga", // 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 ) { 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: {
RenderFrame(); 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, HWND_DESKTOP,
dwBehaviorFlags, &d3dpp, &g_pD3DDevice ) ) ) { // char blah[100];
// snprintf (blah, 1000, "%d", hr); //MessageBox (NULL,blah,NULL,NULL); }
// 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 );
}
You need to add #define _WIN32_WINNT 0x0501 before including windows.h, as SetLayeredWindowAttributes is only declared when _WIN32_WINNT >= 0x0500.
After figuring out how to draw a sprite and examining the possible parameters for each function and some extensive googling I can't find out how to draw to the desktop, can someone point me in the right direction?
EDIT: Here is what I have tried already and what happened, I am using the following code as a learning point for my program:
// main.cpp : Defines the entry point for the application.
//
#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"
#include <windows.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
//-----------------------------------------------------------------------------
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\\45handold2.tga", // 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 )
{
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:
{
RenderFrame();
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 ) ) )
{
MessageBox (NULL,NULL,NULL,NULL);
}
// 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 );
}
I have tried changing the parameter g_hWnd in the CreateDevice method to HWND_DESKTOP, I figured it would work since you can draw directly to the desktop by drawing to HWND_DESKTOP in GDI, unfortunately this simply resulted in the CreateDevice method failing. I looked into the IDirect3D9 class methods for some way to make a device context with HWND_DESKTOP similar to GDI because I suspected that's how I should go about finding a way to draw to the desktop. No luck, I've of course done the obvious google search "how to draw to desktop DirectX"(and various other combinations of the same question) in hopes to find an answer but nothing seems to be turning up, the closest thing I've found is someone drawing a transparent window and drawing the desired contents on top of that window but I thought there's probably a more elegant solution.
I have supplied my DirectX project: http://www.planetchili.net/forum/download/file.php?id=830
It has to be something simple but I just don't know the API well enough to find out where the problem is...
I think the following will help:
class D3DGraphics
{
public:
D3DGraphics( HWND hWnd );
~D3DGraphics();
void Begin();
void End();
void Present();
LPDIRECT3D9 d3dObject;
LPDIRECT3DDEVICE9 d3dDevice;
D3DPRESENT_PARAMETERS presParams;
HRESULT hr;
};
I declare a D3DGraphics class that starts up my object and device:
D3DGraphics::D3DGraphics( HWND hWnd )
:
d3dObject( NULL ),
d3dDevice( NULL )
{
ZeroMemory( &presParams, sizeof( presParams ) );
presParams.Windowed=TRUE;
presParams.SwapEffect=D3DSWAPEFFECT_DISCARD;
presParams.BackBufferFormat=D3DFMT_UNKNOWN;
presParams.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
d3dObject = Direct3DCreate9( D3D_SDK_VERSION );
hr = d3dObject->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&presParams,
&d3dDevice
);
};
My WindowsAPI is creating an instance of a Game class I have made which has constructor declared:
HWND hWnd = CreateWindow("MyWindowClass", "Pubes", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
Game theGame = Game( hWnd );
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
theGame.Go();
}
}
And finally here is my game class that is mucking up on the constructor as it can't create the sprite mentioned in the first block of code, here it is in full:
Game::Game( HWND hWnd )
:
gfx( hWnd )
{
sprite = NULL;
if ( SUCCEEDED( D3DXCreateSprite( gfx.d3dDevice, &sprite ) ) )
{
// returns s_OK
}
pos.x=10.0f;
pos.y=20.0f;
pos.z=0.0f;
gTexture = NULL;
if ( SUCCEEDED( D3DXCreateTextureFromFile( gfx.d3dDevice, "Images/character001.png", &gTexture ) ) )
{
// returns s_OK
}
gfx.d3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
};
Game::~Game()
{
sprite->Release();
gTexture->Release();
};
void Game::Go()
{
gfx.Begin();
ComposeFrame();
gfx.Present();
gfx.End();
};
gfx is an instance of D3DGraphics declared in my Game class header.
gosh, you guys got any idea as to why my sprite isn't being rendered at all?
//Extra notes: I'm getting this in my output, this may have something to do with it??
My hWnd variable containing a handle to my window:
HWND hWnd = CreateWindow("MyWindowClass", "Pubes", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
Game theGame = Game( hWnd );
says:
- hWnd 0x000e0682 {unused=??? } HWND__ *
unused <Unable to read memory>
gfx.Begin();
ComposeFrame();
gfx.End();
gfx.Present();
I was presenting before ending the scene!!!
YIPEEEE