How to get a windows handle?

Started by
6 comments, last by Eliad Moshe 14 years, 2 months ago
Hey guys, Hope you can help me with this or point me to some articles or code samples (although I've researched and read quite a bit already). Basically, I am implementing DirectX Input. The DirectX Input stuff I've separated it into it own class. I was wondering how do I pass my windows handle into a member function of that class (I need to do it because SetCooperativeLevel() needs it yeh). My windows initialization stuff is not done where my main application entry point is either, it is done in a separate class. I'll a sample of my code and maybe you guys can give me hints or ideas...

//--------- MAIN APPLICATION ENTRY POINT ----------//
... //Some code omitted.

#include "Direct3DUtility.h"
#include "Direct3DInput.h"

...// Some code omitted.

Direct3DInput directInput;

//--- Function Prototype ---//
int gameLoop();
void setupGame();
void renderGame();
void initStars();
void cleanUp();

// This function processes messages that the window recieves.
LRESULT CALLBACK Direct3DUtility::WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
		case WM_CLOSE:
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			DestroyWindow( hWnd );
			return 0;
		} break;

		case WM_KEYUP:
		{
			if( wParam == VK_ESCAPE )
			{
				PostQuitMessage(0);
				DestroyWindow( hWnd );
			}

			return 0;
		} break;
	}
	return DefWindowProc( hWnd, msg, wParam, lParam );
}

// Equivalent to the 'main(){}' funtion in a console program. This is the application entry point.
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
	if( Direct3DUtility::init3D( hInstance, &D3DDevice ))
	{
		
	}

	Direct3DUtility::initState( &D3DDevice );

	Direct3DUtility::initDirLight( &D3DDevice, dir, COLOR_WHITE );
	Direct3DUtility::initCamera( &D3DDevice );
	directInput.initDirectInput( hInstance, Direct3DUtility::getHandle());
	
	setupGame();
	
	gameLoop();
	UnregisterClass( WINDOW_NAME, hInstance );

	return 0;
}

int gameLoop()
{
	MSG msg;
	ZeroMemory( &msg, sizeof( MSG ));

	while( msg.message != WM_QUIT )
	{
		if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{
			renderGame();
			Yield();
		}
	}
	return 0;
}

... //Some code omitted.


//---------- Direct3DUtility.h Header file ------------//
#ifndef DIRECT3DUTILITY_H
#define DIRECT3DUTILITY_H

#include <d3d9.h>
#include <d3dx9.h>
#include <Windows.h>
#define WIN32_LEAN_AND_MEAN
#define VC_LEANMEAN

#define WINDOW_NAME "Celestrial Fleet"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

namespace Direct3DUtility
{
	LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
	bool init3D( HINSTANCE hInstance, IDirect3DDevice9 **D3DDevice );
	void initState ( IDirect3DDevice9 **D3DDevice );
	void initCamera( IDirect3DDevice9 **D3DDevice );
	HWND getHandle();
	int gameLoop();
	void updateGame();
	void renderGame();
	void cleanUp();
}

#endif

//------------- Direct3DUtility.cpp Definition file --------//
#include "Direct3DUtility.h"

