Linker issue with Visual Studio 2010 Pro - c++

I'm having a very frustrating issue setting up a DirectX 9 (irrelevant to the issue.. I think) framework in VS 2010. Here is my DirectX framework:
#ifndef _DX9_H_
#define _DX9_H_
// window includes
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// required for ush typedef and window properties to setup backbuffer
#include "sys_params.h"
// directx9 includes
#define DIRECTINPUT_VERSION 0x0800
#include <d3dx9.h>
#include <dinput.h>
#include <DxErr.h>
#include <vector>
#include <iterator>
// directx9 libraries
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dxerr.lib")
namespace nsdx9
{
using nssysprms::ush;
#define CheckHR(hr) CheckForDXError(__FILE__, __LINE__, hr)
class DX9
{
public:
DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy);
~DX9();
// windows message processor
UINT ProcessMessages();
// --- DIRECTX GAME FUNCTIONS --- //
// input functions
void InputUpdate();
BYTE KeyHeld(ush key);
bool KeyPressed(ush key);
// sprite functions
const LPD3DXSPRITE& GetSpriteInterface();
void SpriteBeginDraw(DWORD flags = D3DXSPRITE_ALPHABLEND);
void SpriteEndDraw();
// font functions
void MakeFont(int height, int width, UINT weight = FW_DONTCARE, LPCSTR face = "Calibri", bool italic = false);
const LPD3DXFONT& GetFontAtIndex(ush index);
const std::vector<LPD3DXFONT>& GetFontVector();
// --- END DIRECTX GAME FUNCTIONS --- //
private:
// --- WINDOW FUNCTIONS/VARIABLES --- //
WNDCLASSEX _wc;
HWND _hwnd;
MSG _msg;
HINSTANCE _inst;
std::string _title;
static LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm);
// --- END WINDOW FUNCTIONS/VARIABLES --- //
// --- DIRECTX FUNCTIONS/VARIABLES --- //
// D3D interfaces
LPDIRECT3D9 _d3d;
LPDIRECT3DDEVICE9 _d3ddev;
D3DPRESENT_PARAMETERS _d3dpp;
// directinput interfaces
LPDIRECTINPUT8 _dInput;
LPDIRECTINPUTDEVICE8 _diMouse;
LPDIRECTINPUTDEVICE8 _diKeyboard;
DIMOUSESTATE _mouseState;
BYTE _keys[256];
bool _keyStates[256];
bool _keyboardStateChanged;
void AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev);
// sprite interfaces
LPD3DXSPRITE _spriteBatch;
// font vector
std::vector<LPD3DXFONT> _fonts;
// hresult checker, for debugging only
void CheckForDXError(const char *file, int line, HRESULT hr);
// --- END DIRECTX FUNCTIONS/VARIABLES --- //
};
/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
{
/*=================================================*/
/*--------------WINDOW INITIALIZATION--------------*/
/*=================================================*/
_title = title;
_inst = inst;
// init window class struct
_wc.cbClsExtra = NULL;
_wc.cbSize = sizeof(WNDCLASSEX);
_wc.cbWndExtra = NULL;
_wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
_wc.hCursor = LoadCursor(NULL, IDC_ARROW);
_wc.hIcon = NULL;
_wc.hIconSm = NULL;
_wc.hInstance = inst;
_wc.lpfnWndProc = (WNDPROC)WinProc;
_wc.lpszClassName = title.c_str();
_wc.lpszMenuName = NULL;
_wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&_wc);
// create handle to the window
_hwnd = CreateWindow(title.c_str(),
title.c_str(),
WS_OVERLAPPEDWINDOW,
wndx,
wndy,
wndwidth,
wndheight,
NULL,
NULL,
inst,
NULL);
// required to make the window show up
ShowWindow(_hwnd, cmdShow);
UpdateWindow(_hwnd);
/*=================================================*/
/*--------------END WINDOW INITIALIZATION----------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTX INITIALIZATION-------------*/
/*=================================================*/
// --- INITIALIZE DIRECTX9 VARIABLES --- //
SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
SecureZeroMemory(&_mouseState, sizeof(_mouseState));
SecureZeroMemory(&_keys, sizeof(_keys));
for (int i = 0; i < 256; i++)
{
_keyStates[i] = true;
}
_d3d = NULL;
_d3ddev = NULL;
_dInput = NULL;
_diMouse = NULL;
_diKeyboard = NULL;
_keyboardStateChanged = false;
_spriteBatch = NULL;
// --- END INITIALIZE DIRECTX9 VARIABLES --- //
// --- DIRECTX9 INITIALIZATION --- //
_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!_d3d)
{
OutputDebugString("Error: Failed to create Direct3D.\n");
}
// set d3d present parameters
_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
_d3dpp.BackBufferCount = 1;
_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
_d3dpp.BackBufferHeight = nssysprms::WND_HEIGHT;
_d3dpp.BackBufferWidth = nssysprms::WND_WIDTH;
_d3dpp.EnableAutoDepthStencil = 1;
_d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
//_d3dpp.FullScreen_RefreshRateInHz
_d3dpp.hDeviceWindow = _hwnd;
//_d3dpp.MultiSampleQuality
//_d3dpp.MultiSampleType
_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
_d3dpp.Windowed = nssysprms::isWindowed;
// create d3d device
CheckHR(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &_d3dpp, &_d3ddev));
// --- END DIRECTX9 INITIALIZATION --- //
// --- INITIALIZE DIRECTINPUT --- //
CheckHR(DirectInput8Create(inst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_dInput, NULL));
// create mouse and keyboard
CheckHR(_dInput->CreateDevice(GUID_SysKeyboard, &_diKeyboard, NULL));
CheckHR(_dInput->CreateDevice(GUID_SysMouse, &_diMouse, NULL));
// initialize keyboard
CheckHR(_diKeyboard->SetDataFormat(&c_dfDIKeyboard));
CheckHR(_diKeyboard->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
AcquireInputDevice(_diKeyboard);
// initialize mouse
CheckHR(_diMouse->SetDataFormat(&c_dfDIMouse));
CheckHR(_diMouse->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
AcquireInputDevice(_diMouse);
// create sprite object
CheckHR(D3DXCreateSprite(_d3ddev, &_spriteBatch));
// --- END INITIALIZE DIRECTINPUT --- //
/*=================================================*/
/*--------------END DIRECTX INITIALIZATION---------*/
/*=================================================*/
}
/*=================================================*/
/*--------------END DIRECTX CONSTRUCTOR------------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTX DESTRUCTOR-----------------*/
/*=================================================*/
DX9::~DX9()
{
// set all stack variables to NULL
SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
SecureZeroMemory(&_mouseState, sizeof(_mouseState));
SecureZeroMemory(&_keys, sizeof(_keys));
SecureZeroMemory(&_keyStates, sizeof(_keyStates));
// free all the D3D interfaces from memory
if (!_fonts.empty())
{
for (std::vector<LPD3DXFONT>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
{
// SOLVEPROBLEM figure out why this doesn't work
//*it->OnLostDevice();
}
_fonts.erase(_fonts.begin(), _fonts.end() - 1);
}
if (_spriteBatch != NULL)
{
_spriteBatch->Release();
_spriteBatch = NULL;
}
if (_diKeyboard != NULL)
{
_diKeyboard->Release();
_diKeyboard = NULL;
}
if (_diMouse != NULL)
{
_diMouse->Release();
_diMouse = NULL;
}
if (_d3ddev != NULL)
{
_d3ddev->Release();
_d3ddev = NULL;
}
if (_d3d != NULL)
{
_d3d->Release();
_d3d = NULL;
}
// free the window class from memory
UnregisterClass(_title.c_str(), _inst);
}
/*=================================================*/
/*--------------END DIRECTX DESTRUCTOR-------------*/
/*=================================================*/
/*=================================================*/
/*--------------HRESULT ERROR CHECK----------------*/
/*=================================================*/
void DX9::CheckForDXError(const char *file, int line, HRESULT hr)
{
if (SUCCEEDED(hr))
{
return;
}
// Get the direct X error and description
char desc[1024];
sprintf_s(desc,"(DX) %s - %s", DXGetErrorString(hr), DXGetErrorDescription(hr));
// Output the file and line number in the correct format + the above DX error
char buf[2048];
sprintf_s(buf,"%s(%d) : Error: %s\n", file, line, desc);
OutputDebugString(buf);
}
/*=================================================*/
/*--------------END HRESULT ERROR CHECK------------*/
/*=================================================*/
/*=================================================*/
/*--------------MESSAGE PROCESSOR------------------*/
/*=================================================*/
UINT DX9::ProcessMessages()
{
if (PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&_msg);
DispatchMessage(&_msg);
}
return _msg.message;
}
/*=================================================*/
/*--------------END MESSAGE PROCESSOR--------------*/
/*=================================================*/
/*=================================================*/
/*--------------MESSAGE HANDLER--------------------*/
/*=================================================*/
LRESULT CALLBACK DX9::WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wprm, lprm);
}
/*=================================================*/
/*--------------END MESSAGE HANDLER----------------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTINPUT FUNCTIONS--------------*/
/*=================================================*/
// for init only, helper function to initially acquire the
// mouse and keyboard
void DX9::AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev)
{
// loop and attempt to acquire the device until success
while (FAILED(dev->Acquire()))
{
dev->Acquire();
}
}
// update the state of the mouse and keyboard
void DX9::InputUpdate()
{
_diKeyboard->GetDeviceState(sizeof(_keys), (LPVOID)_keys);
_diMouse->GetDeviceState(sizeof(_mouseState), (LPVOID)&_mouseState);
// after directinput has been updated, check to see if any keys are no,
// longer pressed, and reset the keystate array at that key's index if,
// this is the case
// keystates true = key is available for key press
if (_keyboardStateChanged)
{
for (int i = 0; i < 256; i++)
{
if (!KeyHeld(i))
{
_keyStates[i] = true;
}
}
}
_keyboardStateChanged = false;
}
// captures a key being held down
BYTE DX9::KeyHeld(ush key)
{
return _keys[key] & 0x80;
}
// captures a single key press
bool DX9::KeyPressed(ush key)
{
if (KeyHeld(key) && _keyStates[key])
{
_keyStates[key] = false;
return true;
}
else
{
if (!KeyHeld(key) && !_keyStates[key])
{
_keyboardStateChanged = true;
}
return false;
}
}
/*=================================================*/
/*--------------END DIRECTINPUT FUNCTIONS----------*/
/*=================================================*/
/*=================================================*/
/*--------------SPRITE FUNCTIONS-------------------*/
/*=================================================*/
// returns the sprite interface
const LPD3DXSPRITE& DX9::GetSpriteInterface()
{
return _spriteBatch;
}
// begin drawing with the sprite batch
void DX9::SpriteBeginDraw(DWORD flags)
{
_spriteBatch->Begin(flags);
}
// end sprite batch drawing
void DX9::SpriteEndDraw()
{
_spriteBatch->End();
}
/*=================================================*/
/*--------------END SPRITE FUNCTIONS---------------*/
/*=================================================*/
/*=================================================*/
/*--------------FONT FUNCTIONS---------------------*/
/*=================================================*/
// create a font
void DX9::MakeFont(int height, int width, UINT weight, LPCSTR face, bool italic)
{
LPD3DXFONT newfont;
CheckHR(D3DXCreateFont(_d3ddev,
height,
width,
weight,
0,
italic,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
face,
&newfont));
_fonts.push_back(newfont);
}
// gets a font at the specified index
const LPD3DXFONT& DX9::GetFontAtIndex(ush index)
{
return _fonts[index];
}
const std::vector<LPD3DXFONT>& DX9::GetFontVector()
{
return _fonts;
}
/*=================================================*/
/*--------------END FONT FUNCTIONS-----------------*/
/*=================================================*/
}
#endif
This really doesn't do anything but create and initialize a window, DirectX and some basic DirectX functions.
The actual error is this:
Error 1 error LNK2005: "public: __thiscall nsdx9::DX9::DX9(struct HINSTANCE__ * &,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned short,unsigned short,short,short)" (??0DX9#nsdx9##QAE#AAPAUHINSTANCE__##HABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##GGFF#Z) already defined in game_manager.obj C:\Users\JAREK\documents\visual studio 2010\Projects\example\example\main.obj
This error is repeated for every single function in dx9.h. If I ONLY include dx9.h in main.cpp, I do not get this error. It is only if I include dx9.h in any other cpp file, or use any of the parameters in dx9.h in cpp files that have access to dx9.h by being included after dx9.h in main.cpp that I get this error. This sounds confusing, so here are some samples from other parts of the program:
main.cpp:
#include "sys_params.h"
#include "dx9.h"
#include "game_manager.h"
int WINAPI WinMain (HINSTANCE inst, HINSTANCE pinst, LPSTR cmdLine, int cmdShow)
{
// state of the program
bool appEnd = false;
// create and initialize the window and directx9
nsdx9::DX9* _dx9 = new nsdx9::DX9(inst, cmdShow, nssysprms::GAME_TITLE,
nssysprms::WND_WIDTH, nssysprms::WND_HEIGHT,
nssysprms::WND_POS_X, nssysprms::WND_POS_Y);
// create and initialize the game manager
Game_Manager* _mngr = new Game_Manager(_dx9);
// Windows message handler
// also the entry point for the main game loop
while (_dx9->ProcessMessages() != WM_QUIT && !appEnd)
{
if (!_mngr->Game_Run())
{
appEnd = true;
}
}
// clean up everything
delete _mngr;
delete _dx9;
return 0;
}
game_manager.h:
#ifndef _GAME_MANAGER_H_
#define _GAME_MANAGER_H_
#include <stack>
#include <vector>
#include "dx9.h"
#include "screen.h"
#include "message_handler.h"
class Game_Manager
{
public:
Game_Manager(nsdx9::DX9* dx9);
~Game_Manager();
bool Game_Run();
private:
nsdx9::DX9* _dx9;
std::stack<Screen*> _screens;
Message_Handler* _msg_hnd;
// *** DECLARE SCREENS HERE *** //
void InitFonts();
void InitScreens();
};
#endif
This should be what is actually causing the issue. The issue is originating from main.cpp through game_manager.h. Nothing I've tried has solved the problem for me. I've included header guards in dx9.h, so I have no idea what could be causing this. if you guys need more information, please let me know. Thanks!

Your definitions of the DX9 methods (as opposed to just the class definition) seem to be in the dx9.h header file - so you violate C++'s one-definition rule when you include dx9.h in multiple .cpp files. To solve this, move the method implementations into a .cpp file (e.g. dx9.cpp).

Don't include the implementation in the header file. This causes the implementation to be compiled again everywhere it is included.
for example:
/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
{
.... et al
put that in it's own cpp

Related

undeclared identifer of a wndproc function

I have a class, which I tried in another MFC project which compiled fine, but for some reason in this project it doesn't compile and complains about my wndproc function that is declared in a header file.
Below is the header file of the class I used in another MFC project. I had to comment out #include <windows.h> because it would say it can't be used in MFC, which wasn't the case in the other MFC project (what must be noted is that the other MFC project had precompiled headers).
skin.h
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// WINDOWS SKINNING TUTORIAL - by Vander Nunes - virtware.net
// This is the source-code that shows what is discussed in the tutorial.
// The code is simplified for the sake of clarity, but all the needed
// features for handling skinned windows is present. Please read
// the article for more information.
//
// skin.h : CSkin class declaration
// 28/02/2002 : initial release.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#ifndef _SKIN_H_
#define _SKIN_H_
//#include <windows.h>
#include <afxwin.h>
// --------------------------------------------------------------------------
// The CSkin class will load the skin from a resource
// and subclass the associated window, so that the
// WM_PAINT message will be redirected to the provided
// window procedure. All the skin handling will be automatized.
// --------------------------------------------------------------------------
class CSkin
{
// --------------------------------------------------------------------------
// the skin window procedure, where the class
// will handle WM_PAINT and WM_LBUTTONDOWN automatically.
// --------------------------------------------------------------------------
friend LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
private:
// the associated window handle
HWND m_hWnd;
// the associated CWnd window handle
CWnd * m_cwnd;
// the old window procedure
WNDPROC m_OldWndProc;
// skin region
HRGN m_rgnSkin;
// the internal skin device context handle
HDC m_dcSkin;
// bitmap and old bitmap from the device context
HBITMAP m_hBmp, m_hOldBmp;
// skin dimensions
int m_iWidth, m_iHeight;
// on|off toggle
bool m_bEnabled;
// tell the class if it has a window subclassed.
bool m_bHooked;
// skin retrieval helper
bool GetSkinData(int iSkinRegion, int iSkinBitmap);
public:
// ----------------------------------------------------------------------------
// constructor 1 - use it when you have not already created the app window.
// this one will not subclass automatically, you must call Hook() to subclass.
// will throw an exception if unable to initialize skin from resource.
// ----------------------------------------------------------------------------
CSkin(int iSkinRegion, int iSkinBitmap);
// ----------------------------------------------------------------------------
// constructor 2 - use it when you have already created the app window.
// this one will subclass the window automatically.
// will throw an exception if unable to initialize skin from resource.
// ----------------------------------------------------------------------------
CSkin(HWND hWnd, int iSkinRegion, int iSkinBitmap);
// ----------------------------------------------------------------------------
// destructor - just call the destroyer
// ----------------------------------------------------------------------------
virtual ~CSkin();
// ----------------------------------------------------------------------------
// destroy skin resources and free allocated resources
// ----------------------------------------------------------------------------
void Destroy();
// ----------------------------------------------------------------------------
// subclass a window.
// ----------------------------------------------------------------------------
bool Hook(HWND hWnd);
// ----------------------------------------------------------------------------
// subclass a window. The CWnd version
// ----------------------------------------------------------------------------
bool Hook(CWnd *cwnd);
// ----------------------------------------------------------------------------
// unsubclass the subclassed window.
// ----------------------------------------------------------------------------
bool UnHook();
// ----------------------------------------------------------------------------
// unsubclass the subclassed window. The CWnd version
// ----------------------------------------------------------------------------
bool UnHookCWnd();
// ----------------------------------------------------------------------------
// tell us if we have a window subclassed.
// ----------------------------------------------------------------------------
bool Hooked();
// ----------------------------------------------------------------------------
// toggle skin on/off.
// ----------------------------------------------------------------------------
bool Enable(bool bEnable);
// ----------------------------------------------------------------------------
// tell if the skinning is enabled
// ----------------------------------------------------------------------------
bool Enabled();
// ----------------------------------------------------------------------------
// return the skin bitmap width.
// ----------------------------------------------------------------------------
int Width();
// ----------------------------------------------------------------------------
// return the skin bitmap height.
// ----------------------------------------------------------------------------
int Height();
// ----------------------------------------------------------------------------
// return the skin device context.
// ----------------------------------------------------------------------------
HDC HDC();
// ----------------------------------------------------------------------------
// return the handle region.
// ----------------------------------------------------------------------------
HRGN HRGN();
// toggle skin on/off for Cwnd
bool EnableCWnd(bool bEnable);
};
#endif
This is the cpp file:
skin.cpp
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// WINDOWS SKINNING TUTORIAL - by Vander Nunes - virtware.net
// This is the source-code that shows what is discussed in the tutorial.
// The code is simplified for the sake of clarity, but all the needed
// features for handling skinned windows is present. Please read
// the article for more information.
//
// skin.cpp : CSkin class implementation
// 28/02/2002 : initial release.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "skin.h"
// ----------------------------------------------------------------------------
// constructor 1 - use it when you have not already created the app window.
// this one will not subclass automatically, you must call Hook() and Enable()
// to subclass the app window and enable the skin respectively.
// will throw an exception if unable to initialize skin from resource.
// ----------------------------------------------------------------------------
CSkin::CSkin(int iSkinRegion, int iSkinBitmap)
{
// default starting values
m_bHooked = false;
m_OldWndProc = NULL;
// try to retrieve the skin data from resource.
if ( !GetSkinData(iSkinRegion, iSkinBitmap) )
throw ("Unable to retrieve the skin.");
}
// ----------------------------------------------------------------------------
// constructor 2 - use it when you have already created the app window.
// this one will subclass the window and enable the skin automatically.
// will throw an exception if unable to initialize skin from resource.
// ----------------------------------------------------------------------------
CSkin::CSkin(HWND hWnd, int iSkinRegion, int iSkinBitmap)
{
// default starting values
m_bHooked = false;
m_OldWndProc = NULL;
// initialize
CSkin(iSkinRegion, iSkinBitmap);
// subclass
Hook(hWnd);
// enable
Enable(true);
}
// ----------------------------------------------------------------------------
// destructor - just call the destroyer
// ----------------------------------------------------------------------------
CSkin::~CSkin()
{
Destroy();
}
// ----------------------------------------------------------------------------
// destroy skin resources and free allocated resources
// ----------------------------------------------------------------------------
void CSkin::Destroy()
{
// unhook the window
UnHook();
// free bitmaps and device context
if (m_dcSkin) { SelectObject(m_dcSkin, m_hOldBmp); DeleteDC(m_dcSkin); m_dcSkin = NULL; }
if (m_hBmp) { DeleteObject(m_hBmp); m_hBmp = NULL; }
// free skin region
if (m_rgnSkin) { DeleteObject(m_rgnSkin); m_rgnSkin = NULL; }
}
// ----------------------------------------------------------------------------
// toggle skin on/off - must be Hooked() before attempting to enable skin.
// ----------------------------------------------------------------------------
bool CSkin::Enable(bool bEnable)
{
// refuse to enable if there is no window subclassed yet.
if (!Hooked()) return false;
// toggle
m_bEnabled = bEnable;
// force window repainting
InvalidateRect(m_hWnd, NULL, TRUE);
return true;
}
// ----------------------------------------------------------------------------
// tell if the skinning is enabled
// ----------------------------------------------------------------------------
bool CSkin::Enabled()
{
return m_bEnabled;
}
// ----------------------------------------------------------------------------
// hook a window
// ----------------------------------------------------------------------------
bool CSkin::Hook(HWND hWnd)
{
// unsubclass any other window
if (Hooked()) UnHook();
// this will be our new subclassed window
m_hWnd = hWnd;
// set the skin region to the window
SetWindowRgn(m_hWnd, m_rgnSkin, true);
// subclass the window procedure
m_OldWndProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)SkinWndProc);
// store a pointer to our class instance inside the window procedure.
if (!SetProp(m_hWnd, "skin", (void*)this))
{
// if we fail to do so, we just can't activate the skin.
UnHook();
return false;
}
// update flag
m_bHooked = ( m_OldWndProc ? true : false );
// force window repainting
InvalidateRect(m_hWnd, NULL, TRUE);
// successful return if we're hooked.
return m_bHooked;
}
bool CSkin::Hook(CWnd *cwnd)
{
if (Hooked() )UnHookCWnd();
m_cwnd = cwnd;
m_cwnd->SetWindowRgn(m_rgnSkin, TRUE);
m_bHooked = true;
m_cwnd->InvalidateRect(NULL, TRUE);
//m_cwnd->Invalidate(true);
//m_cwnd->UpdateWindow();
return m_bHooked;
}
// ----------------------------------------------------------------------------
// unhook the window
// ----------------------------------------------------------------------------
bool CSkin::UnHook()
{
// just to be safe we'll check this
WNDPROC OurWnd;
// cannot unsubclass if there is no window subclassed
// returns true anyways.
if (!Hooked()) return true;
// remove the skin region from the window
SetWindowRgn(m_hWnd, NULL, true);
// unsubclass the window procedure
OurWnd = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_OldWndProc);
// remove the pointer to our class instance, but if we fail we don't care.
RemoveProp(m_hWnd, "skin");
// update flag - if we can't get our window procedure address again,
// we failed to unhook the window.
m_bHooked = ( OurWnd ? false : true );
// force window repainting
InvalidateRect(m_hWnd, NULL, TRUE);
// successful return if we're unhooked.
return !m_bHooked;
}
bool CSkin::UnHookCWnd()
{
if (!Hooked()) return true;
m_cwnd->SetWindowRgn(NULL, TRUE);
m_bHooked = false;
m_cwnd->InvalidateRect(NULL, TRUE);
return !m_bHooked;
}
// ----------------------------------------------------------------------------
// tell us if there is a window subclassed
// ----------------------------------------------------------------------------
bool CSkin::Hooked()
{
return m_bHooked;
}
// ----------------------------------------------------------------------------
// return the skin bitmap width
// ----------------------------------------------------------------------------
int CSkin::Width()
{
return m_iWidth;
}
// ----------------------------------------------------------------------------
// return the skin bitmap height
// ----------------------------------------------------------------------------
int CSkin::Height()
{
return m_iHeight;
}
// ----------------------------------------------------------------------------
// return the skin device context
// ----------------------------------------------------------------------------
HDC CSkin::HDC()
{
return m_dcSkin;
}
HRGN CSkin::HRGN()
{
return m_rgnSkin;
}
// ----------------------------------------------------------------------------
// skin retrieval helper
// ----------------------------------------------------------------------------
bool CSkin::GetSkinData(int iSkinRegion, int iSkinBitmap)
{
// get app instance handle
HINSTANCE hInstance = GetModuleHandle(NULL);
// -------------------------------------------------
// retrieve the skin bitmap from resource.
// -------------------------------------------------
m_hBmp = LoadBitmap(hInstance, MAKEINTRESOURCE(iSkinBitmap));
if (!m_hBmp) return false;
// get skin info
BITMAP bmp;
GetObject(m_hBmp, sizeof(bmp), &bmp);
// get skin dimensions
m_iWidth = bmp.bmWidth;
m_iHeight = bmp.bmHeight;
// -------------------------------------------------
// then, we retrieve the skin region from resource.
// -------------------------------------------------
// ask resource for our skin.
HRSRC hrSkin = FindResource(hInstance, MAKEINTRESOURCE(iSkinRegion),"BINARY");
if (!hrSkin) return false;
// this is standard "BINARY" retrieval.
LPRGNDATA pSkinData = (LPRGNDATA)LoadResource(hInstance, hrSkin);
if (!pSkinData) return false;
// create the region using the binary data.
m_rgnSkin = ExtCreateRegion(NULL, SizeofResource(NULL,hrSkin), pSkinData);
// free the allocated resource
FreeResource(pSkinData);
// check if we have the skin at hand.
if (!m_rgnSkin) return false;
// -------------------------------------------------
// well, things are looking good...
// as a quick providence, just create and keep
// a device context for our later blittings.
// -------------------------------------------------
// create a context compatible with the user desktop
m_dcSkin = CreateCompatibleDC(0);
if (!m_dcSkin) return false;
// select our bitmap
m_hOldBmp = (HBITMAP)SelectObject(m_dcSkin, m_hBmp);
// -------------------------------------------------
// done
// -------------------------------------------------
return true;
}
// ------------------------------------------------------------------------
// Default skin window procedure.
// Here the class will handle WM_PAINT and WM_LBUTTONDOWN, originally sent
// to the application window, but now subclassed. Any other messages will
// just pass through the procedure and reach the original app procedure.
// ------------------------------------------------------------------------
LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
// we will need a pointer to the associated class instance
// (it was stored in the window before, remember?)
CSkin *pSkin = (CSkin*)GetProp(hWnd, "skin");
// to handle WM_PAINT
PAINTSTRUCT ps;
// if we fail to get our class instance, we can't handle anything.
if (!pSkin) return DefWindowProc(hWnd,uMessage,wParam,lParam);
switch(uMessage)
{
case WM_PAINT:
{
// ---------------------------------------------------------
// here we just need to blit our skin
// directly to the device context
// passed by the painting message.
// ---------------------------------------------------------
BeginPaint(hWnd,&ps);
// blit the skin
BitBlt(ps.hdc,0,0,pSkin->Width(),pSkin->Height(),pSkin->HDC(),0,0,SRCCOPY);
EndPaint(hWnd,&ps);
break;
}
case WM_LBUTTONDOWN:
{
// ---------------------------------------------------------
// this is a common trick for easy dragging of the window.
// this message fools windows telling that the user is
// actually dragging the application caption bar.
// ---------------------------------------------------------
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION,NULL);
break;
}
}
// ---------------------------------------------------------
// call the default window procedure to keep things going.
// ---------------------------------------------------------
return CallWindowProc(pSkin->m_OldWndProc, hWnd, uMessage, wParam, lParam);
}
// toggle skin on/off for Cwnd
bool CSkin::EnableCWnd(bool bEnable)
{
// TODO: Add your implementation code here.
if (!Hooked()) return false;
// toggle
m_bEnabled = bEnable;
m_cwnd->InvalidateRect(NULL, TRUE);
//m_cwnd->Invalidate(TRUE);
//m_cwnd->UpdateWindow();
return true;
}
Here are my other files, if you think they will be relevant:
Hello.h
#pragma once
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
// This is the height of the bitmap
int iHeight;
int iWidth;
int BitmapId;
// This sets the height variable of the bitmap
void SetHeight(int height);
// This sets the width variable of the bitmap
void SetWidth(int width);
// This is sets the bitmap id for the image
void SetBitmapId(int bitmapid);
};
Hello.cpp
#include <afxwin.h>
#include "Hello.h"
#include "SkinClass/skin.h"
#include "resource.h"
CMyApp myApp;
/////////////////////////////////////////////////////////////////////////
// CMyApp member functions
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWindow;
CSkin ii(ID_bitmap, ID_REGION);
CMainWindow* cmw = dynamic_cast<CMainWindow*>(m_pMainWnd);
cmw->SetHeight(ii.Height());
cmw->SetWidth(ii.Width());
cmw->SetBitmapId(ID_bitmap);
ii.Hook(m_pMainWnd);
ii.Enable(true);
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_PAINT()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
Create(NULL, _T("The Hello Application"));
}
void CMainWindow::OnPaint()
{
//CPaintDC dc(this);
//CRect rect;
//GetClientRect(&rect);
//dc.DrawText(_T("Hello, MFC"), -1, &rect,
// DT_SINGLELINE | DT_CENTER | DT_VCENTER);
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CFrameWnd::OnPaint() for painting messages
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap bm;
bm.LoadBitmap(BitmapId);
memDC.SelectObject(bm);
dc.BitBlt(0, 0, iWidth, iHeight, &memDC, 0, 0, SRCCOPY);
}
void CMainWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
// if (nChar == VK_ESCAPE) {
// MessageBox("we have entered here");
// //std::cout << "some stuff in here";
//}
if (nChar == VK_ESCAPE) {
PostQuitMessage(0);
}
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
// This sets the height variable of the bitmap
void CMainWindow::SetHeight(int height)
{
// TODO: Add your implementation code here.
iHeight = height;
}
// This sets the width variable of the bitmap
void CMainWindow::SetWidth(int width)
{
// TODO: Add your implementation code here.
iWidth = width;
}
// This is sets the bitmap id for the image
void CMainWindow::SetBitmapId(int bitmapid)
{
// TODO: Add your implementation code here.
BitmapId = bitmapid;
}
The error message I am getting is:
Error C2065 'SkinWndProc': undeclared identifier mfcexample2 C:\Users\samsu_kag5dbu\source\repos\mfcexample2\mfcexample2\SkinClass\skin.cpp 134
Per https://en.cppreference.com/w/cpp/language/friend :
A name first declared in a friend declaration within a class or class template X becomes a member of the innermost enclosing namespace of X, but is not visible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at namespace scope is provided - see namespaces for details.
You are declaring SkinWndProc() for the first time in skin.h as a friend of CSkin, and then both declaring and defining the actual SkinWndProc() function only in skin.cpp after the definition of CSkin::Hook() tries to use it. As such, SkinWndProc() has not actually been declared yet in the namespace that owns CSkin, so it is not visible to Hook(), which is why you are getting an "undeclared identifier" error.
To fix this, you can either:
in skin.cpp, add a forward declaration for SkinWndProc() above the definition of CSkin::Hook(), eg:
LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
bool CSkin::Hook(HWND hWnd)
{
// can now use SkinWndProc as needed...
}
LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
...
}
in skin.cpp, move the entire definition of SkinWndProc() above the definition of CSkin::Hook(), eg:
LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
...
}
bool CSkin::Hook(HWND hWnd)
{
// can now use SkinWndProc as needed...
}
in skin.h and skin.cpp, change SkinWndProc() to be a static class method instead of a standalone friend function, eg:
class CSkin
{
static LRESULT CALLBACK SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
...
};
bool CSkin::Hook(HWND hWnd)
{
// can use CSkin::SkinWndProc as needed...
}
LRESULT CALLBACK CSkin::SkinWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
...
}

