I am at my wit's end with this thing. I just can't figure out, why I cannot set the WNDCLASSEX.lpfnWndProc equal to my class's function. Can someone help? Here's my code:
system.h

#ifndef SYSTEM_H
#define SYSTEM_H

#include "stdinc.h"

class System {
  private:
    void initD3D (void);
    void cleanD3D (void);
    LRESULT CALLBACK WindowProc(UINT, WPARAM, LPARAM);
    void setUpHWND (HINSTANCE, LPSTR, int);

    HWND window;
    WNDCLASSEX windowClass;
    LPDIRECT3D9 d3d;
    LPDIRECT3DDEVICE9 d3ddev;

    HINSTANCE hInstance;
    LPSTR lpCmdLine;
    int nCmdShow;
  public:
    System (void);
    System (HINSTANCE, LPSTR, int);
    System (const System&);
    ~System (void);

    void renderFrame (void);
};

#endif

system.cpp

#include "system.h"

//////////////////////////////////////////////////
// Class: System
// Private
//////////////////////////////////////////////////

void System::initD3D (void) {
};

void System::cleanD3D (void) { 
};

LRESULT CALLBACK System::WindowProc (UINT message, WPARAM wParam, LPARAM lParam) {
	switch(message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		} break;
	}
	
	return DefWindowProc(this->window, message, wParam, lParam);
};

void System::setUpHWND (
                        HINSTANCE hInstance,
				        LPSTR lpCmdLine,
				        int nCmdShow) {
    this->hInstance = hInstance;
    this->lpCmdLine = lpCmdLine;
    this->nCmdShow = nCmdShow;

    ZeroMemory(&(this->windowClass), sizeof(WNDCLASSEX));
    this->windowClass.cbSize = sizeof(WNDCLASSEX);
    this->windowClass.style = CS_HREDRAW | CS_VREDRAW;
    this->windowClass.lpfnWndProc = this->WindowProc;
    this->windowClass.hInstance = this->hInstance;
    this->windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	this->windowClass.lpszClassName = "WindowClass";
    RegisterClassEx(&(this->windowClass));

    this->window = CreateWindowEx(NULL, "WindowClass", "The Direct3D Program", 
        WS_OVERLAPPEDWINDOW, SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL, NULL, this->hInstance, NULL);
};

//////////////////////////////////////////////////
// Class: System
// Public
//////////////////////////////////////////////////

/*
System::System (void) {
    this->setUpHWND(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow);
};
*/
System::System (void) {
};

System::System (
                HINSTANCE hInstance,
                LPSTR lpCmdLine,
                int nCmdShow) {
    this->setUpHWND(hInstance, lpCmdLine, nCmdShow);

	ShowWindow(this->window, this->nCmdShow);

    this->initD3D();
};

System::System (const System &) {
};

System::~System (void) {
    this->cleanD3D();
};

void System::renderFrame (void) {
};

And I've already tried making the WindowProc function public instead of private. No go. Here's my exact error:

system.cpp(25) : error C3867: 'System::WindowProc': function call missing argument list; use '&System::WindowProc' to create a pointer to member
system.cpp(25) : error C2440: '=' : cannot convert from 'LRESULT (__stdcall System::* )(UINT,WPARAM,LPARAM)' to 'WNDPROC'

Obviously, I've tried that, still no go.

NOTE:
Never mind, I got it working. Turns out you can't have the WindowProc function set in a class, it has to be a global function.
The way I was doing it was wrong. I got it working.

A simple workaround (you forgot to add a HWND parameter to the window proc):
system.h

#ifndef SYSTEM_H
#define SYSTEM_H

#include "stdinc.h"

class System {
  private:
    void initD3D (void);
    void cleanD3D (void);
    void setUpHWND (HINSTANCE, LPSTR, int);

    HWND window;
    WNDCLASSEX windowClass;
    LPDIRECT3D9 d3d;
    LPDIRECT3DDEVICE9 d3ddev;

    HINSTANCE hInstance;
    LPSTR lpCmdLine;
    int nCmdShow;

