D3DApp Class Problems - c++

So I am in the process of creating a WNDCLASSEX within a method contained in D3DApp class which I am going to be deriving from with another class e.g. Engine, Game, etc... called InitMainWindow (which is also protected in the base class):
bool D3DApp::InitMainWindow() {
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc; // This is where the error is!
wc.hInstance = mAppInst;
wc.hCursor = LoadCursor(mAppInst, IDC_ARROW);
wc.lpszClassName = L"MainWindow";
RegisterClassEx(&wc);
RECT rect = { 0,0,SCREEN_WIDTH,SCREEN_HEIGHT };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
mMainWnd = CreateWindowEx(NULL, L"MainWindow", L"Test", WS_OVERLAPPEDWINDOW, 300, 300, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, mAppInst, NULL);
ShowWindow(mMainWnd, NULL);
return true;
}
My WNDPROC Callback declaration and definition is within the same D3DApp base class where InitMainWindow() is located, defined as such:
virtual LRESULT WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
When I am filling out the lpfnWndProc variable within the WNDCLASSEX struct I receive a C2440 error stating the following
'=': cannot convert from 'LRESULT (__cdecl D3DApp::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
Do I have to create a definition of my WNDPROC Callback in the class deriving from D3DApp? Or do I have to completely remove this callback from the base class and derived class and place it outside and above the scope of my WinMain function? I've been researching for about 2 days on how to fix this error and have had no luck on finding any possible fixes... I think my C++ skills just may not be as excellent as I think they are. But if anyone can help me understand where my problem is that would be amazing!
p.s and yes I know I have some error checking to do but I just want to make sure it works for my compiler first :)

Here's the signature of WNDPROC:
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
but your declaration is different:
LRESULT WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
You should either declare it outside of the class like this:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
or declare it as static and remove virtual keyword. Also notice, you should add CALLBACK which resolves to __stdcall calling convention as your project is configured to use __cdecl calling convention

Related

__stdcall in function paramater [duplicate]

This question already has answers here:
How to declare an __stdcall function pointer
(1 answer)
Function pointer and calling convention
(3 answers)
Closed 8 months ago.
does anybody know if is possible to add __stdcall (CALLBACK) in function parameter like this?:
void Function(LRESULT CALLBACK (*f)(HWND, UINT, WPARAM, LPARAM));
It gives me following error:
a calling convention may not be followed by a nested declarator
Any solutions?
Thx in advance <3
Put the calling convention inside the parenthesis.
void Function(LRESULT (CALLBACK *f)(HWND, UINT, WPARAM, LPARAM));
Usually it is seen in the manual, for example CallWindowProcW function
the lpPrevWndFunc parameter has the data type WNDPROC. The WNDPROC type is declared as follows:
LRESULT (CALLBACK* WNDPROC) (HWND, UINT, WPARAM, LPARAM);
Thus, the correct syntax is (WNDPROC -> f)
void Function(LRESULT (CALLBACK* f)(HWND, UINT, WPARAM, LPARAM));

Storing a function pointer as a member within a class

