Jump to content
  • Advertisement
Sign in to follow this  
GDMichael

WindowProc

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

// Message Processing Functions virtual LRESULT CALLBACK AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam); bool CApplication::Create() { // Init parent window class information ZeroMemory(&m_wcx, sizeof(m_wcx)); m_wcx.cbClsExtra = 0; m_wcx.cbSize = sizeof(WNDCLASSEX); m_wcx.cbWndExtra = 0; m_wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW); m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); m_wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION); m_wcx.hInstance = m_hInstance; m_wcx.lpfnWndProc = CApplication::WndProc; m_wcx.lpszClassName = m_lpClassName; m_wcx.lpszMenuName = NULL; m_wcx.style = CS_CLASSDC; if (!RegisterClassEx(&m_wcx)) return false; // Create parent window m_hWnd = CreateWindowEx( 0, m_lpClassName, m_lpWndName, m_dwstyle, m_nXPos, m_nYPos, m_nWidth, m_nHeight, m_hWnd, NULL, m_hInstance, NULL ); if (!m_hWnd) return false; // Show and update parent window ShowWindow(m_hWnd, SW_SHOW); UpdateWindow(m_hWnd); return true; } LRESULT CApplication::AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_KEYDOWN: if (wParam == VK_ESCAPE) PostQuitMessage(0); return 0; case WM_CLOSE: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,uMsg, wParam, lParam); } ////////////////////////////////////////////////// // WndProc ////////////////////////////////////////////////// LRESULT CALLBACK CApplication::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { CApplication *w = (CApplication *) (LONG)::GetWindowLongPtr(hWnd, GWL_USERDATA); return w->AppProc(hWnd,uMsg, wParam, lParam); } ********************************************************************** In the WndProc, when I run the program, it seems error on the first statement of the WndProc Function. Since, WndProc is the static function, but I want it can call the AppProc function, how can I do it sucess? Thx ***********************************************************************

Share this post


Link to post
Share on other sites
Advertisement
Hi bud,

You can make wndproc a static member function of your class.

Like this:

Header

#pragma once

#include <windows.h>
#include <string>

#include "..\\Kernel\\process.h"
#include "..\\Kernel\\kernel.h"
#include "..\\Kernel\\kbase.h"



struct win_window_props
{
unsigned int x,y;
unsigned int w,h;

std::string className;
std::string windowCaption;

win_window_props() {};
win_window_props( unsigned int x,
unsigned int y,
unsigned int w,
unsigned int h,
std::string className,
std::string windowCaption)
:
x(x), y(y), w(w), h(h), className(className), windowCaption(windowCaption)
{};
};

class win_window : public KERNEL::process
{
public:
win_window(HINSTANCE instance, const std::string& label, const win_window_props& props );
~win_window();

void Initialise( KERNEL::kernel* pKernel );
void Frame();
void Restart();
void End();

HWND& GetWindowRef() { return window; };

static LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );

private:
HWND window;
HINSTANCE instance;
static win_window* pThis;
win_window_props windowProps;

};





CPP

#include "win_window.h"

win_window::win_window(HINSTANCE instance, const std::string& label, const win_window_props& props )
:
process( label )
{
this->instance = instance;
windowProps = props;
}

win_window::~win_window()
{
}

void win_window::Initialise( KERNEL::kernel* pKernel )
{
this->pKernel = pKernel;
this->pThis = this;

// Create the window handle etc
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
&windowProps.className[0], NULL };
RegisterClassEx( &wc );

// Create the application's window
window = CreateWindow( &windowProps.className[0], &windowProps.windowCaption[0],
WS_OVERLAPPEDWINDOW, windowProps.x, windowProps.y, windowProps.w, windowProps.h,
GetDesktopWindow(), NULL, this->instance, NULL );
// Show the window
ShowWindow( window, SW_SHOWDEFAULT );
UpdateWindow( window );
}
void win_window::Frame()
{
MSG msg;
ZeroMemory( &msg, sizeof(msg) );

if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
void win_window::Restart()
{
}
void win_window::End()
{
}


LRESULT WINAPI win_window::MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
{
pThis->pKernel->SetState( KERNEL::KSC_END );
PostQuitMessage( 0 );
return 0;
}
}

return DefWindowProc( hWnd, msg, wParam, lParam );
}

// Give presence to the static member
win_window* win_window::pThis;



Hope that helps mate,

ace

Share this post


Link to post
Share on other sites
It seems quick complex.

I saw some forum or sample, that can use getwindowlong function

Here is my sample:
(.cpp)
LRESULT CALLBACK CApplication::AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0);
return 0;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd,uMsg, wParam, lParam);
}

