home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / dlldemo.pak / DLLDEMO.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  9KB  |  301 lines

  1. // Borland C++ - (C) Copyright 1991, 1992 by Borland International
  2. //
  3. //  Windows DLL example - C++ Version
  4. //
  5.  
  6. #define STRICT
  7. #include <windows.h>
  8. #pragma hdrstop
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #if defined(__WIN32__)
  12. #define _EXPORT
  13. #else
  14. #define _EXPORT huge
  15. #endif
  16. #include "bitmap.h"
  17.  
  18. LRESULT CALLBACK _export WndProc( HWND hWnd, UINT iMessage,
  19.          WPARAM wParam, LPARAM lParam );
  20.  
  21. class Main
  22. {
  23. public:
  24.   static HINSTANCE hInstance;
  25.   static HINSTANCE hPrevInstance;
  26.   static int nCmdShow;
  27.   static int MessageLoop( void );
  28. };
  29.  
  30. class Window
  31. {
  32. protected:
  33.     HWND hWnd;
  34. public:
  35.     // Provide (read) access to the window's handle in case it is needed
  36.     // elsewhere.
  37.     HWND GetHandle( void ) { return hWnd; }
  38.  
  39.     BOOL Show( int nCmdShow ) { return ShowWindow( hWnd, nCmdShow ); }
  40.     void Update( void ) { UpdateWindow( hWnd ); }
  41.     // Pure virtual function makes Window an abstract class.
  42.     virtual LRESULT WndProc( UINT iMessage, WPARAM wParam, LPARAM lParam ) = 0;
  43. };
  44.  
  45. class MainWindow : public Window
  46. {
  47. private:
  48.     static char szClassName[14];
  49.     Bitmap FAR *lpBitmap1;
  50.     Bitmap FAR *lpBitmap2;
  51.     // Helper function used by Paint function; it is used as a
  52.     // callback function by LineDDA.
  53.     static void FAR PASCAL LineFunc( short X, short Y, LPSTR lpData );
  54. public:
  55.     // Register the class only AFTER WinMain assigns appropriate
  56.     // values to static members of Main and only if no previous
  57.     // instances of the program exist (a previous instance would
  58.     // have already performed the registration).
  59.     static void Register( void )
  60.     {
  61.         WNDCLASS wndclass;   // Structure used to register Windows class.
  62.  
  63.         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  64.         wndclass.lpfnWndProc   = ::WndProc;
  65.         wndclass.cbClsExtra    = 0;
  66.         // Reserve extra bytes for each instance of the window;
  67.         // we will use these bytes to store a pointer to the C++
  68.         // (MainWindow) object corresponding to the window.
  69.         // the size of a 'this' pointer depends on the memory model.
  70.         wndclass.cbWndExtra    = sizeof( MainWindow * );
  71.         wndclass.hInstance     = Main::hInstance;
  72.         wndclass.hIcon         = LoadIcon( Main::hInstance, "dlldemo" );
  73.         wndclass.hCursor       = LoadCursor( NULL, IDC_ARROW );
  74.         wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
  75.         wndclass.lpszMenuName  = NULL;
  76.         wndclass.lpszClassName = szClassName;
  77.  
  78.         if ( ! RegisterClass( &wndclass ) )
  79.             exit( FALSE );
  80.     }
  81.  
  82.     // Do not create unless previously registered.
  83.     MainWindow( void )
  84.     {
  85.         HMODULE hModule = GetModuleHandle("BITMAP.DLL");
  86.         lpBitmap1 = new Bitmap( (HINSTANCE)hModule, "dlldemo1" );
  87.         lpBitmap2 = new Bitmap( (HINSTANCE)hModule, "dlldemo2" );
  88.         // Pass 'this' pointer in lpParam of CreateWindow().
  89.         hWnd = CreateWindow( szClassName,
  90.             szClassName,
  91.             WS_OVERLAPPEDWINDOW,
  92.             CW_USEDEFAULT,
  93.             0,
  94.             CW_USEDEFAULT,
  95.             0,
  96.             NULL,
  97.             NULL,
  98.             Main::hInstance,
  99.             (LPSTR) this );
  100.         if ( ! hWnd )
  101.             exit( FALSE );
  102.  
  103.         Show( Main::nCmdShow );
  104.         Update();
  105.     }
  106.     ~MainWindow( void )
  107.     {
  108.         delete lpBitmap1;
  109.         delete lpBitmap2;
  110.     }
  111.     LRESULT WndProc( UINT iMessage, WPARAM wParam, LPARAM lParam );
  112.  
  113.     // Print a message in the client rectangle.
  114.     void Paint( void );
  115.     // Struct used by Paint to pass information to callback function
  116.     // used by LineDDA
  117.     struct LINEFUNCDATA
  118.     {
  119.         HDC hDC;
  120.         Bitmap FAR *lpBM1;
  121.         Bitmap FAR *lpBM2;
  122.         POINT size1;
  123.         POINT size2;
  124.         LINEFUNCDATA( HDC h, Bitmap FAR *lpBitmap1, Bitmap FAR *lpBitmap2 )
  125.         {
  126.             hDC = h;
  127.             lpBM1 = lpBitmap1;
  128.             lpBM2 = lpBitmap2;
  129.             size1 =lpBitmap1->GetSize( hDC );
  130.             size2 =lpBitmap2->GetSize( hDC );
  131.         };
  132.     };
  133. };
  134.  
  135. HINSTANCE Main::hInstance = 0;
  136. HINSTANCE Main::hPrevInstance = 0;
  137. int Main::nCmdShow = 0;
  138.  
  139. int Main::MessageLoop( void )
  140. {
  141.     MSG msg;
  142.  
  143.     while( GetMessage( (LPMSG) &msg, NULL, 0, 0 ) )
  144.     {
  145.         TranslateMessage( &msg );
  146.         DispatchMessage( &msg );
  147.     }
  148.     return msg.wParam;
  149. }
  150.  
  151. char MainWindow::szClassName[] = "DLLDEMO!";
  152.  
  153. void MainWindow::Paint( void )
  154. {
  155.     PAINTSTRUCT ps;
  156.     RECT rect;
  157.     LINEDDAPROC lpLineFunc;
  158.  
  159.     lpLineFunc = (LINEDDAPROC)MakeProcInstance( (FARPROC) MainWindow::LineFunc, Main::hInstance );
  160.     GetClientRect( hWnd, (LPRECT) &rect );
  161.  
  162.     BeginPaint( hWnd, &ps );
  163.     LINEFUNCDATA LineFuncData( ps.hdc, lpBitmap1, lpBitmap2 );
  164.     LineDDA( 0, 0, rect.right - (lpBitmap1->GetSize( ps.hdc )).x,
  165.              0, lpLineFunc, (LPARAM)&LineFuncData );
  166.     EndPaint( hWnd, &ps );
  167.     FreeProcInstance((FARPROC)lpLineFunc );
  168. }
  169.  
  170. void FAR PASCAL MainWindow::LineFunc( short X, short Y, LPSTR lpData )
  171. {
  172.     LINEFUNCDATA FAR * lpLineFuncData = (LINEFUNCDATA FAR *) lpData;
  173.     HDC hDC = lpLineFuncData->hDC;
  174.     Bitmap FAR *lpBitmap1 = lpLineFuncData->lpBM1;
  175.     Bitmap FAR *lpBitmap2 = lpLineFuncData->lpBM2;
  176.     static int i = 0;
  177.  
  178.     if ( !( i % 4 ) ) {
  179.         lpBitmap1->Display( hDC, X, Y );
  180.         // Draw second bitmap below first.
  181.         lpBitmap2->Display( hDC, X / 4, ( Y + (lpLineFuncData->size1).y ) );
  182.     }
  183.     i++;
  184. }
  185.  
  186. LRESULT MainWindow::WndProc( UINT iMessage, WPARAM wParam, LPARAM lParam )
  187. {
  188.     switch (iMessage)
  189.     {
  190.   case WM_CREATE:
  191.       break;
  192.         case WM_PAINT:
  193.             Paint();
  194.             break;
  195.         case WM_DESTROY:
  196.             PostQuitMessage( 0 );
  197.             break;
  198.         default:
  199.             return DefWindowProc( hWnd, iMessage, wParam, lParam );
  200.     }
  201.     return 0;
  202. }
  203.  
  204. // If data pointers are near pointers
  205. #if defined(__SMALL__) || defined(__MEDIUM__)
  206. inline Window *GetPointer( HWND hWnd )
  207. {
  208.     return (Window *) GetWindowWord( hWnd, 0 );
  209. }
  210. inline void SetPointer( HWND hWnd, Window *pWindow )
  211. {
  212.     SetWindowWord( hWnd, 0, (WORD) pWindow );
  213. }
  214.  
  215. // else pointers are far
  216. #elif defined(__LARGE__) || defined(__COMPACT__) || defined(__FLAT__)
  217. inline Window *GetPointer( HWND hWnd )
  218. {
  219.     return (Window *) GetWindowLong( hWnd, 0 );
  220. }
  221. inline void SetPointer( HWND hWnd, Window *pWindow )
  222. {
  223.     SetWindowLong( hWnd, 0, (LONG) pWindow );
  224. }
  225.  
  226. #else
  227.     #error Choose another memory model!
  228. #endif
  229.  
  230.  
  231. LRESULT CALLBACK _export WndProc( HWND hWnd, UINT iMessage, WPARAM wParam,
  232.                                  LPARAM lParam )
  233. {
  234.     // Pointer to the (C++ object that is the) window.
  235.     Window *pWindow = GetPointer( hWnd );
  236.  
  237.     // The pointer pWindow will have an invalid value if the WM_CREATE
  238.     // message has not yet been processed (we respond to the WM_CREATE
  239.     // message by setting the extra bytes to be a pointer to the
  240.     // (C++) object corresponding to the Window identified
  241.     // by hWnd).  The messages that
  242.     // precede WM_CREATE must be processed without using pWindow so we
  243.     // pass them to DefWindowProc.
  244.     // How do we know in general if the pointer pWindow is invalid?
  245.     // Simple: Windows allocates the window extra bytes using LocalAlloc
  246.     // which zero initializes memory; thus, pWindow will have a value of
  247.     // zero before we set the window extra bytes to the 'this' pointer.
  248.     // Caveat emptor: the fact that LocalAlloc will zero initialize the
  249.     // window extra bytes is not documented; therefore, it could change
  250.     // in the future.
  251.  
  252.     if ( pWindow == 0 )
  253.     {
  254.         if ( iMessage == WM_CREATE )
  255.         {
  256.             LPCREATESTRUCT lpcs;
  257.  
  258.             lpcs = (LPCREATESTRUCT) lParam;
  259.             pWindow = (Window *) lpcs->lpCreateParams;
  260.  
  261.             // Store a pointer to this object in the window's extra bytes;
  262.             // this will enable to access this object (and its member
  263.             // functions) in WndProc where we are
  264.             // given only a handle to identify the window.
  265.             SetPointer( hWnd, pWindow );
  266.             // Now let the object perform whatever
  267.             // initialization it needs for WM_CREATE in its own
  268.             // WndProc.
  269.             return pWindow->WndProc( iMessage, wParam, lParam );
  270.         }
  271.         else
  272.             return DefWindowProc( hWnd, iMessage, wParam, lParam );
  273.     }
  274.     else
  275.         return pWindow->WndProc( iMessage, wParam, lParam );
  276. }
  277.  
  278. // Turn off warning: Parameter 'lpszCmdLine' is never used in function WinMain(unsigned int,unsigned int,char far*,int)
  279. #pragma argsused
  280.  
  281. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine,
  282.                     int nCmdShow )
  283. {
  284.     Main::hInstance = hInstance;
  285.     Main::hPrevInstance = hPrevInstance;
  286.     Main::nCmdShow = nCmdShow;
  287.  
  288.     // A Windows class should be registered with Windows before any windows
  289.     // of that type are created.
  290.     // Register here all Windows classes that will be used in the program.
  291.     // Windows classes should not be registered if an instance of
  292.     // the program is already running.
  293.     if ( ! Main::hPrevInstance ) {
  294.         MainWindow::Register();
  295.     }
  296.  
  297.     MainWindow MainWnd;
  298.  
  299.     return Main::MessageLoop();
  300. }
  301.