home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MSJV5-6.ZIP / FORM2.ZIP / PAGE2.C < prev    next >
C/C++ Source or Header  |  1990-11-01  |  22KB  |  750 lines

  1. /*
  2.  * Page Selection Control - WINDOW FUNCTION MODULE
  3.  *
  4.  * LANGUAGE      : Microsoft C5.1
  5.  * MODEL         : small
  6.  * ENVIRONMENT   : Microsoft Windows 3.0 SDK
  7.  * STATUS        : operational
  8.  *
  9.  * This module defines the page control window message processing
  10.  * function.  This function is responsible for interpreting all
  11.  * the commands and generating notification messages.
  12.  *
  13.  *    Eikon Systems, Inc.
  14.  *    989 East Hillsdale Blvd, Suite 260
  15.  *    Foster City, California 94404
  16.  *    415-349-4664
  17.  *
  18.  * 11/30/89 1.00 - Kevin P. Welch - initial creation.
  19.  *
  20.  */
  21.  
  22. #define  NOCOMM
  23.  
  24. #include <windows.h>
  25. #include <control.h>
  26.  
  27. #include "page.h"
  28. #include "page.d"
  29.  
  30. /* instance variable definitions */
  31. #define  PAGE_AUTO         0
  32. #define  PAGE_ROWS         2
  33. #define  PAGE_COLS         4
  34. #define  PAGE_RANGE        6
  35. #define  PAGE_SELECT       8
  36. #define  PAGE_HOFFSET      10
  37. #define  PAGE_VOFFSET      12
  38. #define  PAGE_HSPACING     14
  39. #define  PAGE_VSPACING     16
  40.  
  41. #define  AUTO              GetWindowWord(hWnd,PAGE_AUTO)
  42. #define  ROWS              GetWindowWord(hWnd,PAGE_ROWS)
  43. #define  COLS              GetWindowWord(hWnd,PAGE_COLS)
  44. #define  RANGE             GetWindowWord(hWnd,PAGE_RANGE)
  45. #define  SELECT            GetWindowWord(hWnd,PAGE_SELECT)
  46. #define  HOFFSET           GetWindowWord(hWnd,PAGE_HOFFSET)
  47. #define  VOFFSET           GetWindowWord(hWnd,PAGE_VOFFSET)
  48. #define  HSPACING          GetWindowWord(hWnd,PAGE_HSPACING)
  49. #define  VSPACING          GetWindowWord(hWnd,PAGE_VSPACING)
  50.  
  51. #define  SET_AUTO(x)       SetWindowWord(hWnd,PAGE_AUTO,x)
  52. #define  SET_ROWS(x)       SetWindowWord(hWnd,PAGE_ROWS,x)
  53. #define  SET_COLS(x)       SetWindowWord(hWnd,PAGE_COLS,x)
  54. #define  SET_RANGE(x)      SetWindowWord(hWnd,PAGE_RANGE,x)
  55. #define  SET_SELECT(x)     SetWindowWord(hWnd,PAGE_SELECT,x)
  56. #define  SET_HOFFSET(x)    SetWindowWord(hWnd,PAGE_HOFFSET,x)
  57. #define  SET_VOFFSET(x)    SetWindowWord(hWnd,PAGE_VOFFSET,x)
  58. #define  SET_HSPACING(x)   SetWindowWord(hWnd,PAGE_HSPACING,x)
  59. #define  SET_VSPACING(x)   SetWindowWord(hWnd,PAGE_VSPACING,x)
  60.  
  61. /* local definitions */
  62. #define  PAGE_WIDTH        ((5*GetSystemMetrics(SM_CXHTHUMB))/4)
  63. #define  PAGE_HEIGHT       ((3*GetSystemMetrics(SM_CYVTHUMB))/2)
  64.  
  65. #define  PAGE_CALCWIDTH    ((25*GetSystemMetrics(SM_CXHTHUMB))/16)
  66. #define  PAGE_CALCHEIGHT   ((10*GetSystemMetrics(SM_CYVTHUMB))/6)
  67.  
  68. /* local function definitions */
  69. VOID FAR PASCAL   CvtString( WORD, LPSTR );
  70. VOID FAR PASCAL   DrawCaret( HDC, LPRECT );
  71. VOID FAR PASCAL   CalcPage( HWND, LPRECT, WORD );
  72. VOID FAR PASCAL   DrawPage( HDC, LPRECT, WORD, BOOL, BOOL );
  73.  
  74. /* */
  75.  
  76. /*
  77.  * PageWndFn( hWnd, wMessage, wParam, lParam ) : LONG;
  78.  *
  79.  *    hWnd           handle to page window
  80.  *    wMessage       message number
  81.  *    wParam         single word parameter
  82.  *    lParam         double word parameter
  83.  *
  84.  * This function is responsible for processing all the messages
  85.  * which relate to the page selection control window.  Note how the
  86.  * code is written to avoid potential re-entrancy problems.
  87.  *
  88.  */
  89.  
  90. LONG FAR PASCAL PageWndFn(
  91.    HWND        hWnd,
  92.    WORD        wMessage,
  93.    WORD        wParam,
  94.    LONG        lParam )
  95. {
  96.    LONG        lResult;
  97.  
  98.    /* initialization */
  99.    lResult = TRUE;
  100.  
  101.    /* process message */
  102.    switch ( wMessage )
  103.       {
  104.    case WM_CREATE: /* window being created */
  105.  
  106.       /* define instance variables */
  107.       SET_RANGE( 0 );
  108.       SET_SELECT( 0 );
  109.       SET_AUTO( TRUE );
  110.  
  111.       break;
  112.    case WM_GETDLGCODE : /* interface query by dialog manager */
  113.       lResult = DLGC_WANTARROWS;
  114.       break;
  115.    case WM_SIZE : /* window being resized */
  116.  
  117.       /* calculate number of rows & columns */
  118.       SET_COLS(
  119.          (LOWORD(lParam)<PAGE_CALCWIDTH) ?
  120.             1 :
  121.             LOWORD(lParam)/PAGE_CALCWIDTH
  122.       );
  123.       SET_ROWS(
  124.          (HIWORD(lParam)<PAGE_CALCHEIGHT) ?
  125.             1 :
  126.             HIWORD(lParam)/PAGE_CALCHEIGHT
  127.       );
  128.  
  129.       /* calculate horizontal & vertical page spacing */
  130.       SET_HSPACING( (LOWORD(lParam)-(COLS*PAGE_WIDTH))/(COLS+1) );
  131.       SET_VSPACING( (HIWORD(lParam)-(ROWS*PAGE_HEIGHT))/(ROWS+1) );
  132.       
  133.       /* calculate horizontal & vertical page offsets */
  134.       SET_HOFFSET(
  135.          (LOWORD(lParam)-(COLS*(PAGE_WIDTH+HSPACING))-HSPACING)/2
  136.       );
  137.       SET_VOFFSET(
  138.          (HIWORD(lParam)-(ROWS*(PAGE_HEIGHT+VSPACING))-VSPACING)/2
  139.       );
  140.  
  141.       /* define range if undefined */
  142.       if ( (AUTO)||(RANGE>ROWS*COLS) ) 
  143.          SET_RANGE( ROWS*COLS );
  144.  
  145.       break;
  146.    case WM_SETFOCUS: /* receiving the keyboard focus */
  147.    case WM_KILLFOCUS: /* losing the keyboard focus */
  148.       {
  149.          HDC         hDC;
  150.          RECT        rcPage;
  151.          HBRUSH      hNewBrush;
  152.          HBRUSH      hOldBrush;
  153.  
  154.          /* calculate update region */
  155.          CalcPage( hWnd, &rcPage, SELECT );
  156.  
  157.          /* force a repaint */
  158.          hDC = GetDC( hWnd );
  159.          if ( hDC ) {
  160.    
  161.             /* define appropriate brush & text colors */
  162.             hNewBrush = (HBRUSH)SendMessage( PARENT(hWnd),
  163.                WM_CTLCOLOR, hDC, MAKELONG(hWnd,CTLCOLOR_BTN) );
  164.             hOldBrush = hNewBrush ?
  165.                SelectObject(hDC,hNewBrush) :
  166.                NULL;
  167.  
  168.             /* draw caret */
  169.             DrawCaret( hDC, &rcPage );
  170.  
  171.             /* restore original brush */
  172.             if ( hNewBrush ) {
  173.                SelectObject( hDC, hOldBrush );
  174.                DeleteObject( hNewBrush );
  175.             }
  176.  
  177.             /* release display context */
  178.             ReleaseDC( hWnd, hDC );
  179.  
  180.          }
  181.  
  182.       }
  183.       break;
  184.    case WM_KEYDOWN: /* key pressed */
  185.       {
  186.          HDC         hDC;
  187.          WORD        wSel;
  188.          WORD        wRow;
  189.          WORD        wCol;
  190.          RECT        rcPage;
  191.  
  192.          /* save current selection */
  193.          wSel = SELECT;
  194.          
  195.          /* calculate current row & column */
  196.          wRow = wSel / COLS;
  197.          wCol = wSel % COLS;
  198.       
  199.          /* process virtual key code */
  200.          switch( wParam )
  201.             {
  202.          case VK_HOME : /* home key */
  203.             SET_SELECT( 0 );
  204.             break;
  205.          case VK_END : /* end key */
  206.             SET_SELECT( RANGE-1 );
  207.             break;
  208.          case VK_UP : /* cursor up key */
  209.             SET_SELECT( (wRow) ? ((wRow-1)*COLS)+wCol : wSel );
  210.             break;
  211.          case VK_PRIOR : /* page up key */
  212.          case VK_LEFT : /* cursor left key */
  213.             SET_SELECT( (wSel) ? wSel-1 : wSel );
  214.             break;
  215.          case VK_NEXT : /* page down key */
  216.          case VK_RIGHT : /* cursor right key */
  217.             SET_SELECT( (wSel<(RANGE-1)) ? wSel+1 : wSel );
  218.             break;
  219.          case VK_DOWN : /* cursor down key */
  220.             SET_SELECT(
  221.                (((wRow+1)*COLS)+wCol<RANGE) ?
  222.                   ((wRow+1)*COLS)+wCol :
  223.                   wSel
  224.             );
  225.             break;
  226.          default : /* something else */
  227.             break;
  228.          }
  229.  
  230.          /* update window if necessary */
  231.          if ( wSel != SELECT ) {
  232.  
  233.             /* retrieve display context */
  234.             hDC = GetDC( hWnd );
  235.             if ( hDC ) {
  236.          
  237.                /* update previous page (unselected without caret) */
  238.                CalcPage( hWnd, &rcPage, wSel );
  239.                DrawPage( hDC, &rcPage, wSel, FALSE, FALSE );
  240.             
  241.                /* update new page (selected with caret) */
  242.                CalcPage( hWnd, &rcPage, SELECT );
  243.                DrawPage( hDC, &rcPage, SELECT, TRUE,
  244.                   (GetFocus()==hWnd)?TRUE:FALSE );
  245.  
  246.                /* release display context */
  247.                ReleaseDC( hWnd, hDC );
  248.  
  249.                /* notify parent of change */
  250.                SendMessage( PARENT(hWnd), WM_COMMAND, ID(hWnd),
  251.                   MAKELONG(hWnd,PN_SELCHANGE) );
  252.  
  253.             }
  254.  
  255.          }
  256.  
  257.       }
  258.       break;
  259.    case WM_LBUTTONDOWN: /* left mouse button down */
  260.    case WM_LBUTTONDBLCLK: /* left mouse button double-clicked */
  261.       {
  262.          HDC         hDC;
  263.          BOOL        bHit;
  264.          WORD        wPage;
  265.          RECT        rcNewPage;
  266.          RECT        rcOldPage;
  267.          POINT       ptMouse;
  268.  
  269.          /* define mouse point */
  270.          ptMouse.x = LOWORD(lParam);
  271.          ptMouse.y = HIWORD(lParam);
  272.  
  273.          /* check each page rectangle */
  274.          for (wPage=0,bHit=FALSE;(!bHit)&&(wPage<RANGE);wPage++) {
  275.  
  276.             /* calculate page rectangle */
  277.             CalcPage( hWnd, &rcNewPage, wPage );
  278.          
  279.             /* check if point inside a page */
  280.             if ( PtInRect(&rcNewPage,ptMouse) ) {
  281.        
  282.                /* set hit flag */
  283.                bHit = TRUE;
  284.  
  285.                /* update window if necessary */
  286.                if ( SELECT != wPage ) {
  287.                
  288.                   /* retrieve display context */
  289.                   hDC = GetDC( hWnd );
  290.                   if ( hDC ) {
  291.                      CalcPage( hWnd, &rcOldPage, SELECT );
  292.                      DrawPage( hDC, &rcOldPage, SELECT, FALSE,
  293.                         FALSE );
  294.                      DrawPage( hDC, &rcNewPage, wPage, TRUE,
  295.                         (GetFocus()==hWnd) );
  296.                      ReleaseDC( hWnd, hDC );
  297.                   }
  298.  
  299.                   /* update selection */
  300.                   SET_SELECT( wPage );
  301.  
  302.                   /* notify parent of change */
  303.                   SendMessage( PARENT(hWnd), WM_COMMAND, ID(hWnd),
  304.                      MAKELONG(hWnd,PN_SELCHANGE) );
  305.  
  306.                } 
  307.  
  308.                /* grab focus if necessary */
  309.                if ( GetFocus() != hWnd )
  310.                   SetFocus( hWnd );
  311.  
  312.             }
  313.  
  314.          }
  315.  
  316.       }
  317.       break;
  318.    case WM_PAINT: /* paint control window */
  319.       {
  320.          PAINTSTRUCT Ps;
  321.          WORD        wPage;
  322.          HPEN        hOldPen;
  323.          HPEN        hNewPen;
  324.          RECT        rcClient;
  325.          HBRUSH      hOldBrush;
  326.          HBRUSH      hNewBrush;
  327.  
  328.          /* prepare for painting */
  329.          GetClientRect( hWnd, &rcClient );
  330.  
  331.          /* start paint operation */
  332.          BeginPaint( hWnd, &Ps );
  333.  
  334.          /* define appropriate pen */
  335.          hNewPen = CreatePen( PS_SOLID, 1,
  336.             GetSysColor(COLOR_WINDOWFRAME) );
  337.          hOldPen = (hNewPen) ? SelectObject(Ps.hdc,hNewPen) : NULL;
  338.  
  339.          /* define appropriate brush & text colors */
  340.          hNewBrush = (HBRUSH)SendMessage( PARENT(hWnd), WM_CTLCOLOR,
  341.             Ps.hdc, MAKELONG(hWnd,CTLCOLOR_BTN) );
  342.          hOldBrush = hNewBrush ? SelectObject(Ps.hdc,hNewBrush) :
  343.             NULL;
  344.  
  345.          /* draw border */
  346.          Rectangle(
  347.             Ps.hdc,
  348.             rcClient.left,
  349.             rcClient.top,
  350.             rcClient.right, 
  351.             rcClient.bottom
  352.          );
  353.  
  354.          /* draw individual pages */
  355.          for ( wPage=0; wPage<RANGE; wPage++ ) {
  356.             CalcPage(
  357.                hWnd,
  358.                &rcClient,
  359.                wPage
  360.             );
  361.             DrawPage(
  362.                Ps.hdc,
  363.                &rcClient,
  364.                wPage,
  365.                (SELECT==wPage),
  366.                (GetFocus()==hWnd)&&(SELECT==wPage)
  367.             );
  368.          }
  369.  
  370.          /* restore original brush */
  371.          if ( hNewBrush ) {
  372.             SelectObject( Ps.hdc, hOldBrush );
  373.             DeleteObject( hNewBrush );
  374.          }
  375.  
  376.          /* restore original pen */
  377.          if ( hNewPen ) {
  378.             SelectObject( Ps.hdc, hOldPen );
  379.             DeleteObject( hNewPen );
  380.          }
  381.  
  382.          /* end paint operation */
  383.          EndPaint( hWnd, &Ps );
  384.  
  385.       }
  386.       break;
  387.    case PM_SETRANGE : /* set page range */
  388.  
  389.       /* turn off auto ranging flag */
  390.       SET_AUTO( FALSE );
  391.  
  392.       /* update range (after validation) */
  393.       SET_RANGE(
  394.          (wParam)&&(wParam<=ROWS*COLS) ? 
  395.          wParam : 
  396.          ROWS*COLS
  397.       );
  398.  
  399.       /* update window */
  400.       InvalidateRect( hWnd, NULL, TRUE );
  401.       UpdateWindow( hWnd );
  402.    
  403.       break;
  404.    case PM_GETRANGE : /* get page range */
  405.       lResult = RANGE;
  406.       break;
  407.    case PM_SETSELECT : /* set selected page */
  408.       {
  409.          HDC         hDC;
  410.          WORD        wSel;
  411.          RECT        rcPage;
  412.  
  413.          if ( wParam <= ROWS*COLS ) {
  414.          
  415.             /* retrieve old selection */
  416.             wSel = SELECT;
  417.  
  418.             /* define new selection */
  419.             SET_SELECT( wParam );
  420.  
  421.             /* update window if necessary */
  422.             if ( wSel != SELECT ) {
  423.  
  424.                /* retrieve display context */
  425.                hDC = GetDC( hWnd );
  426.                if ( hDC ) {
  427.          
  428.                   /* update previous page (without caret) */
  429.                   CalcPage( hWnd, &rcPage, wSel );
  430.                   DrawPage( hDC, &rcPage, wSel, FALSE, FALSE );
  431.             
  432.                   /* update new page (selected with caret) */
  433.                   CalcPage( hWnd, &rcPage, SELECT );
  434.                   DrawPage( hDC, &rcPage, SELECT, TRUE, TRUE );
  435.  
  436.                   /* release display context */
  437.                   ReleaseDC( hWnd, hDC );
  438.  
  439.                }
  440.  
  441.             }
  442.  
  443.          }
  444.  
  445.          /* return new selection */
  446.          lResult = SELECT;
  447.  
  448.       }
  449.       break;
  450.    case PM_GETSELECT : /* get selected page */
  451.       lResult = SELECT;
  452.       break;
  453.    default: /* default window message processing */
  454.       lResult = DefWindowProc( hWnd, wMessage, wParam, lParam );
  455.       break;
  456.    }
  457.  
  458.    /* return final result */
  459.    return( lResult );
  460. }
  461.  
  462. /* */
  463.  
  464. /*
  465.  * CalcPage( hWnd, lprcRect, wPage ) : VOID;
  466.  *
  467.  *    hWnd           handle to page selection window
  468.  *    lprcRect       new page rectangle
  469.  *    wPage          desired page number
  470.  *
  471.  * This function calculates a specific page rectangle based
  472.  * on the page number provided.
  473.  *
  474.  */
  475.  
  476. VOID FAR PASCAL CalcPage(
  477.    HWND        hWnd,
  478.    LPRECT      lprcRect,
  479.    WORD        wPage )
  480. {
  481.    WORD        wRow;
  482.    WORD        wCol;
  483.  
  484.    /* calculate row and column */
  485.    wRow = wPage / COLS;
  486.    wCol = wPage % COLS;
  487.  
  488.    /* calculate page rectangle */
  489.    lprcRect->left = (wCol*(HSPACING+PAGE_WIDTH))+HSPACING+HOFFSET;
  490.    lprcRect->top =   (wRow*(VSPACING+PAGE_HEIGHT))+VSPACING+VOFFSET;
  491.    lprcRect->right = ((wCol+1)*(HSPACING+PAGE_WIDTH))+HOFFSET;
  492.    lprcRect->bottom = ((wRow+1)*(VSPACING+PAGE_HEIGHT))+VOFFSET;
  493.    
  494. }
  495.  
  496. /* */
  497.  
  498. /*
  499.  * DrawPage( hDC, lprcPage, wNumber, bSelect, bCaret ) : VOID;
  500.  *
  501.  *    hDC            handle to display context
  502.  *    lprcPage       rectangle in which to draw page
  503.  *    wNumber        number to display inside page
  504.  *    bSelect        boolean page selection flag
  505.  *    bCaret         boolean caret flag
  506.  *
  507.  * This function draws a page icon inside the rectangle provided.  If
  508.  * the bSelect flag is TRUE, the page is displayed in inverse video.
  509.  * If the bCaret flag is TRUE, a caret is displayed inside the page.
  510.  *
  511.  */
  512.  
  513. VOID FAR PASCAL DrawPage(
  514.    HDC         hDC,
  515.    LPRECT      lprcPage,
  516.    WORD        wNumber,
  517.    BOOL        bSelect,
  518.    BOOL        bCaret )
  519. {
  520.    WORD        wFlap;
  521.    HPEN        hOldPen;
  522.    HBRUSH      hOldBrush;
  523.    RECT        rcNumber;
  524.    DWORD       dwOldBkColor;
  525.    DWORD       dwOldTextColor;
  526.    POINT       ptPage[7];
  527.    char        szNumber[16];
  528.  
  529.    /* calculate page flap */
  530.    wFlap = (lprcPage->right-lprcPage->left)/3;
  531.       
  532.    /* convert number to string */
  533.    CvtString( wNumber+1, szNumber );
  534.  
  535.    /* define number rectangle */
  536.    rcNumber.top = lprcPage->top + wFlap + 2;
  537.    rcNumber.left = lprcPage->left + 2;
  538.    rcNumber.right = lprcPage->right - 2;
  539.    rcNumber.bottom = lprcPage->bottom - 2;
  540.  
  541.    /* draw page (based on selection state */
  542.    if ( bSelect ) {
  543.       
  544.       /* define page polygon */
  545.       ptPage[0].x = lprcPage->left;
  546.       ptPage[0].y = lprcPage->top;
  547.       ptPage[1].x = lprcPage->right - wFlap - 1;
  548.       ptPage[1].y = lprcPage->top;
  549.       ptPage[2].x = lprcPage->right - 1;
  550.       ptPage[2].y = lprcPage->top + wFlap;
  551.       ptPage[3].x = lprcPage->right - 1;
  552.       ptPage[3].y = lprcPage->bottom - 1;
  553.       ptPage[4].x = lprcPage->left;
  554.       ptPage[4].y = lprcPage->bottom - 1;
  555.       ptPage[5].x = lprcPage->left;
  556.       ptPage[5].y = lprcPage->top;
  557.  
  558.       /* draw page outline */
  559.       hOldBrush = SelectObject( hDC,
  560.          CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME)) );
  561.       Polygon( hDC, ptPage, 6 );
  562.       DeleteObject( SelectObject(hDC,hOldBrush) );
  563.  
  564.       /* draw flap with background pen color */
  565.       hOldPen = SelectObject( hDC,
  566.          CreatePen(PS_SOLID,1,GetSysColor(COLOR_WINDOW)) );
  567.       MoveTo( hDC, lprcPage->right - wFlap - 1,
  568.          lprcPage->top + 1 );
  569.       LineTo( hDC, lprcPage->right - wFlap - 1,
  570.          lprcPage->top + wFlap );
  571.       LineTo( hDC, lprcPage->right - 1, lprcPage->top + wFlap );
  572.       DeleteObject( SelectObject(hDC,hOldPen) );
  573.  
  574.       /* draw inverted page number */
  575.       dwOldBkColor = SetBkColor( hDC,
  576.          GetSysColor(COLOR_WINDOWFRAME) );
  577.       dwOldTextColor = SetTextColor( hDC,
  578.          GetSysColor(COLOR_WINDOW) );
  579.       DrawText(
  580.          hDC,
  581.          szNumber,
  582.          -1,
  583.          &rcNumber,
  584.          DT_CENTER|DT_VCENTER|DT_SINGLELINE
  585.       );
  586.       SetTextColor( hDC, dwOldTextColor );
  587.       SetBkColor( hDC, dwOldBkColor );
  588.  
  589.    } else {
  590.  
  591.       /* define page polygon */
  592.       ptPage[0].x = lprcPage->left;
  593.       ptPage[0].y = lprcPage->top;
  594.       ptPage[1].x = lprcPage->right - wFlap - 1;
  595.       ptPage[1].y = lprcPage->top;
  596.       ptPage[2].x = lprcPage->right - wFlap - 1;
  597.       ptPage[2].y = lprcPage->top + wFlap;
  598.       ptPage[3].x = lprcPage->right - 1;
  599.       ptPage[3].y = lprcPage->top + wFlap;
  600.       ptPage[4].x = lprcPage->right - 1;
  601.       ptPage[4].y = lprcPage->bottom - 1;
  602.       ptPage[5].x = lprcPage->left;
  603.       ptPage[5].y = lprcPage->bottom - 1;
  604.       ptPage[6].x = lprcPage->left;
  605.       ptPage[6].y = lprcPage->top;
  606.  
  607.       /* draw page outline */
  608.       hOldBrush = SelectObject( hDC,
  609.          CreateSolidBrush(GetSysColor(COLOR_BTNFACE)) );
  610.       Polygon( hDC, ptPage, 7 );
  611.       DeleteObject( SelectObject(hDC,hOldBrush) );
  612.  
  613.       /* draw page flap */
  614.       hOldBrush = SelectObject( hDC,
  615.          CreateSolidBrush(GetSysColor(COLOR_WINDOW)) );
  616.       Polygon( hDC, &ptPage[1], 3 );
  617.       DeleteObject( SelectObject(hDC,hOldBrush) );
  618.  
  619.       /* draw page number */
  620.       dwOldBkColor = SetBkColor( hDC, GetSysColor(COLOR_BTNFACE) );
  621.       dwOldTextColor = SetTextColor( hDC,
  622.          GetSysColor(COLOR_BTNTEXT) );
  623.       DrawText(
  624.          hDC,
  625.          szNumber,
  626.          -1,
  627.          &rcNumber,
  628.          DT_CENTER|DT_VCENTER|DT_SINGLELINE
  629.       );
  630.       SetTextColor( hDC, dwOldTextColor );
  631.       SetBkColor( hDC, dwOldBkColor );
  632.  
  633.       /* draw white border */
  634.       hOldPen = SelectObject( hDC,
  635.          CreatePen(PS_SOLID,1,GetSysColor(COLOR_WINDOW)) );
  636.       MoveTo( hDC, ptPage[5].x + 1, ptPage[5].y - 1 );
  637.       LineTo( hDC, ptPage[5].x + 1, ptPage[6].y + 1 );
  638.       LineTo( hDC, ptPage[1].x, ptPage[1].y + 1 );
  639.       DeleteObject( SelectObject(hDC,hOldPen) );
  640.  
  641.       /* draw shadow */
  642.       hOldPen = SelectObject( hDC,
  643.          CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW)) );
  644.       MoveTo( hDC, ptPage[5].x + 1, ptPage[5].y - 1 );
  645.       LineTo( hDC, ptPage[4].x - 1, ptPage[4].y - 1 );
  646.       LineTo( hDC, ptPage[3].x - 1, ptPage[3].y );
  647.       MoveTo( hDC, ptPage[5].x + 2, ptPage[5].y - 2 );
  648.       LineTo( hDC, ptPage[4].x - 2, ptPage[4].y - 2 );
  649.       LineTo( hDC, ptPage[3].x - 2, ptPage[3].y );
  650.       DeleteObject( SelectObject(hDC,hOldPen) );
  651.  
  652.    }
  653.  
  654.    /* draw caret (if requested) */
  655.    if ( bCaret )
  656.       DrawCaret( hDC, lprcPage );
  657.  
  658. }
  659.  
  660. /* */
  661.  
  662. /*
  663.  * DrawCaret( hDC, lprcPage ) : VOID;
  664.  *
  665.  *    hDC            handle to display context
  666.  *    lprcPage       rectangle in which to draw caret
  667.  *
  668.  * This function draws a caret inside the page icon using the
  669.  * rectangle provided.  Since a PATINVERT operation is used, the
  670.  * previous caret can be erased by a second call with the same
  671.  * function parameters.
  672.  *
  673.  */
  674.  
  675. VOID FAR PASCAL DrawCaret(
  676.    HDC         hDC,
  677.    LPRECT      lprcPage )
  678. {
  679.    WORD        wFlap;
  680.    HBRUSH      hOldBrush;
  681.  
  682.    /* calculate page flap */
  683.    wFlap = (lprcPage->right-lprcPage->left)/3;
  684.       
  685.    /* initialize display context */
  686.    hOldBrush = (HBRUSH)SelectObject( hDC,
  687.       GetStockObject(GRAY_BRUSH) );
  688.  
  689.    /* draw caret */
  690.    PatBlt( hDC, lprcPage->left+1, lprcPage->top+1,
  691.       (lprcPage->right-lprcPage->left)-wFlap-1, 1, PATINVERT );
  692.    PatBlt( hDC, lprcPage->right-2, lprcPage->top+wFlap+1, 1,
  693.       (lprcPage->bottom-lprcPage->top)-wFlap-3, PATINVERT );
  694.    PatBlt( hDC, lprcPage->left+2, lprcPage->bottom-2,
  695.       (lprcPage->right-lprcPage->left)-3, 1, PATINVERT );
  696.    PatBlt( hDC, lprcPage->left+1, lprcPage->top+2, 1,
  697.       (lprcPage->bottom-lprcPage->top)-3, PATINVERT );
  698.  
  699.    /* restore display context */
  700.    SelectObject( hDC, hOldBrush );
  701.  
  702. }
  703.  
  704. /* */
  705.  
  706. /*
  707.  * CvtString( wNumber, lpszNumber ) : VOID;
  708.  *
  709.  *    wNumber        number to convert
  710.  *    lpszNumber     long pointer to string
  711.  *
  712.  * This function converts the number provided into a string,
  713.  * assuming an unsigned number.  This function is used by the page
  714.  * drawing routine to display the current page number.
  715.  *
  716.  */
  717.  
  718. VOID FAR PASCAL CvtString(
  719.    WORD        wNumber, 
  720.    LPSTR       lpszNumber )
  721. {
  722.    WORD        wBase;
  723.    WORD        wRemainder;
  724.    BOOL        bDigit;
  725.  
  726.    /* initialization */
  727.    wBase = 10000;
  728.    bDigit = FALSE;
  729.    
  730.    /* parse digits */
  731.    while ( wBase ) {
  732.  
  733.       /* calculate new remainder & update string */
  734.       wRemainder = wNumber / wBase;
  735.       if ( (wRemainder)||(bDigit)||(wBase==1)) {
  736.          bDigit = TRUE;
  737.          *lpszNumber++ = (char)wRemainder + '0';
  738.       }
  739.    
  740.       /* update number & base */
  741.       wNumber -= (wRemainder * wBase);
  742.       wBase = wBase / 10;
  743.  
  744.    }
  745.  
  746.    /* add trailing null */
  747.    *lpszNumber = 0;
  748.  
  749. }
  750.