DX11 DirectInput8Create causing LNK2019 error

I'm trying to create a GPU rendered particle system, and it uses this input class to handle mouse/keyboard input.
The issue is the line;
HRESULT result = DirectInput8Create(.....);
causes a LNK2019: Unresolved External Symbol error. I've included the necessary files, so I'm not sure why this is happening. Below is the Input.h and Input.cpp files respectively.
INPUT.H file
#ifndef _INPUT_
#define _INPUT_
#include <stdafx.h>
#include <dinput.h>
class Input{
private:
IDirectInputDevice8* _DIKeyboard;
IDirectInputDevice8* _DIMouse;
LPDIRECTINPUT8 _directInput;
LONG _mouseXabsolute, _mouseYabsolute, _mouseZabsolute;
LONG _mouseXrelative, _mouseYrelative, _mouseZrelative;
BYTE _keyboardState[256];
BYTE _leftMouseButton, _rightMouseButton;
int _screenWidth, _screenHeight;
HWND _hWnd;
POINT _point;
RECT _rect;
public:
Input();
~Input();
void unload();
bool initializeInput(HINSTANCE hInstance, HWND hWnd, int screenWidth, int screenHeight);
void updateInput();
BYTE* getKeyboardState();
LONG getMouseXRelative();
LONG getMouseYRelative();
LONG getMouseZRelative();
LONG getMouseXAbsolute();
LONG getMouseYAbsolute();
LONG getMouseZAbsolute();
BYTE getLeftMouseClick();
BYTE getRightMouseClick();
};
#endif
INPUT.CPP File
#include <stdafx.h>
#include <Input.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
using namespace std;
Input::Input() : _DIKeyboard(), _DIMouse(), _directInput(), _point(), _rect(){
_mouseXabsolute = _mouseYabsolute = 0;
_mouseZabsolute = 1;
_mouseXrelative = _mouseXrelative = _mouseXrelative = 0;
}
Input::~Input(){
unload();
}
void Input::unload(){
if (_DIKeyboard) _DIKeyboard->Release();
if (_DIMouse) _DIMouse->Release();
if (_directInput) _directInput->Release();
}
bool Input::initializeInput(HINSTANCE hInstance, HWND hWnd, int screenWidth, int screenHeight){
_screenWidth = screenWidth;
_screenHeight = screenHeight;
_hWnd = hWnd;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////Create direct input, keyboard and mouse devices///////////////////////////////////////////////////
HRESULT result = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_directInput, NULL);
if (FAILED(result)){
MessageBox(0, L"Could not create direct input!", L"Error", MB_OK);
return false;
}
...
...
...
}
I'd appreciate any help to solve this issue.
You should link to dinput8.lib static library:
#pragma comment(lib, "dinput8")
Besides, you should consider using Raw input APIs instead of DirectInput: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx

Solve/Debug unhandled exception error with visual C++ 2008?

I'm making a dll that in the end will need to had some activeX (in this case a activeX contol from a third party) commands in the Window.
When I test the DLL in a solution I get:
"
Process attachFirst-chance exception at 0x076b00bc in SamsungTester.exe: 0xC0000005: Access violation.
Unhandled exception at 0x076b00bc in SamsungTester.exe: 0xC0000005: Access violation.
"
my code I have a class that extends a CDialog ("myDialog.g")
class myDialog : public CDialog
{
DECLARE_DYNAMIC(myDialog)
public:
myDialog(CWnd* pParent = NULL); // standard constructor
virtual ~myDialog();
// Dialog Data
enum { IDD = IDD_DIALOG1 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
CXnssdkdevicectrl1 m_ctrlXnsDevice;
long initializeSDK();
};
Then other class that extends a CWinApp
class CMyMFCDLLApp : public CWinApp
{
public:
HANDLE recMutex;
CMyMFCDLLApp();
// Overrides
public:
virtual BOOL InitInstance();
myDialog dlg;
DECLARE_MESSAGE_MAP()
};
then in CPP
#include "stdafx.h"
#include "MyMFCDLL.h"
#include "mydialog.h";
#include "dllDeclaration.h"
#include "Test.h"
#include <initguid.h>
#include "MyMFCDLL_i.c"
// [ XNS ACTIVEX HELP ]
// -----------------------------------------------------------------------
// This files are installed in {$SDK path}\sample_code\include
// You should include this files
// -----------------------------------------------------------------------
#include "XnsCommon.h"
#include "XnsDeviceInterface.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
class CMyMFCDLLModule :
public CAtlMfcModule
{
public:
DECLARE_LIBID(LIBID_MyMFCDLLLib);
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MYMFCDLL, "{1AFA86BF-3CCC-4A17-B023-F61E8DE38ED6}");};
CMyMFCDLLModule _AtlModule;
BEGIN_MESSAGE_MAP(CMyMFCDLLApp, CWinApp)
END_MESSAGE_MAP()
CMyMFCDLLApp::CMyMFCDLLApp()
{
}
BOOL CMyMFCDLLApp::InitInstance()
{
CWinApp::InitInstance();
AtlAxWinInit();
COleObjectFactory::RegisterAll();
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
AfxOleInit();
AfxEnableControlContainer();
CoInitialize(0);
recMutex=CreateEvent(NULL, FALSE,FALSE, NULL);
return TRUE;
}
long init2(){
AFX_MANAGE_STATE(AfxGetStaticModuleState());
theApp.dlg.Create(myDialog::IDD);
theApp.dlg.ShowWindow(SW_SHOW);
theApp.dlg.initializeSDK();
return 0;
}
When I put the activeX control using in Cdialog this .h is generated:
#pragma once
// ÄÄÇ»ÅÍ¿¡¼­ Microsoft Visual C++¸¦ »ç¿ëÇÏ¿© »ý¼ºÇÑ IDispatch ·¡ÆÛ Å¬·¡½ºÀÔ´Ï´Ù.
// Âü°í: ÀÌ ÆÄÀÏÀÇ ³»¿ëÀ» ¼öÁ¤ÇÏÁö ¸¶½Ê½Ã¿À. Microsoft Visual C++¿¡¼­
// ÀÌ Å¬·¡½º¸¦ ´Ù½Ã »ý¼ºÇÒ ¶§ ¼öÁ¤ÇÑ ³»¿ëÀ» µ¤¾î¾¹´Ï´Ù.
/////////////////////////////////////////////////////////////////////////////
// CXnssdkdevicectrl ·¡ÆÛ Å¬·¡½ºÀÔ´Ï´Ù.
class CXnssdkdevicectrl : public CWnd
{
protected:
DECLARE_DYNCREATE(CXnssdkdevicectrl)
public:
CLSID const& GetClsid()
{
static CLSID const clsid
= { 0xXPTO, 0xXPTO, 0xXPTO, { 0xXP, 0xXP, 0xXP, 0xXP, 0xXP, 0xXP, 0xXP, 0xXP } };
return clsid;
}
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
const RECT& rect, CWnd* pParentWnd, UINT nID,
CCreateContext* pContext = NULL)
{
return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID);
}
BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,
UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE,
BSTR bstrLicKey = NULL)
{
return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
pPersist, bStorage, bstrLicKey);
}
// Ư¼ºÀÔ´Ï´Ù.
public:
// ÀÛ¾÷ÀÔ´Ï´Ù.
public:
// _DXnsSdkDevice
// Functions
//
long Initialize()
{
long result;
InvokeHelper(0x1, DISPATCH_METHOD, VT_I4, (void*)&result, NULL);
return result;
}
To initialize the activeX i call the InitializeSDK that call activeX Initialize function that calls an Invoker:
InvokeHelper(0x1, DISPATCH_METHOD, VT_I4, (void*)&result, NULL);
and then give an exception at:
// make the call
SCODE sc = m_lpDispatch->Invoke(dwDispID, IID_NULL, 0, wFlags,
&dispparams, pvarResult, &excepInfo, &nArgErr);