bool Direct3DUtility::init3D( HINSTANCE hInstance, IDirect3DDevice9 **D3DDevice )
{
	HWND hWnd;
	WNDCLASSEX myWindow;

	ZeroMemory( &myWindow, sizeof( WNDCLASSEX ));

	myWindow.cbSize = sizeof( WNDCLASSEX );
	myWindow.style = CS_CLASSDC;
	myWindow.lpfnWndProc = (WNDPROC) Direct3DUtility::WinProc;
	myWindow.hInstance = hInstance;
	myWindow.lpszClassName = WINDOW_NAME;
	
	if( !(RegisterClassEx( &myWindow )))
	{
		MessageBox( 0, "Direct3DUtility::init3D() - RegisterClassEx - FAILED", 0, 0 );
		return false;
	}

	if( !( hWnd = CreateWindow(
		WINDOW_NAME, "Prototype", WS_OVERLAPPEDWINDOW, 100, 100, WINDOW_WIDTH, WINDOW_HEIGHT, GetDesktopWindow(), NULL, myWindow.hInstance, NULL )))
	{
		MessageBox( 0, "Direct3DUtility::init3D() - CreateWindow - FAILED", 0, 0 );
		return false;
	}

	IDirect3D9 *D3DObject = NULL;
	if( !( D3DObject = Direct3DCreate9( D3D_SDK_VERSION )))
	{
		MessageBox( 0, "Direct3DUtility::init3D() - Direct3DCreate9 - FAILED", 0, 0 );
		return false;
	}

	D3DCAPS9 d3dCaps;
	DWORD vp = 0;

	// Getting capabilities of primary graphics card, and using features it can support only
	D3DObject->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps );
		
	if( d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	D3DPRESENT_PARAMETERS d3dParameters;
	ZeroMemory( &d3dParameters, sizeof( D3DPRESENT_PARAMETERS ));
	d3dParameters.Windowed = TRUE;
	d3dParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
	//d3dParameters.BackBufferFormat = D3DFMT_D16;
	d3dParameters.BackBufferFormat = D3DFMT_UNKNOWN;

	if( FAILED( D3DObject->CreateDevice(
		D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, vp, &d3dParameters, D3DDevice )))
		{
			MessageBox( 0, "Direct3DUtility::init3D() - D3DObject->CreateDevice - FAILED", 0, MB_OK);
			return false;
		}

	// This object no longer needed - Your device actually still holds an internal reference to this interface object, hence it is safe to release.
	D3DObject->Release();

	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow(hWnd);
	
	return true;
}

HWND Direct3DUtility::getHandle()
{
	return GetConsoleWindow();
}
... //Some code omitted.


//----------- Direct3DInput.h header file --------------//
#ifndef DIRECT3DINPUT_H
#define DIRECT3DINPUT_H

#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>

#define KEY_SIZE 256

class Direct3DInput
{
public:
	Direct3DInput();
	void initDirectInput( HINSTANCE hInstance, HWND hWnd );
	bool keyDown( int key );

private:
	// A pointer to my 'Direct Input' object, remember this is an interface and will be used to create our keyboard device and so on later.
	IDirectInput8* inputSystem;
	
	// A pointer to my keyboard device.
	IDirectInputDevice8* keyboard;

	char keys[ KEY_SIZE ];
};

#endif

//---------------------- Direct3DInput.cpp Definition file -------//
#include "Direct3DInput.h"

Direct3DInput::Direct3DInput()
{
	inputSystem = NULL;
	keyboard = NULL;
}

void Direct3DInput::initDirectInput( HINSTANCE hInstance, HWND hWnd )
{
	if( FAILED( DirectInput8Create( hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, ( void ** ) &inputSystem, NULL )))
	{
		MessageBox( 0, "Direct3DInput::initDirectInput() 1", 0, MB_OK );
	}

	if( FAILED( inputSystem->CreateDevice( GUID_SysKeyboard, &keyboard, NULL )))
	{
		MessageBox( 0, "Direct3DInput::initDirectInput() 2", 0, MB_OK );
	}

	if( FAILED( keyboard->SetDataFormat( &c_dfDIKeyboard )))
	{
		MessageBox( 0, "Direct3DInput::initDirectInput() 3", 0, MB_OK );
	}

	if( FAILED( keyboard->SetCooperativeLevel( hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE )))
	{
		MessageBox( 0, "Direct3DInput::initDirectInput() 4", 0, MB_OK );
	}

	if( FAILED( keyboard->Acquire() ))
   {
	   MessageBox( 0, "Direct3DInput::initDirectInput() 5", 0, MB_OK );
   }

   // ClearKeys() will clear out the array of keys we have.
   ZeroMemory(keys, KEY_SIZE * sizeof( char ));
}

bool Direct3DInput::keyDown( int key )
{
   // True if key is pressed. 0X80 just get rids of unneccessary trailing information.
   if( keys[ key ] & 0x80 )
   {
	   return true;
   }

   return false;
}

