// include files ////////////////////////////////////////////////////////////
#include <windows.h> // needed for windows
#include <d3d8.h> // needed for direct 3d
class CEngine {
// declare data members
private:
char *g_strAppName;
LPDIRECT3D8 g_pD3D;
LPDIRECT3DDEVICE8 g_pd3dDevice;
HWND g_hWnd;
public:
char* GetAppName();
CEngine();
void InitD3D();
void UnInitD3D();
void PaintWindow(HDC hdc);
};
CEngine::CEngine() {
g_strAppName = "Dark Age: Rise of The Underworld";
g_pD3D = NULL;
g_pd3dDevice = NULL;
g_hWnd = NULL;
}
void CEngine::InitD3D() {
// create a Direct3D device
g_pD3D = Direct3DCreate8( D3D_SDK_VERSION );
if(g_pD3D == NULL) {
throw("Direct3DCreate8 failed.");
}
// Get the current desktop display mode
D3DDISPLAYMODE d3ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
throw("GetAdapterDisplayMode failed.");
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) ); // this will set all members to zero
// setting zero for width and height will tell windows to use window
// dimensions for backbuffer dimensions.
d3dpp.BackBufferWidth = 0;
d3dpp.BackBufferHeight = 0;
// request a back buffer format that matches the current desktop display
// format.
d3dpp.BackBufferFormat = d3ddm.Format;
// we want 1 back buffer
d3dpp.BackBufferCount = 1;
// no multisampling
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
// "discard" swap effect. This means that we should never care about
// the contents of the front buffer - we should always re-render the
// entire screen on the back buffer each frame. This is the most
// efficient method of presenting the back buffer.
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
// use our window as the device window
d3dpp.hDeviceWindow = g_hWnd;
// we want to do D3D in a window
d3dpp.Windowed = TRUE;
// we don''t want Direct3D to manage depth buffers for us
// (that''s because we don''t use any right now)
d3dpp.EnableAutoDepthStencil = false;
d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
// no special flags
d3dpp.Flags = 0;
// default refresh rate
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
// default presentation interval (we must use this because we''re in
// a window)
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
// Create the Direct3D device.
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice)))
{
throw("CreateDevice failed.");
}
}
void CEngine::UnInitD3D(void) {
// first, release any devices we''ve created.
if(g_pd3dDevice != NULL) {
g_pd3dDevice->Release();
g_pd3dDevice = NULL; // just to be safe
}
// next, release the direct3d interface.
if(g_pD3D != NULL) {
g_pD3D->Release();
g_pD3D = NULL; // just to be safe
}
}
void CEngine::PaintWindow(HDC hdc) {
// most directX games don''t really use WM_PAINT.
// instead, they run their own animation loop, and flip (aka "present")
// their backbuffers several times per second.
// the following code clears the backbuffer black, then displays it.
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
char *CEngine::GetAppName() {
return g_strAppName;
}
CEngine* g_MyEngine;
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg) {
case WM_PAINT:
{
PAINTSTRUCT ps;
// get the DC we''re supposed to use from Windows
BeginPaint(hwnd, &ps);
HDC hdc = ps.hdc;
// paint our window (function is defined above)
g_MyEngine->PaintWindow(hdc);
// tell Windows we''re done painting.
EndPaint(hwnd, &ps);
}
// we processed the message, so return 0.
return(0);
case WM_DESTROY: // our window is being destroyed! quit!
g_MyEngine->UnInitD3D();
PostQuitMessage(0);
return(0);
}
// all the other messages, we don''t care about, so we let DefWindowProc
// handle them.
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE g_hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Allocate memory for engine (IMPORTANT)
g_MyEngine = new CEngine;
// set up and register window class
HWND hwnd;
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc)); // clear everything
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "GameMainWindow";
RegisterClassEx(&wc);
// create a window with a width of 640 pixels wide and a height of 480 pixels
hwnd = CreateWindowEx(0, "GameMainWindow", g_MyEngine->GetAppName(),
WS_OVERLAPPEDWINDOW, 10, 10, 640, 480, NULL, NULL, g_hInstance, NULL);
if (!hwnd) {
::MessageBox(NULL, "Create window failed!", g_MyEngine->GetAppName(), MB_ICONSTOP);
} //After you get a handle to your window then I would create
//an instance of your CEngine classg_MyEngine = new CEngine();
//Now you can use this object in your wndproc function
ShowWindow(hwnd,SW_SHOW);
try {
g_MyEngine->InitD3D();
} catch(const char *errmsg) {
// if we threw any const char *''s, catch them here, display the error,
// then exit.
MessageBox(hwnd, errmsg, g_MyEngine->GetAppName(), 0);
}
catch(...) {
// catch unhandled exceptions.
MessageBox(hwnd, "An unknown error occurred.", g_MyEngine->GetAppName(), 0);
}
// message pump
// message pump
while (1) {
MSG msg;
if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
{
int result = GetMessage(&msg, 0, 0, 0);
if (!result) return(msg.wParam);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//delete the Engine object
delete g_MyEngine;
return 0;
}
Illegal operation
The engine I''m making so far can draw a window and has the code to initialize D3D. Now the code compiles fine, but when I run the program, the program draws the window and then I get an illegal operation. Any suggestions or solutions would be helpful. Here is the code I''m using:
I don't know nothing about D3D, but as far as strings are concerned, u should not do this
g_strAppName = "Dark Age: Rise of The Underworld";
but you should allocate enough memory for your string or just create it as an array of chars and then
strcpy(g_strAppName,"Dark Age:Rise of the Underworld");
And you may need to #include <string.h> for strcpy();
Hope it helps
[edited by - remi on April 6, 2002 9:56:25 PM]
[edited by - remi on April 6, 2002 9:57:10 PM]
g_strAppName = "Dark Age: Rise of The Underworld";
but you should allocate enough memory for your string or just create it as an array of chars and then
strcpy(g_strAppName,"Dark Age:Rise of the Underworld");
And you may need to #include <string.h> for strcpy();
Hope it helps
[edited by - remi on April 6, 2002 9:56:25 PM]
[edited by - remi on April 6, 2002 9:57:10 PM]
"...and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces."----------Scott Meyers, "Effective C++"
April 06, 2002 08:59 PM
Assigning a string literal to a character pointer is perfectly legal, as C statically allocates memory for it before execution.
ah yes, I forgot about the strcpy function, but I''m still getting the illegal operation? Anyone know what''s wrong?
I can guess...
1. the second catch in WinMain looks suscipicious - I assume the unhandled exception falls through?
2. In WM_PAINT you can get the HDC like this as well
HDC hdc = BeginPaint(hwnd, &ps);
3. I think this is it - you''re calling g_MyEngine->InitD3D() before setting g_hWnd equal to hwnd, so you end up crashing when you call g_pD3D->CreateDevice(...) - that would do it - the call to ShowWindow succeed and then the InitD3D fails because of an invalid hwnd parameter in the call to CreateDevice.
1. the second catch in WinMain looks suscipicious - I assume the unhandled exception falls through?
2. In WM_PAINT you can get the HDC like this as well
HDC hdc = BeginPaint(hwnd, &ps);
3. I think this is it - you''re calling g_MyEngine->InitD3D() before setting g_hWnd equal to hwnd, so you end up crashing when you call g_pD3D->CreateDevice(...) - that would do it - the call to ShowWindow succeed and then the InitD3D fails because of an invalid hwnd parameter in the call to CreateDevice.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
I''m sorry, I don''t exactly understand what you mean. The only place where it uses CreateDevice is here:
and g_hWnd is set to NULL, which is what the book I''m using told me to do.
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))
and g_hWnd is set to NULL, which is what the book I''m using told me to do.
Yes, and here you say...
// use our window as the device window
d3dpp.hDeviceWindow = g_hWnd;
So this suggested to me that g_hWnd shouldn''t be null, but should be a handle to the window created in WinMain. The MS docs say that parameter should be the "Window handle to which focus belongs for this Microsoft® Direct3D® device."
Your other comments also suggest that g_hWnd should be set equal to hwnd as well
// we want to do D3D in a window
d3dpp.Windowed = TRUE;
// default presentation interval (we must use this because we''re in
// a window)
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
Otherwise, how do you attach the window to the d3d device? At any rate, it''s worth a shot.
Also - this doesn''t have any thing to do with the error you''re getting, but prefixing member variables with g_ suggests that they are global variables. You might consider using m_ to prefix member vars and use g_ to prefix global vars (like g_MyEngine).
// use our window as the device window
d3dpp.hDeviceWindow = g_hWnd;
So this suggested to me that g_hWnd shouldn''t be null, but should be a handle to the window created in WinMain. The MS docs say that parameter should be the "Window handle to which focus belongs for this Microsoft® Direct3D® device."
Your other comments also suggest that g_hWnd should be set equal to hwnd as well
// we want to do D3D in a window
d3dpp.Windowed = TRUE;
// default presentation interval (we must use this because we''re in
// a window)
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
Otherwise, how do you attach the window to the d3d device? At any rate, it''s worth a shot.
Also - this doesn''t have any thing to do with the error you''re getting, but prefixing member variables with g_ suggests that they are global variables. You might consider using m_ to prefix member vars and use g_ to prefix global vars (like g_MyEngine).
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement