Sign in to follow this  
Erzengeldeslichtes

DirectInputDevice8-SetCooperativeLevel == E_NOTIMPL?

Recommended Posts

Using: Microsoft Visual C++ 2005 Beta 1 Microsoft DirectX 9.0 SDK Update (February 2005) I'm trying to create a device for the system keyboard, and be able to read the keyboard wether the app is in foreground or background. So I use DISCL_NONEXCLUSIVE | DISCL_BACKGROUND. However, when I do this, SetCooperativeLevel returns an HRESULT that it isn't documented to return: E_NOTIMPL. According to the documentation, DISCL_EXLUSIVE | DISCL_BACKGROUND is not valid for the system keyboard, but DISCL_NONESCLUSIVE | DISCL_BACKGROUND is (which is what I'm using). If I use DISCL_FOREGROUND instead, it will set cooperative level fine (but for some reason won't read buffered input). I'm suspecting it has something to do with the console I'm creating. Here's what I have:
//For GetConsoleWindow:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#pragma comment(lib, "user32")

#include <iostream>
#include <string>

#include <dinput.h>
#pragma comment(lib, "dinput8")
#pragma comment(lib, "dxguid")

#include <ipointer.h>	//IPointer is a scope class for COM objects--AddRef when copied, 
			//Release when destroyed, etc.
#include <functor.h>	//Functor# is a templated functor that takes either function pointers 
			//or a pointer to a member function and the class to call on.

#include "hresult_output.h"	//FromHRESULT displays (*[Facility]-[Code]) [System Message] 
				//where * only occurs on an error, 
				//[Facility] is the part of the platform SDK, 
				//[Code] is the 2 byte hexidecimal code. Search WinError.h for the code.
				//[System Message] is the message found in the lookup table.