I did come across a function called GetConsoleWindow() which returns a window handle which I tried using but gives a run-time error. Hmmmm... if I change my window handle variable to a static one... will that work? I don't know.. any help is appreciated guys.
Advertisement
I'm not too versed in DInput - I only have DSound experience -, but won't desktop window cut it for you? GetDesktopWindow()

You might end up being dependent on the desktop window's bit depth, though (although probably not).
Quote:Original post by tenpoundbear
Hmmmm... if I change my window handle variable to a static one... will that work?
I wouldn't use a namespace there - you've got some state you need to keep track of, so a namespace doesn't really help, a class with some member variables would be better. Your code is basically just C code, using a namespace.
Making it static would work, but you're likely to run into similar problems later on.

Also, obligitary "don't use DirectInput for keyboard input, it's a really bad idea which will cause you all sorts of headaches and is less efficient than just using window messages anyway"
Hi,

I only used namespace because I was following the examples in a book... and because I never found myself using namespace extensively while in university, I thought this would be a good opportunity to expand my understanding of it.

But there has been many times where I wished I had used a class instead.

I am using DirectX Input because I wanted to learn it... and understand it as much as I possibly can. I have used the winAPI input initially but now I am switching over to DirectX because it is better for games.

No way to keep my namespace and achieve what I am trying to achieve?
Quote:Original post by tenpoundbear
I am using DirectX Input because I wanted to learn it... and understand it as much as I possibly can. I have used the winAPI input initially but now I am switching over to DirectX because it is better for games.
Using it to learn is fine, but using it because it's "better for games" is wrong. DirectInput is much worse to use than plain Win32 for games - it's slower, far more fragile, more code to write (and therefore more to go wrong), and more difficult to get right.

Quote:Original post by tenpoundbear
No way to keep my namespace and achieve what I am trying to achieve?
You'll need to use a static variable, but that doesn't mean you have to get rid of your namespace. The only advantage to using a namespace here is that your static variable can go in the namespace, which will make the name less likely to clash with something else.
If you didn't use namespaces, you could get almost exactly the same effect by prefixing all of your function names with "Direct3DUtility" - all the namespace does is group functions for you.
Quote:Original post by Evil Steve
Quote:Original post by tenpoundbear
I am using DirectX Input because I wanted to learn it... and understand it as much as I possibly can. I have used the winAPI input initially but now I am switching over to DirectX because it is better for games.
Using it to learn is fine, but using it because it's "better for games" is wrong. DirectInput is much worse to use than plain Win32 for games - it's slower, far more fragile, more code to write (and therefore more to go wrong), and more difficult to get right.

Quote:Original post by tenpoundbear
No way to keep my namespace and achieve what I am trying to achieve?
You'll need to use a static variable, but that doesn't mean you have to get rid of your namespace. The only advantage to using a namespace here is that your static variable can go in the namespace, which will make the name less likely to clash with something else.
If you didn't use namespaces, you could get almost exactly the same effect by prefixing all of your function names with "Direct3DUtility" - all the namespace does is group functions for you.


Hmmm... this is kinda the opposite of what I have been taught.

I thought that the standard win32 API input was slower because it wasn't designed for games, and more designed for keyboard entry applications. It has lots of functionality that isn't needed in a games application like automatically repeating keys, conversion from key
codes to ASCII characters and so on, hence wasting valuable clock cycles.

Also mouse support is limited to 3 buttons, joystick support is flaky, messaging processing isn't the fastest.

I dunno, these are just some points in my lecture notes.

Evil Steve is kinda saying the opposite of this... are you sure about this?
Microsoft themselves have discouraged future use of DirectInput, and have stopped updating it.

Check Steve's journal entry he linked to before for the reasons why, or Wikipedia.

There's a few reasons to still prefer DirectInput, but being "faster/better for games" certainly isn't one of them.
You need to create a parameter, in a constructor for example.
Something like that:

class init_DirectInput{

private:
HWND handle ;

public:

init_DirectInput(HWND handle){
this->handle = handle ;
}

}

Now you can use it where ever you want in your class.

I am working on my own game engine too, maby we can share thoughts.
You can add me to facebook if you want.
(eliad154@gmail.com)

This topic is closed to new replies.

Advertisement