   Custom Control: Infinite Draw Loop
  Hi I am trying to create my own control called an update box which right now looks & acts exactly like a Listbox control but when I get that working I want to add more things. Its programmed in c++ win32.But my problem is that my program crashes. The objects being drawn seem to be constantly being redrawn & I am not sure why(where in my code this is occuring). To describe what it looks like; the object is drawn(a custom made listbox) & a row(cell) is added to the listbox & drawn. Then it seems the whole client window is cleared & everything disappears, then the same things are drawn again, then cleared & it seems the program goes into an infinite loop.Can you help me figure out what is going wrong & where?Header File:#ifndef UPDATEBOX_H#define UPDATEBOX_H#include <windows.h>#include <string>#include <vector>using namespace std;#define UB_DRAWCELL 999// Update Box Cell Objectclass ubCell {public:ubCell(HWND Hwnd, POINT p, int wdth, int hght);bool drawControl();~ubCell();  private:// COLUMN parentCol; // consider a parent object columnPOINT pos;int width;int height;HWND hwnd;HRGN region;HBRUSH bgBrush;HBRUSH frameBrush;string data;};// Visual Control - Similar to a List Box control but with more custom functionalityclass updateBox {  public: updateBox(HWND Hwnd, POINT p, int wdth, int hght); ~updateBox(); bool drawControl(); void addCell();    private: POINT pos; int width; int height; int cellHeight; HWND hwnd; HRGN region; // Why HRGN & not RECT? So I can develop this class further to create controls that have irregular shapes HBRUSH bgBrush; HBRUSH frameBrush; int columns; int rows; ubCell *focusCell; vector <ubCell*> cellList;};#endifImplementation:#include <windows.h>#include <string>#include <vector>#include "updateBox.h"using namespace std;/// Update Box Control Class ////// ///updateBox::updateBox(HWND Hwnd, POINT p, int wdth, int hght){   // Post: Constructor pos.x = p.x;   pos.y = p.y;   width = wdth;   height= hght;   cellHeight = 20;   hwnd  = Hwnd;   bgBrush    = CreateSolidBrush(RGB(255,255,255));   frameBrush = CreateSolidBrush(RGB(0,0,0));   columns    = 2;   rows  = 1; // Call Functions   drawControl();   addCell();}updateBox::~updateBox(){   // Post: Default Destructor   DeleteObject(hwnd);   DeleteObject(region); while (!cellList.empty()) {   delete cellList.back(); // WILL this call the ubCell Destructor??    cellList.pop_back();   }}bool updateBox::drawControl(){   // Post: Draw Control   // IT SEEMS THIS FUNCTION IS BEING PERFORMED REPEATEDLY BUT I DONT KNOW WHY HDC hdc;   PAINTSTRUCT ps;   hdc = BeginPaint(hwnd,&ps); // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  InvalidateRgn(hwnd,region,true);  int success = FillRgn(hdc,region,bgBrush);  success = FrameRgn(hdc,region,frameBrush,1,1);  if (success==0) { MessageBox(hwnd,"Failed to fill/frame background HRGN","Error:",MB_OK|MB_ICONERROR);   return false;    }}   else {  MessageBox(hwnd,"Create background region Failed","Error:",MB_OK|MB_ICONERROR);  return false;   } EndPaint(hwnd,&ps);    return true;}void updateBox::addCell(){   // Post: Add a row to Update Box POINT tPos;   tPos.x = pos.x;   tPos.y = pos.y+(cellList.size()*cellHeight);   ubCell *newCell = new ubCell(hwnd,tPos,width,cellHeight);   focusCell = newCell;   cellList.push_back(newCell);}/// Update Box Cell Object //////    ///ubCell::ubCell(HWND Hwnd, POINT p, int wdth, int hght){   // Post: Constructor pos.x = p.x;   pos.y = p.y;   width = wdth;   height= hght;   hwnd  = Hwnd;   bgBrush    = CreateSolidBrush(RGB(0,0,255));   frameBrush = CreateSolidBrush(RGB(255,0,0));   data  = "...empty"; // Call Functions   drawControl();}ubCell::~ubCell(){   // Post: Destructor   DeleteObject(hwnd);   DeleteObject(region);  }bool ubCell::drawControl(){   // Post: Draw Cell control   // IT SEEMS THIS FUNCTION IS BEING PERFORMED REPEATEDLY BUT I DONT KNOW WHY HDC hdc;   PAINTSTRUCT ps;   hdc = BeginPaint(hwnd,&ps); // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  InvalidateRgn(hwnd,region,true); // I think the problem is here  int success = FillRgn(hdc,region,bgBrush);  success = FrameRgn(hdc,region,frameBrush,1,1);  //success = DrawText(hdc,data.c_str(),data.length(),(LPRECT)region,DT_INTERNAL);  success = SetBkMode(hdc,TRANSPARENT);  success = TextOut(hdc,pos.x+2,pos.y+4,data.c_str(),data.length());  if (success==0) { MessageBox(hwnd,"Failed to fill/frame background HRGN OR draw data contents.","Error:",MB_OK|MB_ICONERROR);   return false;    }}   else {  MessageBox(hwnd,"Create background region Failed","Error:",MB_OK|MB_ICONERROR);  return false;   } MessageBox(hwnd,"","",MB_OK);   EndPaint(hwnd,&ps);   return true;}WinMain:#include <windows.h>#include <cstdlib>#include "updateBox.h"using namespace std;// Global Variablesstatic HINSTANCE gInstance;bool test = true;// FunctionsLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){    WNDCLASSEX wc;    HWND hwnd;    MSG Msg;    //Step 1: Registering the Window Class    wc.cbSize   = sizeof(WNDCLASSEX);    wc.style    = 0;    wc.lpfnWndProc   = WndProc;    wc.cbClsExtra    = 0;    wc.cbWndExtra    = 0;    wc.hInstance= gInstance;    wc.hIcon    = LoadIcon(NULL, IDI_APPLICATION);    wc.hCursor  = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);    wc.lpszMenuName  = NULL;    wc.lpszClassName = "Custom Class";    wc.hIconSm  = LoadIcon(NULL, IDI_APPLICATION);    if(!RegisterClassEx(&wc))    {   MessageBox(NULL, "Window Registration Failed!", "Error!",  MB_ICONEXCLAMATION | MB_OK);   return 0;    }    // Step 2: Creating the Window    hwnd = CreateWindowEx(   WS_EX_CLIENTEDGE,   "Custom Class",   "Custom Control: Update Box Class",   WS_OVERLAPPEDWINDOW,   CW_USEDEFAULT, CW_USEDEFAULT, 600, 600,   NULL, NULL, gInstance, NULL);    if(hwnd == NULL)    {   MessageBox(NULL, "Window Creation Failed!", "Error!",  MB_ICONEXCLAMATION | MB_OK);   return 0;    }    ShowWindow(hwnd, nCmdShow);    UpdateWindow(hwnd);    // Step 3: The Message Loop    while(GetMessage(&Msg, NULL, 0, 0) > 0)    {   TranslateMessage(&Msg);   DispatchMessage(&Msg);    }    return Msg.wParam;}// Step 4: the Window ProcedureLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){    switch(msg)    {   case WM_CREATE:   {   }   break;   case WM_COMMAND:   {   switch(LOWORD(wParam)) {   case WM_KEYDOWN:    {    if (HIWORD(wParam) == VK_SPACE) {   InvalidateRect(hwnd,NULL,true);    }    }   break;    default:    break;    }}  break;   case WM_PAINT:   {   if (test) {  POINT p;  p.x = 10;  p.y = 10;  updateBox ub(hwnd,p,200,200);  test = false;  MessageBox(hwnd,"code Performed","",MB_OK);   }   else MessageBox(hwnd,"code NOT performed","",MB_OK);   }   break;   case WM_CLOSE:  DestroyWindow(hwnd);   break;   case WM_DESTROY:  PostQuitMessage(0);   break;   default:  return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}
  As you suspected: The InvalidateRgn call seems to set the window to dirty again.Also, never use MessageBoxes inside WM_PAINT calls to "debug". You only repeatedly invalidate the window region.Also, MOVE THE return DefWindowProc AFTER THE SWITCH. NOT IN THE DEFAULT CASE. EVER.I've removed the MessageBox stuff from the WM_PAINT handler and also the test=false line.Also, initialize the region to NULL and DO NOT CALL DeleteObject on HWND (Destructor of updateBox). HWNDs are not GDI objects.After those changes it runs quite smooth (your cell is a white square with a thin black border?)   ;  Hi thanks for your helpIt seems now your advice has fixed the repeated repainting but when I delete the lines that invalidate the regions in both classes drawControl() functions then yes it just draws the list box outline. But it is meant to draw the row(cell) aswell, which right now is a blue background, red frame & text "...empty". So if I delete the InvalidateRgn(); from ubCell class but keep the InvalidateRgn() funct in updateBox class then the row is drawn BUT not the listbox outline?Hmm, its really confusing why I am getting this error? Do you think this is a really hack/bad way of creating my own control? Is there a better way of doing what I am trying to do? Is this how an Edit box or List box is coded?   ;  Good Effort. Creating a custom win32 Control is not easy. But I love to do it.Your Object Oriented Paradigm is a bit wrong the updateBox object is supposed to be persistent, either global or created with new.Then you need a way of mapping an HWND to an updateBox object. You can use an STL map or store the Pointer to the updateBox object in the Window extra Data.Binding C++ to GUI objects is not a trivial subject. MFC does it one way, ATL does it a bit different, WxWidgets and Qt will also have their own binding Technology.Here is a very old code of mine. It should give you an Idea of how to bind a C++ object to an HWND. My current technology is a bit more complex than this example, but is still based in the same Principle of having a Temporary Window Procedure that allocates the Object.void RegisterGridCtrl ( HINSTANCE hinst ){WNDCLASS wc ;    if ( ! ( ::GetClassInfo ( hinst,GRIDCTRL_WNDCLASS, & wc ) ) ) {InitIELib () ;wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW ;wc.lpfnWndProc = RawGridCtrl::CreateWndProc ;wc.cbClsExtra = 0 ;wc.cbWndExtra = 0 ;wc.hInstance = hinst ;wc.hIcon = NULL ;wc.hCursor = ::LoadCursor ( NULL, IDC_ARROW ) ;wc.hbrBackground = ::GetSysColorBrush ( COLOR_WINDOW ) ;//wc.hbrBackground = ( HBRUSH ) ::GetStockObject ( BLACK_BRUSH ) ;wc.lpszClassName = GRIDCTRL_WNDCLASS ;wc.lpszMenuName  =NULL ;::RegisterClass ( & wc ) ;    }}HWND GridCtrl::Create ( int x, int y, int nWidth, int nHeight,HWND hWndparent, int id, HINSTANCE hInstance ){hwnd = CreateWindow ( GRIDCTRL_WNDCLASS, "",WS_CHILD | WS_VISIBLE | WS_BORDER,x, y, nWidth, nHeight,hWndparent, ( HMENU ) id, hInstance, NULL ) ;::SendMessage ( hwnd, GCM_SETROWWIDTH, cxRowWidth, 0 ) ;::SendMessage ( hwnd, GCM_SETROWCOUNT, 0, nRows ) ;return hwnd ;}LRESULT CALLBACK RawGridCtrl::CreateWndProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ){RawGridCtrl * prgc ;prgc = new RawGridCtrl ;::SetWindowLong ( hwnd, GWL_USERDATA, ( long ) prgc ) ;::SetWindowLong ( hwnd, GWL_WNDPROC, ( long ) RawGridCtrl::WndProc ) ;return CallWindowProc ( RawGridCtrl::WndProc, hwnd, message,wParam, lParam ) ;}LRESULT CALLBACK RawGridCtrl::WndProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ){RawGridCtrl * prgc ;//////////////////////////////////prgc = ( RawGridCtrl * ) ::GetWindowLong ( hwnd, GWL_USERDATA ) ;// Now you can use prgc anyway you like to process the messages switch ( message ) {...    case WM_PAINT :prgc->Paint () ;return 0 ;...About your bug, make your Object persistent first, then it will be easier for someone to help you.   ;  * In the WM_KEYDOWN switch case, you should call UpdateWindow() right after you call InvalidateRect(). Without this call pressing space will not cause the control to be updated (it won't receive a WM_PAINT message).* In updateBox::drawControl(), EndPaint() seems to never be reached. This is bad. You should be doing this instead:case WM_PAINT:    {   PAINTSTRUCT ps;   HDC hdcPaint = BeginPaint( hWnd, &ps );   // Call a function or method to draw the control here.   EndPaint( hWnd, &ps );    }    break;This ensures a BeginPaint() call will be matched with a corresponding EndPaint() call.* You seem to be filling the background with some color when you paint the control. If so, consider addingcase WM_ERASEBKGND: return 1; // You're painting the background anyway, avoid flicker.* A region for each element? I really can't imagine why. You are already keeping what seems to be "bounding box" information for each cell, so why not use just rectangles? You can use bitmaps to draw irregularly shaped cells, but their placement in the control as well as user interaction with them should really use rectangles. Of course, this is a general advice as I'm not sure what exactly the control you are creating is supposed to be for.* There is an article on catch22.net titled "custom control from scratch" I think. It's a must read for anyone wanting to create their own win32 control.* Instead of creating solid brushes for each item, use this, it's faster and more efficient:// From catch22.net - could be faster than FillRect.inline VOID FillRect( HDC hDC, const RECT* pRect, COLORREF color ){COLORREF oldColor = SetBkColor( hDC, color );ExtTextOut( hDC, 0, 0, ETO_OPAQUE, pRect, TEXT(""), 0, 0 );SetBkColor( hDC, oldColor );};  Thanks for all your help :)The tutorial was really helpful. I have made alot of progress but I am trying to figure out if it is possible to do this:-Have an object(window) for the custom control called an updateBox-Have the object create & run its own Windows Proceedure function as a member function of the class updateBoxBut my problem is how to do this, it all gets a bit inbred & "chicken & the egg" problem when I imagine I want to create the control using the function CreateWindowEx() but how, when & where will my object updateBox be created(where should I code this?) from the previous mentioned functioned & can my main Windows Proceedure pass messages to my updateBoxes Windows Proceedure IF its a member function of a class?Hope this makes sense. Here is the progress I have made:#ifndef UPDATEBOX_H#define UPDATEBOX_H#include <windows.h>#include <string>#include <vector>using namespace std;// Update Box Cell Objectstruct ubCell { ubCell(HWND Hwnd, POINT p, int wdth, int hght); bool drawControl(); ~ubCell(); // COLUMN parentCol; // consider a parent object column POINT pos; POINT textPos; int width; int height; HWND hwnd; HRGN region; HBRUSH bgBrush; HBRUSH frameBrush; string data;};// Visual Control - Similar to a List Box control but with more custom functionalityclass updateBox {  public: updateBox(HWND Hwnd, POINT p, int wdth, int hght); ~updateBox(); //LRESULT CALLBACK createWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); //LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); ubCell* addCell(); bool drawControl(HDC hdc); bool drawFocusCell(HDC hdc); bool drawDefaultCell(HDC hdc); bool inCellRgn(int mouse_x, int mouse_y); ubCell* findSelection(int mouse_x, int mouse_y); void SelectCell(int mouse_x, int mouse_y); void eraseRgn(); //HWND createNewMDIChild(HWND hMDIClient); //bool setUpMDIChildWindowClass(HINSTANCE hInstance);    private: POINT pos; int width; int height; int cellHeight; HWND hwnd; HRGN region; // Why HRGN & not RECT? So I can develop this class further to create controls that have irregular shapes HRGN cellRegion; HBRUSH bgBrush; HBRUSH frameBrush; int columns; ubCell *focusCell; ubCell *prevFocusCell; vector <ubCell*> cellList;   bool initialiseDraw;   };/// Functions ///void InitUpdateboxClass();static updateBox* GetUpdateBox(HWND hwnd);void SetUpdateBox(HWND hwnd, updateBox *udb);LRESULT CALLBACK UpdateBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);#endif#include <windows.h>#include <string>#include <vector>#include "updateBox.h"using namespace std;/// Register Custom Control Class ////// ///void InitUpdateboxClass() {   // Post: Register custom class   WNDCLASSEX wc; wc.cbSize   = sizeof(wc);wc.lpszClassName = "updateBox";   wc.hInstance= GetModuleHandle(NULL);   wc.lpfnWndProc   = UpdateBoxWndProc;   wc.hCursor  = LoadCursor(NULL,IDC_ARROW);   wc.hIcon    = NULL;   wc.lpszMenuName  = NULL;   wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE);   wc.style    = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;   wc.cbClsExtra    = 0;   wc.cbWndExtra    = sizeof(updateBox*);   wc.hIconSm  = NULL; if(!RegisterClassEx(&wc))    {   MessageBox(NULL, "Update Box Class Registration Failed", "Error",  MB_ICONEXCLAMATION | MB_OK);    }  }static updateBox* GetUpdateBox(HWND hwnd){   // Post:    return (updateBox*)GetWindowLong(hwnd,0);}void SetUpdateBox(HWND hwnd, updateBox *udb){// Post: SetWindowLong(hwnd,0,(LONG)udb);}LRESULT CALLBACK UpdateBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){   // Post: Receives all UpdateBox window messages updateBox *udb = GetUpdateBox(hwnd); switch (msg)    {    case WM_NCCREATE:    {    udb = (updateBox*)malloc(sizeof(updateBox));   if (udb==false) {   MessageBox(NULL,"Failed to create Update Box window","Error",MB_OK|MB_ICONERROR);   return 0;    }   SetUpdateBox(hwnd,udb); // Attach custom class to this window.    }    break;    case WM_LBUTTONDOWN:    {    // Select/Click a new cell to append/alter    if (udb.inCellRgn(LOWORD(lParam),HIWORD(lParam))) {   udb.SelectCell(LOWORD(lParam),HIWORD(lParam));   udb.eraseRgn();    }    }   break;    case WM_LBUTTONDBLCLK:    {    // Add new cell to update boxif (!udb.inCellRgn(LOWORD(lParam),HIWORD(lParam))) {   prevFocusCell = focusCell;   focusCell= addCell();   udb.eraseRgn();    }else { // Select Cell   udb.SelectCell(LOWORD(lParam),HIWORD(lParam));   udb.eraseRgn();    }    }    break;    case WM_PAINT:    {    HDC hdc;    PAINTSTRUCT ps;    hdc = BeginPaint(hwnd,&ps);if (initialiseDraw) {   drawControl(hdc);   initialiseDraw = false;    }    if (focusCell != prevFocusCell) {   drawDefaultCell(hdc);    }   drawFocusCell(hdc);    EndPaint(hwnd,&ps);    }   break;    /* case WM_ERASEBKGND:return 1; // You're painting the background anyway, avoid flicker.    break; */    case WM_NCDESTROY:    free(udb);    break;    default:    break;   }   return DefWindowProc(hwnd, msg, wParam, lParam);}/// Update Box Control Class ////// ///updateBox::updateBox(HWND Hwnd, POINT p, int wdth, int hght){   // Post: Constructor pos.x= p.x;   pos.y= p.y;   width= wdth;   height    = hght;   cellHeight= 20;   hwnd = Hwnd;   region    = NULL;   cellRegion= NULL;   bgBrush   = CreateSolidBrush(RGB(255,255,255));   frameBrush= CreateSolidBrush(RGB(0,0,0));   columns   = 2;   focusCell = addCell();   prevFocusCell  = focusCell;   initialiseDraw = true;  }updateBox::~updateBox(){   // Post: Default Destructor   DeleteObject(region);   DeleteObject(cellRegon); while (!cellList.empty()) {    delete cellList.back(); // WILL this call the ubCell Destructor??    cellList.pop_back();   }}/* LRESULT CALLBACK updateBox::createWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){   // Post:    updateBox *newObj = new updateBox(hwnd,p,width,height);   SetWindowLong ( hwnd, GWL_USERDATA, ( long )) ;   SetWindowLong ( hwnd, GWL_WNDPROC, ( long )updateBox::UpdateBoxWndProc ) ;   return CallWindowProc (updateBox::UpdateBoxWndProc, hwnd, message,wParam, lParam ) ;} */ubCell* updateBox::addCell(){   // Post: Add a ubCell/row to Update BoxPOINT tPos;   tPos.x = pos.x;   tPos.y = pos.y+(cellList.size()*cellHeight);   ubCell *newCell = new ubCell(hwnd,tPos,width,cellHeight);   cellList.push_back(newCell);   int success = CombineRgn(cellRegion,newCell->region,cellRegion,RGN_XOR); // update cellRegion   if (success==NULLREGION || success==ERROR) {  MessageBox(hwnd,"Failed to combine new ubCell region & cellRegion.","Error",MB_OK|MB_ICONERROR);   }   return newCell;}bool updateBox::drawControl(HDC hdc){   // Post: Draw Control   // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  //InvalidateRgn(hwnd,region,true);  int success = FillRgn(hdc,region,bgBrush);  success = FrameRgn(hdc,region,frameBrush,1,1);  if (success==0) { //MessageBox(hwnd,"Failed to fill/frame background HRGN","Error:",MB_OK|MB_ICONERROR);   return false;    }}   else {  //MessageBox(hwnd,"Create background region Failed","Error:",MB_OK|MB_ICONERROR);  return false;   }    return true;}bool updateBox::drawFocusCell(HDC hdc){   // Post: Draw ubCell 'appending' style   // CREATE CARAT }bool updateBox::drawDefaultCell(HDC hdc){   // Post: Draw ubCell 'default' style   // Write time in bold, other data in normal font, if other data is longer than cell width, we resize ubCell height}bool updateBox::inCellRgn(int mouse_x, int mouse_y){   // Post: Returns true if mouse lies/clicked any ubCell else false    int collision = PtInRegion(cellRegion,mouse_x,mouse_y);   if (collision != 0) {  return true;  }   else return false}ubCell* updateBox::findSelection(int mouse_x, int mouse_y){   // Post: Return the ubCell the user has selected with mouse   // ITERATIVE METHOD !!!! NOT EFFICIENT FIND OTHER WAY   for (int i=0 i<cellList.size(); i++) {   int collision = PtInRegion(cellList.at(i)->region,mouse_x,mouse_y);   if (collision != 0) {  return cellList.at(i);   }   }   return NULL; // Should not get to this point if function is used correctly but just incase return NULL pointer}void SelectCell(int mouse_x, int mouse_y){   // Post:    ubCell *selectedCell = findSelection(LOWORD(lParam),HIWORD(lParam)); if (selectedCell != focusCell) {  prevFocusCell = focusCell;  focusCell= selectedCell;   }}void updateBox::eraseRgn(){   // Post:    InvalidateRgn(hwnd,focusCell.region,true);// Clear new focus cells rgn   InvalidateRgn(hwnd,prevFocusCell.region,true); // clear prev focus cells rgn   UpdateWindow(hwnd);   // Send message WM_PAINT}/* HWND updateBox::createNewMDIChild(HWND hMDIClient){MDICREATESTRUCT mcs;HWND hChild;mcs.szTitle = "Update Box";mcs.szClass = "updateBox";mcs.hOwner  = GetModuleHandle(NULL);mcs.x = mcs.cx = CW_USEDEFAULT;mcs.y = mcs.cy = CW_USEDEFAULT;mcs.style = MDIS_ALLCHILDSTYLES;hChild = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG)&mcs);if(!hChild){MessageBox(hMDIClient, "MDI Child creation failed.", "Oh Oh...",MB_ICONEXCLAMATION | MB_OK);}return hChild;}bool updateBox::setUpMDIChildWindowClass(HINSTANCE hInstance){WNDCLASSEX wc;wc.cbSize = sizeof(WNDCLASSEX);wc.style = CS_HREDRAW | CS_VREDRAW;wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);wc.lpszMenuName  = NULL;wc.lpszClassName = "updateBox";wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);if(!RegisterClassEx(&wc)){MessageBox(0, "Could Not Register Child Window", "Oh Oh...",MB_ICONEXCLAMATION | MB_OK);return false;}elsereturn true;} *//// Update Box Cell Object //////    ///ubCell::ubCell(HWND Hwnd, POINT p, int wdth, int hght){   // Post: Constructor pos.x = p.x;   pos.y = p.y;   width = wdth;   height= hght;   hwnd  = Hwnd;   region= NULL;   textPos.x  = pos.x+2;   textPos.y  = pos.y+1;   bgBrush    = CreateSolidBrush(RGB(0,0,255));   frameBrush = CreateSolidBrush(RGB(255,0,0));   data  = "...empty";}ubCell::~ubCell(){   // Post: Destructor   DeleteObject(region);  }bool ubCell::drawControl(){   // Post: Draw Cell control // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  //InvalidateRgn(hwnd,region,true);  int success = FillRgn(hdc,region,bgBrush);  success = FrameRgn(hdc,region,frameBrush,1,1);  //success = DrawText(hdc,data.c_str(),data.length(),(LPRECT)region,DT_INTERNAL);  success = SetBkMode(hdc,TRANSPARENT);  success = TextOut(hdc,textPos.x,textPos.y,data.c_str(),data.length());  if (success==0) { //MessageBox(hwnd,"Failed to fill/frame background HRGN OR draw data contents.","Error:",MB_OK|MB_ICONERROR);   return false;    }}   else {  //MessageBox(hwnd,"Create background region Failed","Error:",MB_OK|MB_ICONERROR);  return false;   } return true;} 