I created this account to ask a question because I'm pretty lost right now and I couldn't find an answer. I'm not sure if what I'm trying to do is even possible, or perhaps I'm taking an incorrect approach.
I'm writing a windows socket wrapper class for asynchronous sockets, mostly so I never have to write this code again, and I'm trying to store a function pointer as a member variable inside my netcode class that points to a windows event handler that's called inside the application's normal win32 message pump that points elsewhere. Basically, I'm trying to create a programmer-defined callback function so that when I compile this netcode class into a .dll I never have to touch it again.
As a clarification, what I'm trying to do is, for example, write the event handler for WM_SOCKET (which is a windows message I have defined) somewhere other than inside the network code class (so it can be portable to different win32/C++ projects) and outside of the main win32 message pump (so my WndProc() doesn't become absolutely massive).
I don't even know what to search for, but all of the information I'm finding is about creating a pointer to a member function or a member of a template, which isn't what I want.
Here's the code I've already tried to write (only the relevant bits), which is what is giving me problems. I'm probably royally screwing something up here.
//// Sockets.h
class NetworkConnection
{
private:
void (*WMSocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
public:
void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));
};
//// Sockets.cpp
#include "Sockets.h"
void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))
{
WMSocketFunction = SocketFunction;
};
void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WMSocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
}
//// Application.cpp
void SocketEventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Do socket stuff here
};
int SetupApp()
{
NetworkConnection NetConnection;
NetConnection.registerSocketFunction(&SocketEventHandler);
return 0;
}
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
case WM_SOCKET:
{
NetConnection.HandleEvents(hwnd, msg, wParam, lParam);
break;
}
case WM_DESTROY:
{
ReleaseDevices();
break;
}
case WM_KEYDOWN:
{
#ifdef _DEBUG
if (lParam == VK_ESCAPE)
PostQuitMessage(0);
#endif
}
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
I'd be really grateful for some help, here. I totally have no clue why this isn't working.
The errors I receive are:
Error 1 error C2440: '=' : cannot convert from 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' sockets.cpp (in function registerSocketFunction)
Error 2 error C2275: 'HWND' : illegal use of this type as an expression sockets.cpp (in function HandleEvents)
Error 3 error C2146: syntax error : missing ')' before identifier 'hwnd' sockets.cpp (in function HandleEvents)
Error 4 error C2059: syntax error : ')' sockets.cpp (in function HandleEvents)
Error 8 error C2664: 'NetworkConnection::registerSocketFunction' : cannot convert parameter 1 from 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' application.cpp
If you need any better explanation, because I've likely explained this problem poorly, please don't hesitate to ask.
I'm using Visual Studio 2010, so I don't think I can use C++/11 features like std::function.
Exclude arguments names from function pointer declaration
Use typedef to make code cleaner
typedef void(*WMSocketFunction_Ptr)(HWND, UINT, WPARAM, LPARAM);
class NetworkConnection
{
private:
WMSocketFunction_Ptr WMSocketFunction;
public:
void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void registerSocketFunction(WMSocketFunction_Ptr SocketFunction);
};
void NetworkConnection::registerSocketFunction(WMSocketFunction_Ptr SocketFunction)
{
WMSocketFunction = SocketFunction;
};
Prefer to use STL facilities to naked pointers: std::function of boost::function
typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr;
You have to enclose the function pointer name in brackets like this: void (*SocketFunction)(...)
So instead of your method declaration:
void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));
You have to write:
void registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam));
Also rewrite your method body to this:
void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND, UINT, WPARAM, LPARAM))
{
WMSocketFunction = SocketFunction;
};
Next thing, i think your HandleEvents is unfinished yet, you have a syntax error there, i think you wanted to call the function behind the pointer.
void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WMSocketFunction(hwnd,msg,wParam,lParam);
}
Here is my suspicion. I think the way you've declared the function argument SocketFunction for registerSocketFunction is wrong.
void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))
should be,
void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))
I ran a similar test on GCC, and it threw a similar error, so this might be your problem.

Error LNK2019 during linking in VS2010

