Ok then, this will be my basecode (it should compile just fine, the input isn't tied in with the code, but it's not too hard to tie in (make sure you call ShowForeground and SetFocus before creating the input object or the device acquire can fail):
Libraries needed: OpenGL32.lib glu32.lib dxguid.lib dinput.lib dinput8.lib
Input.h
#ifndef H_INPUT
#define H_INPUT
#include <dinput.h>
#include "glheaders.h"
#include "point.h"
class Input
{
public:
explicit Input() : mouse_x(), mouse_y() { Init(); }
~Input();
void Update();
Point2d<long> mousePos() const { return Point2d<long>(mouse_x, mouse_y); }
bool leftUp() const { return !mouse_data.rgbButtons[0] && last_mouse.rgbButtons[0]; }
bool rightUp() const { return !mouse_data.rgbButtons[1] && last_mouse.rgbButtons[1]; }
bool leftDown() const { return mouse_data.rgbButtons[0] && !last_mouse.rgbButtons[0]; }
bool rightDown() const { return mouse_data.rgbButtons[1] && !last_mouse.rgbButtons[1]; }
bool rightClick() const { return mouse_data.rgbButtons[1]; }
bool leftClick() const { return mouse_data.rgbButtons[0]; }
float xDrag() const { if(rightClick()) return xMove(); else return 0.0f; }
float yDrag() const { if(rightClick()) return yMove(); else return 0.0f; }
float xMove() const { return static_cast<float>(mouse_data.lX); }
float yMove() const { return static_cast<float>(mouse_data.lY); }
float xMouse() const { return static_cast<float>(mouse_x); }
float yMouse() const { return static_cast<float>(mouse_y); }
char key(const char c) const { return keys[c]; }
char keyDown(const char c) const { return (keys[c] && !last_keys[c]); }
char keyUp(const char c) const { return (!keys[c] && last_keys[c]); }
private:
bool Init();
void KillInput();
char last_keys[256];
char keys[256];
DIMOUSESTATE last_mouse;
DIMOUSESTATE mouse_data;
long mouse_x;
long mouse_y;
LPDIRECTINPUT8 lpdi;
LPDIRECTINPUTDEVICE8 keyboard_device;
LPDIRECTINPUTDEVICE8 mouse_device;
};
#endif
Input.cpp
#include "input.h"
Input::~Input()
{
KillInput();
}
bool Input::Init()
{
HWND hWnd = GetForegroundWindow();
for(int i = 0; i < sizeof(keys); i++) {
keys[i] = 0;
last_keys[i] = 0;
}
lpdi = 0;
keyboard_device = 0;
mouse_device = 0;
HRESULT hr = DirectInput8Create(GetModuleHandle(0),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
reinterpret_cast<LPVOID*>(&lpdi),
0);
if(FAILED(hr)) {
MessageBox(0, "DirectInput8Create() failed miserably.", "IT CAN'T BE, BUT IT IS!", MB_OK);
return false;
}
hr = lpdi->CreateDevice(GUID_SysKeyboard, &keyboard_device, 0);
if(FAILED(hr)) {
MessageBox(0, "createdevice", ".", MB_OK);
KillInput();
return false;
}
hr = keyboard_device->SetDataFormat(&c_dfDIKeyboard);
if(FAILED(hr)) {
MessageBox(0, "setdataformat", ".", MB_OK);
KillInput();
return false;
}
hr = keyboard_device->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
if(FAILED(hr)) {
MessageBox(0, "set co-op level failed", ".", MB_OK);
KillInput();
return false;
}
if(keyboard_device) {
hr = keyboard_device->Acquire();
if(FAILED(hr)) {
MessageBox(0, "initial keyboard acquire", "!", MB_OK);
KillInput();
return false;
}
}
hr = lpdi->CreateDevice(GUID_SysMouse, &mouse_device, 0);
if(FAILED(hr)) {
KillInput();
return false;
}
hr = mouse_device->SetDataFormat(&c_dfDIMouse);
if(FAILED(hr)) {
KillInput();
return false;
}
hr = mouse_device->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
if(FAILED(hr)) {
KillInput();
return false;
}
if(mouse_device) {
if(FAILED(mouse_device->Acquire())) {
MessageBox(0, "initial mouse acquire", "!", MB_OK);
KillInput();
return false;
}
}
return true;
}
void Input::KillInput()
{
if(keyboard_device) keyboard_device->Unacquire();
if(keyboard_device) keyboard_device->Release();
if(mouse_device) mouse_device->Unacquire();
if(mouse_device) mouse_device->Release();
if(lpdi) lpdi->Release();
}
void Input::Update()
{
HRESULT hr = 0;
for(int i = 0; i < sizeof(keys); i++) {
last_keys[i] = keys[i];
}
hr = keyboard_device->GetDeviceState(sizeof(keys), static_cast<LPVOID>(&keys));
if(FAILED(hr))
{
if(FAILED(keyboard_device->Acquire())) {
MessageBox(0, "Keyboard died.", "F1 F1!", MB_OK);
PostQuitMessage(0);
return;
}
keyboard_device->GetDeviceState(256, static_cast<LPVOID>(&keys));
}
last_mouse = mouse_data;
hr = mouse_device->GetDeviceState(sizeof(mouse_data), static_cast<LPVOID>(&mouse_data));
if(FAILED(hr))
{
if(FAILED(mouse_device->Acquire())) {
MessageBox(0, "Mouse died.", "F1 F1!", MB_OK);
PostQuitMessage(0);
return;
}
mouse_device->GetDeviceState(sizeof(mouse_data), static_cast<LPVOID>(&mouse_data));
}
mouse_x += mouse_data.lX;
mouse_y += mouse_data.lY;
if(mouse_x > 800) mouse_x = 800;
if(mouse_x < 0) mouse_x = 0;
if(mouse_y > 600) mouse_y = 600;
if(mouse_y < 0) mouse_y = 0;
}
Window.h
#ifndef H_WINDOW
#define H_WINDOW
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
#include "glheaders.h"
class OGLWindow
{
public:
OGLWindow();
OGLWindow(int, int, int, bool, WNDPROC);
~OGLWindow();
HWND GetHWND() const { return hWnd; }
HDC GetHDC() const { return hDC; }
int GetWidth() const { return current_width; }
int GetHeight() const { return current_height; }
int GetBits() const { return current_bits; }
bool GetFullscreen() const { return current_fullscreen; }
void SetWidth(int w) { width = w; }
void SetHeight(int h) { height = h; }
void SetBits(int b) { bits = b; }
void SetFullscreen(bool f) { fullscreen = f; }
bool BuildWindow();
private:
HDC hDC;
HGLRC hRC;
HWND hWnd;
WNDPROC WndPrc;
int width;
int height;
int bits;
bool fullscreen;
int current_width;
int current_height;
int current_bits;
bool current_fullscreen;
bool SetupOpenGL();
bool SetFS(bool&);
void KillWindow();
void InitGL();
};
#endif
Window.cpp
#include <memory>
#include "window.h"
OGLWindow::OGLWindow() : width(), height(), bits(), fullscreen(), WndPrc()
{
}
OGLWindow::OGLWindow(int w, int h, int b, bool f, WNDPROC wp) : width(w), height(h), bits(b), fullscreen(f), WndPrc(wp)
{
hDC = 0;
hRC = 0;
if(!BuildWindow()) {
MessageBox(0, "build window", "s", MB_OK);
}
}
OGLWindow::~OGLWindow()
{
KillWindow();
}
void OGLWindow::InitGL()
{
glViewport(0, 0, width, height);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, (float)width, (float)height, 0.0f, -4.0f, 4.0f);
glMatrixMode(GL_MODELVIEW);
}
bool OGLWindow::SetFS(bool& fs)
{
DEVMODE dmScreenSettings;
std::uninitialized_fill_n(&dmScreenSettings, 1, DEVMODE());
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {
if (MessageBox(NULL,"No fullscreen for this mode!","YOUR FAULT",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) {
fs=false;
}
else {
return false;
}
}
return true;
}
bool OGLWindow::SetupOpenGL()
{
unsigned int PixelFormat;
static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
current_bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
if (!(hDC=GetDC(hWnd))) {
KillWindow();
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return false;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) {
KillWindow();
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","PIXELS ARE EVERYTHING",MB_OK|MB_ICONEXCLAMATION);
return false;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) {
KillWindow();
MessageBox(NULL,"Can't Set The PixelFormat.","OH LORDY",MB_OK|MB_ICONEXCLAMATION);
return false;
}
if (!(hRC=wglCreateContext(hDC))) {
KillWindow();
MessageBox(NULL,"Can't Create A GL Rendering Context.","UNGODLY ERROR",MB_OK|MB_ICONEXCLAMATION);
return false;
}
if(!wglMakeCurrent(hDC,hRC)) {
KillWindow();
MessageBox(NULL,"Can't Activate The GL Rendering Context.","HORRIBLE ERROR",MB_OK|MB_ICONEXCLAMATION);
return false;
}
InitGL();
return true;
}
bool OGLWindow::BuildWindow()
{
DWORD dwExStyle = 0;
DWORD dwStyle = 0;
WNDCLASSEX wndclassx;
RECT WndRect;
WndRect.left = static_cast<long>(0);
WndRect.right = static_cast<long>(width);
WndRect.top = static_cast<long>(0);
WndRect.bottom = static_cast<long>(height);
HINSTANCE hInstance = GetModuleHandle(0);
wndclassx.cbSize = sizeof(wndclassx);
wndclassx.style = CS_HREDRAW | CS_VREDRAW;
wndclassx.lpfnWndProc = WndPrc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hCursor = LoadCursor(0, IDC_ARROW);
wndclassx.hIcon = LoadIcon(0, IDI_WINLOGO);
wndclassx.hIconSm = LoadIcon(0, IDI_WINLOGO);
wndclassx.hbrBackground = 0;
wndclassx.lpszClassName = "^_^";
wndclassx.lpszMenuName = 0;
if(!RegisterClassEx(&wndclassx)) {
MessageBox(0, "RegisterClassEx() failed :-(", "HORRIBLE ERROR!", MB_OK);
return false;
}
if(fullscreen) {
if(!(SetFS(fullscreen))) {
return false;
}
}
if(fullscreen) {
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(true);
} else {
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_CAPTION | WS_SYSMENU;
}
AdjustWindowRectEx(&WndRect, dwStyle, 0, dwExStyle);
hWnd = CreateWindowEx(dwExStyle,
"^_^",
"^_^",
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CW_USEDEFAULT,
CW_USEDEFAULT,
WndRect.right - WndRect.left,
WndRect.bottom - WndRect.top,
0,
0,
hInstance,
0);
if(!(SetupOpenGL())) {
return false;
}
current_width = width;
current_height = height;
current_bits = bits;
current_fullscreen = fullscreen;
return true;
}
void OGLWindow::KillWindow()
{
HINSTANCE hInstance = GetModuleHandle(0);
if(current_fullscreen) {
ChangeDisplaySettings(0,0);
ShowCursor(true);
}
if (hRC)
{
if (!wglMakeCurrent(0, 0)) {
MessageBox(NULL,"Release Of DC And RC Failed.", "AWFUL", MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) {
MessageBox(NULL,"Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
hRC=0;
}
if (hDC && !ReleaseDC(hWnd, hDC)) {
MessageBox(NULL,"Release Device Context Failed.", "OH NO", MB_OK | MB_ICONINFORMATION);
hDC=0;
}
if (hWnd && !DestroyWindow(hWnd)) {
MessageBox(NULL,"Could Not Release hWnd.", "SOMETHING'S WRONG", MB_OK | MB_ICONINFORMATION);
hWnd=0;
}
if (!UnregisterClass("^_^", hInstance)) {
MessageBox(NULL,"Could Not Unregister Class.", "YOU BROKE MY PROGRAM", MB_OK | MB_ICONINFORMATION);
hInstance=0;
}
}
Main.cpp
#include <memory>
#include "window.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int active;
int done;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR szCmdLine, int iCmdShow)
{
active = 0;
done = 0;
MSG msg;
std::auto_ptr<OGLWindow> wnd(new OGLWindow(800, 600, 32, 0, WndProc));
ShowWindow(wnd->GetHWND(), iCmdShow);
UpdateWindow(wnd->GetHWND());
while(!done)
{
SwapBuffers(wnd->GetHDC());
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg)
{
case WM_ACTIVATE:
if(LOWORD(wParam) == WA_INACTIVE)
active = 0;
else
active = 1;
return 0;
case WM_CLOSE:
done = 1;
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
Point.h (the only math-base stuff I'll have)
#ifndef H_POINT
#define H_POINT
#include <limits>
template<typename T> class Point2d
{
public:
template<typename U> Point2d(U nx, U ny) : x_val(nx), y_val(ny) { }
template<typename U> Point2d(U nx) : x_val(nx), y_val() { }
template<typename U> void operator=(const Point2d<U>& rhs) { x_val = rhs.x(); y_val = rhs.y(); }
Point2d() : x_val(), y_val() { }
~Point2d() {}
template<typename U> void operator+=(const Point2d<U>& rhs) { x_val += rhs.x(); y_val += rhs.y(); }
template<typename U> void operator-=(const Point2d<U>& rhs) { x_val += rhs.x(); y_val += rhs.y(); }
template<typename U> void operator*=(const U& rhs) { x_val *= rhs; y_val *= rhs; }
template<typename U> void operator/=(const U& rhs) { x_val /= rhs; y_val /= rhs; }
friend const bool operator==(const Point2d& lhs, const Point2d& rhs);
friend const bool operator!=(const Point2d& lhs, const Point2d& rhs);
friend const Point2d operator*(const Point2d& lhs, const T& rhs);
friend const Point2d operator/(const Point2d& lhs, const T& rhs);
friend const Point2d operator*(const T& lhs, const Point2d& rhs);
friend const Point2d operator/(const T& lhs, const Point2d& rhs);
friend const Point2d operator+(const Point2d& lhs, const Point2d& rhs);
friend const Point2d operator-(const Point2d& lhs, const Point2d& rhs);
T x() { return x_val; }
T y() { return y_val; }
void reset() { x_val -= x_val; y_val -= y_val; }
void set(T& nx, T& ny) { x_val = nx; y_val = ny; }
void set_x(T& nx) { x_val = nx; }
void set_y(T& ny) { y_val = ny; }
private:
T x_val;
T y_val;
};
template<typename T> const bool operator==(const Point2d<T>& lhs, const Point2d<T>& rhs)
{
return ((rhs.x() - lhs.x()) <= std::numeric_limits<T>::epsilon()) &&
((rhs.y() - lhs.y()) <= std::numeric_limits<T>::epsilon());
}
template<typename T> const bool operator!=(const Point2d<T>& lhs, const Point2d<T>& rhs)
{
return (!(lhs == rhs));
}
template<typename T> const Point2d<T> operator*(const Point2d<T>& lhs, const T& rhs)
{
return Point2d<T>(lhs.x() * rhs, lhs.y() * T);
}
template<typename T> const Point2d<T> operator/(const Point2d<T>& lhs, const T& rhs)
{
return Point2d<T>(lhs.x() / rhs, lhs.y() / rhs);
}
template<typename T> const Point2d<T> operator*(const T& lhs, const Point2d<T>& rhs)
{ return rhs*lhs; }
template<typename T> const Point2d<T> operator/(const T& lhs, const Point2d<T>& rhs)
{ return rhs/lhs; }
template<typename T> const Point2d<T> operator+(const Point2d<T>& lhs, const Point2d<T>& rhs)
{
return Point2d<T>(lhs.x() + rhs.x(), lhs.y() + rhs.y());
}
template<typename T> const Point2d<T> operator-(const Point2d<T>& lhs, const Point2d<T>& rhs)
{
return Point2d<T>(lhs.x() - rhs.x(), lhs.y() - rhs.y());
}
#endif
glheaders.h
#ifndef H_GLHEADERS
#define H_GLHEADERS
#include <windows.h>
#include <gl.h>
#include <glu.h>
#endif