home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / progjour / 1991 / 06 / winclass.cpp < prev    next >
C/C++ Source or Header  |  1991-10-31  |  14KB  |  490 lines

  1. /*--------------------------------------------------------
  2.   A tiny Windows class library
  3.   John Dimm, June 1991
  4. --------------------------------------------------------*/
  5. #include <windows.h>
  6. #include <dos.h>
  7.  
  8. #include "winclass.h"
  9.  
  10. #define MAX_WINCLASSES 32
  11. #define WW_POINTER 0
  12. #define WP_POINTER_OFF "PDLG_OFF"
  13. #define WP_POINTER_SEG "PDLG_SEG"
  14. #define NEAR_POINTERS defined (__TINY__) || \
  15.                       defined (__SMALL__) || \
  16.                       defined (__MEDIUM__)
  17.  
  18.  
  19. long FAR PASCAL _export ExportWndProc( HWND hWnd,
  20.          WORD iMessage, WORD wParam, LONG lParam );
  21. long FAR PASCAL _export ExportDlgProc( HWND hDlg,
  22.          WORD iMessage, WORD wParam, LONG lParam );
  23.  
  24. struct MAIN
  25. {
  26.   BOOLPROC InitInst[MAX_WINCLASSES];
  27.   BOOLPROC InitApp[MAX_WINCLASSES];
  28.   int nApp;
  29.   int nInst;
  30.   HANDLE hInstance;
  31.   HANDLE hPrevInstance;
  32.   int nCmdShow;
  33.  
  34.   MAIN () {nApp = 0; nInst = 0;};
  35.   BOOL InitApplication();
  36.   BOOL InitInstance();
  37.   void Init (HANDLE hInstancePrm,
  38.              HANDLE hPrevInstancePrm, int nCmdShowPrm);
  39. };
  40. MAIN Main;
  41.  
  42. /*--------------------------------------------------------
  43.   Main Windows function
  44. --------------------------------------------------------*/
  45. #pragma argsused
  46. int PASCAL WinMain( HANDLE hInstance,
  47.                     HANDLE hPrevInstance,
  48.                     LPSTR lpszCmdLine,
  49.                     int nCmdShow )
  50. {
  51.   MSG msg;
  52.  
  53.   Main.Init (hInstance, hPrevInstance, nCmdShow);
  54.  
  55.   if ( ! hPrevInstance )
  56.     if ( ! Main.InitApplication() )
  57.       return FALSE;
  58.  
  59.   if ( ! Main.InitInstance() )
  60.     return FALSE;
  61.  
  62.   while( GetMessage( &msg, NULL, 0, 0 ) )
  63.   {
  64.     TranslateMessage( &msg );
  65.     DispatchMessage( &msg );
  66.   }
  67.   return msg.wParam;
  68. }
  69.  
  70. /*--------------------------------------------------------
  71.   Main stores the parameters passed to WinMain, and stores
  72.   the InitApplication and InitInstance procs for each
  73.   module.
  74. --------------------------------------------------------*/
  75. void MAIN::Init (HANDLE hInstancePrm,
  76.                  HANDLE hPrevInstancePrm, int nCmdShowPrm)
  77. {
  78.   hInstance = hInstancePrm;
  79.   hPrevInstance = hPrevInstancePrm;
  80.   nCmdShow = nCmdShowPrm;
  81. }
  82.  
  83. /*--------------------------------------------------------
  84.   Each module registers its InitInstance function with
  85.   Main. The InitInstance functions will be called after the
  86.   instance handle is stored.
  87. --------------------------------------------------------*/
  88. void RegisterInstance ( BOOLPROC InitInstance )
  89. {
  90.   if (Main.nInst < MAX_WINCLASSES)
  91.     Main.InitInst[Main.nInst++] = InitInstance;
  92. }
  93.  
  94. /*--------------------------------------------------------
  95.   Call the InitInstance for each module.
  96. --------------------------------------------------------*/
  97. BOOL MAIN::InitInstance()
  98. {
  99.   int i;
  100.   for (i=0; i<nInst; i++)
  101.     if ( ! InitInst[i]() )
  102.       return FALSE;
  103.   return TRUE;
  104. }
  105.  
  106. /*--------------------------------------------------------
  107.   Same thing with the InitApplication functions.
  108. --------------------------------------------------------*/
  109. void RegisterApplication ( BOOLPROC InitApplication )
  110. {
  111.   if (Main.nApp < MAX_WINCLASSES)
  112.     Main.InitApp[Main.nApp++] = InitApplication;
  113. }
  114.  
  115. /*--------------------------------------------------------
  116.   Call the InitApplication for each module.
  117. --------------------------------------------------------*/
  118. BOOL MAIN::InitApplication()
  119. {
  120.   int i;
  121.   for (i=0; i<nApp; i++)
  122.     if ( ! InitApp[i]() )
  123.       return FALSE;
  124.   return TRUE;
  125. }
  126.  
  127. /*--------------------------------------------------------
  128.   Store the nCmdShow passed in from Windows.
  129. --------------------------------------------------------*/
  130. WINDOW::WINDOW()
  131. {
  132.   nCmdShow = Main.nCmdShow;
  133. }
  134.  
  135. /*--------------------------------------------------------
  136.   Register a class and create a window
  137. --------------------------------------------------------*/
  138. BOOL WINDOW::Make()
  139. {
  140.   WNDCLASS WndClass;
  141.   CREATESTRUCT CreateStruct;
  142.  
  143.   // Call the virtual function DefineWClass, allowing
  144.   // descendents of WINDOW to override the default values
  145.   // for the window class
  146.  
  147.   DefineWClass( WndClass );
  148.  
  149.   // Register the class, if it's not already registered
  150.  
  151.   if ( ! GetClassInfo (Main.hInstance,
  152.                        WndClass.lpszClassName,
  153.                        (LPWNDCLASS)&WndClass) )
  154.     if ( ! RegisterClass( (LPWNDCLASS) &WndClass ) )
  155.       return FALSE;
  156.  
  157.   // Allow descendents of WINDOW to change the default
  158.   // values for the create structure, by overriding
  159.   // DefineCreate().
  160.  
  161.   DefineCreate( CreateStruct );
  162.   CreateWindow( CreateStruct.lpszClass,
  163.                 CreateStruct.lpszName,
  164.                 CreateStruct.style,
  165.                 CreateStruct.x,
  166.                 CreateStruct.y,
  167.                 CreateStruct.cx,
  168.                 CreateStruct.cy,
  169.                 CreateStruct.hwndParent,
  170.                 CreateStruct.hMenu,
  171.                 CreateStruct.hInstance,
  172.                 CreateStruct.lpCreateParams );
  173.  
  174.   // The object's hWnd was set in ExportWndProc when the
  175.   // WM_CREATE was processed
  176.  
  177.   if ( ! hWnd )
  178.     return FALSE;
  179.  
  180.   Show();
  181.   Update();
  182.  
  183.   return TRUE;
  184. }
  185.  
  186. /*--------------------------------------------------------
  187.   Default window class
  188. --------------------------------------------------------*/
  189. void WINDOW::DefineWClass ( WNDCLASS &WndClass )
  190. {
  191.   WndClass.style         = NULL;
  192.   WndClass.lpfnWndProc   = ExportWndProc;
  193.   WndClass.cbClsExtra    = 0;
  194.   WndClass.cbWndExtra    = sizeof( PWINDOW );
  195.   WndClass.hInstance     = Main.hInstance;
  196.   WndClass.hIcon         = NULL;
  197.   WndClass.hCursor       = LoadCursor( NULL, IDC_ARROW );
  198.   WndClass.hbrBackground = GetStockObject( WHITE_BRUSH );
  199.   WndClass.lpszMenuName  = NULL;
  200.   WndClass.lpszClassName = GetClassName();
  201. }
  202.  
  203. /*--------------------------------------------------------
  204.   Default create structure
  205. --------------------------------------------------------*/
  206. void WINDOW::DefineCreate ( CREATESTRUCT &CreateStruct )
  207. {
  208.   CreateStruct.lpszClass      = GetClassName();
  209.   CreateStruct.lpszName       = GetWindowName();
  210.   CreateStruct.style          = WS_OVERLAPPEDWINDOW;
  211.   CreateStruct.x              = CW_USEDEFAULT;
  212.   CreateStruct.y              = 0;
  213.   CreateStruct.cx             = CW_USEDEFAULT;
  214.   CreateStruct.cy             = 0;
  215.   CreateStruct.hwndParent     = NULL;
  216.   CreateStruct.hMenu          = NULL;
  217.   CreateStruct.hInstance      = Main.hInstance;
  218.   CreateStruct.lpCreateParams = (LPSTR) this;
  219. }
  220.  
  221. /*--------------------------------------------------------
  222.   Store pointer to window object
  223. --------------------------------------------------------*/
  224. inline void SetWndPointer( HWND hWnd, PWINDOW pWindow )
  225. {
  226.   #if NEAR_POINTERS
  227.     SetWindowWord( hWnd, WW_POINTER, (WORD) pWindow );
  228.   #else
  229.     SetWindowLong( hWnd, WW_POINTER, (LONG) pWindow );
  230.   #endif
  231. }
  232.  
  233. /*--------------------------------------------------------
  234.   Retrieve pointer to window object
  235. --------------------------------------------------------*/
  236. inline PWINDOW GetWndPointer( HWND hWnd )
  237. {
  238.   #if NEAR_POINTERS
  239.     return (PWINDOW) GetWindowWord( hWnd, WW_POINTER );
  240.   #else
  241.     return (PWINDOW) GetWindowLong( hWnd, WW_POINTER );
  242.   #endif
  243. }
  244.  
  245. /*--------------------------------------------------------
  246.   See the warning in Borland's example WHELLO.CPP.  We get
  247.   the C++ window object pointer from the window extra
  248.   bytes, which are zero-initialized by Windows.  So we can
  249.   safely assume any non-zero value is a pointer to a
  250.   window object.  Unfortunately, the fact that extra bytes
  251.   are zero-initialized is undocumented. If this changes in
  252.   a future version of Windows, of if you don't like using
  253.   undocumented features, you can store the pointer in a
  254.   property rather than extra bytes.  The property method
  255.   is completely standard and is implemented below for
  256.   dialog boxes.
  257. --------------------------------------------------------*/
  258. inline BOOL IsWndPointer ( PWINDOW pWindow)
  259. {
  260.   return (pWindow != NULL);
  261. }
  262.  
  263. /*--------------------------------------------------------
  264.   The WndProc called by Windows
  265. --------------------------------------------------------*/
  266. long FAR PASCAL _export ExportWndProc( HWND hWnd,
  267.                  WORD iMessage, WORD wParam, LONG lParam )
  268. {
  269.   PWINDOW pWindow = GetWndPointer( hWnd );
  270.  
  271.   // If the window has already been initialized, call its
  272.   // WndProc
  273.  
  274.   if ( IsWndPointer(pWindow) )
  275.     return pWindow->WndProc( iMessage, wParam, lParam );
  276.  
  277.   // The window is not yet initialized.
  278.  
  279.   if ( iMessage == WM_CREATE )
  280.   {
  281.     // Extract the pointer to the WINDOW object, placed by
  282.     // DefineCreate
  283.  
  284.     pWindow =
  285.        (PWINDOW) ((LPCREATESTRUCT)lParam)->lpCreateParams;
  286.  
  287.     // Store a pointer to the WINDOW object in the Window
  288.     // words
  289.  
  290.     SetWndPointer( hWnd, pWindow );
  291.  
  292.     // Store the window handle in the WINDOW object, so
  293.     // that it's available when the object processes the
  294.     // WM_CREATE message
  295.  
  296.     pWindow->PutHandle ( hWnd );
  297.  
  298.     // Pass the WM_CREATE message to the WINDOW object
  299.  
  300.     return pWindow->WndProc( iMessage, wParam, lParam );
  301.   }
  302.  
  303.   // The window is not yet initialized, but this is not
  304.   // the WM_CREATE message.
  305.  
  306.   return DefWindowProc( hWnd, iMessage, wParam, lParam );
  307. }
  308.  
  309. /*--------------------------------------------------------
  310.   Handle Windows messages, calling the appropriate virtual
  311.   functions. Add cases as needed.
  312. --------------------------------------------------------*/
  313. long WINDOW::WndProc( WORD iMessage,
  314.                       WORD wParamPrm, LONG lParamPrm )
  315. {
  316.   long retcode = TRUE;
  317.  
  318.   // Save the wParam and lParam, so we don't have to pass
  319.   // them around as parameters
  320.  
  321.   wParam = wParamPrm;
  322.   lParam = lParamPrm;
  323.  
  324.   switch (iMessage)
  325.   {
  326.     case WM_CREATE:
  327.       Create();
  328.       break;
  329.     case WM_INITDIALOG:
  330.       InitDialog();
  331.       break;
  332.     case WM_COMMAND:
  333.       retcode = Command ();
  334.       break;
  335.     case WM_PAINT:
  336.       CallPaint();
  337.       break;
  338.     case WM_SIZE:
  339.       Size ();
  340.       break;
  341.     case WM_MOUSEMOVE:
  342.       MouseMove();
  343.       break;
  344.     case WM_LBUTTONDOWN:
  345.       LButtonDown();
  346.       break;
  347.     case WM_LBUTTONUP:
  348.       LButtonUp();
  349.       break;
  350.     case WM_TIMER:
  351.       Timer();
  352.       break;
  353.     case WM_DESTROY:
  354.       Destroy();
  355.       break;
  356.     default:
  357.       return DefaultProc( iMessage );
  358.   }
  359.   return retcode;
  360. }
  361.  
  362. /*--------------------------------------------------------
  363.   Get the paint structure and call Paint
  364. --------------------------------------------------------*/
  365. void WINDOW::CallPaint ()
  366. {
  367.   PAINTSTRUCT ps;
  368.  
  369.   lpPaint = (LPPAINTSTRUCT) &ps;
  370.   BeginPaint ( hWnd, lpPaint );
  371.   Paint();
  372.   EndPaint ( hWnd, lpPaint );
  373. }
  374.  
  375. /*--------------------------------------------------------
  376.  Set the windows words containing object pointer to NULL,
  377.  and set the window handle in the object to NULL.  Any
  378.  further messages, such as WM_NCDESTROY, will be handled
  379.  by Windows.
  380. --------------------------------------------------------*/
  381. void WINDOW::Destroy()
  382. {
  383.   SetWndPointer (hWnd, NULL);
  384.   hWnd = NULL;
  385. }
  386.  
  387. /*--------------------------------------------------------
  388.   Make a modeless dialog box and wait until it's done
  389. --------------------------------------------------------*/
  390. int DIALOG::Make (HWND hParent)
  391. {
  392.   FARPROC lpfnDlg;
  393.   int nResult;
  394.  
  395.   lpfnDlg = MakeProcInstance((FARPROC)ExportDlgProc,
  396.                              Main.hInstance);
  397.   nResult = DialogBoxParam (Main.hInstance,
  398.                             GetTemplateName(),
  399.                             hParent,
  400.                             lpfnDlg,
  401.                             (DWORD) this);
  402.   FreeProcInstance(lpfnDlg);
  403.   return nResult;
  404. }
  405.  
  406. /*--------------------------------------------------------
  407.   Store pointer to dialog object
  408. --------------------------------------------------------*/
  409. inline void SetDlgPointer ( HWND hDlg, PDIALOG pDialog )
  410. {
  411.   #if NEAR_POINTERS
  412.     SetProp ( hDlg, WP_POINTER_OFF, (HANDLE)pDialog );
  413.   #else
  414.     SetProp ( hDlg, WP_POINTER_SEG,
  415.               (HANDLE) FP_SEG(pDialog) );
  416.     SetProp ( hDlg, WP_POINTER_OFF,
  417.               (HANDLE) FP_OFF(pDialog) );
  418.   #endif
  419. }
  420.  
  421. /*--------------------------------------------------------
  422.   Retrieve pointer to dialog object
  423. --------------------------------------------------------*/
  424. inline PDIALOG GetDlgPointer ( HWND hDlg )
  425. {
  426.   #if NEAR_POINTERS
  427.     return (PDIALOG) GetProp ( hDlg, WP_POINTER_OFF );
  428.   #else
  429.     return
  430.       (PDIALOG) MK_FP ( GetProp ( hDlg, WP_POINTER_SEG ),
  431.                         GetProp ( hDlg, WP_POINTER_OFF ) );
  432.   #endif
  433. }
  434.  
  435. /*--------------------------------------------------------
  436.   Remove the property used to store the dialog object
  437.   pointer
  438. --------------------------------------------------------*/
  439. inline void DeleteDlgPointer ( HWND hDlg )
  440. {
  441.   #if NEAR_POINTERS
  442.     RemoveProp ( hDlg, WP_POINTER_OFF );
  443.   #else
  444.     RemoveProp ( hDlg, WP_POINTER_SEG );
  445.     RemoveProp ( hDlg, WP_POINTER_OFF );
  446.   #endif
  447. }
  448.  
  449. /*--------------------------------------------------------
  450.   The DlgProc called by Windows
  451. --------------------------------------------------------*/
  452. long FAR PASCAL _export ExportDlgProc( HWND hDlg,
  453.                  WORD iMessage, WORD wParam, LONG lParam )
  454. {
  455.   PDIALOG pDialog = GetDlgPointer ( hDlg );
  456.  
  457.   // GetDlgPointer will return zero if the dialog is not yet
  458.   // initialized
  459.  
  460.   if ( pDialog )
  461.     return pDialog->WndProc( iMessage, wParam, lParam );
  462.  
  463.   if ( iMessage == WM_INITDIALOG )
  464.   {
  465.     pDialog = (PDIALOG) lParam;
  466.  
  467.     SetDlgPointer ( hDlg, pDialog );
  468.     pDialog->PutHandle ( hDlg );
  469.  
  470.     return pDialog->WndProc( iMessage, wParam, lParam );
  471.   }
  472. }
  473.  
  474. /*--------------------------------------------------------
  475.  Remove the property used to store the pointer to the
  476.  C++ dialog object.  From here on, GetDlgPointer will
  477.  return zero.
  478. --------------------------------------------------------*/
  479. void DIALOG::Destroy()
  480. {
  481.   DeleteDlgPointer (hWnd);
  482.   hWnd = NULL;
  483. }
  484.  
  485. /*--------------------------------------------------------
  486.   For unprocessed messages to dialog boxes, return FALSE
  487. --------------------------------------------------------*/
  488. #pragma argsused
  489. long DIALOG::DefaultProc(WORD iMessage) { return FALSE; }
  490.