2 x "LNK2019: unresolved external symbol" errors when compiling

I get the below two linking errors when I try to compile in VS 2010. I have ensured that my include & library settings are correct in the project properties > VC ++ Directories & also checked to make sure that Project > Linker > Input has d3d9.lib & d3dx9.lib in it which it does.
I've also tried adding #pragma comment for the two above libraries in D3DGraphics.h but to no avail :(
The compile errors....
1>D3DGraphics.obj : error LNK2019: unresolved external symbol _Direct3DCreate9#4 referenced in function "public: long thiscall D3DGraphics::SetupD3D(struct HWND *)" (?SetupD3D#D3DGraphics##QAEJPAUHWND__###Z)
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall FIREWORKCLASS::FIREWORKCLASS(struct IDirect3DDevice9 *)" (??0FIREWORKCLASS##QAE#PAUIDirect3DDevice9###Z) referenced in function "void __cdecl SetupFirework1(void)" (?SetupFirework1##YAXXZ)
... : fatal error LNK1120: 2 unresolved externals
Full program structure below...
D3DGraphics.h
#include <d3d9.h> // necessary Direct3D libraries
// Global pointer to the Direct 3D device
extern IDirect3DDevice9* g_pd3dDevice;
// Used to create the Direct3D object
extern IDirect3D9* g_pD3D;
class D3DGraphics
{
public:
// Global pointer to the Direct3D object
IDirect3D9* g_pD3D;
// Global pointer to the Direct 3D device
IDirect3DDevice9* g_pd3dDevice;
//The class constructor - executes whenever an instance is created.
//D3DGraphics() { /* does nothing */ }
// Method to setup D3D parameters
HRESULT SetupD3D ( HWND hWnd );
// Destructor.
// A method that executes when an instance is destroyed.
~D3DGraphics();
void Render();
void Cleanup(); // close Direct3D and release resources
};
D3DGraphics.cpp
#include "D3DGraphics.h"
// Global pointer to the Direct 3D device
IDirect3DDevice9* g_pd3dDevice;
// Used to create the Direct3D object
IDirect3D9* g_pD3D;
//// Constructor code
//D3DGraphics :: D3DGraphics()
//{
//
//}
// TYPE Classname :: MethodName
HRESULT D3DGraphics :: SetupD3D ( HWND hWnd)
{
// Create a D3D object called g_pD3D, return a fail message if this can't be done.
if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL;
/* *** Setup a data structure of paramteres to create the Direct3D device *** */
// data structure is called d3dpp
D3DPRESENT_PARAMETERS d3dpp;
// used to clear all data from the structure to ensure no spurious values will be used
ZeroMemory( &d3dpp,sizeof( d3dpp ) );
// application will be windowed
d3dpp.Windowed = TRUE;
// back to front buffer behavior - DISCARD = random data used for error checking
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
// back buffer format - UNKNOWN = use current display resolution to retain consistency
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// D3D device to create and manage depth and stencil buffer automatically
d3dpp.EnableAutoDepthStencil = TRUE;
// format of the surfaces which hold the depth & stencil buffers - D16 = 16Bit colours
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
////////////* ***END data structure creation*** *////////////
/* *** Create the Direct3D Device using the defined parameters from the data strucutre d3dpp *** */
// Create the Direct3D Device and return a pointer to it, or return E_FAIL if it can't be created
if (FAILED(g_pD3D -> CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pd3dDevice)))
{
return E_FAIL;
}
// Enable the Z buffer
g_pd3dDevice -> SetRenderState(D3DRS_ZENABLE, TRUE);
return S_OK;
}
// Destructor code
D3DGraphics :: ~D3DGraphics()
{
//???
}
void D3DGraphics :: Cleanup()
{
//release the D3DDevice creation resources
if (g_pD3D != NULL) g_pD3D -> Release();
//release the rendering device creation resources
if (g_pd3dDevice !=NULL) g_pd3dDevice -> Release();
// Render the frame to the back buffer.
}
/* *** The Render cycle for drawing graphics on the screen *** */
void D3DGraphics :: Render()
{
// black background colour
DWORD BackgroundColour = 0x0000000;
// Clear the contents of the backbuffer & Zbuffer and set its colour.
g_pd3dDevice -> Clear(0, // 0 rectangles to be cleared
NULL, // no array of rectangle coordinates
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, // which buffers should be cleared
BackgroundColour, // the background colour to use, defined as black 0x0000000
1.0f, // Z buffer value
0); // stencil buffer value
// Begin rendering the scene.
if (SUCCEEDED(g_pd3dDevice -> BeginScene()))
{
/// ...GRAPHICS ARE DRAWN HERE...///
// end the rendering
g_pd3dDevice -> EndScene();
}
// Present the backbuffer to the display.
g_pd3dDevice -> Present(NULL, NULL, NULL, NULL);
}
////////////* *** END The Render cycle *** *////////////
Fireworks.h
#include "D3DGraphics.h"
#include <d3dx9math.h> // required in this file for D3DXVECTOR3
// class for a single firework spark
class SPARKCLASS
{
public:
SPARKCLASS();
D3DXVECTOR3 Position;
float XVelocity, YVelocity, ZVelocity;
float Time;
int LifeTime;
};
// max number of sparks that can exist in the system
const int MaxNumberOfSparks = 500;
// class for the firework particle system
class FIREWORKCLASS
{
public:
FIREWORKCLASS (LPDIRECT3DDEVICE9);
void Update();
void Render();
float LaunchAngle;
float LaunchVelocity;
float ParticleSize;
int Lifetime;
int StartInterval, StartCounter, NumberToStart;
float TimeIncrement;
D3DCOLOR SparkColour;
D3DXVECTOR3 Origin;
private:
//array of sparks
SPARKCLASS Sparks[MaxNumberOfSparks];
//starts a new particle
void StartParticle(int);
//counter for the number of sparks that are alive
int SparksAlive;
//vertex buffer for the points
LPDIRECT3DVERTEXBUFFER9 pPointBuffer;
//the Direct3D Deice onto which sparks will be rendered
LPDIRECT3DDEVICE9 pRenderTarget;
};
struct POINTVERTEX
{
D3DXVECTOR3 Position;
D3DCOLOR Colour;
};
// the structure of a vertex in our vertex buffer
#define D3DFVF_POINTVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
Fireworks.cpp
#include "Fireworks.h"
void FIREWORKCLASS :: StartParticle(int P)
{
// set this spark's lifetime to the maximum
Sparks[P].LifeTime = Lifetime;
Sparks[P].Time = 0.0f;
Sparks[P].Position.x = 0;
Sparks[P].Position.y = 0;
Sparks[P].Position.z = 0;
// select a random angle around a circle
float DirectionAngle = (float)rand()/(180/D3DX_PI);
//calculate the vertical component of velocity
Sparks[P].YVelocity = LaunchVelocity
* (float)sin(LaunchAngle);
//calculate the horizontal components of velocity - X & Z
Sparks[P].XVelocity = LaunchVelocity
* (float)sin(LaunchAngle)
* (float)cos(DirectionAngle);
Sparks[P].ZVelocity = LaunchVelocity
* (float)sin(LaunchAngle)
* (float)cos(DirectionAngle);
//since another spark now exists, increment the spark counter
SparksAlive++;
}
void FIREWORKCLASS :: Render()
{
//enable point sprites and set the size of the point
pRenderTarget -> SetRenderState(D3DRS_POINTSPRITEENABLE, true);
pRenderTarget -> SetRenderState(D3DRS_POINTSCALEENABLE, true);
pRenderTarget -> SetRenderTarget(D3DRS_LIGHTING, false);
//scale the points according to distance
pRenderTarget -> SetRenderState(D3DRS_POINTSIZE,
FtoDW(ParticleSize));
pRenderTarget -> SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
pRenderTarget -> SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
//render the contents of the vertex buffer
pRenderTarget -> SetStreamSource(0, pPointBuffer, 0,
sizeof(POINTVERTEX));
pRenderTarget -> SetFVF(D3DFVF_POINTVERTEX);
pRenderTarget -> DrawPrimitive(D3DPT_POINTLIST, 0, 0); // 0, ??
//reset the render states
pRenderTarget -> SetRenderState(D3DRS_POINTSPRITEENABLE, false);
pRenderTarget -> SetRenderState(D3DRS_POINTSCALEENABLE, false);
pRenderTarget -> SetRenderState(D3DRS_LIGHTING, true);
}
* Main.cpp *
#define D3D_DEBUG_INFO // Enable debugging information
#include "Windows.h"
#include "Fireworks.h"
//global pointer to Firework1 object
FIREWORKCLASS *g_Firework1 = NULL;
void SetupFirework1()
{
g_Firework1 = new FIREWORKCLASS(g_pd3dDevice);
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> Origin.x = 0.0f;
g_Firework1 -> StartInterval = 10;
g_Firework1 -> StartCounter = 10;
g_Firework1 -> LaunchAngle = D3DXToRadian(80);
g_Firework1 -> LaunchVelocity = 40.0f;
g_Firework1 -> TimeIncrement = 0.04f;
g_Firework1 -> Lifetime = 200;
g_Firework1 -> NumberToStart = 8;
g_Firework1 -> ParticleSize = 2.0f;
g_Firework1 -> SparkColour = 0x00FFE000; // yellow
}
// The window's message handling function.
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
// The user has clicked on the 'close' button on the window's title bar.
// Send a 'WM_QUIT' message to the application to close it down.
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// WinMain() - The application's entry point.
// This sort of procedure is mostly standard, and could be used in most
// DirectX applications.
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
/* ***Create the application window*** */
// Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Blank", NULL};
RegisterClassEx(&wc);
// Create the application's window
HWND hWnd = CreateWindow( "Blank", "---Fireworks---",
WS_OVERLAPPEDWINDOW, 100, 100, 800, 800, // ?, ?, size(x), size(y)
GetDesktopWindow(), NULL, wc.hInstance, NULL);
/* ***END application window creation*** */
// Create an instance of the D3DGraphics class called D3D
D3DGraphics D3D;
// Initialize Direct3D
if (SUCCEEDED(D3D.SetupD3D(hWnd)))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
// Respond to messages until a 'WM_QUIT' message is received.
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
// g_Firework1 -> Update(); // update Firework1 particles
D3D.Render(); // render the scene
}
// Execute the class destructor to clear any resources that
// D3DGraphics class has created/used.
D3D.Cleanup();
}
UnregisterClass("Blank", wc.hInstance);
return 0;
}

