home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / MUTLITRG.PAK / MULTITRG.CPP next >
C/C++ Source or Header  |  1995-08-29  |  9KB  |  280 lines

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