extern void RedirectIOToConsole();//This creates a console window and redirects fprint, cout, etc, to it.
IPointer<IDirectInput8> g_Input;
IPointer<IDirectInputDevice8> CreateSysMouse()
{
	IPointer<IDirectInputDevice8> Mouse;
	if(FAILED(g_Input->CreateDevice(GUID_SysMouse, Mouse, 0)))
	{
		std::wcerr << "Error, could not get mouse!" << std::endl;
	}
	else if(FAILED(Mouse->SetDataFormat(&c_dfDIMouse)))
	{
		std::wcerr << "Error, could not set data format on mouse!" << std::endl;
	}
	else if(FAILED(Mouse->SetCooperativeLevel(GetConsoleWindow(), 		DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
	{
		std::wcerr << "Error, could not set cooperative level on mouse" << std::endl;
	}
	else
	{
		DIPROPDWORD buffsize;
		buffsize.diph.dwSize = sizeof(buffsize);
		buffsize.diph.dwHeaderSize = sizeof(buffsize.diph);
		buffsize.diph.dwObj = 0;
		buffsize.diph.dwHow = DIPH_DEVICE;
		buffsize.dwData = 32;
		if(FAILED(Mouse->SetProperty(DIPROP_BUFFERSIZE, &buffsize.diph)))
		{
			std::wcerr << "Error, could not set buffer size." << std::endl;
		}
		else if(FAILED(Mouse->Acquire()))
		{
			std::wcerr << "Error, could not acquire mouse" << std::endl;
		}
		else
		{
			return Mouse;
		}
	}
	return IPointer<IDirectInputDevice8>();
}
#if 0
#define MY_DISCL_GROUND DISCL_FOREGROUND
#else
#define MY_DISCL_GROUND DISCL_BACKGROUND
#endif
IPointer<IDirectInputDevice8> CreateSysKeyboard()
{
	IPointer<IDirectInputDevice8> Keyboard;
	HRESULT hr=0;
	if(FAILED(hr = g_Input->CreateDevice(GUID_SysKeyboard, Keyboard, 0)))
	{
		std::wcerr << "Error, could not get Keyboard! Result: " << FromHRESULT(hr) << std::endl;
	}
	else if(FAILED(hr = Keyboard->SetDataFormat(&c_dfDIKeyboard)))
	{
		std::wcerr << "Error, could not set data format on Keyboard! Result: " << FromHRESULT(hr) 
			<< std::endl;
	}
	else if(FAILED(hr = Keyboard->SetCooperativeLevel(GetConsoleWindow(), 
		DISCL_NONEXCLUSIVE | MY_DISCL_GROUND)))
	{
		std::wcerr << "Error, could not set cooperative level on keyboard, \n\t";
		if(hr == DIERR_INVALIDPARAM)
		{
			std::wcerr << "invalid parameter.";
		}
		else if(hr == DIERR_NOTINITIALIZED)
		{
			std::wcerr << "not initialized.";
		}
		else if(hr == E_HANDLE)
		{
			std::wcerr << "invalid window.";
		}
		else
		{
			std::wcerr << "unknown error (" << FromHRESULT(hr) << ").";
		}
		std::wcerr << std::endl;
	}
	else
	{
		DIPROPDWORD buffsize;
		buffsize.diph.dwSize = sizeof(buffsize);
		buffsize.diph.dwHeaderSize = sizeof(buffsize.diph);
		buffsize.diph.dwObj = 0;
		buffsize.diph.dwHow = DIPH_DEVICE;
		buffsize.dwData = 32;
		if(FAILED(hr = Keyboard->SetProperty(DIPROP_BUFFERSIZE, &buffsize.diph)))
		{
			std::wcerr << "Error, could not set buffer size on keyboard. Result: " << FromHRESULT(hr) 
				<< std::endl;
		}
		else if(FAILED(hr = Keyboard->Acquire()))
		{
			std::wcerr << "Error, could not acquire Keyboard. Result: " << FromHRESULT(hr) << std::endl;
		}
		else
		{
			return Keyboard;
		}
	}
	return IPointer<IDirectInputDevice8>();
}
//void InputCallback(DWORD Data, DWORD TimeStamp, DWORD Sequence)
typedef Functor3<void, DWORD, DWORD, DWORD> InputCallback;
void CheckBufferedData(IPointer<IDirectInputDevice8> BufferedDevice, InputCallback* ArrayOfCallbacks)
{
	DIDEVICEOBJECTDATA TheBuffer[32];
	DWORD NumRead=32;
	HRESULT hr;
CheckBufferedData_Start:
	if(FAILED(hr = BufferedDevice->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), TheBuffer, &NumRead, 0)))
	{
		if(hr == DIERR_NOTACQUIRED)
		{
			Sleep(10);//Yes, I could do this better with window messages, etc, but right now,
				  //that's not the point.
			goto CheckBufferedData_Start;
		}
		else if(hr == DIERR_INPUTLOST)
		{
			BufferedDevice->Acquire();
			goto CheckBufferedData_Start;//Sorry, but would you rather I use a loop, replacing this 
						     //with a continue and putting a break at the end? I thought 
						     //not.
		}
		else if(hr == DIERR_NOTBUFFERED)
		{
			std::wcerr << "Error, device not buffered." << std::endl;
		}
		else if(hr == DIERR_NOTINITIALIZED)
		{
			std::wcerr << "Error, device not initialized." << std::endl;
		}
		else if(hr == DIERR_INVALIDPARAM)
		{
			std::wcerr << "Error, bad parameter." << std::endl;
		}
		else
		{
			std::wcerr << "Unknown Error" <<std::endl;
		}
		return;
	}
	for(unsigned int i=0; i<NumRead; ++i)
	{
		DIDEVICEOBJECTDATA& CurData = TheBuffer[i];
		InputCallback &TheCallback = ArrayOfCallbacks[CurData.dwOfs];
		if(TheCallback.operator bool()) TheCallback(CurData.dwData, CurData.dwTimeStamp, 
			CurData.dwSequence);
	}
}
void Pause()
{
	char a[256];
	std::cin.getline(a, 256);
}
bool g_Done=false;
void Quit(DWORD, DWORD, DWORD)
{
	g_Done = true;
}
void xChange(DWORD amount, DWORD, DWORD)
{
	std::wcout << L"X: " << (signed long)amount << std::endl;
}
void yChange(DWORD amount, DWORD, DWORD)
{
	std::wcout << L"Y: " << (signed long)amount << std::endl;
}
struct KeyChange
{
	std::wstring MyName;
	KeyChange(const std::wstring& TheName) : MyName(TheName) {}
	void Output(DWORD data, DWORD,DWORD)
	{
		std::wcout << MyName << L": " << (bool)(0x800 & data) << std::endl;
	}
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	RedirectIOToConsole();
	if(FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, 
		(void**)&g_Input,0)))//Yes, operator& returns IDirectInput8**, not IPointer*
	{
		std::wcerr << L"Error, couldn't create DInput!" << std::endl;
	}
	else
	{
		IPointer<IDirectInputDevice8> Mouse = CreateSysMouse();
		IPointer<IDirectInputDevice8> Keyboard = CreateSysKeyboard();
		if((bool)Mouse && (bool)Keyboard)
		{
			InputCallback MouseCallback[sizeof(DIMOUSESTATE)];
			MakeFunctor(&MouseCallback[DIMOFS_X], xChange);
			MakeFunctor(&MouseCallback[DIMOFS_Y], yChange);
			InputCallback KBCallback[256];
			KeyChange* Keys[256];
			for(unsigned int i=0; i<=DIK_Z; ++i)
			{
				wchar_t temp[64];
				Keys[i] = new KeyChange(std::wstring("0x") + std::wstring(_itow(i, temp, 16)));
				MakeFunctor(&KBCallback[i], *Keys[i], &KeyChange::Output);
			}
			MakeFunctor(&KBCallback[DIK_ESCAPE], Quit);
			while(!g_Done)
			{
				CheckBufferedData(Mouse, MouseCallback);
				CheckBufferedData(Keyboard, KBCallback);
			}
			for(unsigned int i=0; i<=DIK_Z; ++i)
			{
				delete Keys[i];
			}
		}
	}
	Pause();
	return 0;
}







The mouse works fine, but the keyboard either doesn't do anything (in foreground mode) or (in background mode) displays "Error, could not set cooperative level on keyboard, unknown error ((*NULL-0x4001) Not Implemented)" If it is the console, I find it interesting that it only messes up the keyboard and not the mouse... [Edited by - Erzengeldeslichtes on March 27, 2005 10:04:27 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this