home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_sdk / rainbow / rainbow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  23.8 KB  |  883 lines

  1. /*
  2.  * RAINBOW -- Example Dialog Editor custom control
  3.  *
  4.  */
  5.  
  6. #include <windows.h>
  7. #include <custcntl.h>
  8. #include "rainbow.h"
  9.  
  10. /* global static variables */
  11. HANDLE        hLibData;
  12. HANDLE        hLibInstance;
  13. LPFNSTRTOID      lpfnVerId;
  14. LPFNIDTOSTR      lpfnIdStr;
  15.  
  16. /* string for property lists */
  17. #define    IDFNLO                    "lpfnIdFnLo"
  18. #define    IDFNHI                    "lpfnIdFnHi"
  19.  
  20. #define    RAINBOWCLASS            "Rainbow"
  21.  
  22. /* general rainbow definitions */
  23. #define    ID                            GetWindowWord( hWnd, GWW_ID )
  24. #define    PARENT                    GetWindowWord( hWnd, GWW_HWNDPARENT )
  25. #define    INSTANCE                    GetWindowWord( hWnd, GWW_HINSTANCE )
  26.  
  27. /* rainbow specific definitions */
  28. #define    RAINBOW_EXTRA            12                
  29.  
  30. #define    RANGE                        GetWindowWord( hWnd, 0 )
  31. #define    TABLE                        GetWindowWord( hWnd, 2 )
  32. #define    WIDTH                        GetWindowWord( hWnd, 4 )
  33. #define    HEIGHT                    GetWindowWord( hWnd, 6 )
  34. #define    CHOICE                    GetWindowWord( hWnd, 8 )
  35. #define    CAPTURE                    GetWindowWord( hWnd, 10 )
  36.  
  37. #define    SET_RANGE(x)            SetWindowWord( hWnd, 0, x )
  38. #define    SET_TABLE(x)            SetWindowWord( hWnd, 2, x )
  39. #define    SET_WIDTH(x)            SetWindowWord( hWnd, 4, x )
  40. #define    SET_HEIGHT(x)            SetWindowWord( hWnd, 6, x )
  41. #define    SET_CHOICE(x)            SetWindowWord( hWnd, 8, x )
  42. #define    SET_CAPTURE(x)            SetWindowWord( hWnd, 10, x )
  43.  
  44. /* caret related definitions */
  45. #define    CARET_XPOS                ((CHOICE*WIDTH)+3)
  46. #define    CARET_YPOS                (3)
  47. #define    CARET_WIDTH                (WIDTH-6)
  48. #define    CARET_HEIGHT            (HEIGHT-6)
  49.  
  50. /* selector related definitions */
  51. #define    SELECTOR_XPOS            ((CHOICE*WIDTH)+1)
  52. #define    SELECTOR_YPOS            (1)
  53. #define    SELECTOR_WIDTH            (WIDTH-2)
  54. #define    SELECTOR_HEIGHT        (HEIGHT-2)
  55.  
  56. /* undocumented internal function definitions */
  57. int FAR PASCAL        lstrlen( LPSTR );
  58. int FAR PASCAL        lstrcmp( LPSTR, LPSTR );
  59. LPSTR FAR PASCAL    lstrcpy( LPSTR, LPSTR );
  60. LPSTR FAR PASCAL    lstrcat( LPSTR, LPSTR );
  61.  
  62. /* internal rainbow function prototypes */
  63. BOOL FAR PASCAL     RainbowDlgFn( HWND, WORD, WORD, LONG );
  64. LONG FAR PASCAL     RainbowWndFn( HWND, WORD, WORD, LONG );
  65. void static            DrawSelector( HWND, HDC );
  66.  
  67. /* */
  68.  
  69. /*
  70.  * LibMain( hInstance, wDataSegment, wHeapSize, lpszCmdLine ) : WORD
  71.  *
  72.  *    hInstance      library instance handle
  73.  *    wDataSegment   library data segment
  74.  *    wHeapSize      default heap size
  75.  *    lpszCmdLine    command line arguments
  76.  *
  77.  * LibMain is called by LibEntry, which is called by Windows when 
  78.  * the DLL is loaded.  The LibEntry routine is provided 
  79.  * in the LIBENTRY.OBJ in the SDK Link Libraries disk.  (The source 
  80.  * LIBENTRY.ASM is also provided.)  
  81.  *
  82.  * LibEntry initializes the DLL's heap, if a HEAPSIZE value is
  83.  * specified in the DLL's DEF file.  Then LibEntry calls
  84.  * LibMain.  The LibMain function below satisfies that call.
  85.  *
  86.  * LibMain performs all the initialization necessary to use the
  87.  * rainbow user control.  Included in this initialization is the
  88.  * registration of the Rainbow window class.
  89.  *
  90. */
  91.  
  92. int FAR PASCAL LibMain(
  93.    HANDLE      hInstance,
  94.    WORD        wDataSegment,
  95.    WORD        wHeapSize,
  96.    LPSTR       lpszCmdLine )
  97. {
  98.     HANDLE            hClassStruct;
  99.     LPWNDCLASS        lpClassStruct;
  100.  
  101.     /* register rainbow window if necessary */
  102.     if ( hLibInstance == NULL ) {
  103.  
  104.         /* allocate memory for class structure */
  105.         hClassStruct = GlobalAlloc( GHND, (DWORD)sizeof(WNDCLASS) );
  106.         if ( hClassStruct ) {
  107.  
  108.             /* lock it down */
  109.             lpClassStruct = (LPWNDCLASS)GlobalLock( hClassStruct );
  110.             if ( lpClassStruct ) {
  111.     
  112.                 /* define class attributes */
  113.                 lpClassStruct->lpszClassName =     (LPSTR)RAINBOWCLASS;
  114.                 lpClassStruct->hCursor =            LoadCursor( NULL, IDC_ARROW );
  115.                 lpClassStruct->lpszMenuName =        (LPSTR)NULL;
  116.                 lpClassStruct->style =                CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS|CS_GLOBALCLASS;
  117.                 lpClassStruct->lpfnWndProc =        RainbowWndFn;
  118.                 lpClassStruct->hInstance =            hInstance;
  119.                 lpClassStruct->hIcon =                NULL;
  120.                 lpClassStruct->cbWndExtra =        RAINBOW_EXTRA;
  121.                 lpClassStruct->hbrBackground =    (HBRUSH)(COLOR_WINDOW + 1 );
  122.     
  123.                 /* register rainbow window class */
  124.                 hLibInstance = ( RegisterClass(lpClassStruct) ) ? hInstance : NULL;
  125.  
  126.                 /* unlock structure */
  127.                 GlobalUnlock( hClassStruct );
  128.  
  129.             }
  130.  
  131.             /* release class structure */
  132.             GlobalFree( hClassStruct );
  133.  
  134.         }
  135.  
  136.     }
  137.  
  138.     /* return result 1 = success; 0 = fail */
  139.     return( hLibInstance? 1:0 );
  140. }
  141.  
  142. /* */
  143.  
  144.  
  145. /****************************************************************************
  146.     FUNCTION:  WEP(int)
  147.  
  148.     PURPOSE:  Performs cleanup tasks when the DLL is unloaded.  WEP() is
  149.               called automatically by Windows when the DLL is unloaded
  150.               (no remaining tasks still have the DLL loaded).  It is
  151.               strongly recommended that a DLL have a WEP() function,
  152.               even if it does nothing but return, as in this example.
  153.  
  154. *******************************************************************************/
  155. VOID FAR PASCAL WEP (bSystemExit)
  156. int  bSystemExit;
  157. {
  158.     return;
  159. }
  160.  
  161.  
  162. /*
  163.  * RainbowInfo() : HANDLE
  164.  *
  165.  * This function returns a handle to a global block of memory that
  166.  * contains various information about the kinds of controls the library
  167.  * is capable of supporting.  This data block can, for example, be used
  168.  * by the dialog editor when determining the capabilities of a particular
  169.  * control library.
  170.  *
  171.  * Note that this handle becomes the property of the caller once this
  172.  * function returns.  This implies that the caller must call GlobalFree
  173.  * once it is finished with the data.
  174.  *
  175.  */
  176.  
  177. HANDLE FAR PASCAL RainbowInfo()
  178. {
  179.     HANDLE        hCtlInfo;
  180.     LPCTLINFO    lpCtlInfo;
  181.  
  182.     /* allocate space for information structure */
  183.     hCtlInfo = GlobalAlloc( GHND, (DWORD)sizeof(CTLINFO) );
  184.     if ( hCtlInfo ) {
  185.  
  186.         /* attempt to lock it down */
  187.         lpCtlInfo = (LPCTLINFO)GlobalLock( hCtlInfo );
  188.         if ( lpCtlInfo ) {
  189.  
  190.             /* define the fixed portion of the structure */
  191.             lpCtlInfo->wVersion = 100;
  192.             lpCtlInfo->wCtlTypes = 1;
  193.             lstrcpy( lpCtlInfo->szClass, RAINBOWCLASS );
  194.             lstrcpy( lpCtlInfo->szTitle, "Sample User Control" );
  195.  
  196.             /* define the variable portion of the structure */
  197.             lpCtlInfo->Type[0].wWidth = 33;
  198.             lpCtlInfo->Type[0].wHeight = 20;
  199.             lpCtlInfo->Type[0].dwStyle = WS_CHILD;
  200.             lstrcpy( lpCtlInfo->Type[0].szDescr, "Rainbow" );
  201.  
  202.             /* unlock it */
  203.             GlobalUnlock( hCtlInfo );
  204.         
  205.         } else {
  206.             GlobalFree( hCtlInfo );
  207.             hCtlInfo = NULL;
  208.         }
  209.     
  210.     }
  211.  
  212.     /* return result */
  213.     return( hCtlInfo );
  214.  
  215. }
  216.  
  217. /* */
  218.  
  219. /*
  220.  * RainbowStyle( hWnd, hCtlStyle, lpfnVeriyId, lpfnGetIdStr ) : BOOL;
  221.  *
  222.  *    hWnd           handle to parent window
  223.  *    hCtlStyle      handle to control style
  224.  *    lpfnVerifyId   pointer to the VerifyId function from Dialog editor
  225.  *    lpfnGetIdStr   pointer to the GetIdStr functionn from Dialog editor
  226.  *
  227.  * This function enables the user to edit the style of a particular
  228.  * control provided.  The current control style information is passed
  229.  * in using a handle to a control style data structure.
  230.  *
  231.  * This function returns this same handle (referencing updated
  232.  * information) if the dialog box is normally closed.  A value of
  233.  * NULL is returned if the user cancelled the operation.
  234.  *
  235.  */
  236.  
  237. BOOL FAR PASCAL RainbowStyle(
  238.     HWND        hWnd,
  239.     HANDLE      hCtlStyle,
  240.     LPFNSTRTOID         lpfnVerifyId,
  241.     LPFNIDTOSTR    lpfnGetIdStr )
  242. {
  243.     FARPROC        lpDlgFn;
  244.     HANDLE        hNewCtlStyle;
  245.  
  246.     /* initialization */
  247.     hLibData = hCtlStyle;
  248.     lpfnVerId = lpfnVerifyId;
  249.     lpfnIdStr = lpfnGetIdStr;
  250.  
  251.     /* display dialog box */
  252.     lpDlgFn = MakeProcInstance( (FARPROC)RainbowDlgFn, hLibInstance );
  253.     hNewCtlStyle = ( DialogBox(hLibInstance,"RainbowStyle",hWnd,lpDlgFn) ) ? hLibData : NULL;
  254.     FreeProcInstance( lpDlgFn );
  255.  
  256.     /* return updated data block */
  257.     return( hNewCtlStyle );
  258.  
  259. }
  260.  
  261. /* */
  262.  
  263. /*
  264.  * RainbowFlags( wFlags, lpszString, wMaxString ) : WORD;
  265.  *
  266.  *    wFlags         class style flags
  267.  *    lpszString     class style string
  268.  *    wMaxString     maximum size of class style string
  269.  *
  270.  * This function translates the class style flags provided into a
  271.  * corresponding text string for output to an RC file.  The general
  272.  * windows flags (contained in the low byte) are not interpreted,
  273.  * only those in the high byte.
  274.  *
  275.  * The value returned by this function is the library instance
  276.  * handle when sucessful, and NULL otherwise.
  277.  *
  278.  */
  279.  
  280. WORD FAR PASCAL RainbowFlags(
  281.     WORD        wFlags,
  282.     LPSTR       lpszString,
  283.     WORD        wMaxString )
  284. {
  285.     lpszString[0] = NULL;
  286.     return( 0 );
  287. }
  288.  
  289. /* */
  290.  
  291. /*
  292.  * RainbowWndFn( hWnd, wMsg, wParam, lParam ) : LONG
  293.  *
  294.  *        hWnd                    handle to rainbow window
  295.  *        wMsg                    message number
  296.  *        wParam                single word parameter
  297.  *        lParam                double word parameter
  298.  *
  299.  * This function is responsible for processing all the messages
  300.  * which relate to the rainbow control window.  Note how the
  301.  * code is written to avoid potential problems when re-entrancy
  302.  * ocurrs - this involves the use of extra bytes associated with
  303.  * the window data structure.
  304.  *
  305.  * The LONG value returned by this function is either a value
  306.  * returned by the internal handling of the message or by the
  307.  * default window procedure.
  308.  *
  309.  */
  310.  
  311. LONG FAR PASCAL RainbowWndFn( hWnd, wMsg, wParam, lParam )
  312.     HWND            hWnd;
  313.     WORD            wMsg;
  314.     WORD            wParam;
  315.     LONG            lParam;
  316. {
  317.     /* local variables */
  318.     LONG            lResult;                    /* temporary result variable */
  319.     
  320.     /* initialization */
  321.     lResult = TRUE;
  322.     
  323.     /* process message */
  324.     switch( wMsg )
  325.         {
  326.     case WM_GETDLGCODE : /* capture all key strokes */
  327.         lParam = DLGC_WANTARROWS;        
  328.         break;
  329.     case WM_CREATE : /* create pallette window */
  330.         
  331.         {
  332.             /* temporary variables */
  333.             HANDLE        hrgbList;                /* handle to rgb list */
  334.             LONG FAR *    lprgbEntry;                /* pointer to rgb list */
  335.             
  336.             /* allocate space for rgb color list */
  337.             hrgbList = GlobalAlloc( GMEM_MOVEABLE, sizeof(LONG)*16L );
  338.             if ( hrgbList ) {
  339.             
  340.                /*
  341.                  * Define initial rgb color & value list - note that
  342.                  * eight default colors are selected with the values
  343.                  * matching each of the colors.
  344.                  */
  345.  
  346.                 lprgbEntry = (LONG FAR *)GlobalLock( hrgbList );
  347.                 lprgbEntry[0] = RGB( 0x00, 0x00, 0x00 );
  348.                 lprgbEntry[1] = RGB( 0x00, 0x00, 0xFF );
  349.                 lprgbEntry[2] = RGB( 0x00, 0xFF, 0x00 );
  350.                 lprgbEntry[3] = RGB( 0xFF, 0x00, 0x00 );
  351.                 lprgbEntry[4] = RGB( 0x00, 0xFF, 0xFF );
  352.                 lprgbEntry[5] = RGB( 0xFF, 0xFF, 0x00 );
  353.                 lprgbEntry[6] = RGB( 0xFF, 0x00, 0xFF );
  354.                 lprgbEntry[7] = RGB( 0xFF, 0xFF, 0xFF );
  355.                 lprgbEntry[8] = RGB( 0x00, 0x00, 0x00 );
  356.                 lprgbEntry[9] = RGB( 0x00, 0x00, 0xFF );
  357.                 lprgbEntry[10] = RGB( 0x00, 0xFF, 0x00 );
  358.                 lprgbEntry[11] = RGB( 0xFF, 0x00, 0x00 );
  359.                 lprgbEntry[12] = RGB( 0x00, 0xFF, 0xFF );
  360.                 lprgbEntry[13] = RGB( 0xFF, 0xFF, 0x00 );
  361.                 lprgbEntry[14] = RGB( 0xFF, 0x00, 0xFF );
  362.                 lprgbEntry[15] = RGB( 0xFF, 0xFF, 0xFF );
  363.                 GlobalUnlock( hrgbList );
  364.             
  365.                 /* define instance variables */
  366.                 SET_RANGE( 8 );
  367.                 SET_TABLE( hrgbList );
  368.                 SET_WIDTH( ((LPCREATESTRUCT)lParam)->cx / 8 );
  369.                 SET_HEIGHT( ((LPCREATESTRUCT)lParam)->cy );
  370.                 SET_CHOICE( 0 );
  371.                 SET_CAPTURE( FALSE );
  372.     
  373.             } else
  374.                 DestroyWindow( hWnd );
  375.                 
  376.         }
  377.         
  378.         break;
  379.     case WM_SIZE : /* window being resized */
  380.     
  381.         /* redefine width & height instance variables */
  382.         SET_WIDTH( LOWORD(lParam) / 8 );
  383.         SET_HEIGHT( HIWORD(lParam) );
  384.  
  385.         break;
  386.     case WM_PAINT : /* paint control window */
  387.         
  388.         {
  389.             PAINTSTRUCT        Ps;                    /* paint structure */
  390.             WORD                wEntry;                /* current color entry */
  391.             HANDLE            hBrush;                /* handle to new brush */
  392.             HANDLE            hOldBrush;            /* handle to old brush */
  393.             LONG FAR *        lprgbEntry;            /* pointer to rgb list */
  394.                     
  395.             /* start paint operation */
  396.             BeginPaint( hWnd, (LPPAINTSTRUCT)&Ps );
  397.             
  398.             /* iteratively paint each color patch */
  399.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  400.             for ( wEntry=0; wEntry<RANGE; wEntry++ ) {
  401.  
  402.                 /* create solid brush for patch & select */
  403.                 hBrush = CreateSolidBrush( lprgbEntry[wEntry] );
  404.                 hOldBrush = SelectObject( Ps.hdc, hBrush );
  405.     
  406.                 /* draw rectangle with brush fill */
  407.                 Rectangle(
  408.                     Ps.hdc,
  409.                     wEntry*WIDTH,
  410.                     0,
  411.                     (wEntry*WIDTH)+WIDTH,
  412.                     HEIGHT
  413.                 );
  414.  
  415.                 /* unselect brush and delete */
  416.                 SelectObject( Ps.hdc, hOldBrush );
  417.                 DeleteObject( hBrush );
  418.     
  419.             }
  420.             GlobalUnlock( TABLE );
  421.                     
  422.             /* End paint operation */
  423.             EndPaint( hWnd, (LPPAINTSTRUCT)&Ps );
  424.         }
  425.         
  426.         break;
  427.     case WM_KEYDOWN : /* key being pressed */
  428.         
  429.         {
  430.             /* local variables */
  431.             HDC                hDC;                    /* display context handle */
  432.             LONG FAR *        lprgbEntry;            /* pointer to rgb list */    
  433.         
  434.             /* retrieve display context & unmark current selection */
  435.             hDC = GetDC( hWnd );
  436.             DrawSelector( hWnd, hDC );            
  437.  
  438.             /* process virtual key codes */
  439.             switch( wParam )
  440.                 {
  441.             case VK_HOME : /* home key */
  442.                 SET_CHOICE( 0 );
  443.                 break;
  444.             case VK_UP : /* up cursor key */
  445.             case VK_LEFT : /* left cursor key */
  446.                 SET_CHOICE( (CHOICE > 0) ? CHOICE-1 : RANGE-1 );
  447.                 break;
  448.             case VK_DOWN : /* down cursor key */
  449.             case VK_RIGHT : /* right cursor key */
  450.             case VK_SPACE : /* space bar - move right */
  451.                 SET_CHOICE( (CHOICE < RANGE-1) ? CHOICE+1 : 0 );
  452.                 break;
  453.             case VK_END : /* end key */
  454.                 SET_CHOICE( RANGE-1 );
  455.                 break;
  456.             default : /* some other key */
  457.                 lResult = FALSE;
  458.                 break;
  459.             }
  460.  
  461.             /* mark new selection & release display context */
  462.             DrawSelector( hWnd, hDC );
  463.             ReleaseDC( hWnd, hDC );
  464.  
  465.             /* move caret to new position */
  466.             SetCaretPos( CARET_XPOS, CARET_YPOS );
  467.  
  468.             /* notify parent of new selection */
  469.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  470.             SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
  471.             GlobalUnlock( TABLE );
  472.                     
  473.         }
  474.         
  475.         break;
  476.     case WM_SETFOCUS : /* get focus - display caret */
  477.         /* create caret & display */
  478.         CreateCaret( hWnd, NULL, CARET_WIDTH, CARET_HEIGHT );
  479.         SetCaretPos( CARET_XPOS, CARET_YPOS );
  480.         ShowCaret( hWnd );
  481.         break;
  482.  
  483.     case WM_LBUTTONDOWN : /* left button depressed - fall through */
  484.  
  485.         {
  486.             /* local variables */
  487.             HDC                hDC;                    /* display context handle */
  488.             LONG FAR *        lprgbEntry;            /* pointer to rgb list */    
  489.  
  490.             /* retrieve display context */
  491.             hDC = GetDC ( hWnd );
  492.  
  493.             /* unmark old selection & mark new one */
  494.             DrawSelector( hWnd, hDC );            
  495.             SET_CHOICE( LOWORD(lParam)/WIDTH );
  496.             DrawSelector( hWnd, hDC );
  497.         
  498.             /* release display context & move caret */
  499.             ReleaseDC( hWnd, hDC );
  500.  
  501.             /* capture focus & move caret */
  502.             SetFocus(hWnd);
  503.             SetCaretPos( CARET_XPOS, CARET_YPOS );
  504.  
  505.             /* notify parent of new selection */
  506.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  507.             SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
  508.             GlobalUnlock( TABLE );
  509.             
  510.             /* activate capture */
  511.             SetCapture( hWnd );
  512.             SET_CAPTURE( TRUE );            
  513.  
  514.         }
  515.         
  516.         break;
  517.     case WM_MOUSEMOVE : /* mouse being moved */
  518.  
  519.         /* track mouse only if capture on */
  520.         if ( CAPTURE ) {
  521.         
  522.             /* local variables */
  523.             HDC                hDC;                    /* display context handle */
  524.             WORD                wNewChoice;            /* new mouse selection */
  525.             LONG FAR *        lprgbEntry;            /* pointer to rgb list */    
  526.         
  527.             /* calculate new selection */
  528.             wNewChoice = ( LOWORD(lParam) <= 0 ) ?
  529.                 0 :
  530.                 ( LOWORD(lParam)/WIDTH >= RANGE ) ?
  531.                     RANGE - 1 :
  532.                     LOWORD(lParam) / WIDTH;
  533.             
  534.             /* update display if different */
  535.             if ( wNewChoice != CHOICE ) {
  536.  
  537.                 /* retrieve display context */
  538.                 hDC = GetDC ( hWnd );
  539.  
  540.                 /* unmark old selection & mark new one */
  541.                 DrawSelector( hWnd, hDC );            
  542.                 SET_CHOICE( wNewChoice );
  543.                 DrawSelector( hWnd, hDC );
  544.         
  545.                 /* release display context & move caret */
  546.                 ReleaseDC( hWnd, hDC );
  547.                 SetCaretPos( CARET_XPOS, CARET_YPOS );
  548.             
  549.                 /* notify parent of new selection */
  550.                 lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  551.                 SendMessage(PARENT,WM_COMMAND,ID,lprgbEntry[RANGE+CHOICE]);
  552.                 GlobalUnlock( TABLE );
  553.             
  554.             }
  555.             
  556.         }
  557.         
  558.         break;
  559.     case WM_LBUTTONUP : /* left button released */
  560.  
  561.         /* release capture if active */
  562.         if ( CAPTURE ) {
  563.             SET_CAPTURE( FALSE );
  564.             ReleaseCapture();
  565.         }            
  566.  
  567.         break;
  568.     case WM_KILLFOCUS : /* kill focus - hide caret */
  569.         DestroyCaret();
  570.         break;
  571.     case RM_SETSEL : /* select a color entry */
  572.         {
  573.             LONG FAR *        lprgbEntry;            
  574.     
  575.             /* update selection & redraw rainbow */
  576.             SET_CHOICE( (wParam >= RANGE) ? 0 : wParam );
  577.             InvalidateRect( hWnd, NULL, TRUE );
  578.         
  579.             /* notify parent of change in color */
  580.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  581.             SendMessage( PARENT, WM_COMMAND, ID, lprgbEntry[RANGE+CHOICE] );
  582.             GlobalUnlock( TABLE );
  583.  
  584.             /* return new choice */
  585.             lResult = CHOICE;
  586.  
  587.         }
  588.         break;
  589.     case RM_GETSEL : /* retrieve selected color */
  590.         {
  591.             LONG FAR *        lprgbEntry;            
  592.     
  593.             /* return selected entry */
  594.             lResult = CHOICE;
  595.  
  596.             /* define selected color */
  597.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );
  598.             *(LONG FAR *)lParam = lprgbEntry[RANGE+CHOICE];
  599.             GlobalUnlock( TABLE );
  600.  
  601.         }
  602.         break;
  603.     case RM_SETCOLORS : /* define rainbow color table */
  604.         {
  605.             WORD            wEntry;
  606.             HANDLE        hrgbList;
  607.             RECT            rectClient;
  608.             LONG FAR *    lprgbEntry;
  609.     
  610.             /* release previous table from memory */
  611.             GlobalFree( TABLE );
  612.     
  613.             hrgbList = GlobalAlloc(    GMEM_MOVEABLE,    sizeof(LONG)*wParam*2L);        
  614.             if ( hrgbList ) {
  615.             
  616.                 /* define initial rgb colors & values */
  617.                 lprgbEntry = (LONG FAR *)GlobalLock( hrgbList );        
  618.                 for ( wEntry=0; wEntry < wParam; wEntry++ ) {
  619.                     lprgbEntry[wEntry] = ((LONG FAR*)lParam)[wEntry];        
  620.                     lprgbEntry[wParam+wEntry] = ((LONG FAR*)lParam)[wParam+wEntry];
  621.                 }    
  622.                 GlobalUnlock( hrgbList );
  623.             
  624.                 /* retrieve current window dimensions */
  625.                 GetClientRect( hWnd, &rectClient );
  626.  
  627.                 /* re-define instance variables */
  628.                 SET_RANGE( wParam );
  629.                 SET_TABLE( hrgbList );
  630.                 SET_WIDTH( (rectClient.right-rectClient.left)/wParam );
  631.                 SET_HEIGHT( rectClient.bottom-rectClient.top );
  632.                 SET_CHOICE( 0 );
  633.     
  634.                 /* update window & notify parent of new selection */
  635.                 InvalidateRect( hWnd, NULL, TRUE );
  636.                 SendMessage( PARENT, WM_COMMAND, ID, lprgbEntry[RANGE+CHOICE] );
  637.  
  638.                 /* normal return */
  639.                 lResult = wParam;
  640.         
  641.             } else
  642.                 lResult = -1L;
  643.  
  644.         }
  645.         break;
  646.     case RM_GETCOLORS : /* retrieve rainbow color table */
  647.         {
  648.             WORD            wEntry;      
  649.             LONG FAR *    lprgbEntry;
  650.  
  651.             /* retrieve number of colors */
  652.             lResult = RANGE;
  653.     
  654.             /* retrieve rgb color list */
  655.             lprgbEntry = (LONG FAR *)GlobalLock( TABLE );        
  656.             for ( wEntry=0; (wEntry < RANGE)&&(wEntry < wParam); wEntry++ ) {
  657.                 ((LONG FAR *)lParam)[wEntry] = lprgbEntry[wEntry];        
  658.                 ((LONG FAR *)lParam)[RANGE+wEntry] = lprgbEntry[RANGE+wEntry];
  659.             }
  660.             GlobalUnlock( TABLE );
  661.     
  662.         }
  663.         break;
  664.     case WM_DESTROY : /* window being destroyed */
  665.         GlobalFree( TABLE );        
  666.         break;
  667.     default : /* default window message processing */
  668.         lResult = DefWindowProc( hWnd, wMsg, wParam, lParam );
  669.         break;
  670.     }
  671.     
  672.     /* return final result */
  673.     return( lResult );
  674.  
  675. }
  676.  
  677. /* */
  678.  
  679. /*
  680.  * RainbowDlgFn( hDlg, wMessage, wParam, lParam ) : BOOL;
  681.  *
  682.  *    hDlg           dialog box handle
  683.  *    wMessage       current window message
  684.  *    wParam         word parameter
  685.  *    lParam         long parameter
  686.  *
  687.  * This function is responsible for processing all the messages that
  688.  * relate to the style dialog box.  This function transfers data 
  689.  * between itself and the RainbowStyle using a global data handle.
  690.  *
  691.  * If the user presses the OK button, this data handle is used to pass
  692.  * back a new style data block.  It is left to the calling routine to
  693.  * delete this new block.
  694.  *
  695.  */
  696.  
  697. BOOL FAR PASCAL RainbowDlgFn(
  698.     HWND        hDlg,
  699.     WORD        wMessage,
  700.     WORD        wParam,
  701.     LONG        lParam )
  702. {
  703.     BOOL            bResult;
  704.  
  705.     /* initialization */
  706.     bResult = TRUE;
  707.  
  708.     /* process message */
  709.     switch( wMessage )
  710.         {
  711.     case WM_INITDIALOG :
  712.         {
  713.             HANDLE        hCtlStyle;
  714.             LPCTLSTYLE    lpCtlStyle;
  715.             char            szId[  20 ];    /* temp. string to hold id */
  716.  
  717.             /* disable Ok button & save dialog data handle */
  718.             hCtlStyle = hLibData;
  719.             EnableWindow( GetDlgItem(hDlg,IDOK), FALSE );
  720.  
  721.             /* retrieve & display style parameters */
  722.             if ( hCtlStyle ) {
  723.  
  724.                 /* add handle to property list */
  725.                 SetProp( hDlg, MAKEINTRESOURCE(1), hCtlStyle );
  726.                 
  727.                 /* update dialog box fields */
  728.                 lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
  729.                 SetDlgItemText( hDlg, IDTEXT, lpCtlStyle->szTitle );
  730.  
  731.                 /* Kanhom Ng 2/7/89 
  732.                  * Set the id value string correctly.
  733.                  * Save the pointer to the verify id function from dialog editor
  734.                  */
  735.                 if ( lpfnIdStr )
  736.                 {
  737.                     (*lpfnIdStr)(lpCtlStyle->wId, (LPSTR)szId, sizeof( szId ) );
  738.                     SetDlgItemText( hDlg, IDVALUE, szId );
  739.                 }
  740.                 else
  741.                 {
  742.                     EnableWindow( GetDlgItem( hDlg, IDVALUE ), FALSE );
  743.                 }
  744.                 lstrcpy( lpCtlStyle->szClass, RAINBOWCLASS );
  745.                 SetProp( hDlg, IDFNHI, HIWORD( (DWORD)lpfnVerId ) );
  746.                 SetProp( hDlg, IDFNLO, LOWORD( (DWORD)lpfnVerId ) );
  747.  
  748.                 GlobalUnlock( hCtlStyle );
  749.                     
  750.             } else
  751.                 EndDialog( hDlg, FALSE );
  752.             
  753.         }
  754.         break;
  755.     case WM_COMMAND :
  756.  
  757.         /* process sub-message */
  758.         switch( wParam )
  759.             {
  760.         case IDCANCEL : /* cancel dialog box */
  761.             RemoveProp( hDlg, MAKEINTRESOURCE(1) );
  762.             RemoveProp( hDlg, IDFNLO );
  763.             RemoveProp( hDlg, IDFNHI );
  764.             EndDialog( hDlg, FALSE );
  765.             break;
  766.         case IDOK : /* save dialog changes */
  767.             {
  768.                 HANDLE        hCtlStyle;
  769.                 LPCTLSTYLE    lpCtlStyle;
  770.                 LPFNSTRTOID      lpfnId;          /* pointer to the verify id function from dialog editor */
  771.                 char            szId[ 20 ];        /* temp. string to hold the id */
  772.  
  773.                 hCtlStyle = GetProp( hDlg, MAKEINTRESOURCE(1) );
  774.  
  775.                 /* update structure contents */
  776.                 lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
  777.  
  778.                 szId[ 0 ] = NULL;
  779.                 GetDlgItemText( hDlg, IDVALUE, szId, sizeof(szId) );
  780.                 lpfnId = (LPFNSTRTOID)MAKELONG( GetProp( hDlg, IDFNLO ), GetProp( hDlg, IDFNHI ) );
  781.                 if ( lpfnId )
  782.                 {
  783.                     DWORD        dwResult; /* result ofthe verifyId function */
  784.  
  785.                     dwResult = (*lpfnId)( (LPSTR)szId );
  786.                     if ( !(BOOL)dwResult )
  787.                     {
  788.                         /* Wrong id */
  789.                         GlobalUnlock( hCtlStyle );
  790.                         break;        
  791.                     }
  792.  
  793.                     lpCtlStyle->wId = HIWORD( dwResult );
  794.                 }
  795.                         
  796.                 GetDlgItemText( hDlg, IDTEXT, lpCtlStyle->szTitle, sizeof(lpCtlStyle->szTitle) );
  797.                 GlobalUnlock( hCtlStyle );
  798.  
  799.                 RemoveProp( hDlg, MAKEINTRESOURCE(1) );
  800.                 RemoveProp( hDlg, IDFNLO );
  801.                 RemoveProp( hDlg, IDFNHI );
  802.             
  803.                 /* end dialog box */
  804.                 hLibData = hCtlStyle;
  805.                 EndDialog( hDlg, TRUE );
  806.  
  807.             }
  808.             break;
  809.         case IDTEXT : /* control text */
  810.         case IDVALUE : /* control id */
  811.  
  812.             /* enable or disable Ok button */
  813.             if ( HIWORD(lParam) == EN_CHANGE )
  814.                 EnableWindow(
  815.                     GetDlgItem(hDlg,IDOK),
  816.                     (SendMessage(GetDlgItem(hDlg,IDTEXT),WM_GETTEXTLENGTH,0,0L) &&
  817.                      SendMessage(GetDlgItem(hDlg,IDVALUE),WM_GETTEXTLENGTH,0,0L)) ? TRUE : FALSE
  818.                 );
  819.  
  820.             break;
  821.         default : /* something else */
  822.             bResult = FALSE;
  823.             break;
  824.         }
  825.  
  826.         break;
  827.     default :
  828.         bResult = FALSE;
  829.         break;
  830.     }
  831.  
  832.     /* return final result */
  833.     return( bResult );
  834.  
  835. }
  836.  
  837. /* */
  838.  
  839. /*
  840.  * DrawSelector( hWnd, hDC ) : void;
  841.  *
  842.  *        hWnd            window handle
  843.  *        hDC            handle to display context
  844.  *
  845.  *    This function is responsible for drawing the selector
  846.  * which surrounds the active color patch.  This drawing
  847.  * process involves the use of the R2_NOT operator to
  848.  * simplify the drawing & re-drawing process.
  849.  *
  850.  */
  851.  
  852. void static DrawSelector( hWnd, hDC )
  853.     HWND            hWnd;
  854.     HDC            hDC;
  855. {
  856.     /* local variables */
  857.     HANDLE        hOldPen;                    /* old pen */
  858.     WORD            wOldROP2;                /* old raster op code */
  859.     WORD            wOldBkMode;                /* old background mode */
  860.     
  861.     /* setup display context */
  862.     wOldROP2 = SetROP2( hDC, R2_NOT );
  863.     wOldBkMode = SetBkMode( hDC, TRANSPARENT );
  864.  
  865.     hOldPen = SelectObject( hDC, CreatePen(0,1,RGB(0,0,0)) );
  866.     
  867.     /* draw selector rectangle */
  868.     Rectangle(
  869.         hDC,
  870.         SELECTOR_XPOS,
  871.         SELECTOR_YPOS,
  872.         SELECTOR_XPOS+SELECTOR_WIDTH,
  873.         SELECTOR_YPOS+SELECTOR_HEIGHT
  874.     );
  875.  
  876.     DeleteObject( SelectObject(hDC,hOldPen) );
  877.  
  878.     /* restore display context */
  879.     SetBkMode( hDC, wOldBkMode );
  880.     SetROP2( hDC, wOldROP2 );
  881.  
  882. }
  883.