Gyannea
October 17th, 2004, 09:05 AM
I am trying to subclass an edit box to have very restricted input. The user is sending an interactive message over a long distance HF radio link, and all he can do is type a character which is immediately transmitted and type the backspace delete which erases the previously typed character. He can't select text, copy and paste and all that.
So I have subclassed the edit box and tried to limit its activities. In order to do that I need to keep track of the position of the last character in the buffer. Now in my VC documentation is says you can get the position of the last character by sending a message with one of the parameters being the zero-based character index.
That term was never defined. But I am assuming it means the position in the edit box character buffer. Is this true?
I am also having some other funny behaviors and I am wondering if I have done my subclassing wrong. When all I did was include the subclass {remove the entire switch statement in 'EditProc()'] which did nothing but pass everything to the original procedure, the behavior was not correct. Primarily updating the edit window.
If I moved the cursor back and started typing, the display would overwrite what was already there. If I clicked on another window and came back, the text was shown correctly. The same with a backspace. The "backspaced" char was not erased on the screen until I clicked on another window and returned. In other words, forcing a repaint. Is there anything I am doing stupid in setting up my subclassing?
The code below has a bunch of crap for custom coloring the controls, so ignore that.
/*=============================================================================================*/
/* */
/* TELEX DIALOG CALLBACK */
/* */
/*=============================================================================================*/
BOOL KTelexDlg::ModelessProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
DRAWITEMSTRUCT *item;
switch(message)
{
//--- INITIALIZING ------------------------------------------------------------------------:
case WM_INITDIALOG:
c = (struct DLGCOLORS *)*(long int *)((long int *)sptr + 1); // Points to colors
hbrushdlg = CreateSolidBrush(c->bkg); // Gets color of dialog box background
colors.bkg = c->extra->bkg;
hbrushedit = CreateSolidBrush(c->bkg);
originaleditproc = (WNDPROC)SetWindowLong( // Get the original edit procedure
GetDlgItem(hwindow, EDIT_TELEX), // Edit box handle
GWL_WNDPROC, (long int)EditSubclassProc); // Replace with new procedure
SetWindowLong(GetDlgItem(hwindow, EDIT_TELEX), // Store a pointer to this class in
GWL_USERDATA, (long int)this); // the edit procedure
previous_char = 0; // For erasing previously input char
break;
//--- COLOR DIALOG BOX:------------------------------------------------------------------------
case WM_CTLCOLORDLG:
return((BOOL)hbrushdlg);
//--- COLOR EDIT BOX:------------------------------------------------------------------------
case WM_CTLCOLOREDIT:
case WM_CTLCOLORSCROLLBAR:
SetTextColor((HDC)wParam, c->extra->labeltext);
SetBkMode((HDC)wParam, TRANSPARENT);
return((BOOL)hbrushedit);
//--- DRAW CONTROLS:---------------------------------------------------------------------------
case WM_DRAWITEM:
item = (DRAWITEMSTRUCT *)lParam;
if(item->CtlType == ODT_BUTTON)
{
colors.hfont = timesroman12;
colors.framewidth = FRAMEWIDTH + 1;
colors.options = PUSH | UPPERLEFT;
LoadPushButtonColors(&colors, c->push);
}
else if(item->CtlType == ODT_STATIC)
{
colors.hfont = c->hfont;
LoadPushButtonColors(&colors, c->frame);
colors.text = c->extra->labeltext;
colors.options = FRAMEONLY | UPPERLEFT;
}
OnOwnerDraw(item, &colors);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case BUTTON_CHANGEOVER:
break;
}
break;
case WM_NCDESTROY:
SetWindowLong(GetDlgItem(hwindow, EDIT_TELEX), // Restore original edit procedure
GWL_WNDPROC, (long int)originaleditproc);
DeleteObject(hbrushdlg);
DeleteObject(hbrushedit);
*(long int *)(*(long int *)sptr) = NULL; // Sets pointer to this instance to NULL
delete this;
break;
default:
return(0);
}
return(1);
}
/*=============================================================================================*/
/* */
/* STATIC SUBCLASS CALLBACK */
/* */
/*=============================================================================================*/
LRESULT APIENTRY KTelexDlg::EditSubclassProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
KTelexDlg *kptr;
kptr = (KTelexDlg *)GetWindowLong(hwindow, GWL_USERDATA);
return(kptr->EditProc(hwindow, message, wParam,lParam)); // Call instance subclass procedure
}
/*=============================================================================================*/
/* */
/* EDIT SUBCLASS PROC */
/* */
/*=============================================================================================*/
LRESULT KTelexDlg::EditProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_LBUTTONDOWN:
SetFocus(hwindow);
return(0);
case WM_LBUTTONUP:
return(0);
case WM_CHAR:
if(wParam == 8 && // If a backspace character and
previous_char != 0) // there is a character to delete then:
{
message = WM_UNDO; // Delete it.
wParam = 0;
lParam = 0;
char_to_send = 8;
}
else // If a deletable character then:
{
previous_char = wParam;
char_to_send = (long int)wParam;
}
break;
}
return(CallWindowProc(originaleditproc, hwindow, message, wParam, lParam));
}
So I have subclassed the edit box and tried to limit its activities. In order to do that I need to keep track of the position of the last character in the buffer. Now in my VC documentation is says you can get the position of the last character by sending a message with one of the parameters being the zero-based character index.
That term was never defined. But I am assuming it means the position in the edit box character buffer. Is this true?
I am also having some other funny behaviors and I am wondering if I have done my subclassing wrong. When all I did was include the subclass {remove the entire switch statement in 'EditProc()'] which did nothing but pass everything to the original procedure, the behavior was not correct. Primarily updating the edit window.
If I moved the cursor back and started typing, the display would overwrite what was already there. If I clicked on another window and came back, the text was shown correctly. The same with a backspace. The "backspaced" char was not erased on the screen until I clicked on another window and returned. In other words, forcing a repaint. Is there anything I am doing stupid in setting up my subclassing?
The code below has a bunch of crap for custom coloring the controls, so ignore that.
/*=============================================================================================*/
/* */
/* TELEX DIALOG CALLBACK */
/* */
/*=============================================================================================*/
BOOL KTelexDlg::ModelessProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
DRAWITEMSTRUCT *item;
switch(message)
{
//--- INITIALIZING ------------------------------------------------------------------------:
case WM_INITDIALOG:
c = (struct DLGCOLORS *)*(long int *)((long int *)sptr + 1); // Points to colors
hbrushdlg = CreateSolidBrush(c->bkg); // Gets color of dialog box background
colors.bkg = c->extra->bkg;
hbrushedit = CreateSolidBrush(c->bkg);
originaleditproc = (WNDPROC)SetWindowLong( // Get the original edit procedure
GetDlgItem(hwindow, EDIT_TELEX), // Edit box handle
GWL_WNDPROC, (long int)EditSubclassProc); // Replace with new procedure
SetWindowLong(GetDlgItem(hwindow, EDIT_TELEX), // Store a pointer to this class in
GWL_USERDATA, (long int)this); // the edit procedure
previous_char = 0; // For erasing previously input char
break;
//--- COLOR DIALOG BOX:------------------------------------------------------------------------
case WM_CTLCOLORDLG:
return((BOOL)hbrushdlg);
//--- COLOR EDIT BOX:------------------------------------------------------------------------
case WM_CTLCOLOREDIT:
case WM_CTLCOLORSCROLLBAR:
SetTextColor((HDC)wParam, c->extra->labeltext);
SetBkMode((HDC)wParam, TRANSPARENT);
return((BOOL)hbrushedit);
//--- DRAW CONTROLS:---------------------------------------------------------------------------
case WM_DRAWITEM:
item = (DRAWITEMSTRUCT *)lParam;
if(item->CtlType == ODT_BUTTON)
{
colors.hfont = timesroman12;
colors.framewidth = FRAMEWIDTH + 1;
colors.options = PUSH | UPPERLEFT;
LoadPushButtonColors(&colors, c->push);
}
else if(item->CtlType == ODT_STATIC)
{
colors.hfont = c->hfont;
LoadPushButtonColors(&colors, c->frame);
colors.text = c->extra->labeltext;
colors.options = FRAMEONLY | UPPERLEFT;
}
OnOwnerDraw(item, &colors);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case BUTTON_CHANGEOVER:
break;
}
break;
case WM_NCDESTROY:
SetWindowLong(GetDlgItem(hwindow, EDIT_TELEX), // Restore original edit procedure
GWL_WNDPROC, (long int)originaleditproc);
DeleteObject(hbrushdlg);
DeleteObject(hbrushedit);
*(long int *)(*(long int *)sptr) = NULL; // Sets pointer to this instance to NULL
delete this;
break;
default:
return(0);
}
return(1);
}
/*=============================================================================================*/
/* */
/* STATIC SUBCLASS CALLBACK */
/* */
/*=============================================================================================*/
LRESULT APIENTRY KTelexDlg::EditSubclassProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
KTelexDlg *kptr;
kptr = (KTelexDlg *)GetWindowLong(hwindow, GWL_USERDATA);
return(kptr->EditProc(hwindow, message, wParam,lParam)); // Call instance subclass procedure
}
/*=============================================================================================*/
/* */
/* EDIT SUBCLASS PROC */
/* */
/*=============================================================================================*/
LRESULT KTelexDlg::EditProc(HWND hwindow, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_LBUTTONDOWN:
SetFocus(hwindow);
return(0);
case WM_LBUTTONUP:
return(0);
case WM_CHAR:
if(wParam == 8 && // If a backspace character and
previous_char != 0) // there is a character to delete then:
{
message = WM_UNDO; // Delete it.
wParam = 0;
lParam = 0;
char_to_send = 8;
}
else // If a deletable character then:
{
previous_char = wParam;
char_to_send = (long int)wParam;
}
break;
}
return(CallWindowProc(originaleditproc, hwindow, message, wParam, lParam));
}