   [Win32 C++] Custom Ctr String contents not being saved
  Hello I have my own control that I made which is really just like a list box. I'll call my custom control a List box to make it more understandable.My problem is:When I change the string in a cell of my listbox to a different value, the new value is not stored. Instead the string just becomes empty, it has nothing in it. I dont know why this happens & if anyone could help me figure out whats going wrong I'd really appreciate it. I have a feeling it has to do with my pointers.The way my custom control works:- Double click the control: creates a new cell in the control- Change the string in a cell: type in some text in the cell & press enter. A messagebox should appear with the new string in it to confirm the window received enter.Custom control Cell structure:struct ubCell { ubCell(HWND Hwnd, POINT p, int nWidth, int nHeight); ~ubCell(); bool drawControl(HDC hdc); bool drawEditControl(); void setDataValue(string value); // 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; // the string that can be altered};When the custom control receives the VK_RETURN msg it captures the text inside the ubCell's edit box & saves it to the ubCells member string called datacase WM_KEYDOWN:    {    switch(LOWORD(wParam)) {case VK_RETURN:{string controlText = "";int len = GetWindowTextLength(GetDlgItem(hwnd,UB_FOCUSCELL));GetDlgItemText(hwnd,UB_FOCUSCELL,(LPTSTR)controlText.c_str(),len+2); // get text from editobxudb->focusCell->data = controlText; // udb is the custom control class objectMessageBox(hwnd,controlText.c_str(),"FocusCell text set",MB_OK); }break;default:break; }    }    break;This memeber function of the ubCell structure paints the data string contents on the client window. But the problem is the string contents keep getting erased somewherebool ubCell::drawControl(HDC hdc){   // Post: Draw Cell control // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  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);  // Draw data string text  success = SetBkMode(hdc,TRANSPARENT);  success = TextOut(hdc,textPos.x,textPos.y,data.c_str(),data.length());  if (success!=0) { return true;    }} return false;}[Edited by - gretty on April 18, 2010 4:24:51 PM]
  There were (and probably still are) a few bugs in there. The main problem though: You create a child HWND (the edit), but check for VK_RETURN in the main window. The edit has the focus, so it received VK_RETURN. In the modified code I've subclasses the edit to preprocess WM_KEYDOWN and notify the parent (assuming that the parent is your UpdateBox).I've added comments on every modification (// GR). I also had to add three return bools since VS didn't want to compile. You should maybe consider to drop Dev-C++ and get something more standards compliant.UpdateBox.h#ifndef UPDATEBOX_H#define UPDATEBOX_H#include <windows.h>#include <string>#include <vector>using namespace std;/// Constants ///#define UB_FOCUSCELL 50001/// Functions ///void InitUpdateboxClass();LRESULT CALLBACK UpdateBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);/// Update Box Cell Object ///struct ubCell { ubCell(HWND Hwnd, POINT p, int nWidth, int nHeight); ~ubCell(); bool drawControl(HDC hdc); bool drawEditControl(); void setDataValue(string value); // 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 functionality ///class updateBox {  public: // Public Variables ubCell *focusCell; ubCell *prevFocusCell; bool initialiseDraw;  // Public Functions updateBox(HWND Hwnd, POINT p); ~updateBox(); ubCell* addCell(); void setDimensions(int nWidth, int nHeight); void setFocusCell(); bool drawControl(HDC hdc); bool drawFocusCell(); 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();    private: POINT pos; int width; int height; int cellHeight; HWND hwnd; HWND focusEdit; 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; vector <ubCell*> cellList;    // GR: Added edit subclass proc static WNDPROC  OriginalEditProc; static LRESULT CALLBACK UpdateBoxCellProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );};#endifUpdateBox.cpp#include <windows.h>#include <string>#include <vector>#include <sstream>#include <iostream>#include "debuggingFile.h"#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);    }  }LRESULT CALLBACK UpdateBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){   // Post: Receives all UpdateBox window messages updateBox *udb = (updateBox*)GetWindowLong(hwnd,GWL_USERDATA);   switch (msg)    {    case WM_NCCREATE:    {    POINT p;    p.x = 0; p.y = 0;    udb = new updateBox(hwnd,p);   // GR: new throws an exception, if not, it would return NULL, not false    if ( udb == NULL ){   MessageBox(NULL,"Failed to create Update Box window","Error",MB_OK|MB_ICONERROR);   return 0;    }   // Attach custom class to this window.    // GR: Shouldn't that be udb here?    //SetWindowLong(hwnd, GWL_USERDATA,static_cast<LONG>((LONG)new updateBox(hwnd, p)));    SetWindowLong( hwnd, GWL_USERDATA, static_cast<LONG>( (LONG)udb ) );    //SetWindowLongPtr(hwnd,0,reinterpret_cast<LONG_PTR>(udb));    //SetWindowLong(hwnd,0,(LONG)udb);    //SetWindowLong (hwnd,GWL_USERDATA,(long)udb) ;    //SetWindowLong (hwnd, GWL_WNDPROC,(long)UpdateBoxWndProc) ;    }    break;    case WM_LBUTTONDOWN:    {    // Select/Click a new cell to append/alter    SetFocus(hwnd);    if ( udb->inCellRgn(LOWORD(lParam),HIWORD(lParam)) ) {   udb->SelectCell(LOWORD(lParam),HIWORD(lParam));   udb->eraseRgn();   udb->drawFocusCell();    }    }   break;    case WM_LBUTTONDBLCLK:    {    // Add new cell to update boxif (!udb->inCellRgn(LOWORD(lParam),HIWORD(lParam))) {   udb->prevFocusCell = udb->focusCell;   udb->focusCell= udb->addCell();   udb->eraseRgn();   udb->drawFocusCell();    }else { // Select Cell   udb->SelectCell(LOWORD(lParam),HIWORD(lParam));   udb->eraseRgn();    }    }    break;    case WM_KEYDOWN:    {    switch(LOWORD(wParam)) {case VK_RETURN:{string controlText = "";int len = GetWindowTextLength(GetDlgItem(hwnd,UB_FOCUSCELL));GetDlgItemText(hwnd,UB_FOCUSCELL,(LPTSTR)controlText.c_str(),len+2); // get text from editobx//udb->focusCell->data = controlText;udb->focusCell->setDataValue(controlText);MessageBox(hwnd,controlText.c_str(),"FocusCell text set",MB_OK); }break;default:break; }    }    break;    case WM_COMMAND:    {    switch(LOWORD(wParam)) {default:break; }    }break;    case WM_PAINT:    {    HDC hdc;    PAINTSTRUCT ps;    hdc = BeginPaint(hwnd,&ps);if (udb->initialiseDraw) {   RECT clientR;   GetClientRect(hwnd,&clientR);   udb->setDimensions(clientR.right,clientR.bottom);   udb->drawControl(hdc);   udb->setFocusCell();   udb->initialiseDraw = false;    }    if (udb->focusCell != udb->prevFocusCell) {   udb->drawDefaultCell(hdc);    }   EndPaint(hwnd,&ps);    }   break;    case WM_ERASEBKGND:return 1;    break;    case WM_NCDESTROY:    delete udb;    break;    // GR: Handle return notification    case WM_USER + 17: {   // copied the VK_RETURN handling code here   string controlText = "";   int len = GetWindowTextLength(GetDlgItem(hwnd,UB_FOCUSCELL));   // GR: Make sure controlText contains enough space for all the data!   controlText.resize( len + 1 );   GetDlgItemText(hwnd,UB_FOCUSCELL,(LPTSTR)controlText.data(),len + 1 ); // get text from editobx   //udb->focusCell->data = controlText;   udb->focusCell->setDataValue(controlText);   MessageBox(hwnd,controlText.c_str(),"FocusCell text set",MB_OK);  } break;    default:    break;   }   return DefWindowProc(hwnd, msg, wParam, lParam);}/// Update Box Control Class ////// ///updateBox::updateBox(HWND Hwnd, POINT p){   // Post: Constructor pos.x= p.x;   pos.y= p.y;   width= 100;   height    = 200;   cellHeight= 20;   hwnd = Hwnd;   focusEdit = NULL;   region    = NULL;   cellRegion= CreateRectRgn(0,0,width,1); // Create small region otherwise we cant combine rgns   bgBrush   = CreateSolidBrush(RGB(0,255,255));   frameBrush= CreateSolidBrush(RGB(0,0,0));   columns   = 2;   focusCell = NULL;   prevFocusCell  = NULL;   initialiseDraw = true; openConsoleWindow();}updateBox::~updateBox(){   // Post: Default Destructor   DeleteObject(region);   DeleteObject(cellRegion); while (!cellList.empty()) {    delete cellList.back(); // WILL this call the ubCell Destructor??    cellList.pop_back();   }}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_OR); // update cellRegion   if (success==NULLREGION || success==ERROR) {  MessageBox(hwnd,"Failed to combine new ubCell region & cellRegion.","Error",MB_OK|MB_ICONERROR);   }   return newCell;}void updateBox::setDimensions(int nWidth, int nHeight){   // Post: Set objects dimensions   width  = nWidth;   height = nHeight;}WNDPROC updateBox::OriginalEditProc;LRESULT CALLBACK updateBox::UpdateBoxCellProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ){   switch ( msg )    { case WM_KEYDOWN:   if ( LOWORD( wParam ) == VK_RETURN )   {// notify parentreturn SendMessage( GetParent( hwnd ), WM_USER + 17, 0, 0 );   }   break;   }   // pass message on to original WNDPROC   return CallWindowProc( OriginalEditProc, hwnd, msg, wParam, lParam );}void updateBox::setFocusCell(){   // Post: Initialise Focus cell   focusCell = addCell();   prevFocusCell  = focusCell; // Create focusEdit (edit box)   focusEdit = CreateWindowEx(0,"edit",focusCell->data.c_str(),WS_CHILD|WS_VISIBLE,pos.x,pos.y,width,cellHeight-3,hwnd,(HMENU)UB_FOCUSCELL,GetModuleHandle(NULL),NULL);    if (!focusEdit) MessageBox(hwnd,"Failed to create focusEdit HWND.","ERROR",MB_OK|MB_ICONERROR); // GR: subclass edit   OriginalEditProc = (WNDPROC)SetWindowLong( focusEdit, GWL_WNDPROC, (LONG)UpdateBoxCellProc );}bool updateBox::drawControl(HDC hdc){   // Post: Draw Control - background colour    // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  int success = FillRgn(hdc,region,bgBrush);  if (success!=0) { return true;    }}    return false;}bool updateBox::drawFocusCell(){   // Post: Draw ubCell 'appending' style   focusCell->drawEditControl();   printCellData(cellList);   // GR: Added - missing return   return true;}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   prevFocusCell->drawControl(hdc);   // GR: Added - missing return   return true;}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 mouse cursor lies inside cell group region   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 mouse cursor lies within individual cells region   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 updateBox::SelectCell(int mouse_x, int mouse_y){   // Post: Set the ubCell selected by the mouse as focusCell   ubCell *selectedCell = findSelection(mouse_x,mouse_y); if (selectedCell != focusCell) {  // Set our old focusCell's data string value   /*string controlText = "";  int len = GetWindowTextLength(GetDlgItem(hwnd,UB_FOCUSCELL));  GetDlgItemText(hwnd,UB_FOCUSCELL,(LPTSTR)controlText.c_str(),len+2); // get text from editobx  focusCell->data = controlText; */    // Set new focus cell  prevFocusCell = focusCell;  focusCell= selectedCell;   }}void updateBox::eraseRgn(){   // Post: Clear focusCell & prevFocusCell regions & call WM_PAINT message   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}/// Update Box Cell Object //////    ///ubCell::ubCell(HWND Hwnd, POINT p, int nWidth, int nHeight){   // Post: Constructor pos.x = p.x;   pos.y = p.y;   width = nWidth;   height= nHeight;   hwnd  = Hwnd;   region= CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   textPos.x  = pos.x+2;   textPos.y  = pos.y+1;   bgBrush    = CreateSolidBrush(RGB(255,0,255));   frameBrush = CreateSolidBrush(RGB(255,255,0));   data  = "...empty";   }ubCell::~ubCell(){   // Post: Destructor   DeleteObject(region);  }bool ubCell::drawControl(HDC hdc){   // Post: Draw Cell control // Create Background   region = CreateRectRgn(pos.x,pos.y,pos.x+width,pos.y+height);   if (region != NULL)    {  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);  // Draw data string text  success = SetBkMode(hdc,TRANSPARENT);  success = TextOut(hdc,textPos.x,textPos.y,data.c_str(),data.length());  if (success!=0) { return true;    }} return false;}bool ubCell::drawEditControl(){   // Post: Move edit box from prevFocusCell to focusCell location    HWND myEdit = GetDlgItem(hwnd,UB_FOCUSCELL);   SetWindowPos(myEdit,HWND_TOPMOST,pos.x,pos.y,width,height,SWP_NOZORDER);   SetWindowText(myEdit,data.c_str());   // GR: Added - missing return   return true;}void ubCell::setDataValue(string value){   // Post:   data = value;   MessageBox(hwnd,data.c_str(),"setDataValue()",MB_OK);}