  public:
    System (void);
    System (HINSTANCE, LPSTR, int);
    System (const System&);
    ~System (void);

    static LRESULT CALLBACK StaticWindowProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT WindowProc(HWND, UINT, WPARAM, LPARAM);

    void renderFrame (void);
};

#endif

system.cpp

#include "system.h"

//////////////////////////////////////////////////
// Class: System
// Private
//////////////////////////////////////////////////

void System::initD3D (void) {
};

void System::cleanD3D (void) { 
};

LRESULT CALLBACK System::StaticWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    System *SystemPtr = (System*)GetWindowLong(hWnd, GWLP_USERDATA);

    if(SystemPtr)
    {
        return SystemPtr->WindowProc(hWnd, message, wParam, lParam);
    }
    else
    {
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
};

LRESULT System::WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	switch(message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		} break;
	}
	
	return DefWindowProc(hWnd, message, wParam, lParam);
};

void System::setUpHWND (
                        HINSTANCE hInstance,
				        LPSTR lpCmdLine,
				        int nCmdShow) {
    this->hInstance = hInstance;
    this->lpCmdLine = lpCmdLine;
    this->nCmdShow = nCmdShow;

    ZeroMemory(&(this->windowClass), sizeof(WNDCLASSEX));
    this->windowClass.cbSize = sizeof(WNDCLASSEX);
    this->windowClass.style = CS_HREDRAW | CS_VREDRAW;
    this->windowClass.lpfnWndProc = System::StaticWindowProc;
    this->windowClass.hInstance = this->hInstance;
    this->windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	this->windowClass.lpszClassName = "WindowClass";
    RegisterClassEx(&(this->windowClass));

    this->window = CreateWindowEx(NULL, "WindowClass", "The Direct3D Program", 
        WS_OVERLAPPEDWINDOW, SCREEN_X, SCREEN_Y, SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL, NULL, this->hInstance, NULL);

    SetWindowLongPtr(this->window, GWLP_USERDATA, (LONG_PTR)this);
};

//////////////////////////////////////////////////
// Class: System
// Public
//////////////////////////////////////////////////

/*
System::System (void) {
    this->setUpHWND(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow);
};
*/
System::System (void) {
};

System::System (
                HINSTANCE hInstance,
                LPSTR lpCmdLine,
                int nCmdShow) {
    this->setUpHWND(hInstance, lpCmdLine, nCmdShow);

	ShowWindow(this->window, this->nCmdShow);

    this->initD3D();
};

System::System (const System &) {
};

System::~System (void) {
    this->cleanD3D();
};

void System::renderFrame (void) {
};

Edited 5 Years Ago by venomxxl: n/a

Oh, so it requires that too. I guess I missed that.
So, what exactly does that code do additionally? I mean, I can understand what it does, but why do you need to do that?

The window proc has to be static. A nonstatic method also takes 'this' pointer (which points to the object) as an argument (it is implicit in C++) and 'some C function in Windows API' won't know about that. That's why you got an error. Though it was also because lpfnWndProc is a pointer to a function with 4 arguments - HWND, UINT, WPARAM and LPARAM (you forgot to add HWND as I mentioned before).

GWLP_USERDATA is intended for use by the application that created the window (from MSDN) and can be any LONG_PTR. In the example above GWLP_USERDATA is set to store the address of 'this' (current object). When the static method (StaticWindowProc) is called by 'some C function in Windows API' to handle some event, it gets the window's GWLP_USERDATA and (if it isn't null) calls the WindowProc method or calls DefWindowProc. (more here and here)

You should also use GetWindowLongPtr instead of GetWindowLong if you are building a 64-bit application (for compatibility reasons).

Sorry if that's a bit chaotic :D not my native language.

Btw, your problem has nothing to do with DX.

Edited 5 Years Ago by venomxxl: n/a

Jesus XD
That's a lot of info to take. Needless to say, saved into a .txt file for further review.
Thank you very much for the explanation.
And I guess it doesn't have anything to do with DirectX, but I'm a huge newb at windows programming, so I didn't know what to classify it as.

This question has already been answered. Start a new discussion instead.