I began C++ quite recently and I obviously have the famous LNK2019 issue. I roamed a few hours on google but nothing solved my problem.
My project is half way coded, since I separate the view and the model.
I work with Visual Studio 2010.
Here is the class whose function is not retrieved:
Display.h:
#ifndef DEF_DISPLAY
#define DEF_DISPLAY
#include <Windows.h>
#include <exception>
class Display{
public:
HWND mainWindow, gameWindow;
WNDCLASS mainClass, gameClass;
public:
Display();
static LRESULT CALLBACK mainWindowProc(HWND mainWin, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK gameWindowProc(HWND gameWin, UINT message, WPARAM wParam, LPARAM lParam);
**int run();** // This function is not retrieved by the linker.
};
#endif
And here is the Display.cpp:
#include "Display.h"
HINSTANCE instanceMain = 0, instanceGame = 0;
Display::Display(){...}
LRESULT CALLBACK Display::mainWindowProc(HWND mainWin, UINT message, WPARAM wParam, LPARAM lParam){...}
LRESULT CALLBACK Display::gameWindowProc(HWND gameWin, UINT message, WPARAM wParam, LPARAM lParam){...}
int run(){
MSG message;
while(GetMessage(&message, 0, 0, 0)){
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
And finally here is my main.cpp:
#include "Display.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow){
Display game;
return game.run();
}
I did not finished to code my project because I found out that issue when building it:
1> All outputs are up-to-date.
1>main.obj : error LNK2019: unresolved external symbol "public: int __thiscall Display::run(void)" (?run#Display##QAEHXZ) referenced in function _WinMain#16
1>C:\Users\glembalis\Documents\Visual Studio 2010\Projects\pendu\Debug\pendu.exe : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED.
I don't know where the error can occur.
Display.h and Display.cpp are included in the project
The option in Project > Properties > Linker > System > SubSystem is "Windows"
I do not use external libraries (only Windows.h and exception)
The compiler seems to work well. I don't really care if the program works properly, I would correct it later. For now, this linker issue is my major concern! I guess it is just a tiny little stupid mistake, but I cannot find it out!
Thanks to everyone for your time and attention, looking forward to have your answers! Last, I apologise but english is not my native language and I may have written some mistakes.
Have a nice day!
NoobFeeder
Your definition (implementation) has the wrong signature.
It should look like this:
int Display::run(){
This tells the compiler that your run is the one that's a member of your Display class.
Currently you have implemented a free function called run.

"Unresolved external _WinMain#16" if I move WndProc to another cpp file

For a Windows application I'm trying to get CreateWindow() and WndProc() (or my versions of them) to be part of a singleton class that is created at the beginning of _tWinMain() but since trying to shift the functions to GameHandler.h and GameHandler.cpp I keep getting "unresolved external symbol _WinMain#16". They were originally global functions in main.cpp and everything was compiling fine then I decided to move them to GameHandler and ever since all I get is the unresolved external, even if I try to move them back to main.cpp.
I'm doing this in VS2010, the project was created as a Windows Application and there's no specific entry point set in properties (I double checked as every solution I've found so far says that it's because it's a console app - this isn't).
The code I currently have is shown below. The actual project has a couple of thousand lines of other code that I've left out as I don't think it's relevant (but will happily proved wrong. While the actual window creation code is related, I don't think the code itself is the problem (apart from what I left in), it's the location of GameWindowProc() &/or CreateGameWindow() or how they're called. The actual window creation code is taken from NeHe's tutorial. Trying to compile the following code only gives the aforementioned unresolved external.
main.cpp:
#include <Windows.h>
#include "GameManager.h"
#ifndef USEGMGR
bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
LRESULT CALLBACK GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPTSTR lpCmdLine, int nCmdShow)
{
GameManager::Startup();
GameManager* GMgr = GameManager::GetInstance();
GMgr->SetProgramState(GAME_MODE);
while(GMgr->GetProgramState() != GAME_MODE) // Normally this would be if (State != GAME_QUIT)
{ /* do game related stuff */ }
GameManager::Shutdown();
return 0;
}
#ifndef USEGMGR
bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag)
{
// Fairly complex but flexible creation code, taken from NeHe's tutorials. Of relevant interest is:
WNDCLASS wc; // Windows Class Structure
wc.lpfnWndProc = (WNDPROC) GameWindowProc; // WndProc Handles Messages
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return false;
}
return true;
}
LRESULT CALLBACK GameWindowProc(HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
// various custom message handling, if not processed:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
#endif
in GameManager.h:
#ifndef GAMEMANAGER_H
#define GAMEMANAGER_H
#define USEGMGR // makes CreateGameWindow() and GameWindowProc() methods in GameManager instead of global
#include <Windows.h>
enum ProgramState
{
GAME_MODE,
GAME_QUIT,
};
class GameManager
{
public:
static void Startup();
static void Shutdown();
static GameManager* GetInstance();
void Update(); // code not shown, check quit key etc
#ifdef USEGMGR
const bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
static LRESULT CALLBACK GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
void KillGameWindow(void);
const int GetProgramState() const;
void SetProgramState(const int& newMode);
private:
GameManager();
~GameManager();
GameManager(const GameManager&);
GameManager& operator=(const GameManager&);
HINSTANCE m_hInstance;
HWND m_hWnd;
HDC m_hDC;
static GameManager* s_instance;
int m_programState; // uses ProgramState enum
};
#endif
in GameManager.cpp:
#include "GameManager.h"
#include <Windows.h>
#include <assert.h>
#ifndef USEGMGR
extern bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
#endif
GameManager* GameManager::s_instance = NULL;
GameManager::GameManager(){}
GameManager::~GameManager(){}
void GameManager::Startup()
{
assert(s_instance == NULL);
s_instance = new GameManager;
#ifdef USEGMGR
if (! (s_instance->CreateGameWindow("Game Window", 800, 600, 32, true )) )
#else
if (! (CreateGameWindow("Game Window", 800, 600, 32, true )) )
#endif
assert("CreateGameWindow failed! Need an error here"); // Quit If Window Was Not Created - clean this up later
}
void GameManager::Shutdown()
{
assert(s_instance != NULL);
delete s_instance;
s_instance = NULL;
}
GameManager* GameManager::GetInstance(){return s_instance;}
void GameManager::Update(){/* msg handling, watch for quit key, etc */}
const int GameManager::GetProgramState() const{return s_instance->m_programState;}
void GameManager::SetProgramState(const int& newState){s_instance->m_programState = newState;}
#ifdef USEGMGR
const bool GameManager::CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag)
{
// Fairly complex but flexible creation code, taken from NeHe's tutorials. Of relevant interest is:
WNDCLASS wc; // Windows Class Structure
wc.lpfnWndProc = (WNDPROC) GameManager::GameWindowProc; // WndProc Handles Messages
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return false;
}
return true;
}
LRESULT CALLBACK GameManager::GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// various custom message handling, if not processed:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
#endif
As you can see, I've set up some preprocessor conditionals to switch between the troublesome functions being in main.cpp or as part of GameManager. Comment out #define USEGMGR at the beginning of GameManager.h to have them as global funcs in main.cpp.
Can someone please tell me what I'm doing wrong?
Edit: removed comment about not being able to quit if you get it to run.
The WinMain function cannot be a member function of a class, even a "singleton" class.
Since it functions as the "entry point" for the program, essentially replacing the main function you'd find in a traditional C++ application, it needs to be a free global function.
The message Unresolved external _WinMain#16 is simply the compiler's cryptic way of telling you that it cannot locate the expected entry point, named WinMain (plus some name mangling).
Add
#include <tchar.h>
to the top of main.cpp so that the _tWinMain macro gets defined properly.
What happens if you don't have the macro definition is that you end up with a function named _tWinMain() (or some mangled version of the name like ?_tWinMain##YGHPAUHINSTANCE__##0PADH#Z()) in the object file, but the linker and runtime initialization code are looking for WinMain() or wWinMain(). They don't find it.
<tchar.h> defines a macro that transforms the name _tWinMain() into one of the two names everything else is looking for. You must have had something including that header before you started your refactoring (quite possibly indirectly), and lost it somehow.
Or you can dispense with the macro version and name the function WinMain or wWinMain (either one should work, regardless of whether you're building for UNICODE or not). If you do that, just remember to change the LPTSTR parameter declaration to match the one you choose.

C2440 Can't convert LRESULT to WNDPROC in C++ WinApi

I'm trying to write this win32 program with WinApi and I'm stuck because the tutorial I'm following seems to have a problem.
MainWindow.h:
class MainWindow
{
public:
MainWindow(HINSTANCE);
~MainWindow(void);
LRESULT CALLBACK WndProcedure(HWND, UINT, WPARAM, LPARAM);
// [...]
MainWindow.cpp:
MainWindow::MainWindow(HINSTANCE hInstance) : hwnd(0)
{
WNDCLASSEX WndClsEx;
// [...]
WndClsEx.lpfnWndProc = &MainWindow::WndProcedure;
// [...]
}
LRESULT CALLBACK MainWindow::WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// [...]
}
I must be referencing MainWindow::WndProcedure wrong because I'm following the signature exactly as the tutorial says, however the lpfnWndProc line in the constructor gives a compile-time error:
error C2440: '=' : cannot convert from 'LRESULT (__stdcall MainWindow::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
replace
LRESULT CALLBACK WndProcedure(HWND, UINT, WPARAM, LPARAM);
by
static LRESULT CALLBACK WndProcedure(HWND, UINT, WPARAM, LPARAM);
The this pointer is a hidden parameter in your function call and by declaring it static the this pointer is not a parameter anymore and the signature of the two functions match.
That's because your WndProcedure function must be either a global function or a static member function.
You can't use a non-static member function as a window procedure. If you declare WndProcedure as static it should compile. A non-member function would work as well.
Non-static member functions have a different signature than static members. This is because they receive an implicit this parameter in addition to the explicitly defined parameters.