home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 6.ddi / WEXAMPLE.ZIP / WHELLO.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  8.7 KB  |  275 lines

  1. // Borland C++ - (C) Copyright 1991, 1992 by Borland International
  2. //
  3. //  Windows HELLO WORLD - C++ Version 
  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 long WndProc( UINT iMessage, WPARAM wParam, LPARAM lParam ) = 0;
  35. };
  36.  
  37. class MainWindow : public Window
  38. {
  39. private:
  40.     static char szClassName[14];
  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, "whello" );
  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.     long 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. char MainWindow::szClassName[] = "Hello, World!";
  132.  
  133. void MainWindow::Paint( void )
  134. {
  135.     PAINTSTRUCT ps;
  136.     RECT rect;
  137.     FARPROC lpLineFunc;
  138.     LINEFUNCDATA LineFuncData( "Borland C++ welcomes you to the Wonderful World of Windows Programming!" );
  139.  
  140.     lpLineFunc = MakeProcInstance( (FARPROC) MainWindow::LineFunc, (HINSTANCE)Main::hInstance );
  141.     BeginPaint( hWnd, &ps );
  142.     GetClientRect( hWnd, (LPRECT) &rect );
  143.     LineFuncData.hDC = ps.hdc;
  144.     SetTextAlign( ps.hdc, TA_BOTTOM );
  145.     LineDDA( 0, 0, 0,
  146.      rect.bottom / 2, (LINEDDAPROC)lpLineFunc, (LPARAM) &LineFuncData );
  147.     EndPaint( hWnd, &ps );
  148.     FreeProcInstance( lpLineFunc );
  149. }
  150.  
  151. void FAR PASCAL _export MainWindow::LineFunc( int X, int Y, LPSTR lpData )
  152. {
  153.     LINEFUNCDATA FAR * lpLineFuncData = (LINEFUNCDATA FAR *) lpData;
  154.     TextOut( lpLineFuncData->hDC, X, Y,
  155.              lpLineFuncData->LineMessage, lpLineFuncData->MessageLength );
  156. }
  157.  
  158. long MainWindow::WndProc( UINT iMessage, WPARAM wParam, LPARAM lParam )
  159. {
  160.     switch (iMessage)
  161.     {
  162.         case WM_CREATE:
  163.         break;
  164.         case WM_PAINT:
  165.             Paint();
  166.             break;
  167.         case WM_DESTROY:
  168.             PostQuitMessage( 0 );
  169.             break;
  170.         default:
  171.             return DefWindowProc( hWnd, iMessage, wParam, lParam );
  172.     }
  173.     return 0;
  174. }
  175.  
  176. // If data pointers are near pointers
  177. #if defined(__SMALL__) || defined(__MEDIUM__)
  178. inline Window *GetPointer( HWND hWnd )
  179. {
  180.     return (Window *) GetWindowWord( hWnd, 0 );
  181. }
  182. inline void SetPointer( HWND hWnd, Window *pWindow )
  183. {
  184.     SetWindowWord( hWnd, 0, (WORD) pWindow );
  185. }
  186.  
  187. // else pointers are far
  188. #elif defined(__LARGE__) || defined(__COMPACT__)
  189. inline Window *GetPointer( HWND hWnd )
  190. {
  191.     return (Window *) GetWindowLong( hWnd, 0 );
  192. }
  193. inline void SetPointer( HWND hWnd, Window *pWindow )
  194. {
  195.     SetWindowLong( hWnd, 0, (LONG) pWindow );
  196. }
  197.  
  198. #else
  199.     #error Choose another memory model!
  200. #endif
  201.  
  202. LRESULT  CALLBACK _export WndProc( HWND hWnd, UINT iMessage, WPARAM wParam,
  203.                                  LPARAM lParam )
  204. {
  205.     // Pointer to the (C++ object that is the) window.
  206.     Window *pWindow = GetPointer( hWnd );
  207.  
  208.     // The pointer pWindow will have an invalid value if the WM_CREATE
  209.     // message has not yet been processed (we respond to the WM_CREATE
  210.     // message by setting the extra bytes to be a pointer to the
  211.     // (C++) object corresponding to the Window identified
  212.     // by hWnd).  The messages that
  213.     // precede WM_CREATE must be processed without using pWindow so we
  214.     // pass them to DefWindowProc.
  215.     // How do we know in general if the pointer pWindow is invalid?
  216.     // Simple: Windows allocates the window extra bytes using LocalAlloc
  217.     // which zero initializes memory; thus, pWindow will have a value of
  218.     // zero before we set the window extra bytes to the 'this' pointer.
  219.     // Caveat emptor: the fact that LocalAlloc will zero initialize the
  220.     // window extra bytes is not documented; therefore, it could change
  221.     // in the future.
  222.  
  223.     if ( pWindow == 0 )
  224.     {
  225.         if ( iMessage == WM_CREATE )
  226.         {
  227.             LPCREATESTRUCT lpcs;
  228.  
  229.             lpcs = (LPCREATESTRUCT) lParam;
  230.             pWindow = (Window *) lpcs->lpCreateParams;
  231.  
  232.             // Store a pointer to this object in the window's extra bytes;
  233.             // this will enable us to access this object (and its member
  234.             // functions) in WndProc where we are
  235.             // given only a handle to identify the window.
  236.             SetPointer( hWnd, pWindow );
  237.             // Now let the object perform whatever
  238.             // initialization it needs for WM_CREATE in its own
  239.             // WndProc.
  240.         return pWindow->WndProc( iMessage, wParam, lParam );
  241.         }
  242.         else
  243.             return DefWindowProc( hWnd, iMessage, wParam, lParam );
  244.     }
  245.     else
  246.         return pWindow->WndProc( iMessage, wParam, lParam );
  247. }
  248.  
  249. // Turn off warning: Parameter 'lpszCmdLine' is never used in function WinMain(unsigned int,unsigned int,char far*,int)
  250. #pragma argsused
  251.  
  252. // Turn off warning: 'MainWnd' is assigned a value that is never used in function WinMain(unsigned int,unsigned int,char far*,int)
  253. #pragma option -w-aus
  254.  
  255. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine,
  256.                     int nCmdShow )
  257. {
  258.     Main::hInstance = hInstance;
  259.     Main::hPrevInstance = hPrevInstance;
  260.     Main::nCmdShow = nCmdShow;
  261.  
  262.     // A Windows class should be registered with Windows before any windows
  263.     // of that type are created.
  264.     // Register here all Windows classes that will be used in the program.
  265.     // Windows classes should not be registered if an instance of
  266.     // the program is already running.
  267.     if ( ! Main::hPrevInstance ) {
  268.         MainWindow::Register();
  269.     }
  270.  
  271.     MainWindow MainWnd;
  272.  
  273.     return Main::MessageLoop();
  274. }
  275.