Drawing a jpg in MFC

I've been trying to show a jpg image in MFC, but I can't get it drawn. I'm a complete MFC newbie an everything I got up until now is mostly adapted from things I found on the net. Currently I have this:
Picture.h:
#pragma once
#include <afxwin.h>
class Picture
{
public:
Picture();
bool load(LPCTSTR filePath);
bool draw( CDC* deviceContext
, CRect clientRect
, LPCRECT prcMFBounds);
CSize getSize(CDC* pDC);
private:
LPPICTURE m_picture;
};
Picture.cpp:
#include "Picture.h"
Picture::Picture()
: m_picture(0)
{
}
bool Picture::load(LPCTSTR szFile)
{
HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return false;
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == (DWORD)-1)
{
CloseHandle(hFile);
return false;
}
LPVOID pvData = NULL;
// alloc memory based on file size
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
if (hGlobal == NULL)
{
CloseHandle(hFile);
return false;
}
pvData = GlobalLock(hGlobal);
if (pvData == NULL)
{
GlobalUnlock(hGlobal);
CloseHandle(hFile);
return false;
}
DWORD dwBytesRead = 0;
// read file and store in global memory
bool bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL) != 0;
GlobalUnlock(hGlobal);
CloseHandle(hFile);
if (!bRead)
return false;
LPSTREAM pstm = NULL;
// create IStream* from global memory
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
if (!(SUCCEEDED(hr)))
{
if (pstm != NULL)
pstm->Release();
return false;
}
else if (pstm == NULL)
return false;
// Create IPicture from image file
if (m_picture)
m_picture->Release();
hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&(m_picture));
if (!(SUCCEEDED(hr)))
{
pstm->Release();
return false;
}
else if (m_picture == NULL)
{
pstm->Release();
return false;
}
pstm->Release();
return true;
}
bool Picture::draw(CDC* deviceContext, CRect clientRect, LPCRECT prcMFBounds)
{
if (clientRect.IsRectNull())
{
CSize imageSize = getSize(deviceContext);
clientRect.right = imageSize.cx;
clientRect.bottom = imageSize.cy;
}
long pictureWidth = 0;
long pictureHeigth = 0;
m_picture->get_Width(&pictureWidth);
m_picture->get_Height(&pictureHeigth);
m_picture->Render( *deviceContext
, clientRect.left
, clientRect.top
, clientRect.Width()
, clientRect.Height()
, 0
, pictureHeigth
, pictureWidth
, -pictureHeigth
, prcMFBounds);
return true;
}
CSize Picture::getSize(CDC* deviceContext)
{
if (!m_picture)
return CSize(0,0);
LONG width, height; // HIMETRIC units
m_picture->get_Width(&width);
m_picture->get_Height(&height);
CSize size(width, height);
if (deviceContext==NULL)
{
CWindowDC dc(NULL);
dc.HIMETRICtoDP(&size); // convert to pixels
}
else
{
deviceContext->HIMETRICtoDP(&size);
}
return size;
}
PictureView.h:
#pragma once
#include <afxwin.h>
#include <string>
class Picture;
class PictureView : public CStatic
{
public:
PictureView(std::string path);
protected:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
private:
Picture* m_picture;
};
PictureView.cpp:
#include "PictureView.h"
#include "Picture.h"
PictureView::PictureView(std::string path)
{
m_picture = new Picture();
m_picture->load(path.c_str());
}
void PictureView::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
{
CRect rect;
GetClientRect(&rect);
m_picture->draw(GetDC(), rect, rect);
}
Constructor call:
CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId)
{
PictureView* image = new PictureView(path);
image->Create("", SS_OWNERDRAW, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId);
return image;
}
The problem is that I can't get the DrawItem function to be called. What am I doing wrong?
Any help will be appreciated.
Here's an easy way to draw an image in an MFC dialog box:
link with gdiplus.dll
#include "atlimage.h>
#include "gdiplus.h>
using namespace Gdiplus
.
.
.
CImage ci;
ci.Load((CString)"D:\\Pictures\\mycat.jpg");
CDC *dc = AfxGetMainWnd()->GetDC();
HDC hdc = *dc;
ci.Draw(hdc,10,10);
Hope it works!
with the help of a colleague of mine I've found the answer. He told me it's not possible to have an ownerdrawn CStatic. So when I now inherit PictureView from CButton and make it BS_OWNERDRAW my image is rendered.
Personally I think this is an ugly solution but I'm so tired of this problem now that I don't really care that much. These are the changes I've made to make it work:
Constructor call:
CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId)
{
PictureView* image = new PictureView(path);
image->Create("", BS_OWNERDRAW | WS_CHILD | WS_VISIBLE, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId);
return image;
}
PictureView.h:
#pragma once
#include <afxwin.h>
#include <string>
class Picture;
class PictureView : public CButton
{
public:
PictureView(std::string path);
protected:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
private:
Picture* m_picture;
};
Thank's everybody for all the help.
I'm not sure that the GetDC in the call to m_picture->draw will necessarily refer to the same DC that's given in the CREATESTRUCT. What I've done is:
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
EDIT: Since I can't comment, hopefully an edit will suffice. I think your colleague is mistaken, as I just recently implemented a CStatic control using SS_OWNERDRAW. I'm guessing that the addition of WS_CHILD | WS_VISIBLE on the Create call is key.
I've never used MFC but a quick perusal of the CStatic::DrawItem documentation says that it must be created with the SS_OWNERDRAW style for DrawItem to get called. You haven't shown the Create line for your PictureView so perhaps it's that?