access violation at render function c++ directx9 - c++

#include <Windows.h>
#include <d3dx9.h>
#include <sstream>
#include <string>
void initD3D(HWND hWnd);
void Render();
void cleanD3D();
LPDIRECT3D9 d3d ;
LPDIRECT3DDEVICE9 d3ddev;
LRESULT CALLBACK MainWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{
switch(uMsg){
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
HWND mainWnd;
WNDCLASSEX wndClassData;
memset(&wndClassData, 0x00, sizeof(wndClassData));
wndClassData.cbSize = sizeof(wndClassData);
wndClassData.style = CS_CLASSDC;
wndClassData.lpfnWndProc = MainWindowProc;
wndClassData.hInstance = hInstance;
wndClassData.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClassData.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndClassData.lpszClassName="ColourMatchingWindow";
RegisterClassEx(&wndClassData);
mainWnd = CreateWindowEx(NULL,
"wndClass",
"ColourMatching",
WS_OVERLAPPEDWINDOW,
100,100,
800,600,
GetDesktopWindow(),
NULL,
hInstance,
NULL);
ShowWindow(mainWnd, nCmdShow);
initD3D(mainWnd);
MSG msg;
for(;;){
while(PeekMessage(&msg, NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message==WM_QUIT)
break;
Render();
}
cleanD3D();
UnregisterClass("ColourMatchingWindow", hInstance);
return 0;
}
void initD3D(HWND hWnd){
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DDISPLAYMODE displayMode;
d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);
D3DPRESENT_PARAMETERS d3dpp;
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = displayMode.Format;
d3dpp.BackBufferCount = 1;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
}
//---------------------problem starts here-------------------------
void Render(){
d3ddev->Clear(0, NULL, (D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER),
D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
//------------------------problem ends-------------------------------
void cleanD3D(){
d3d->Release();
d3ddev->Release();
}
VS2010 gave me the error message about access violation at render() , and I tried to debug the code, realised that error might be caused by d3ddev wasn't assigned to a proper value, but im quite confused by why it is't assigned a proper value and whats the logic behind it? I thought d3ddev would be created once CreateDevice() was called, but it isn't for some reasons.

Related

DirectX9 Windows-Desktop-App transparency problems

I wrote a simple directX9 app (code below) which is working fine for at least 25 Windows 10 setups but on one the background of the window is just black instead of transparent (with the test draw on it).
All the systems are running dedicated NVIDIA GPUs (10 series) so this should not be the problem and they use the latest Windows 10 version with the latest Nvidia drivers.
A workaround is to add LWA_COLORKEY to SetLayeredWindowAttributes but I would like to know how I can fix the system instead of using LWA_COLORKEY. (Because adding LWA_COLORKEY costs a lot of performance).
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA | LWA_COLORKEY);
This is a sample that can replicate the problem:
#pragma once
#include <Windows.h>
#include <string>
#include <iostream>
// DirectX9
#pragma warning( push )
#pragma warning( disable : 4005)
#include <d3d9.h>
#include <d3dx9.h>
#include <Dwmapi.h>
#include <TlHelp32.h>
#include <Directxmath.h>
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "Dwmapi.lib")
#pragma warning( pop )
using namespace std;
using namespace DirectX;
int s_width = 800;
int s_height = 600;
#define CENTERX (GetSystemMetrics(SM_CXSCREEN)/2)-(s_width/2)
#define CENTERY (GetSystemMetrics(SM_CYSCREEN)/2)-(s_height/2)
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
HWND hWnd;
LPD3DXFONT pFont;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferWidth = s_width;
d3dpp.BackBufferHeight = s_height;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.FullScreen_RefreshRateInHz = 0;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.MultiSampleQuality = DEFAULT_QUALITY;
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
D3DXCreateFont(d3ddev, 50, 0, FW_BOLD, 1, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &pFont);
}
void DrawString(int x, int y, DWORD color, LPD3DXFONT g_pFont, const char *fmt, ...)
{
RECT FontPos = { x, y, x + 120, y + 16 };
char buf[1024] = { '\0' };
va_list va_alist;
va_start(va_alist, fmt);
vsprintf_s(buf, fmt, va_alist);
va_end(va_alist);
g_pFont->DrawText(NULL, buf, -1, &FontPos, DT_NOCLIP, color);
}
void render()
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
DrawString(10, 50, D3DCOLOR_ARGB(100, 255, 0, 0), pFont, "Test rendering");
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
int main()
{
RECT rc = { 0 };
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = NULL;
wc.lpfnWndProc = WindowProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowExA(WS_EX_LAYERED | WS_EX_TRANSPARENT, "WindowClass", "Title", WS_POPUP | WS_VISIBLE, rc.left, rc.top, s_width, s_height, NULL, NULL, hInstance, NULL);
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
//DWM_BLURBEHIND bb = { DWM_BB_ENABLE | DWM_BB_BLURREGION, true, CreateRectRgn(0, 0, -1, -1), true };
//if (DwmEnableBlurBehindWindow(hWnd, &bb) != S_OK)
MARGINS margin = { -1 };
DwmExtendFrameIntoClientArea(hWnd, &margin);
initD3D(hWnd);
MSG msg;
while (TRUE)
{
render();
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT)
exit(0);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
}break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

