In other word, can I use a member function in class to be a window message processing function?
Posted on 2004-03-26 02:12:45 by optimus
Probably not, but even if it could it still wouldn't work. You always need to have a 'this' pointer that identifies the right object instance. However you can make a static member use stdcall, but then you don't have a 'this' pointer. You could use Set/GetWindowLong to store the object pointer, read it in the static WndProc function, cast it to the right class and call some function on it.

Thomas
Posted on 2004-03-26 02:52:53 by Thomas
Just curious. What does stack clearing have to do with this ptr? I don't see any relevance.
Posted on 2004-03-26 03:07:15 by Starless
class one{
long Loop(hWnd,msg,w,l); // lazy me
}

long one::Loop(hWnd,msg,w,l){ // again lazy
_this = GetWindowLong(hWnd);
switch(msg){

}
}

class members are always stdcall. _this is in ECX. Only problem might be not being able to trick the compiler to accept
one::Loop as a wc.lpfnWndLoop.
Posted on 2004-03-26 05:42:49 by Ultrano
Hmm ultrano was right, member functions are usually stdcall, I thought they were using C convention. Actually, they are thiscall (search msdn for it) which comes down to stdcall with the this pointer passed in ECX. Except for functions with a variable number of arguments, where the C calling convention is used.


Just curious. What does stack clearing have to do with this ptr?

Nothing :) At least not as long as the this pointer is not passed on the stack, which isn't done in any calling convention at the moment.

Thomas
Posted on 2004-03-26 10:35:42 by Thomas
Yes member functions are "_thiscall" though you cannot explicitly declare a function with it.

optimus, here's some pseudocode that illustrates a little bit of what Thomas was explaining. I've used this model in many programs. Hope it helps.

[size=12]class BasicWindow

{
public:
static LRESULT CALLBACK _WndProc(HWND h, UINT msg, WPARAM wp, LPARAM lp)
{
BasicWindow * _this;

if(msg == WM_NCCREATE)
{
_this = (BasicWindow *)((CREATESTRUCT*)lp)->lpCreateParams;
_this->hwnd = h;
SetWindowLong(h, GWL_USERDATA, (LONG)_this);
}
else
_this = (BasicWindow *)GetWindowLong(h, GWL_USERDATA);

return _this->WndProc(msg, wp, lp);
}

LRESULT WndProc(UINT msg, WPARAM wp, LPARAM lp)
{
// Main Window procedure.
// Handle window messages here.
}

BOOL RegisterClass(void)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = _WndProc;
// etc. etc.

RegisterClassEx(&wc);
}

BOOL Create(void)
{
CreateWindowEx(..., etc. etc., this); // lpParam = this
}

private:
HWND hwnd;

};


// ...
// ...


WinMain(...)
{
// Do stuff

BasicWindow * MyWindow = new BasicWindow;
MyWindow->RegisterClass();
MyWindow->Create();

// Do stuff
}[/size]



Although I usually have a separate class that handles window class registration, this is just a very basic idea of how to handle windows in c++.
Posted on 2004-03-26 11:01:07 by iblis
that's just what i need in my program!! thanks iblis!!
Posted on 2004-03-27 06:48:27 by optimus
Remember that's just a basic idea. Doing things exactly as described above is a little dangerous and error prone. For example you'd have to ensure that the window object remains in memory until the window is destroyed.

But it does show you how to handle the Window procedure. So with that knowledge I'm sure you can come up with a nice way to handle things that works for you.

Good luck.
Posted on 2004-03-27 08:29:01 by iblis
I tried the code. Unfortunately, after calling the class' create function, my app ends up. It seems that the create function does not return to the caller.
Posted on 2004-03-27 09:07:42 by optimus