Click to See Complete Forum and Search --> : Encapsulation of the Window


Rich2189
June 2nd, 2006, 04:37 AM
Here's my window creation code.



#include <windows.h>

// Declare WndProcedure




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

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg;
HWND hWnd;
HRESULT hRet;
WNDCLASSEX WndClsEx;

// Populate the WNDCLASSEX structure
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = WndProcedure;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClsEx.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT+1);//(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClsEx.lpszMenuName = NULL;
WndClsEx.lpszClassName = "MyWindow";
WndClsEx.hInstance = hInstance;
WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);


/* COLOURS :)
COLOR_ACTIVEBORDER
COLOR_ACTIVECAPTION
COLOR_APPWORKSPACE
COLOR_BACKGROUND
COLOR_BTNFACE
COLOR_BTNSHADOW
COLOR_BTNTEXT
COLOR_CAPTIONTEXT
COLOR_GRAYTEXT
COLOR_HIGHLIGHT
COLOR_HIGHLIGHTTEXT
COLOR_INACTIVEBORDER
COLOR_INACTIVECAPTION
COLOR_MENU
COLOR_MENUTEXT
COLOR_SCROLLBAR
COLOR_WINDOW
COLOR_WINDOWFRAME
COLOR_WINDOWTEXT
*/



// Register the class
RegisterClassEx(&WndClsEx);





// Create the window object
hWnd = CreateWindow("MyWindow",
"Rich's Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);








// Verify window creation
if( !hWnd ) // If the window was not created,
return 0; // stop the application

// Show the window
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);

// message pump
while( (hRet = GetMessage( &Msg, NULL, 0, 0 )) != 0)
{
if (hRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}

return 0;

}



LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
// user wants to exit
PostQuitMessage(WM_QUIT);
break;
default:
// Hand off unprocessed messages to DefWindowProc
return DefWindowProc(hWnd, Msg, wParam, lParam);
}

return 0;
}



I am unsure of how to put it in a class so I can create as many windows as i want in an application.

-What do i do with the message handler? Do i declare it static
-Once classed to i added member functions like set window caption, using sendmessage.

A description of how to do it would be fantastic :), i want to try and do as much myself, its the only way i learn.

kirants
June 2nd, 2006, 07:45 PM
If you add a class , then the minimum data you keep there would be the HWND. Now, once you have that and have a static wndproc, you have to find a way to get to the C++ object for a particular window and there are many ways to do it.

One way is to make a framework where the framework maintains a mapping of HWNDs to the C++ objects. ( MFC style )
Another way could be to , in case they are your own registered classes, to store the C++ object pointer as data for the window using SetWindowLong ( beware that if you overwrite this area ), it will be messy.

You can come up with any other way..

JamesSchumacher
June 3rd, 2006, 08:20 AM
Below is a simple implementation of a C++ encapsulation of the window process.

It uses a window property (SetPropA, GetPropA) to store the window objects pointer. (Create all windows on the heap to be sure it's valid. Also, in WM_NCDESTROY, you can 'delete this' so when a window is destroyed the destructor gets called.


class Window
{
public:
// Normal
protected:
HWND Handle;
virtual INT_PTR WindowProcess(UINT message,WPARAM wParam,LPARAM lParam) throw();
private:
static INT_PTR __stdcall HandleWindowProcess(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) throw();
};

/////////////////////////////////////////////////////////////
//// HandleWindowProcess

INT_PTR __stdcall Window::HandleWindowProcess(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) throw()
{
// pass your this pointer as the last parameter to CreateWindowEx
if (message == WM_NCCREATE)
{
LPCREATESTRUCT lpCreate = reinterpret_cast<LPCREATESTRUCT>(lParam);

Window * pWindow = reinterpret_cast<Window *>(lpCreate->lpCreateParams);
/* Comment out above line and uncomment the below for an MDI Child Window

LPMDICREATESTRUCT lpMdiCreate = reinterpret_cast<LPMDICREATESTRUCT>(lpCreate->lpCreateParams);
Window * pWindow = reinterpret_cast<Window *>(lpMdiCreate->lParam);

*/

pWindow->Handle = hWnd;

// Set a window property to store the window object pointer
::SetPropA(hWnd,"WindowObject",reinterpret_cast<HANDLE>(pWindow));

return pWindow->WindowProcess(message,wParam,lParam);
}
else
{
// try to obtain a pointer to the window object
Window * pWindow = reinterpret_cast<Window *>(::GetPropA(hWnd,"WindowObject"));
if (pWindow != NULL)
{
return pWindow->WindowProcess(message,wParam,lParam);
}
else
{
// not a window object
return ::DefWindowProc(hWnd,message,wParam,lParam);
}
}
}

Rich2189
June 5th, 2006, 05:26 AM
Thanks, I'll book mark this thread and give it a shot sometime soon.

Hmm looking at james example maybe I should finish learning OPP for C++ first, I see type casting and throws, haven't looked at them yet.