home *** CD-ROM | disk | FTP | other *** search
/ Windoware / WINDOWARE_1_6.iso / source / 3dbutn / odbutton.c < prev    next >
C/C++ Source or Header  |  1991-12-06  |  19KB  |  473 lines

  1. /****************************************************************************
  2.  
  3. PROGRAM: Odbutton.c
  4.  
  5. PURPOSE: Based on Generic template for Windows applications,
  6.          but the dialog box has been modified to demonstrate an
  7.          owner-draw button that mimics the appearance of a
  8.          Windows 3.0 gray 3-dimensional style push button by using
  9.          two bitmaps and text centered in the face of the bitmaps.
  10.  
  11. FUNCTIONS:
  12.  
  13. HandleFocusState() ------ handles drawing dashed rectangle around text in
  14.                           owner-draw button
  15. HandleSelectionState() -- handles drawing button with one bitmap for "up"
  16.                           and another bitmap when button is pressed.
  17. About() ----------------- processes messages for "About" dialog box and
  18.                           handles the owner-draw messages for the od button
  19. DrawBitmap() ------------ draw the 2 bitmaps for the owner-draw button
  20. InitApplication() ------- initializes window data and registers window
  21. InitInstance() ---------- saves instance handle and creates main window
  22. MainWndProc() ----------- processes messages
  23. WinMain() --------------- calls initialization function, processes message loop
  24.  
  25. COMMENTS:
  26.     Bitmaps are display resolution specific, so to have buttons of
  27.     comparible size to non-owner-draw buttons, a pair of button "up" and
  28.     "down" bitmaps is required for each supported display resolution.
  29.     StretchBlt can have the effect of making the button's borders too thick.
  30.  
  31.     Windows can have several copies of an application running at the
  32.     same time.  The variable hInst keeps track of which instance this
  33.     application is so that processing will be to the correct window.
  34.  
  35. Copyright (c) 1991 Microsoft Corporation. All rights reserved.
  36.  
  37. ****************************************************************************/
  38.  
  39. #include "windows.h"              /* required for all Windows applications */
  40. #include "odbutton.h"             /* specific to this program              */
  41.  
  42. HANDLE              hInst;          // current instance
  43. POINT               pt;             // button bitmap's dimensions
  44. DWORD               dwRectDim;      // used for text rectangle dimensions
  45. LPDRAWITEMSTRUCT    lpdis;          // Long Pointer to owner-draw struct
  46. HBITMAP             hButtonBitmap,  // for button's regular state bm
  47.                     hButtonDown;    // for button's pushed state bm
  48. RECT                rectHi,         // rectangle around up button's "Hi!"
  49.                     rectHiDown;     // rectangle around down button's "Hi!"
  50. int                 nSpaceWidth,    // space between text and dashed focus
  51.                     nSpaceHeight,   //   rectangle
  52.                     nOldBkMode;     // original text background mode
  53. HDC                 hDC;            // handle to device context of various wins
  54. BITMAP              bm;             // 1 of 2 bitmaps for owner-draw button
  55. DWORD               dwSize;         // size of bitmap
  56.  
  57.  
  58. /*****************************************************************************
  59.  
  60.     FUNCTION: HandleFocusState
  61.  
  62.     PURPOSE:  If button has focus, draw dashed rectangle around text in button
  63.  
  64. *****************************************************************************/
  65. void HandleFocusState(LPDRAWITEMSTRUCT lpdis)
  66. {
  67.     // if focus state, draw a dashed rect around text
  68.     if (lpdis->itemState & ODS_FOCUS)
  69.     {
  70.         // if selected, shift focus rect right and down 2 pixels around text
  71.         if (lpdis->itemState & ODS_SELECTED)
  72.             DrawFocusRect(lpdis->hDC, (LPRECT)&rectHiDown);
  73.         // else text centered, so focus rect will be too
  74.         else
  75.             DrawFocusRect(lpdis->hDC, (LPRECT)&rectHi);
  76.     }
  77.     return;
  78. }
  79.  
  80.  
  81. /*****************************************************************************
  82.  
  83.     FUNCTION: HandleSelectedState
  84.  
  85.     PURPOSE:  Draw button bitmaps and text:
  86.                   if button selected, draw "down"/pressed button bitmap
  87.                       with text shifted right and down 2 pixels
  88.                   else draw "up"/unpressed button bitmap
  89.                       with text centered in button
  90.  
  91. *****************************************************************************/
  92. void HandleSelectedState(LPDRAWITEMSTRUCT lpdis)
  93. {
  94.     // handle button pressed down select state -- button down bitmap
  95.     //   text is right & down 2 pixels
  96.     if (lpdis->itemState & ODS_SELECTED)
  97.     {
  98.         DrawBitmap(lpdis->hDC,lpdis->rcItem.left,
  99.             lpdis->rcItem.top, hButtonDown,SRCCOPY);
  100.  
  101.         // put text 2 pixels right and down of center of bitmap
  102.         nOldBkMode = SetBkMode(lpdis->hDC,TRANSPARENT);
  103.         TextOut(lpdis->hDC, 2 + ((pt.x - LOWORD(dwRectDim)) >> 1),
  104.             2 + ((pt.y - HIWORD(dwRectDim)) >> 1), "Hi!", lstrlen("Hi!"));
  105.  
  106.         SetBkMode(lpdis->hDC,nOldBkMode);
  107.     }
  108.     // not selected -- button up; text is in normal position
  109.     else
  110.     {
  111.         DrawBitmap(lpdis->hDC,lpdis->rcItem.left,
  112.             lpdis->rcItem.top, hButtonBitmap,SRCCOPY);
  113.  
  114.         // center text in bitmap
  115.         nOldBkMode = SetBkMode(lpdis->hDC,TRANSPARENT);
  116.         TextOut(lpdis->hDC, (pt.x - LOWORD(dwRectDim) ) >> 1,
  117.             (pt.y - HIWORD(dwRectDim)) >> 1, "Hi!", lstrlen("Hi!"));
  118.  
  119.         SetBkMode(lpdis->hDC,nOldBkMode);
  120.     }
  121.     return;
  122. }
  123.  
  124.  
  125. /****************************************************************************
  126.  
  127.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  128.  
  129.     PURPOSE:  Processes messages for "About" dialog box
  130.  
  131.     MESSAGES:
  132.  
  133.         WM_DRAWITEM   - draw owner-draw button control
  134.         WM_INITDIALOG - initialize dialog box
  135.         WM_COMMAND    - Input received
  136.  
  137.     COMMENTS:
  138.  
  139.         Demonstrates drawing owner-draw button in response to various
  140.         states (default ODA_DRAWENTIRE, ODS_SELECT, or ODS_FOCUS).
  141.  
  142.         No initialization is needed for this particular dialog box, but TRUE
  143.         must be returned to Windows to indicate the message was handled.
  144.  
  145.         Wait for user to click on "Ok" button, then close the dialog box.
  146.  
  147. ****************************************************************************/
  148.  
  149. BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
  150. HWND hDlg;                                /* window handle of the dialog box */
  151. unsigned message;                         /* type of message                 */
  152. WORD wParam;                              /* message-specific information    */
  153. LONG lParam;
  154. {
  155.     switch (message)
  156.         {
  157.     /* Get dimensions text rectangle and set dimensions of focus rect */
  158.     case WM_INITDIALOG:
  159.         // load bitmap
  160.         hButtonBitmap = LoadBitmap(hInst,"BUTTONBITMAP"); // regular state
  161.         hButtonDown   = LoadBitmap(hInst,"BUTTONDOWN");   // pushed state
  162.         GetObject(hButtonBitmap, sizeof (BITMAP), (LPSTR) &bm);
  163.         pt.x = bm.bmWidth;
  164.         pt.y = bm.bmHeight;
  165.  
  166.         // define size of dashed rectangles around text in both bitmaps
  167.         hDC           = GetDC(hDlg);
  168.         dwRectDim     = GetTextExtent(hDC, "Hi!", lstrlen("Hi!"));
  169.         ReleaseDC(hDlg, hDC);
  170.         nSpaceWidth   = GetSystemMetrics(SM_CXBORDER) << 1;
  171.         nSpaceHeight  = GetSystemMetrics(SM_CYBORDER) << 1;
  172.         rectHi.top    = -nSpaceHeight + ((pt.y - HIWORD(dwRectDim)) >> 1);
  173.         rectHi.bottom = (nSpaceHeight << 1) + rectHi.top + HIWORD(dwRectDim);
  174.         rectHi.left   = -nSpaceWidth + ((pt.x - LOWORD(dwRectDim)) >> 1);
  175.         rectHi.right  = (nSpaceWidth << 1) + rectHi.left + LOWORD(dwRectDim);
  176.         rectHiDown.top    = 2 + rectHi.top;
  177.         rectHiDown.bottom = 2 + rectHi.bottom;
  178.         rectHiDown.left   = 2 + rectHi.left;
  179.         rectHiDown.right  = 2 + rectHi.right;
  180.         return TRUE;
  181.  
  182.     /* draw owner-draw button in all its states: normal, selected, focus */
  183.     case WM_DRAWITEM:
  184.         lpdis = (LPDRAWITEMSTRUCT)lParam;    // for convenience
  185.  
  186.         switch (lpdis->itemAction)
  187.             {
  188.         // handle normal drawing of button, but check if its
  189.         // selected or focus
  190.         case ODA_DRAWENTIRE:
  191.             // this handles both button down and button up
  192.             HandleSelectedState(lpdis);
  193.  
  194.             // this handles focus rectangle around "Hi!"
  195.             HandleFocusState(lpdis);
  196.             return TRUE;
  197.  
  198.         // handle drawing selection if needed
  199.         //   selected is button down, not selected is button up
  200.         //   focus will occur when button is pressed.
  201.         case ODA_SELECT:
  202.             HandleSelectedState(lpdis);
  203.             HandleFocusState(lpdis);
  204.             return TRUE;
  205.  
  206.         // handle focus drawing if needed
  207.         case ODA_FOCUS:
  208.             HandleFocusState(lpdis);
  209.             return TRUE;
  210.             }  //itemAction
  211.         break;
  212.  
  213.     case WM_COMMAND:                      /* message: received a command */
  214.         if (wParam == IDD_OWNBUT)         // owner-draw button selected
  215.             {
  216.             if (HIWORD(lParam) == BN_CLICKED)
  217.                 {
  218.                 MessageBeep(0);
  219.                 MessageBeep(0);
  220.                 MessageBeep(0);
  221.                 }
  222.             }
  223.         else
  224.             if ((wParam == IDOK) || (wParam == IDCANCEL))
  225.             {
  226.                 EndDialog(hDlg, TRUE);    /* Exits the dialog box        */
  227.                 return TRUE;
  228.             }
  229.         break;
  230.  
  231.     case WM_DESTROY:
  232.         DeleteObject(hButtonBitmap);
  233.         DeleteObject(hButtonDown);
  234.         break;
  235.     }
  236.     return FALSE;                       /* Didn't process a message    */
  237. }
  238.  
  239.  
  240. /****************************************************************************
  241.  
  242.     FUNCTION: DrawBitmap
  243.  
  244.     PURPOSE:  Draw default or pushed button bitmap
  245.  
  246. ****************************************************************************/
  247.  
  248. void DrawBitmap(hDC, xStart, yStart, hBitmap, rop)
  249.  
  250. HDC     hDC;
  251. short   xStart, yStart;
  252. HBITMAP hBitmap;
  253. DWORD   rop;
  254. {
  255.     HDC           hMemDC;
  256.  
  257.     hMemDC = CreateCompatibleDC(hDC);
  258.     SelectObject(hMemDC, hBitmap);
  259.     BitBlt(hDC, xStart, yStart, pt.x, pt.y, hMemDC, 0, 0, rop);
  260.     DeleteDC(hMemDC);
  261. }
  262.  
  263.  
  264. /****************************************************************************
  265.  
  266.     FUNCTION: InitApplication(HANDLE)
  267.  
  268.     PURPOSE: Initializes window data and registers window class
  269.  
  270.     COMMENTS:
  271.  
  272.         This function is called at initialization time only if no other
  273.         instances of the application are running. This function performs
  274.         initialization tasks that can be done once for any number of running
  275.         instances.  
  276.  
  277.         In this case, we initialize a window class by filling out a data
  278.         structure of type WNDCLASS and calling the Windows RegisterClass()
  279.         function. Since all instances of this application use the same window
  280.         class, we only need to do this when the first instance is initialized.
  281.  
  282.  
  283. ****************************************************************************/
  284.  
  285. BOOL InitApplication(hInstance)
  286. HANDLE hInstance;                               /* current instance        */
  287. {
  288.     WNDCLASS  wc;
  289.  
  290.     /* Fill in window class structure with parameters that describe the       */
  291.     /* main window.                                                           */
  292.  
  293.     wc.style = NULL;                    /* Class style(s).                    */
  294.     wc.lpfnWndProc = MainWndProc;       /* Function to retrieve messages for  */
  295.                                         /* windows of this class.             */
  296.     wc.cbClsExtra = 0;                  /* No per-class extra data.           */
  297.     wc.cbWndExtra = 0;                  /* No per-window extra data.          */
  298.     wc.hInstance = hInstance;           /* Application that owns the class.   */
  299.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  300.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  301.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  302.     wc.lpszMenuName =  "odbuttonMenu";   /* Name of menu resource in .RC file. */
  303.     wc.lpszClassName = "odbuttonWClass"; /* Name used in call to CreateWindow. */
  304.  
  305.     /* Register the window class and return success/failure code. */
  306.  
  307.     return RegisterClass(&wc);
  308. }
  309.  
  310.  
  311. /****************************************************************************
  312.  
  313.     FUNCTION:  InitInstance(HANDLE, int)
  314.  
  315.     PURPOSE:  Saves instance handle and creates main window
  316.  
  317.     COMMENTS:
  318.  
  319.         This function is called at initialization time for every instance of
  320.         this application. This function performs initialization tasks that
  321.         cannot be shared by multiple instances.
  322.  
  323.         In this case, we save the instance handle in a static variable and
  324.         create and display the main program window.
  325.  
  326. ****************************************************************************/
  327.  
  328. BOOL InitInstance(hInstance, nCmdShow)
  329. HANDLE          hInstance;          /* Current instance identifier.       */
  330. int             nCmdShow;           /* Param for first ShowWindow() call. */
  331. {
  332.     HWND            hWnd;               /* Main window handle.                */
  333.  
  334.     /* Save the instance handle in static variable, which will be used in  */
  335.     /* many subsequence calls from this application to Windows.            */
  336.  
  337.     hInst = hInstance;
  338.  
  339.     /* Create a main window for this application instance. */
  340.  
  341.     hWnd = CreateWindow(
  342.         "odbuttonWClass",               /* See RegisterClass() call.          */
  343.         "OD Button Sample Application", /* Text for window title bar.         */
  344.         WS_OVERLAPPEDWINDOW,            /* Window style.                      */
  345.         CW_USEDEFAULT,                  /* Default horizontal position.       */
  346.         CW_USEDEFAULT,                  /* Default vertical position.         */
  347.         CW_USEDEFAULT,                  /* Default width.                     */
  348.         CW_USEDEFAULT,                  /* Default height.                    */
  349.         NULL,                           /* Overlapped windows have no parent. */
  350.         NULL,                           /* Use the window class menu.         */
  351.         hInstance,                      /* This instance owns this window.    */
  352.         NULL                            /* Pointer not needed.                */
  353.     );
  354.  
  355.     /* If window could not be created, return "failure" */
  356.     if (!hWnd)
  357.         return FALSE;
  358.  
  359.     /* Make the window visible; update its client area; and return "success" */
  360.     ShowWindow(hWnd, nCmdShow);  /* Show the window                        */
  361.     UpdateWindow(hWnd);          /* Sends WM_PAINT message                 */
  362.     return TRUE;               /* Returns the value from PostQuitMessage */
  363. }
  364.  
  365.  
  366. /****************************************************************************
  367.  
  368.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  369.  
  370.     PURPOSE:  Processes messages
  371.  
  372.     MESSAGES:
  373.  
  374.         WM_COMMAND    - application menu (About dialog box)
  375.         WM_DESTROY    - destroy window
  376.  
  377.     COMMENTS:
  378.  
  379.         To process the IDM_ABOUT message, call MakeProcInstance() to get the
  380.         current instance address of the About() function. Then call DialogBox
  381.         which will create the box according to the information in the
  382.         odbutton.rc file and turn control over to the About() function. When
  383.         About returns, free the intance address.
  384.  
  385. ****************************************************************************/
  386.  
  387. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  388. HWND hWnd;                                /* window handle                   */
  389. unsigned message;                         /* type of message                 */
  390. WORD wParam;                              /* additional information          */
  391. LONG lParam;                              /* additional information          */
  392. {
  393.     FARPROC lpProcAbout;                  /* pointer to the "About" function */
  394.  
  395.     switch (message)
  396.         {
  397.     case WM_COMMAND:           /* message: command from application menu */
  398.         switch (wParam)
  399.             {
  400.         case IDM_ABOUT:
  401.             lpProcAbout = MakeProcInstance(About, hInst);
  402.             DialogBox(hInst,          /* current instance         */
  403.                 "AboutBox",           /* resource to use          */
  404.                 hWnd,                 /* parent handle            */
  405.                 lpProcAbout);         /* About() instance address */
  406.  
  407.             FreeProcInstance(lpProcAbout);
  408.             break;
  409.             }
  410.         break;
  411.  
  412.     case WM_DESTROY:            /* message: window being destroyed */
  413.         PostQuitMessage(0);
  414.         break;
  415.  
  416.     default:                    /* Passes it on if unproccessed    */
  417.         return DefWindowProc(hWnd, message, wParam, lParam);
  418.     }
  419.     return NULL;
  420. }
  421.  
  422.  
  423. /****************************************************************************
  424.  
  425.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  426.  
  427.     PURPOSE: calls initialization function, processes message loop
  428.  
  429.     COMMENTS:
  430.  
  431.         Windows recognizes this function by name as the initial entry point 
  432.         for the program. This function calls the application initialization 
  433.         routine, if no other instance of the program is running, and always 
  434.         calls the instance initialization routine. It then executes a message 
  435.         retrieval and dispatch loop that is the top-level control structure 
  436.         for the remainder of execution. The loop is terminated when a WM_QUIT 
  437.         message is received, at which time this function exits the application 
  438.         instance by returning the value passed by PostQuitMessage(). 
  439.  
  440.         If this function must abort before entering the message loop, it 
  441.         returns the conventional value NULL.
  442.  
  443. ****************************************************************************/
  444.  
  445. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  446. HANDLE hInstance;                       /* current instance             */
  447. HANDLE hPrevInstance;                   /* previous instance            */
  448. LPSTR lpCmdLine;                        /* command line                 */
  449. int nCmdShow;                           /* show-window type (open/icon) */
  450. {
  451.     MSG msg;                            /* message                      */
  452.  
  453.     if (!hPrevInstance)                 /* Other instances of app running? */
  454.         if (!InitApplication(hInstance)) /* Initialize shared things */
  455.             return FALSE;             /* Exits if unable to initialize */
  456.  
  457.     /* Perform initializations that apply to a specific instance */
  458.     if (!InitInstance(hInstance, nCmdShow))
  459.         return FALSE;
  460.  
  461.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  462.  
  463.     while (GetMessage(&msg,      /* message structure          */
  464.         NULL,        /* handle of window receiving the message */
  465.         NULL,        /* lowest message to examine              */
  466.         NULL))       /* highest message to examine             */
  467.     {
  468.         TranslateMessage(&msg);     /* Translates virtual key codes       */
  469.         DispatchMessage(&msg);      /* Dispatches message to window       */
  470.     }
  471.     return msg.wParam;          /* Returns the value from PostQuitMessage */
  472. }
  473.