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