//////////////////////////////////////////////////
// WndProc
//////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CApplication *app = (CApplication*)GetWindowLong(hWnd, GWL_USERDATA);

return app->AppProc(hWnd,uMsg, wParam, lParam);
}


(.h)
public:
void Init(HINSTANCE hInstance);
bool Create();
void Run();

// Message Processing Functions
virtual LRESULT CALLBACK AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

// Get Method
HINSTANCE GetHInstance();
HWND GetHWnd();

protected:
// Main Data
HINSTANCE m_hInstance; // Handle to application instance
HWND m_hWnd; // Handle to parent window
WNDCLASSEX m_wcx; // Structure contains parent window class information
MSG m_msg;
char* m_lpClassName; // Class name of parent window
char* m_lpWndName; // Name of parent window
DWORD m_dwstyle; // Parent window style
int m_nXPos; // Horizontal position of parent window
int m_nYPos; // Vertical position of parent window
int m_nWidth; // Parent window width
int m_nHeight; // Parent window height
};

static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);




*******************************************
there has the warning, why?
warning C4312: 'type cast' : conversion from 'LONG' to 'CApplication *' of greater size
*******************************************

Would you mind to answer me some questions?
Why I need to use static function for the wndclassex.lpfnwndproc?
Why I cannot use the class member directly?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by GDMichael
...there has the warning, why?
warning C4312: 'type cast' : conversion from 'LONG' to 'CApplication *' of greater size

Because your compiler is set to check for 64 bit compatibility issues. Uncheck that option in the project options, and this warning will disappear. Or use Get / SetWindowLongPtr (I believe) in place of Get / SetWindowLong.

Quote:
Would you mind to answer me some questions?
Why I need to use static function for the wndclassex.lpfnwndproc?
Why I cannot use the class member directly?


Both of these are because Windows does not know how to call back into a class. Windows only knows how to call back to C'ish functions, as that's what Windows was primarily written in back in the days.

Another issue is that every compiler vendor is free to implement class functions in a variety of ways, and there is no 'standard' way for a class function to be called. The 'this' pointer can be placed on the stack or in a register - it is up to the implementation.

For a little more on this, see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_thiscall.asp. Note the statement 'The thiscall calling convention cannot be explicitly specified in a program, because thiscall is not a keyword.' 'thiscall' is specific to MS, and other compiler vendors can do it differently.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
(.cpp)

//////////////////////////////////////////////////
// Include
//////////////////////////////////////////////////
#include "Core_Global.h"


//////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////
CApplication::CApplication()
{
m_hInstance = NULL;
m_hWnd = NULL;
m_lpClassName = "CoreAppWnd";
m_lpWndName = "Core Game";
m_dwstyle = WS_OVERLAPPEDWINDOW;
m_nXPos = 0;
m_nYPos = 0;
m_nWidth = 800;
m_nHeight = 600;
}

//////////////////////////////////////////////////
// Destructor
//////////////////////////////////////////////////
CApplication::~CApplication()
{

}

//////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////
void CApplication::Init(HINSTANCE hInstance)
{
m_hInstance = hInstance;
}

//////////////////////////////////////////////////
// Create
//////////////////////////////////////////////////
bool CApplication::Create()
{
// Init parent window class information
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbClsExtra = 0;
m_wcx.cbSize = sizeof(WNDCLASSEX);
m_wcx.cbWndExtra = 0;
m_wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hInstance = m_hInstance;
m_wcx.lpfnWndProc = WndProc;
m_wcx.lpszClassName = m_lpClassName;
m_wcx.lpszMenuName = NULL;
m_wcx.style = CS_CLASSDC;

if (!RegisterClassEx(&m_wcx))
return false;

// Create parent window
m_hWnd = CreateWindowEx(
0,
m_lpClassName,
m_lpWndName,
m_dwstyle,
m_nXPos,
m_nYPos,
m_nWidth,
m_nHeight,
m_hWnd,
NULL,
m_hInstance,
NULL
);
if (!m_hWnd)
return false;

// Show and update parent window
ShowWindow(m_hWnd, SW_SHOW);
UpdateWindow(m_hWnd);

return true;
}

//////////////////////////////////////////////////
// Run
//////////////////////////////////////////////////
void CApplication::Run()
{
ZeroMemory(&m_msg, sizeof(MSG));
while (m_msg.message != WM_QUIT)
{
if (PeekMessage(&m_msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&m_msg);
DispatchMessage(&m_msg);
}
else {
if (!Render())
break;
}
}

UnregisterClass(m_lpClassName, m_hInstance);
}

//////////////////////////////////////////////////
// Render
//////////////////////////////////////////////////
bool CApplication::Render()
{
return true;
}

