Hook windows control messages through subclassing

d_arin100's Avatar author of Hook windows control messages through subclassing
This is an article on Hook windows control messages through subclassing in Win32.

Introduction



Subclassing is a very powerful tool in creating your own custom controls and modifying the standard windows interface. This is typically done by replacing the Window Procedure for a window with application-defined window procedure. Subclassing is a technique that allows an application to intercept messages destined for another window. This article contains subclassing in SDK as well as subclassing in MFC programs.

SDK subclassing



Sometimes we need to modify the functionality of control and customize it slightly depending on the application. Let we need a letter only edit control (A control which take only letter no numeric & other special character.). Here subclassing is a rescuer for resolving it. Subclassing involves replacing the Message Handlers of the control, and passing any unprocessed message to the controls Message Handler. By using SetWindowLong() we can specify a new Window Procedure for the control which needs to be subclass.

Code: Cpp
WNDPROC g_pOldProc;
BOOL CALLBACK MyDialogProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MyEditProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,   HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MyDialogProc, 0);
    return TRUE;
}
 
BOOL CALLBACK MyDialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{     
      HWND hMyEdit;
      switch (uMsg)
      {
         case WM_INITDIALOG:
               hMyEdit = GetDlgItem(hWndDlg, IDC_EDIT);
               /// Subclass the Edit control
               g_pOldProc = (WNDPROC)SetWindowLong(hMyEdit, GWL_WNDPROC, (LONG)MyEditProc);
               return TRUE;
         case WM_COMMAND:
                 switch(LOWORD(wParam))
                   {
                      case IDOK:
                                EndDialog(hWndDlg, LOWORD(wParam));
                   }
                 return TRUE;
      }
      return FALSE;
}
 
LRESULT CALLBACK MyEditProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      TCHAR chChar;
      switch (message)
      {
          case WM_CHAR:
                    chChar = (TCHAR) wParam;
                    /// Is the char is an alphabetic character
                        if(!IsCharAlpha(chChar))
                              return 0;
                        break;
      }
      return CallWindowProc (g_pOldProc, hwnd, message, wParam, lParam);
}
Now any message to the edit control will first go through the "[COLOR=#990000]MyEditProc" Window Procedure, which will decide whether the message will go or not to the edit control's Window Procedure.

MFC Subclassing



Subclassing in a MFC program is similar to SDK subclassing. MFC Subclassing also done by replacing the message handlers of a control. First we need to inherit the class from a control class.
Code: Cpp
class CLetterEdit : public CEdit
{
 
   public:
         CLetterEdit();
 
   public:
         virtual ~CLetterEdit();
 
   protected:
      //{{AFX_MSG(CLetterEdit)
      afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
      //}}AFX_MSG
 
      DECLARE_MESSAGE_MAP()
};
Then we need to add Message Handlers of the new class.
Code: Cpp
void CLetterEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
      if(IsCharAlpha((TCHAR)nChar))
            /// The control's message handler has been called
            CEdit::OnChar(nChar, nRepCnt, nFlags);
}
Next we need to associate the window with an instance of our new class.
Code: Cpp
CLetterEdit m_edit;
 
DDX_Control(pDX, IDC_EDIT, m_edit);
0
chyssa's Avatar, Join Date: Oct 2009
Newbie Member
Thanks for sharing your codes...
0
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Nominate this article for Article of the month - Oct 2009