[comp.windows.ms.programmer] Windows Subclassing

raab@novavax.UUCP (Moshe Raab) (04/28/91)

i would appreciate someone's help with the following windows
problem (i wish there was better windows documentation).
 
i am trying to create my own windows subclass. i created a
dialog box using the sdk dialog editor. the diaolg actually
contains 12 edit controls. i want some of those controls to
accept only numeric characters. i need to trap te WM_CHAR
messages and to accept only those with numeric character
values. i created NumericProc to handle this:
 
FARPROC lpfnNumericProc;
FARPROC lpfnOldEdit;
 
long FAR PASCAL NumericProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
extern FARPROC lpfnOldEdit;
  switch(message)
  {
    case WM_CHAR:
    if (!isdigit(wParam))
      MessageBeep(0);
    break;
  }
  return CallWindowProc(lpfnOldEdit,hwnd,message,wParam,lParam);
}
 
 
i get the instance of the proc in WinMain as follows:
 
  lpfnNumericProc = MakeProcInstance((FARPROC)NumericProc, hInstance);
 
 
i call "DialogBox". The following is the dialog box code.
 
BOOL FAR PASCAL DlgProc(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
static int iCurrentFieldType;
extern FARPROC lpfnNumericProc;
switch(message)
  {
    case WM_INITDIALOG:
    return TRUE;
 
    case WM_COMMAND:
    switch(wParam)
    {
      case IDOK:
      EndDialog(hDlg,TRUE);
      return TRUE;
 
      case IDCANCEL:
      EndDialog(hDlg,FALSE);
      return TRUE;
 
      default:
      if (HIWORD(lParam) == EN_SETFOCUS)
      {
// get field type
        iCurrentFieldType = FieldType(GoldCosts, NUM_GOLD_COSTS, iCurrentControl);
        switch(iCurrentFieldType)
        {
          case NUMERIC:
// use numeric control
          lpfnOldEdit = (FARPROC)GetWindowLong(hDlg,GWL_WNDPROC);
          SetWindowLong(hDlg, GWL_WNDPROC,(LONG) lpfnNumericProc);
          break;
          default:
          break;
        }
      } 
      if (HIWORD(lParam) == EN_KILLFOCUS)
      {
// reset to original edit control
         SetWindowLong(hDlg, GWL_WNDPROC,(LONG) lpfnOldEdit);
      } 
      return FALSE;
    }
  }
  return FALSE;
}
 
The above code doesn't work. i think it is because i am not
passing the proper handle of the edit control. ( i am
passing the address of the current dialog box). if i
understand things correctly, i need to pass the address of
the edit control. is that right? if so, how do i obtain the
handle of the original (or current) edit control handle? if
not, what am i doing wrong?
 
thanks for your help
moshe raab
raab@novavax

bonneau@hyper.hyper.com (Paul Bonneau) (04/30/91)