//////////////////////////////////////////////////
// AppProc
//////////////////////////////////////////////////
LRESULT CALLBACK CApplication::AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0);
return 0;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd,uMsg, wParam, lParam);
}

//////////////////////////////////////////////////
// WndProc
//////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CApplication *app = (CApplication *) (LONG_PTR)::GetWindowLongPtr(hWnd, GWLP_USERDATA);

return app->AppProc(hWnd,uMsg, wParam, lParam);
/*switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0);
return 0;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd,uMsg, wParam, lParam);*/
}

//////////////////////////////////////////////////
// GetHInstance
//////////////////////////////////////////////////
HINSTANCE CApplication::GetHInstance()
{
return m_hInstance;
}

//////////////////////////////////////////////////
// GetHWnd
//////////////////////////////////////////////////
HWND CApplication::GetHWnd()
{
return m_hWnd;
}



(.h)

#ifndef CORE_APPLICATION_H
#define CORE_APPLICATION_H

class CApplication
{
public:
CApplication(); // Constructor
virtual ~CApplication(); // Destructor

public:
void Init(HINSTANCE hInstance);
bool Create();
void Run();
virtual bool Render();

// Message Processing Functions
virtual LRESULT CALLBACK AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

// Get Method
HINSTANCE GetHInstance();
HWND GetHWnd();

protected:
// Main Data
HINSTANCE m_hInstance; // Handle to application instance
HWND m_hWnd; // Handle to parent window
WNDCLASSEX m_wcx; // Structure contains parent window class information
MSG m_msg;
char* m_lpClassName; // Class name of parent window
char* m_lpWndName; // Name of parent window
DWORD m_dwstyle; // Parent window style
int m_nXPos; // Horizontal position of parent window
int m_nYPos; // Vertical position of parent window
int m_nWidth; // Parent window width
int m_nHeight; // Parent window height
};

static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

#endif





**************************************************************
I have several questions to ask?
1. For your suggestion, I try to use GetWindowLongPtr, but when run-time, it still error occur, am I anything incorrect?
2. I don't know what is the meaning of 64 bit compliant code? What's that?
3. "thiscall" does mean this->abc();, right?

Thx your help
and I am really sorry that make all of you trouble
**************************************************************

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
First, when posting code, surround it in '[_source_]' '[_\source_]' tags (without the underscores), as per the faq (http://www.gamedev.net/community/forums/faq.asp). It is much more considerate to those of us who read your posts, versus just pasting it as you have done.

Second, I'm not going to delve into the GetWindowLongPtr issue, and solve your bug, because you haven't told us what the error is. I would guess that you need to call SetWindowLongPtr at the correct time. Looking a little closer, I see that is indeed the case. Where are you setting the pointer at? You must do this before trying to access the pointer at GWLP_USERDATA.

Third, 64 bit compliant code is code that is ready to run on the new and upcoming 64 bit operating systems. If you don't need the 64 bit capabilities in your programs, you are more than welcome to keep your code as 32 bit, as those operating systems will be capable of running 32 bit executables.

Fourth, 'thiscall' means how the machine processes 'this->abc()'. It doesn't mean 'this->abc()', but rather how the stack and registers are used 'under-the-hood', when your program executes that statement. Google 'thiscall', 'stdcall', and 'cdecl' to start your learning process.

Have fun!

Share this post


Link to post
Share on other sites
(.h)

#ifndef CORE_APPLICATION_H
#define CORE_APPLICATION_H

class CApplication
{
public:
CApplication(); // Constructor
virtual ~CApplication(); // Destructor

public:
void Init(HINSTANCE hInstance);
bool Create();
void Run();
virtual bool Render();

// Message Processing Functions
virtual LRESULT CALLBACK AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

// Get Method
HINSTANCE GetHInstance();
HWND GetHWnd();

protected:
// Main Data
HINSTANCE m_hInstance; // Handle to application instance
HWND m_hWnd; // Handle to parent window
WNDCLASSEX m_wcx; // Structure contains parent window class information
MSG m_msg;
char* m_lpClassName; // Class name of parent window
char* m_lpWndName; // Name of parent window
DWORD m_dwStyle; // Parent window style
int m_nXPos; // Horizontal position of parent window
int m_nYPos; // Vertical position of parent window
int m_nWidth; // Parent window width
int m_nHeight; // Parent window height
};

static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam);

#endif



(*.cpp)
[sourcelang="cpp"]

//////////////////////////////////////////////////
// Include
//////////////////////////////////////////////////
#include "CApplication.h"


