wMainWindow::wMainWindow(HINSTANCE hofProgram){
setInstance(hofProgram);
// define the window class
#ifndef Main_Window_Class
#define Main_Window_Class
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &wMainWindow::WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(wMainWindow*);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName = "Main Window Class";
// Create the Window Class
RegisterClass(&wc);
#endif
// Create an actual instance of the Window
hMainWindow = CreateWindow(
"Main Window Class", // Type of window we want to create
"Transport manager Server", // Name of our Window
WS_VISIBLE, // Style of our Window
0,0,640,480, // Position and Size
NULL, //No Parent
NULL, //No Menu
hInstance, // Belongs to the calling Program
NULL);
// Put a pointer to this instance of the class in the Window Header
SetWindowLong(hMainWindow,GWL_USERDATA,(long)this);
// create the exit button
hbExit = CreateWindow(
"BUTTON",
"Exit",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
570,410,
50,30,
hMainWindow,
NULL,
(HINSTANCE) GetWindowLong(hMainWindow, GWL_HINSTANCE),
NULL);
//create the Add server button
hbAddServer= CreateWindow(
"BUTTON",
"Add Server",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
470,410,
90,30,
hMainWindow,
NULL,
(HINSTANCE) GetWindowLong(hMainWindow, GWL_HINSTANCE),
NULL);
};
LRESULT CALLBACK wMainWindow::WindowProc(HWND hwnd, // handle of window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
){
// retrieve the pointer from the Window header
wMainWindow* ThisWindow = (wMainWindow*) GetWindowLong (hwnd,GWL_USERDATA);
switch (uMsg)
{
case WM_CLOSE :
ProgActive = false;
break;
case WM_COMMAND :
switch HIWORD(wParam)
{
case BN_CLICKED :
if ((HWND)lParam == ThisWindow->hbExit)
ProgActive = false;
if ((HWND)lParam == ThisWindow->hbAddServer){
HWND Temp = ThisWindow->GetHandle();
wServerWindow TestWindow(Temp);
TestWindow.Show();
};
break;
} // switch HIWORD(wParam)
break;
} // switch uMsg
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
};
for the second class
wServerWindow::wServerWindow(HWND ParentWindow){
setInstance((HINSTANCE) GetWindowLong(ParentWindow, GWL_HINSTANCE)); \\ sets hInstance
// Create an actual instance of the Window
hServerWindow = CreateWindow(
"Server Window Class", // Type of window we want to create
"Servers", // Name of our Window
WS_OVERLAPPEDWINDOW, // Style of our Window
0,0,320,240, // Position and Size
NULL, //Parent Window
NULL, //No Menu
hInstance, // Belongs to the calling Program
NULL);
if (!(hServerWindow)) {
// define the window class
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &wServerWindow::WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(wServerWindow*);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName = "Server Window Class";
// Create the Window Class
RegisterClass(&wc);
hServerWindow = CreateWindow(
"Server Window Class", // Type of window we want to create
"Servers", // Name of our Window
WS_OVERLAPPEDWINDOW, // Style of our Window
0,0,320,240, // Position and Size
NULL, //Parent Window
NULL, //No Menu
hInstance, // Belongs to the calling Program
NULL);
};
// Put a pointer to this instance of the class in the Window Header
SetWindowLong(hServerWindow,GWL_USERDATA,(long)this);
// create the exit button
hbExit = CreateWindow(
"BUTTON",
"Exit",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,10,
50,30,
hServerWindow,
NULL,
(HINSTANCE) GetWindowLong(ParentWindow, GWL_HINSTANCE),
NULL);
};
LRESULT CALLBACK wServerWindow::WindowProc(HWND hwnd, // handle of window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
){
// retrieve the pointer from the Window header
wServerWindow* ThisWindow = (wServerWindow*) GetWindowLong (hwnd,GWL_USERDATA);
switch (uMsg)
{
case WM_COMMAND :
switch HIWORD(wParam)
{
case BN_CLICKED :
ThisWindow->Close();
break;
} // switch HIWORD(wParam)
break;
} // switch uMsg
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
};
The message handling procedure of the first class creates a new window of the second class!! but it does not function correctly, If a create a new window of the second class from within the main programm and not from the Message handling procedure the second window behaves correctly.
What am I missing?
Thanks for the help,
MK83
Edited by - mk83 on November 8, 2001 4:29:59 AM
Windows in a class
Hi Guys,
I am trying to write a program, but to make it neater + in order to learn, I am trying to put the windows code into classes, it seemed to be going pretty well, I have managed to create a simple windows class that calls a static message handler, that is able to get a pointer to the class by using the getwindowlong function. All fine and well, when having multiple instances of a window each one responds only to the commands clicked on it! But then I created a second class, I create a window in this class by handing it the handle of the first window I have created and using GetWindowLong(ParentWindow, GWL_HINSTANCE) to get the instance of the program. This new class also has a static Message handling procedure, with the same code as for the previous class only modified to be applicable to the new class. When I create a new window with the class in my main program, it works fine, all the buttons work etc. when I create the new window from within the Message handling procedure of the first class I created, nothing works, the window appears, but the buttons don't work and if I trace through it, the Instance of the the class and the HWND of the window seem to get all jumbled up!!! I have tried many things, but just don't seem to see where I am going wrong, please help!!
Source to create the first class
I looked it over and what''s wrong isn''t jumping out at me.
Though that''s not the way I''ve seen most people go about it, I think it should work. The problem code may lie elsewhere.
Though that''s not the way I''ve seen most people go about it, I think it should work. The problem code may lie elsewhere.
Hi Magmai,
How would it normally be done? this is the first time I am trying it so any help would be great!!
Thanks,
Robert
How would it normally be done? this is the first time I am trying it so any help would be great!!
Thanks,
Robert
From a quick lookover it looks as if in the wServerWindow ctor you are creating a window of class "Server Window Class" before you have actually registered that class.
Often a window class is registered for each window, and the code for registration and creation is pushed into a base class. And they usually use RegisterWindowEx and CreateWindowEx (they were added with Win95 for additional window styles).
He tries to create a window, and if it fails he calls the register and then create again. Thought you had it for a minute...
quote:
From a quick lookover it looks as if in the wServerWindow ctor you are creating a window of class "Server Window Class" before you have actually registered that class.
He tries to create a window, and if it fails he calls the register and then create again. Thought you had it for a minute...
Oops - I missed that.
Anyway (luckily), I''m pretty confident that the problem is this:
When you call CreateWindow() in the wServerWindow ctor you are not passing in the handle of the parent window (which is the handle given to the ctor). This would account for messages failing to reach the window.
Anyway (luckily), I''m pretty confident that the problem is this:
When you call CreateWindow() in the wServerWindow ctor you are not passing in the handle of the parent window (which is the handle given to the ctor). This would account for messages failing to reach the window.
Thanks for the help so far, unfortunatly I have still not been able to fix the problem! I''m wondering if it is perhaps a scope problem? I.e. the instance of the class I create only has scope in the function that that creates it? That would explain why calls to the instance of the class don''t work outside of the original creating function?
I''m gonna try using global variables and see if I can get around the problem that way,
Just another question is there a way of declaring something so that it has a wider scope than just the creating structure?
Magmai, should I create a base class and then inherit from those for my new classes? That would make sense because most of the windows will have the same class and create functions, my only problem with that is that the base class would have to have the Message handling function as part of it! but the different versions of windows would have different buttons etc on it so each message handling function would have to be different and that would not be possible with a base class, or am I missing something? I''ll play around a bit and see if I can get it to work!
Thanks,
MK83
I''m gonna try using global variables and see if I can get around the problem that way,
Just another question is there a way of declaring something so that it has a wider scope than just the creating structure?
Magmai, should I create a base class and then inherit from those for my new classes? That would make sense because most of the windows will have the same class and create functions, my only problem with that is that the base class would have to have the Message handling function as part of it! but the different versions of windows would have different buttons etc on it so each message handling function would have to be different and that would not be possible with a base class, or am I missing something? I''ll play around a bit and see if I can get it to work!
Thanks,
MK83
This is a very interesting subject, I think, and I would appreciate it if someone could post a link to a tutorial or source code on the subject.
Judging by the past, it seems certain that something we cannot imagine today will dominate the landscape in 2021. That''''s why the future of the PC is even more exciting than the past.
Judging by the past, it seems certain that something we cannot imagine today will dominate the landscape in 2021. That''''s why the future of the PC is even more exciting than the past.
Ok, there''s a very simple reason why what your trying to do will not work. The address your providing for the wndProc is the address of a function in a class. When you call the function in a line of code like...
MyWindow.WndProc();
the compiler will secretly pass a parameter to the function telling it which instance of that class type (i.e. the ''this'' pointer value).
When windows calls the WndProc function it does not pass the ''this'' parameter. Therefore the function has no idea which instance it is and act''s unpredictably.
P:\ray\main.cpp(74) : error C2440: ''type cast'' : cannot convert from ''long (__thiscall Wnd::*)(struct HWND__ *,unsigned int,unsigned int,long)'' to ''long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)''
if you look at this error you''ll notice that the WndProc of the class is a function call of type __thiscall, meaning that it passes the ''this'' parameter. and the (WNDPROC) definition is a __stdcall meaning that no extra info is passed to the call.
The only way I''ve found to be able to do something like what you want is to do the following...
after the call to CreateWindow add this...
SetWindowLong(hWnd,GWL_USERDATA,this);
this stoues a reference to the object in the windows own data space.
Then write a standalone WndProc function like this...
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
MyWndClass *CurrentWnd = (MyWndClass *)GetWindowLong(hWnd,GWL_USERDATA);
if(!CurrentWnd)
return DefWindowProc(hWnd,uMsg,wParam,lParam);
return CurrentWnd->WndProc(hWnd,uMsg,wParam,lParam);
}
this retrieves the reference to the window class and calls it WndProc function.
And refer to this function in the WNDCLASS struct...
wc.lpfnWndProc = (WNDPROC)WndProc;
Thats what I do.
MyWindow.WndProc();
the compiler will secretly pass a parameter to the function telling it which instance of that class type (i.e. the ''this'' pointer value).
When windows calls the WndProc function it does not pass the ''this'' parameter. Therefore the function has no idea which instance it is and act''s unpredictably.
P:\ray\main.cpp(74) : error C2440: ''type cast'' : cannot convert from ''long (__thiscall Wnd::*)(struct HWND__ *,unsigned int,unsigned int,long)'' to ''long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)''
if you look at this error you''ll notice that the WndProc of the class is a function call of type __thiscall, meaning that it passes the ''this'' parameter. and the (WNDPROC) definition is a __stdcall meaning that no extra info is passed to the call.
The only way I''ve found to be able to do something like what you want is to do the following...
after the call to CreateWindow add this...
SetWindowLong(hWnd,GWL_USERDATA,this);
this stoues a reference to the object in the windows own data space.
Then write a standalone WndProc function like this...
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
MyWndClass *CurrentWnd = (MyWndClass *)GetWindowLong(hWnd,GWL_USERDATA);
if(!CurrentWnd)
return DefWindowProc(hWnd,uMsg,wParam,lParam);
return CurrentWnd->WndProc(hWnd,uMsg,wParam,lParam);
}
this retrieves the reference to the window class and calls it WndProc function.
And refer to this function in the WNDCLASS struct...
wc.lpfnWndProc = (WNDPROC)WndProc;
Thats what I do.
In the original post the poster says that the WindowProc() methods for the classes are static, as they have to be. This means they are not passed an invisible ''this'' pointer (since they can be used from outside a member of the class).
The real problem is the failure to give ''wServerWindow'' windows a handle to their parent when CreateWindow is called for them. The difference in behaviour described in the original post between creation from inside a ''wMainWindow'' and directly from the app is that when created directly, the window doesn''t need a parent as it is effectively the main window.
The real problem is the failure to give ''wServerWindow'' windows a handle to their parent when CreateWindow is called for them. The difference in behaviour described in the original post between creation from inside a ''wMainWindow'' and directly from the app is that when created directly, the window doesn''t need a parent as it is effectively the main window.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement