How to Subclass a VB Form Using VB CDK Custom Control

Last reviewed: December 8, 1995
Article ID: Q140883
The information in this article applies to:

- Professional and Enterprise Editions of Microsoft Visual Basic,

  16-bit only, for Windows, version 4.0

SUMMARY

In Windows programming terms, subclassing is the process of creating a message handling procedure and intercepting messages for a given window, handling any messages you choose, and passing the rest to the window's original message handler.

The subclass procedure is basically a message filter that performs non-default processing for a few key messages, and passes other messages to a default window procedure using CallWindowProc(). The CallWindowProc() function passes a message to the Windows system, which in turns sends the message to the target window procedure. The target window procedure cannot be called directly by the subclass procedure because the target procedure (in this case a window procedure) is exported.

Below is a simple example of how to subclass a Visual Basic form by writing a custom control using the Visual Basic Control Development Kit (CDK). The Visual Basic CDK is shipped as part of Microsoft Professional Toolkit for Microsoft Visual Basic version 1.0 for Windows and as part of the Professional Edition of Microsoft Visual Basic versions 2.0, 3.0 and 4.0 for Windows.

MORE INFORMATION

The following code example demonstrates how to subclass a form from a custom control using the Visual Basic Custom CDK.

This example is developed using the CIRCLE.C program example from the CIRCLE1 project supplied with the CDK package. Only the file(s) that have changed from this project are included, and it is assumed that you have the additional CDK files as well as a C compiler capable of creating a Windows 3.0 compatible dynamic link library (DLL).

The basic idea for subclassing is to examine the window structure for a window directly using the GetWindowLong function to determine the address of the original window procedure. You can then change the address of the target window's window procedure to the address of your subclass procedure using SetWindowLong. In your subclass window procedure, you handle the messages you wish and use CallWindowProc to pass along other messages to the original window procedure.

//=================== CIRCLE1 ==================
// CIRCLE.C
// An example of subclassing a Visual Basic Form
//==============================================

#define  NOCOMM
#include <windows.h>

#include <vbapi.h>
#include "circle.h"

//declare the subclass procedure
LONG FAR PASCAL _export SbClsProc(HWND,USHORT,USHORT,LONG);

//far pointer to the default procedure
FARPROC lpfnOldProc = (FARPROC) NULL ;

//get the controls parent handle(form1)
HWND    hParent ;

//----------------------------------------------------------
// Circle Control Procedure
//----------------------------------------------------------
LONG FAR PASCAL _export CircleCtlProc (HCTL hctl, HWND hwnd,
     USHORT msg, USHORT wp, LONG lp)
{
   LONG lResult ;
   switch (msg)
   {
      case WM_CREATE:
         switch (VBGetMode())
         {
            //this will only be processed during run mode
            case MODE_RUN:
            {
               hParent = GetParent (hwnd) ;
               //get the address instance to normal proc
               lpfnOldProc = (FARPROC) GetWindowLong
                              (hParent, GWL_WNDPROC) ;
               //reset the address instance to the new proc
               SetWindowLong (hParent,
                        GWL_WNDPROC, (LONG) SbClsProc) ;
            }
            break ;
         }
         break ;
   }
   // call the default VB proc
   lResult = VBDefControlProc(hctl, hwnd, msg, wp, lp);
   return lResult;

}

LONG FAR PASCAL _export SbClsProc (HWND hwnd, USHORT msg,

     USHORT wp, LONG lp)
{
   switch (msg)
   {
      case WM_SIZE:
      {
      //place size event here for example...
      }
      break;
      case WM_DESTROY:
         SetWindowLong (hwnd, GWL_WNDPROC,
                        (LONG) lpfnOldProc) ;
      break ;
   }
   // call CircleCtlProc to process any other messages
   return (CallWindowProc(lpfnOldProc, hwnd, msg, wp, lp));
}

;========================================================== ;Circle.def - module definition file for CIRCLE3.VBX control ;==========================================================

LIBRARY         CIRCLE
EXETYPE         WINDOWS
DESCRIPTION     'Visual Basic Circle Custom Control'

CODE            MOVEABLE
DATA            MOVEABLE SINGLE

HEAPSIZE        1024

EXPORTS
           WEP       @1 RESIDENTNAME
           SbClsProc @2
;------------------------------------------------------


Additional reference words: 1.00 2.00 3.00 4.00 vb4win vb416
KBCategory: kbtool kbprg
KBSubcategory: TlsCDK


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: December 8, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.