//////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////
CApplication::CApplication()
{
m_hInstance = NULL;
m_hWnd = NULL;
m_lpClassName = "CoreAppWnd";
m_lpWndName = "Core Game";
m_dwStyle = WS_OVERLAPPEDWINDOW;
m_nXPos = 0;
m_nYPos = 0;
m_nWidth = 800;
m_nHeight = 600;
}

//////////////////////////////////////////////////
// Destructor
//////////////////////////////////////////////////
CApplication::~CApplication()
{

}

//////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////
void CApplication::Init(HINSTANCE hInstance)
{
m_hInstance = hInstance;
}

//////////////////////////////////////////////////
// Create
//////////////////////////////////////////////////
bool CApplication::Create()
{
// Init parent window class information
ZeroMemory(&m_wcx, sizeof(m_wcx));
m_wcx.cbClsExtra = 0;
m_wcx.cbSize = sizeof(WNDCLASSEX);
m_wcx.cbWndExtra = 0;
m_wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
m_wcx.hInstance = m_hInstance;
m_wcx.lpfnWndProc = WndProc;
m_wcx.lpszClassName = m_lpClassName;
m_wcx.lpszMenuName = NULL;
m_wcx.style = CS_CLASSDC;

if (!RegisterClassEx(&m_wcx))
return false;

// Create parent window
m_hWnd = CreateWindowEx(
0,
m_lpClassName,
m_lpWndName,
m_dwStyle,
m_nXPos,
m_nYPos,
m_nWidth,
m_nHeight,
m_hWnd,
NULL,
m_hInstance,
NULL
);
if (!m_hWnd)
return false;

// Show and update parent window
ShowWindow(m_hWnd, SW_SHOW);
UpdateWindow(m_hWnd);

return true;
}

//////////////////////////////////////////////////
// Run
//////////////////////////////////////////////////
void CApplication::Run()
{
ZeroMemory(&m_msg, sizeof(MSG));
while (m_msg.message != WM_QUIT)
{
if (PeekMessage(&m_msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&m_msg);
DispatchMessage(&m_msg);
}
else {
if (!Render())
break;
}
}

UnregisterClass(m_lpClassName, m_hInstance);
}

//////////////////////////////////////////////////
// Render
//////////////////////////////////////////////////
bool CApplication::Render()
{
return true;
}

//////////////////////////////////////////////////
// AppProc
//////////////////////////////////////////////////
LRESULT CALLBACK CApplication::AppProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0);
return 0;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd,uMsg, wParam, lParam);
}

//////////////////////////////////////////////////
// WndProc
//////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CApplication *app = (CApplication *) (LONG_PTR)::GetWindowLongPtr(hWnd, GWLP_USERDATA);

return app->AppProc(hWnd,uMsg, wParam, lParam);
/* switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
PostQuitMessage(0);
return 0;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd,uMsg, wParam, lParam);*/

}

//////////////////////////////////////////////////
// GetHInstance
//////////////////////////////////////////////////
HINSTANCE CApplication::GetHInstance()
{
return m_hInstance;
}

//////////////////////////////////////////////////
// GetHWnd
//////////////////////////////////////////////////
HWND CApplication::GetHWnd()
{
return m_hWnd;
}



*********************************************
1. What is the usage of WIndowLongPtr?
2. The Error is on run-time:
"Unhandled exception at 0x0042307b in 3DPRGApp.exe: 0xC000000005: Access violation reading location 0X00000000.
And the error is point to "return app->App(hwnd, uMsg, wParam, lParam);
***********************************************

I am really sorry make all of you trouble becuase my english is not really good, may be I don't fully understand the MSDN.. Hope you can help me ...and many many thanks.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You have to call 'SetWindowLongPtr' somewhere, and that somewhere must be before you try to use the pointer set there. According to Oluseyi (http://www.gamedev.net/reference/articles/article1810.asp), the first Window message a window receives is WM_NCCREATE, therefore, this message is the logical one to call SetWindowLongPtr from. (I have heard that WM_NCCREATE is not the actual first message from other places, though, so you will have to debug if this is not the case.)

Your call to SetWindowLongPtr would look like:

if(message == WM_NCCREATE) {
// retrieve Window instance from window creation data and associate
wnd = reinterpret_cast<Window *>((LPCREATESTRUCT)lparam)->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<long>(wnd));

// save window handle
wnd->SetHWND(hwnd);
}


Or something of that nature.

Good luck.

Share this post


Link to post
Share on other sites
This article here on Gamedev, and this one at Code Project are useful for learning how to do this. The second one is written for Windows CE, but there are notes for applying it to desktop versions of Windows.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
There is also http://www.codeproject.com/library/DWinLib.asp.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!