#include <windows.h> //include windows header for some function like MessageBox, creating the window.
#include "d3dx9.h" //include a directx header
#include <stdio.h> //for the sprinf_s function used by DrawString
#pragma comment(lib, "d3dx9.lib") //link the library
#pragma comment(lib, "d3d9.lib") //link the library
#define Emsg(msg){MessageBox(NULL,msg,"Error",MB_OK|MB_ICONEXCLAMATION);} //macro for error pop-up
int WINDOW_WIDTH = 1024; //window width
int WINDOW_HEIGHT = 768; //window height
bool windowed = true; //window mode, change to false for full screen
IDirect3D9 *pD3D; //global variable that will be used by a couple of our function
IDirect3DDevice9 *pDevice; //a device that will be used for msot of our function created inside *pD3D
LPD3DXFONT pFont; //font variable to use with our create font function and to display text after
LPDIRECT3DTEXTURE9 imagetex; //textute our image will be loaded into
LPD3DXSPRITE sprite; //sprite to display our image
D3DXVECTOR3 imagepos; //vector for the position of the sprite
LRESULT CALLBACK wndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) //callback function for our GetMessage function on the while statement inside the main function
{
switch(uMsg) //switch the MSG variable passed
{
case WM_CLOSE: //case it's a Window Close MSG
PostQuitMessage(0); //Apply a Quit Message
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam); //pass the variable
}
HRESULT initialize()
{
if(FAILED(D3DXCreateTextureFromFile(pDevice,"test.png",&imagetex)))//first parameter is our device,second is the path to our image, third is a texture variable to load the image into
{
Emsg("Failed to laod the image"); //error pop-up for debug purpose
return E_FAIL; //return it failed
}
if(FAILED(D3DXCreateSprite(pDevice,&sprite)))//first parameter is our device, second is a empty sprite variable
{
Emsg("Failed to create the sprite"); //error pop-up for debug purpose
return E_FAIL; //return it failed
}
imagepos.x=8.0f; //coord x of our sprite
imagepos.y=18.0f; //coord y of out sprite
imagepos.z=0.0f; //coord z of out sprite
return S_OK;
}
HRESULT render() //function where all Drawing/Render stuff go
{
if(SUCCEEDED(pDevice->BeginScene())) //Call the BeginScene function with our Device and see if it succeeded, all drawing/render code go behind BeginScene and EndScene
{
sprite->Begin(D3DXSPRITE_ALPHABLEND); //begin our sprite with alphablend so it support alpha, like png use alpha
sprite->Draw(imagetex,NULL,NULL,&imagepos,0xFFFFFFFF); //Draw the sprite, first parameter is the image texture, 4th parameter is the position, last parameter is the color change leave to 0xFFFFFFFF for no change
sprite->End(); //end the sprite
pDevice->EndScene(); //Call the EndScene function with our Device
return S_OK; //return it succeeded
}
return E_FAIL; //return it failed
}
void CleanUp() //function to delete/release things to prevent memory leak
{
if(pD3D) //check if pD3D ism't released
pD3D->Release(); //release it
if(pDevice) //check if pDevice ism't released
pDevice->Release(); //release it
if(sprite) //check if sprite ism't released
sprite->Release(); //release it
if(imagetex) //check if imagetex ism't released
imagetex->Release(); //release it
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) //our main function the first function called of the program
{
WNDCLASSEX wc; //window class won't go in detail not related to this tutorial really
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)wndProc;
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "D3DTEST"; //class name
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
RECT rect; //window rectangle
rect.top = (long)0;
rect.left = (long)0;
rect.right = WINDOW_WIDTH; //use our global WINDOW_WIDTH variable
rect.bottom = WINDOW_HEIGHT; //use our global WINDOW_HEIGHT variable
if(!RegisterClassEx(&wc)) //register the window cs
{
Emsg("Could not register window class"); //error pop-up for debug purpose
return 1; //return error
}
AdjustWindowRectEx(&rect,WS_OVERLAPPEDWINDOW,false,WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); //set the window width and height with the rect above
//the D3DTEST must match the class name of the window class and D3D TEST is the window name
HWND hWindow = CreateWindowEx(NULL,"D3DTEST","D3D TEST",WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW,0,0,rect.right-rect.left,rect.bottom-rect.top,NULL,NULL,hInstance,NULL); //create the window
if(!hWindow) //if the window failed to create
{
DestroyWindow(hWindow); //destroy the window
UnregisterClass("D3DTEST",hInstance); //unregister our window class
Emsg("Failed to create the window"); //error pop-up for debug purpose
return 1; //return error
}
ShowWindow(hWindow,SW_SHOW); //show our window
UpdateWindow(hWindow); //update our window
SetForegroundWindow(hWindow); //set our window on top
SetFocus(hWindow); //set the focus on our window
D3DPRESENT_PARAMETERS d3dpp; //the presentation parameters that will be used when we will create the device
ZeroMemory(&d3dpp,sizeof(d3dpp)); //to be sure d3dpp is empty
d3dpp.Windowed = windowed; //use our global windowed variable to tell if the program is windowed or not
d3dpp.hDeviceWindow = hWindow; //give the window handle of the window we created above
d3dpp.BackBufferCount = 1; //set it to only use 1 backbuffer
d3dpp.BackBufferWidth = WINDOW_WIDTH; //set the buffer to our window width
d3dpp.BackBufferHeight = WINDOW_HEIGHT; //set the buffer to out window height
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; //the backbuffer format
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //SwapEffect
pD3D = Direct3DCreate9(D3D_SDK_VERSION); //Create the presentation parameters
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWindow,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&pDevice))) //create the device and check if it failed
{
Emsg("Failed to create device"); //error pop-up for debug purpose
CleanUp(); //call your CleanUp() function to prevent memory leak
return 1; //exit the program return 1 error
}
if(FAILED(initialize())) //call the initialize() function and check if it failed
{
Emsg("Failed to initialize"); //error pop-up for debug purpose
CleanUp(); //call your CleanUp() function to prevent memory leak
return 1; //exit the program return 1 error
}
MSG msg; //declare a MSG local variable for the GetMessage of the while loop
while(GetMessage(&msg,NULL,0,0)) //GetMessage reffer to the wndProc() function
{
pDevice->Clear(0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0.0f); //Clear the screen with black, basically since we only draw text here it's like your background change the D3DCOLOR_XRGB(0,0,0) to change the color the 3 number additioned must make 255 maximum
if(FAILED(render())) //call the function render() and verify if it worked
{
Emsg("Render failed"); //error pop-up for debug purpose
}
pDevice->Present(NULL,NULL,NULL,NULL); //display your buffer on screen
TranslateMessage(&msg); //translate the msg of the GetMessage of your while loop
DispatchMessage(&msg); //dispath the msg of the GetMessage of your while loop
}
CleanUp(); //call your CleanUp() function to prevent memory leak
return 0; //return 0 no problem
}
note: if you test your program directly from your compiler you need to provide the full path to the image