Direct3D window opens to white screen

In the source code I'm using my program is opening a window which displays a white screen and immediately becomes unresponsive. Please help me find the issue with my code.
Windows.cpp
#include "DirectX.h"
using namespace std;
bool gameover = false;
//Windows event handler
LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
gameover = true;
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//Windows entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
//initializes window settings
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"MainWindowClass";
wc.hIconSm = NULL;
RegisterClassEx(&wc);
//create a new window
HWND window = CreateWindow(L"MainWindowClass", APPTITLE,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
SCREENW, SCREENH, NULL, NULL, hInstance, NULL);
if (window == 0) return 0;
//display the window
ShowWindow(window, nCmdShow);
UpdateWindow(window);
//initialize the game
if (!Game_Init(window)) return 0;
//main message loop
MSG message;
while (!gameover) {
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
//process game loop
Game_Run(window);
}
//shutdown game
Game_End();
return message.wParam;
}
DirectX.cpp
I assume this is where the problem is happening
bool Direct3D_Init(HWND window, int width, int height, bool fullscreen)
{
//initialize Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) return false;
//set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = !fullscreen;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = window;
//create Direct3D device
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
if (!d3ddev) return false;
//get a pointer to the back buffer surface
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//create sprite object
D3DXCreateSprite(d3ddev, &spriteobj);
return true;
}
My Game project just have the same issue. The Game was built success but when I start it. It show white screen.
I've just fixed this error. If you have a GPU (NVidia or ...) you should disable it. Like I did in this image.enter image description here

DirectX 9 window doesnt show