In article <2368@novavax.UUCP> raab@novavax.UUCP (Moshe Raab) writes:
>
>          case NUMERIC:
>// use numeric control
>          lpfnOldEdit = (FARPROC)GetWindowLong(hDlg,GWL_WNDPROC);
>          SetWindowLong(hDlg, GWL_WNDPROC,(LONG) lpfnNumericProc);
>          break;
>          default:
>          break;
>        }
The problem is that you are subclassing the dialog itself!  Replace
the above GetWindowLong() and SetWindowLong() window handles with
GetDlgItem(hDlg, id).  Also, no need to subclass and unsubclass on
focus changes.  Do it once when the dialog gets WM_INITDIALOG, and
remove subclass (and don't forget to FreeProcInstance()!) on
WM_DESTROY.

cheers - Paul Bonneau.

cadsi@ccad.uiowa.edu (CADSI) (04/30/91)

From article <1991Apr29.190909.12436@hyper.hyper.com>, by bonneau@hyper.hyper.com (Paul Bonneau):
> In article <2368@novavax.UUCP> raab@novavax.UUCP (Moshe Raab) writes:
>>
>>          case NUMERIC:
>>// use numeric control
>>          lpfnOldEdit = (FARPROC)GetWindowLong(hDlg,GWL_WNDPROC);
>>          SetWindowLong(hDlg, GWL_WNDPROC,(LONG) lpfnNumericProc);
>>          break;
>>          default:
>>          break;
>>        }
> The problem is that you are subclassing the dialog itself!  Replace
> the above GetWindowLong() and SetWindowLong() window handles with
> GetDlgItem(hDlg, id).  Also, no need to subclass and unsubclass on
> focus changes.  Do it once when the dialog gets WM_INITDIALOG, and
> remove subclass (and don't forget to FreeProcInstance()!) on
> WM_DESTROY.
> 

You both realize, of course, Reference 1 of the Windows SDK says, explicitly,
that you should NOT subclass Window's edit control windows.

|----------------------------------------------------------------------------|
|Tom Hite					|  The views expressed by me |
|Manager, Product development			|  are mine, not necessarily |
|CADSI (Computer Aided Design Software Inc.	|  the views of CADSI.       |
|----------------------------------------------------------------------------|

chrisr@cognos.UUCP (Christine Roine) (05/01/91)

Tom Hite writes:
>
>You both realize, of course, Reference 1 of the Windows SDK says, explicitly,
>that you should NOT subclass Window's edit control windows.

I went on the Microsoft Windows Application Development course two weeks ago
and they said that this is a typo in the documentation.  What they meant
to say is that you should not SUPERCLASS Windows' edit controls.  It's
absolutely ok to subclass them in your application.

What is superclassing?  That's when you do a SetClassLong(hEditWnd,
GCL_WNDPROC, myOwnEditProc);  This causes all subsequently-created
edit windows to use myOwnEditProc as their window proc.  Since this applies
to ALL applications, not just the edits created by your application, this
is a potentially nasty thing to do.

-- 
Christine Roine          Cognos Incorporated     S-mail: P.O. Box 9707
Voice: (613) 738-1338 x6205                              3755 Riverside Drive
  FAX: (613) 738-0002                                    Ottawa, Ontario
 UUCP: mitel!cunews!cognos!chrisr                        CANADA  K1G 3Z4

risto@tuura.UUCP (Risto Lankinen) (05/03/91)

cadsi@ccad.uiowa.edu (CADSI) writes:

>>[preceding discussion deleted]

>You both realize, of course, Reference 1 of the Windows SDK says, explicitly,
>that you should NOT subclass Window's edit control windows.

Hi!

I've seen it in Ref.manual, too, but I take it to mean that you shouldn't
modify the existing window *classes*, because doing so will affect any and
all windows belonging to that class.  Modifying separate windows, however,
affects only those windows and no other.

In other words, I'd use SetClassXxxx() with anything I've called Register-
Class() for, and SetWindowXxxx() with anything I've called CreateWindow()
for, including edit controls, buttons, etc. which just happen to have their
classes predefined.

Terveisin: Risto Lankinen
-- 
Risto Lankinen / product specialist ***************************************
Nokia Data Systems, Technology Dept *  2                              2   *
THIS SPACE INTENTIONALLY LEFT BLANK * 2 -1 is PRIME!  Now working on 2 +1 *
replies: risto@yj.data.nokia.fi     ***************************************

cadsi@ccad.uiowa.edu (CADSI) (05/06/91)

From article <1158@tuura.UUCP>, by risto@tuura.UUCP (Risto Lankinen):
> cadsi@ccad.uiowa.edu (CADSI) writes:
> 
> 
>>You both realize, of course, Reference 1 of the Windows SDK says, explicitly,
>>that you should NOT subclass Window's edit control windows.
> 
> Hi!
> 
> I've seen it in Ref.manual, too, but I take it to mean that you shouldn't
> modify the existing window *classes*, because doing so will affect any and
> all windows belonging to that class.  Modifying separate windows, however,
> affects only those windows and no other.
> 
[ other stuff deleted]

I think I agree.  <pause with finger on the chin...>  Good point.

|----------------------------------------------------------------------------| |Tom Hite					|  The views expressed by me |
|Manager, Product development			|  are mine, not necessarily |
|CADSI (Computer Aided Design Software Inc.	|  the views of CADSI.       |
|----------------------------------------------------------------------------|