I am trying to make a simple DirectX 9 program that creates a windowed mode window and shows it (nothing will be drawn to the window yet). When I compile the program, I get no errors. When I run the program, the window doesn't show and the program terminates.
/*
* A simple DirectX 9 program to create a windowed mode window with nothing drawn on it. No errors when compiled or ran, but no window * pops up and program terminates almost immediately.
*/
#include <Windows.h>
#include <d3d9.h>
#include <time.h>
#include <iostream>
using namespace std;
//program settings
const string APPTITLE = "Direct3D_Windowed";
const int SCREENW = 1024;
const int SCREENH = 768;
//Direct3D object
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
bool gameOver = false;
//macro to detect key presses
#define KEY_DOWN(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1:0)
/*
* Game initialization function
*/
bool Game_Init(HWND window)
{
//init Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
{
return 0;
}
//set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = SCREENW;
d3dpp.BackBufferHeight = SCREENH;
d3dpp.hDeviceWindow = window;
//create Direct3D device
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
window,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
if (d3ddev == NULL)
{
return 0;
}
return true;
}
/*
* Game update function
*/
void Game_Run(HWND hwnd)
{
//make sure the Direct3D device is valid
if (!d3ddev)
{
return;
}
//clear the backbuffer to bright green
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
//start rendering
if (d3ddev->BeginScene())
{
//do something?
//stop rendering
d3ddev->EndScene();
//copy back buffer on the screen
d3ddev->Present(NULL, NULL, NULL, NULL);
}
//check for escape key (to exit program)
if (KEY_DOWN(VK_ESCAPE))
{
PostMessage(hwnd, WM_DESTROY, 0, 0);
}
}
/*
* Game shutdown function
*/
void Game_End(HWND hwnd)
{
//free the memory
if (d3ddev)
{
d3ddev->Release();
}
if (d3d)
{
d3d->Release();
}
}
/*
* Windows event handling function
*/
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
gameOver = true;
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
/*
* Main Windows entry function
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//set the new window's properties
WNDCLASSEX wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE.c_str();
wc.hIconSm = NULL;
RegisterClassEx(&wc);
//create a new window
HWND window = CreateWindow(
APPTITLE.c_str(), //window class
APPTITLE.c_str(), //title bar
//fullscreen mode
//WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP,
//windowed mode
WS_OVERLAPPEDWINDOW, //window style
CW_USEDEFAULT, //x position of window
CW_USEDEFAULT, //y position of window
640, //width of the window
480, //height of the window
NULL, //parent window
NULL, //menu
hInstance, //appkication instance
NULL); //window parameters
//was there an error creating the window?
if (window == 0)
{
return 0;
}
//display the window
ShowWindow(window, nCmdShow);
UpdateWindow(window);
//initialize the game
if (!Game_Init(window))
{
return 0;
}
//main message loop
MSG message;
while (!gameOver)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
Game_Run(window);
}
Game_End(window);
return message.wParam;
}
When you set the window's properties, you need to set the cbSize member.
wc.cbSize = sizeof(WNDCLASSEX);

GDIplus flickering

I'm trying to draw with GDIplus on an transparent window and experiencing a lot of flickering. I've read plenty of threads that suggest implementing double-buffering or rendering to offscreen surface would help, which I've done but to no avail.
Any idea what I've done wrong and how to fix it?
Thanks.
#include <Windows.h>
#include <stdio.h>
#include <time.h>
#include <GdiPlus.h>
#pragma comment(lib, "GdiPlus.lib")
HWND hWnd = NULL;
WNDCLASSEX wcex;
HDC hdc = NULL;
PAINTSTRUCT ps;
HGDIOBJ hfDefault;
MSG msg;
COLORREF transKey = RGB(37,14,103);
ULONG_PTR m_gdiplusToken;
char window_title[9] = "testings";
char window_class[9] = "testings";
int window_width = GetSystemMetrics(SM_CXSCREEN);
int window_height = GetSystemMetrics(SM_CYSCREEN);
DWORD MainThread(LPVOID lpArgs)
{
while(1)
{
RECT rc = {0,0,window_width,window_height};
InvalidateRect(hWnd, &rc, false);
UpdateWindow(hWnd);
Sleep(50);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_CREATE)
{
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
SetLayeredWindowAttributes(hWnd, transKey, 128, LWA_COLORKEY);
}
else if(msg == WM_PAINT)
{
hdc = BeginPaint(hWnd, &ps);
Gdiplus::Graphics g(hdc);
g.Clear(Gdiplus::Color(37,14,103));
Gdiplus::Bitmap* curBitmap = new Gdiplus::Bitmap(window_width, window_height);
Gdiplus::Graphics* g1 = g.FromImage(curBitmap);
static int x=1,y=1;
// x += 3;
y += 2;
Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 255));
g1->DrawLine(&pen, x, y, window_width/2, window_height/2);
g.DrawImage(curBitmap, 0, 0);
EndPaint(hWnd, &ps);
}
else if(msg == WM_CLOSE)
{
DestroyWindow(hWnd);
}
else if(msg == WM_DESTROY)
{
PostQuitMessage(0);
}
else
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HBRUSH hbrBackground = CreateSolidBrush(transKey);
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = hbrBackground;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = window_class;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if(!RegisterClassEx(&wcex))
return 1;
hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
window_class,
window_title,
WS_POPUP,
0,
0,
window_width,
window_height,
NULL,
NULL,
hInstance,
NULL
);
if(!hWnd)
return 1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, NULL, NULL, NULL);
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return msg.wParam;
}
You have the WS_EX_TRANSPARENT attribute on your window, which causes the window underneath it to repaint every time your window is invalidated. Try removing it.
The meaning of WS_EX_TRANSPARENT is to tell Windows that you won't be drawing on the full window surface (i.e. leaving parts of it transparent), so it needs to make sure everything underneath is rendered first so it can show through.

Directx Bitmap can't load

I am currently learning DirectX so I am a starter and I am stuck at one code. I am studying from a book and I have written this code. It should draw a bitmap on the window but its giving me a blank screen. Moreover when I click esc button it gives an error but if I move or stretch the window before pressing esc, it doesnt give an error. Any help appreciated. I am using Visual Studio 2010 and C++. I have one assumption that the error might be at D3DXCreateSurfaceFromFile. Here is the code;
//Header files to include
#include <d3d9.h>
#include <time.h>
#include <d3dx9.h>
//Application title
#define APPTITLE L"Load_Bitmap"
//Screen Resolution
#define WIDTH 640
#define HEIGHT 480
//Forward Declarations
LRESULT WINAPI WinProc( HWND, UINT, WPARAM, LPARAM);
ATOM MyRegisterClass( HINSTANCE);
int GameInit(HWND);
void GameRun(HWND);
void GameEnd(HWND);
//Direct3d objects
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;
LPDIRECT3DSURFACE9 surface = NULL;
//Macros to read the keyboard asynchronously
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
//Window Event Callback Function
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
GameEnd( hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam);
}
//Helper function to set up the window properties
ATOM MyRegisterClass( HINSTANCE hInstance)
{
WNDCLASSEX wc;
wc.cbSize = sizeof( WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE;
wc.hIconSm = NULL;
//Set up the window with the class info
return RegisterClassEx(&wc);
}
//Entry point for a windows program
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstancem, LPSTR lpCmdLine, int nCmdShow)
{
//Declare variables
MSG msg;
//Register the class
MyRegisterClass( hInstance);
//Initialize Application
HWND hWnd;
//Create new Window
hWnd = CreateWindow( APPTITLE, APPTITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL);
if( !hWnd)
return FALSE;
//Display the Window
ShowWindow( hWnd, nCmdShow);
UpdateWindow( hWnd);
//Initialize the Game
if( !GameInit( hWnd))
return FALSE;
//Main Message Loop
int done = 0;
while(!done)
{
if(PeekMessage( &msg, hWnd, 0, 0, PM_REMOVE))
{
//Look for quit message
if( msg.message == WM_QUIT)
done = 1;
//Decode and pass messages on to WndProc
TranslateMessage( &msg);
DispatchMessage( &msg);
}
else
//Process game loop( else prevents running after window is closed)
GameRun(hWnd);
}
return msg.wParam;
}
int GameInit( HWND hWnd)
{
HRESULT result;
//Initialize Direct3d
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if( d3d == NULL)
{
MessageBox( hWnd, L"Error initializing Direct3d", L"Error", MB_OK);
return 0;
}
//Set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = WIDTH;
d3dpp.BackBufferHeight = HEIGHT;
d3dpp.hDeviceWindow = hWnd;
//Create Direct3D device
d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
if( d3ddev == NULL)
{
MessageBox( hWnd, L"Error creating Direct3d device", L"Error", MB_OK);
return 0;
}
//Set Random number seed
//srand( time(NULL));
//Clear the backbuffer to black
d3ddev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0,0,0), 1.0f, 0);
//Create pointer to the back buffer
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//Create surface
result = d3ddev->CreateOffscreenPlainSurface( 640, 480, D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT, &surface, NULL);
if( result != D3D_OK)
return 1;
//load surface from file
result = D3DXLoadSurfaceFromFile(
surface, NULL, NULL, L"c.bmp", NULL, D3DX_DEFAULT, 0, NULL);
//Make sure file was loaded okay
if( result != D3D_OK)
return 1;
d3ddev->StretchRect( surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
//Return okay
return 1;
}
void GameRun(HWND hWnd)
{
//Make Sure the Direct3d device is valid
if( d3ddev == NULL)
return;
//Start Rendering
if( d3ddev->BeginScene())
{
//Create pointer to the back buffer
d3ddev->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//Draw surface to the backbuffer
d3ddev->StretchRect( surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
//StopRendering
d3ddev->EndScene();
}
//Display the back buffer on the screen
d3ddev->Present( NULL, NULL, NULL, NULL);
//Check for escape key( to exit program)
if( KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
}
void GameEnd(HWND hWnd)
{
//free the surface
if( surface != NULL)
surface->Release();
//Release the Direct3D device
if( d3ddev != NULL)
d3ddev->Release();
if( d3d != NULL)
d3d->Release();
}
Post WM_QUIT instead of WM_DESTROY when you check the escape key. As it stands now the message-loop will never quit since it depends on WM_QUIT being posted, and it will keep calling GameRun even after the surfaces are deleted.