Annotation of mstools/ole20/samples/bttncur/bttncur.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * BTTNCUR.C
                      3:  * Buttons & Cursors Version 1.1, March 1993
                      4:  *
                      5:  * Public functions to generate different states of toolbar buttons from
                      6:  * a single bitmap.  States are normal, pressed, checked, and disabled.
                      7:  *
                      8:  * Copyright (c)1992-1993 Microsoft Corporation, All Rights Reserved,
                      9:  * as applied to redistribution of this source code in source form
                     10:  * License is granted to use of compiled code in shipped binaries.
                     11:  */
                     12: 
                     13: #ifdef WIN32
                     14: #define _INC_OLE
                     15: #define __RPC_H__
                     16: #endif
                     17: 
                     18: 
                     19: #define STRICT
                     20: #include <windows.h>
                     21: #include <memory.h>
                     22: #include "bttncur.h"
                     23: #include "bttncuri.h"
                     24: 
                     25: 
                     26: 
                     27: //Display sensitive information
                     28: TOOLDISPLAYDATA     tdd;
                     29: 
                     30: //Library instance
                     31: HINSTANCE           ghInst;
                     32: 
                     33: 
                     34: //Cache GDI objects to speed drawing.
                     35: HDC     hDCGlyphs    = NULL;
                     36: HDC     hDCMono      = NULL;
                     37: HBRUSH  hBrushDither = NULL;
                     38: 
                     39: //Standard images to use in case caller doesn't provide them
                     40: HBITMAP rghBmpStandardImages[3];
                     41: 
                     42: //Standard button colors.
                     43: const COLORREF crStandard[4]={ RGB(0, 0, 0)          //STDCOLOR_BLACK
                     44:                              , RGB(128, 128, 128)    //STDCOLOR_DKGRAY
                     45:                              , RGB(192, 192, 192)    //STDCOLOR_LTGRAY
                     46:                              , RGB(255, 255, 255)};  //STDCOLOR_WHITE
                     47: 
                     48: 
                     49: /*
                     50:  * Mapping from image identifier to button type (command/attribute).
                     51:  * Version 1.00 of this DLL has no attribute images defined, so
                     52:  * the code will only support three states for each command
                     53:  * button.  Any state is, however, valid for an application
                     54:  * defined image.
                     55:  */
                     56: 
                     57: UINT mpButtonType[TOOLIMAGE_MAX-TOOLIMAGE_MIN+1]=
                     58:         {
                     59:         BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND,
                     60:         BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND,
                     61:         BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND
                     62:         };
                     63: 
                     64: 
                     65: 
                     66: 
                     67: /*
                     68:  * LibMain
                     69:  *
                     70:  * Purpose:
                     71:  *  DLL-specific entry point called from LibEntry.  Initializes
                     72:  *  global variables and loads standard image bitmaps.
                     73:  *
                     74:  * Parameters:
                     75:  *  hInstance       HANDLE instance of the DLL.
                     76:  *  wDataSeg        WORD segment selector of the DLL's data segment.
                     77:  *  wHeapSize       WORD byte count of the heap.
                     78:  *  lpCmdLine       LPSTR to command line used to start the module.
                     79:  *
                     80:  * Return Value:
                     81:  *  HANDLE          Instance handle of the DLL.
                     82:  */
                     83: 
                     84: BOOL xxxLibMain(HINSTANCE hInstance)
                     85:        {
                     86:         int i;
                     87: 
                     88:     ghInst=hInstance;
                     89: 
                     90:         tdd.uDPI     =96;
                     91:     tdd.cyBar    =CYBUTTONBAR96;
                     92:     tdd.cxButton =TOOLBUTTON_STD96WIDTH;
                     93:     tdd.cyButton =TOOLBUTTON_STD96HEIGHT;
                     94:     tdd.cxImage  =TOOLBUTTON_STD96IMAGEWIDTH;
                     95:     tdd.cyImage  =TOOLBUTTON_STD96IMAGEHEIGHT;
                     96:     tdd.uIDImages=IDB_STANDARDIMAGES96;
                     97: 
                     98:     for (i=0; i < 3; i++)
                     99:         {
                    100:         rghBmpStandardImages[i]=LoadBitmap(hInstance
                    101:             , MAKEINTRESOURCE(IDB_STANDARDIMAGESMIN+i));
                    102: 
                    103:         if (NULL==rghBmpStandardImages[i])
                    104:             return FALSE;
                    105:         }
                    106: 
                    107: 
                    108:     //Perform global initialization.
                    109:     if (ToolButtonInit())
                    110:         {
                    111:         CursorsCache(hInstance);
                    112: 
                    113: 
                    114:         return TRUE;
                    115:         }
                    116: 
                    117:     return FALSE;
                    118: 
                    119:        }
                    120: 
                    121: #ifdef WIN32
                    122: 
                    123: extern  BOOL WINAPI _CRT_INIT(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved);
                    124: extern  _cexit(void);
                    125: void FAR PASCAL WEP(int);
                    126:                                       
                    127: extern  BOOL __stdcall LibMain
                    128: (                       
                    129:     HINSTANCE hInstance,                    
                    130:     ULONG        Reason,                    
                    131:     PCONTEXT  Context                 
                    132: )
                    133: {
                    134:     OutputDebugString("bttncur LibMain:  bttncur.dll loaded\r\n");
                    135: 
                    136:     UNREFERENCED_PARAMETER(Context);
                    137: 
                    138:     if (Reason == DLL_PROCESS_DETACH) {
                    139: 
                    140:         _CRT_INIT(hInstance,Reason,NULL);
                    141:         WEP(0);
                    142:         return TRUE;
                    143:     }
                    144:     else if (Reason != DLL_PROCESS_ATTACH)
                    145:         return TRUE;
                    146: 
                    147:     if (!_CRT_INIT(hInstance,Reason,NULL))
                    148:          return FALSE;
                    149: 
                    150:         return xxxLibMain(hInstance);
                    151: 
                    152: }
                    153: 
                    154: #else
                    155: 
                    156: HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg
                    157:                           , WORD cbHeapSize, LPSTR lpCmdLine)
                    158:     {
                    159: 
                    160:         //Perform global initialization.
                    161:     if (xxxLibMain(hInstance))
                    162:         if (0!=cbHeapSize)
                    163:             UnlockData(0);
                    164: 
                    165:     return hInstance;
                    166: 
                    167:     }
                    168: 
                    169: #endif
                    170: 
                    171: 
                    172: /*
                    173:  * WEP
                    174:  *
                    175:  * Purpose:
                    176:  *  Required DLL Exit function.  Does nothing.
                    177:  *
                    178:  * Parameters:
                    179:  *  bSystemExit     BOOL indicating if the system is being shut
                    180:  *                  down or the DLL has just been unloaded.
                    181:  *
                    182:  * Return Value:
                    183:  *  void
                    184:  *
                    185:  */
                    186: 
                    187: void FAR PASCAL WEP(int bSystemExit)
                    188:     {
                    189:     /*
                    190:      * **Developers:  Note that WEP is called AFTER Windows does any
                    191:      *                automatic task cleanup.  You may see warnings for
                    192:      *                that two DCs, a bitmap, and a brush, were not
                    193:      *                deleted before task termination.  THIS IS NOT A
                    194:      *                PROBLEM WITH THIS CODE AND IT IS NOT A BUG.  This
                    195:      *                WEP function is properly called and performs the
                    196:      *                cleanup as appropriate.  The fact that Windows is
                    197:      *                calling WEP after checking task cleanup is not
                    198:      *                something we can control.  Just to prove it, the
                    199:      *                OutputDebugStrings in this and ToolButtonFree
                    200:      *                show that the code is exercised.
                    201:      */
                    202: 
                    203:    #ifdef DEBUG
                    204:     OutputDebugString("WEP Entry\r\n");
                    205:    #endif
                    206: 
                    207:     CursorsFree();
                    208:     ToolButtonFree();
                    209: 
                    210:    #ifdef DEBUG
                    211:     OutputDebugString("WEP Exit\r\n");
                    212:    #endif
                    213:     return;
                    214:     }
                    215: 
                    216: 
                    217: 
                    218: 
                    219: 
                    220: /*
                    221:  * UIToolConfigureForDisplay
                    222:  * Public API
                    223:  *
                    224:  * Purpose:
                    225:  *  Initializes the library to scale button images for the display type.
                    226:  *  Without calling this function the library defaults to 96 DPI (VGA).
                    227:  *  By calling this function an application acknowledges that it must
                    228:  *  use the data returned from this function to configure itself for
                    229:  *  the display.
                    230:  *
                    231:  * Parameters:
                    232:  *  lpDD            LPTOOLDISPLAYDATA to fill with the display-sensitive
                    233:  *                  size values.
                    234:  *
                    235:  * Return Value:
                    236:  *  BOOL            TRUE if the sizes were obtained, FALSE otherwise.
                    237:  */
                    238: 
                    239: BOOL WINAPI UIToolConfigureForDisplay(LPTOOLDISPLAYDATA lpDD)
                    240:     {
                    241:     int         cy;
                    242:     HDC         hDC;
                    243: 
                    244: 
                    245:     if (NULL==lpDD || IsBadWritePtr(lpDD, sizeof(TOOLDISPLAYDATA)))
                    246:         return FALSE;
                    247: 
                    248:     /*
                    249:      * Determine the aspect ratio of the display we're currently
                    250:      * running on and calculate the necessary information.
                    251:      *
                    252:      * By retrieving the logical Y extent of the display driver, you
                    253:      * only have limited possibilities:
                    254:      *      LOGPIXELSY      Display
                    255:      *      ----------------------------------------
                    256:      *         48             CGA    (unsupported)
                    257:      *         72             EGA
                    258:      *         96             VGA
                    259:      *        120             8514/a (i.e. HiRes VGA)
                    260:      */
                    261: 
                    262:     hDC=GetDC(NULL);
                    263: 
                    264:     if (NULL==hDC)
                    265:         return FALSE;
                    266: 
                    267:     cy=GetDeviceCaps(hDC, LOGPIXELSY);
                    268:     ReleaseDC(NULL, hDC);
                    269: 
                    270:     /*
                    271:      * Instead of single comparisons, check ranges instead, so in case
                    272:      * we get something funky, we'll act reasonable.
                    273:      */
                    274:     if (72 >=cy)
                    275:         {
                    276:         lpDD->uDPI     =72;
                    277:         lpDD->cyBar    =CYBUTTONBAR72;
                    278:         lpDD->cxButton =TOOLBUTTON_STD72WIDTH;
                    279:         lpDD->cyButton =TOOLBUTTON_STD72HEIGHT;
                    280:         lpDD->cxImage  =TOOLBUTTON_STD72IMAGEWIDTH;
                    281:         lpDD->cyImage  =TOOLBUTTON_STD72IMAGEHEIGHT;
                    282:         lpDD->uIDImages=IDB_STANDARDIMAGES72;
                    283:         }
                    284:     else
                    285:         {
                    286:         if (72 < cy && 120 > cy)
                    287:             {
                    288:             lpDD->uDPI     =96;
                    289:             lpDD->cyBar    =CYBUTTONBAR96;
                    290:             lpDD->cxButton =TOOLBUTTON_STD96WIDTH;
                    291:             lpDD->cyButton =TOOLBUTTON_STD96HEIGHT;
                    292:             lpDD->cxImage  =TOOLBUTTON_STD96IMAGEWIDTH;
                    293:             lpDD->cyImage  =TOOLBUTTON_STD96IMAGEHEIGHT;
                    294:             lpDD->uIDImages=IDB_STANDARDIMAGES96;
                    295:             }
                    296:         else
                    297:             {
                    298:             lpDD->uDPI     =120;
                    299:             lpDD->cyBar    =CYBUTTONBAR120;
                    300:             lpDD->cxButton =TOOLBUTTON_STD120WIDTH;
                    301:             lpDD->cyButton =TOOLBUTTON_STD120HEIGHT;
                    302:             lpDD->cxImage  =TOOLBUTTON_STD120IMAGEWIDTH;
                    303:             lpDD->cyImage  =TOOLBUTTON_STD120IMAGEHEIGHT;
                    304:             lpDD->uIDImages=IDB_STANDARDIMAGES120;
                    305:             }
                    306:         }
                    307: 
                    308:     return TRUE;
                    309:     }
                    310: 
                    311: 
                    312: 
                    313: 
                    314: 
                    315: 
                    316: 
                    317: 
                    318: /*
                    319:  * ToolButtonInit
                    320:  * Internal
                    321:  *
                    322:  * Purpose:
                    323:  *  Initializes GDI objects for drawing images through UIToolButtonDraw.
                    324:  *  If the function fails, the function has already performed proper
                    325:  *  cleanup.
                    326:  *
                    327:  * Parameters:
                    328:  *  None
                    329:  *
                    330:  * Return Value:
                    331:  *  BOOL            TRUE if initialization succeeded.  FALSE otherwise.
                    332:  */
                    333: 
                    334: static BOOL ToolButtonInit(void)
                    335:     {
                    336:     COLORREF        rgbHi;
                    337: 
                    338:     //DC for BitBltting the image (the glyph)
                    339:     hDCGlyphs=CreateCompatibleDC(NULL);
                    340: 
                    341:     //Create a monochrome DC and a brush for doing pattern dithering.
                    342:     hDCMono=CreateCompatibleDC(NULL);
                    343: 
                    344:     //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white.
                    345:     if (0x0300 < (UINT)GetVersion())
                    346:         rgbHi=GetSysColor(COLOR_BTNHIGHLIGHT);
                    347:     else
                    348:         rgbHi=crStandard[STDCOLOR_WHITE];
                    349: 
                    350:     hBrushDither=HBrushDitherCreate(GetSysColor(COLOR_BTNFACE), rgbHi);
                    351: 
                    352:     if (NULL==hDCGlyphs || NULL==hDCMono || NULL==hBrushDither)
                    353:         {
                    354:         //On failure, cleanup whatever might have been allocated.
                    355:         ToolButtonFree();
                    356:         return FALSE;
                    357:         }
                    358: 
                    359:     return TRUE;
                    360:     }
                    361: 
                    362: 
                    363: 
                    364: 
                    365: 
                    366: /*
                    367:  * ToolButtonFree
                    368:  * Internal
                    369:  *
                    370:  * Purpose:
                    371:  *  Free all GDI allocations made during initialization.  Note that the
                    372:  *  DEBUG output included here shows that WEP is called and cleanup actually
                    373:  *  occurs.  However, if you watch debug output in DBWIN or on a terminal,
                    374:  *  the debugging version of Windows does automatic app cleanup before WEP
                    375:  *  is called, leading some to believe that this code is buggy.  The
                    376:  *  debug output below shows that we do perform all necessary cleanup.
                    377:  *
                    378:  * Parameters:
                    379:  *  None
                    380:  *
                    381:  * Return Value:
                    382:  *  None
                    383:  */
                    384: 
                    385: static void ToolButtonFree(void)
                    386:     {
                    387:     UINT        i;
                    388: 
                    389:     if (NULL!=hDCMono)
                    390:         DeleteDC(hDCMono);
                    391:     hDCMono=NULL;
                    392: 
                    393: 
                    394:     if (NULL!=hDCGlyphs)
                    395:         DeleteDC(hDCGlyphs);
                    396:     hDCGlyphs=NULL;
                    397: 
                    398:     if (NULL!=hBrushDither)
                    399:         DeleteObject(hBrushDither);
                    400:     hBrushDither=NULL;
                    401: 
                    402:     for (i=0; i < 3; i++)
                    403:         {
                    404:         if (NULL!=rghBmpStandardImages[i])
                    405:             DeleteObject(rghBmpStandardImages[i]);
                    406:         rghBmpStandardImages[i]=NULL;
                    407:         }
                    408: 
                    409:     return;
                    410:     }
                    411: 
                    412: 
                    413: 
                    414: 
                    415: 
                    416: /*
                    417:  * HBrushDitherCreate
                    418:  * Internal
                    419:  *
                    420:  * Purpose:
                    421:  *  Creates and returns a handle to a pattern brush created from
                    422:  *  an 8*8 monochrome pattern bitmap.  We use the button face and
                    423:  *  highlight colors to indicate the resulting colors of a PatBlt
                    424:  *  using this brush.
                    425:  *
                    426:  * Parameters:
                    427:  *  rgbFace         COLORREF of the button face color.
                    428:  *  rgbHilight      COLORREF of the button highlight color.
                    429:  *
                    430:  * Return Value:
                    431:  *  HBITMAP         Handle to the dither bitmap.
                    432:  */
                    433: 
                    434: static HBRUSH HBrushDitherCreate(COLORREF rgbFace, COLORREF rgbHilight)
                    435:     {
                    436:     struct  //BITMAPINFO with 16 colors
                    437:         {
                    438:         BITMAPINFOHEADER    bmiHeader;
                    439:         RGBQUAD             bmiColors[16];
                    440:         } bmi;
                    441: 
                    442:     HBRUSH          hBrush=NULL;
                    443:     DWORD           patGray[8];
                    444:     HDC             hDC;
                    445:     HBITMAP         hBmp;
                    446:     static COLORREF rgbFaceOld   =0xFFFFFFFF;  //Initially an impossible color
                    447:     static COLORREF rgbHilightOld=0xFFFFFFFF;  //so at first we always create
                    448: 
                    449:     /*
                    450:      * If the colors haven't changed from last time, just return the
                    451:      * existing brush.
                    452:      */
                    453:     if (rgbFace==rgbFaceOld && rgbHilight==rgbHilightOld)
                    454:         return hBrushDither;
                    455: 
                    456:     rgbFaceOld=rgbFace;
                    457:     rgbHilightOld=rgbHilight;
                    458: 
                    459:     /*
                    460:      * We're going to create an 8*8 brush for PatBlt using the
                    461:      * button face color and button highlight color.  We use this
                    462:      * brush to affect the pressed state and the disabled state.
                    463:      */
                    464:     bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
                    465:     bmi.bmiHeader.biWidth        = 8;
                    466:     bmi.bmiHeader.biHeight       = 8;
                    467:     bmi.bmiHeader.biPlanes       = 1;
                    468:     bmi.bmiHeader.biBitCount     = 1;
                    469:     bmi.bmiHeader.biCompression  = BI_RGB;
                    470:     bmi.bmiHeader.biSizeImage    = 0;
                    471:     bmi.bmiHeader.biXPelsPerMeter= 0;
                    472:     bmi.bmiHeader.biYPelsPerMeter= 0;
                    473:     bmi.bmiHeader.biClrUsed      = 0;
                    474:     bmi.bmiHeader.biClrImportant = 0;
                    475: 
                    476:     bmi.bmiColors[0].rgbBlue     = GetBValue(rgbFace);
                    477:     bmi.bmiColors[0].rgbGreen    = GetGValue(rgbFace);
                    478:     bmi.bmiColors[0].rgbRed      = GetRValue(rgbFace);
                    479:     bmi.bmiColors[0].rgbReserved = 0;
                    480: 
                    481:     bmi.bmiColors[1].rgbBlue     = GetBValue(rgbHilight);
                    482:     bmi.bmiColors[1].rgbGreen    = GetGValue(rgbHilight);
                    483:     bmi.bmiColors[1].rgbRed      = GetRValue(rgbHilight);
                    484:     bmi.bmiColors[1].rgbReserved = 0;
                    485: 
                    486:     //Create the byte array for CreateDIBitmap.
                    487:     patGray[6]=patGray[4]=patGray[2]=patGray[0]=0x5555AAAAL;
                    488:     patGray[7]=patGray[5]=patGray[3]=patGray[1]=0xAAAA5555L;
                    489: 
                    490:     //Create the bitmap
                    491:     hDC=GetDC(NULL);
                    492:     hBmp=CreateDIBitmap(hDC, &bmi.bmiHeader, CBM_INIT, patGray
                    493:                         , (LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
                    494:     ReleaseDC(NULL, hDC);
                    495: 
                    496:     //Create the brush from the bitmap
                    497:     if (NULL!=hBmp)
                    498:         {
                    499:         hBrush=CreatePatternBrush(hBmp);
                    500:         DeleteObject(hBmp);
                    501:         }
                    502: 
                    503:     /*
                    504:      * If we could recreate a brush, clean up and make it the current
                    505:      * pattern.  Otherwise the best we can do it return the old one,
                    506:      * which will be colored wrong, but at least it works.
                    507:      */
                    508:     if (NULL!=hBrush)
                    509:         {
                    510:         if (NULL!=hBrushDither)
                    511:             DeleteObject(hBrushDither);
                    512: 
                    513:         hBrushDither=hBrush;
                    514:         }
                    515: 
                    516:     return hBrushDither;
                    517:     }
                    518: 
                    519: 
                    520: 
                    521: 
                    522: 
                    523: /*
                    524:  * UIToolButtonDraw
                    525:  * Public API
                    526:  *
                    527:  * Purpose:
                    528:  *  Draws the complete image of a toolbar-style button with a given
                    529:  *  image in the center and in a specific state.  The button is drawn
                    530:  *  on a specified hDC at a given location, so this function is useful
                    531:  *  on standard owner-draw buttons as well as on toolbar controls that
                    532:  *  have only one window but show images of multiple buttons.
                    533:  *
                    534:  * Parameters:
                    535:  *  hDC             HDC on which to draw.
                    536:  *  x, y            int coordinates at which to draw.
                    537:  *  dx, dy          int dimensions of the *button*, not necessarily the image.
                    538:  *  hBmp            HBITMAP from which to draw the image.
                    539:  *  bmx, bmy        int dimensions of each bitmap in hBmp.  If hBmp is NULL
                    540:  *                  then these are forced to the standard sizes.
                    541:  *  iImage          int index to the image to draw in the button
                    542:  *  uStateIn        UINT containing the state index for the button and the
                    543:  *                  color control bits.
                    544:  *
                    545:  * Return Value:
                    546:  *  BOOL            TRUE if drawing succeeded, FALSE otherwise meaning that
                    547:  *                  hDC is NULL or hBmp is NULL and iImage is not a valid
                    548:  *                  index for a standard image.
                    549:  */
                    550: 
                    551: BOOL WINAPI UIToolButtonDraw(HDC hDC, int x, int y, int dx, int dy
                    552:     , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn)
                    553:     {
                    554:     return UIToolButtonDrawTDD(hDC, x, y, dx, dy, hBmp, bmx, bmy, iImage
                    555:         , uStateIn, &tdd);
                    556:     }
                    557: 
                    558: 
                    559: 
                    560: 
                    561: 
                    562: 
                    563: /*
                    564:  * UIToolButtonDrawTDD
                    565:  * Public API
                    566:  *
                    567:  * Purpose:
                    568:  *  Draws the complete image of a toolbar-style button with a given
                    569:  *  image in the center and in a specific state.  The button is drawn
                    570:  *  on a specified hDC at a given location, so this function is useful
                    571:  *  on standard owner-draw buttons as well as on toolbar controls that
                    572:  *  have only one window but show images of multiple buttons.
                    573:  *
                    574:  *  This is the same as UIToolButtonDraw but adds the pTDD configuration
                    575:  *  structure.  UIToolButtonDraw calls us with that pointing to the
                    576:  *  default 96dpi structure.
                    577:  *
                    578:  * Parameters:
                    579:  *  hDC             HDC on which to draw.
                    580:  *  x, y            int coordinates at which to draw.
                    581:  *  dx, dy          int dimensions of the *button*, not necessarily the image.
                    582:  *  hBmp            HBITMAP from which to draw the image.
                    583:  *  bmx, bmy        int dimensions of each bitmap in hBmp.  If hBmp is NULL
                    584:  *                  then these are forced to the standard sizes.
                    585:  *  iImage          int index to the image to draw in the button
                    586:  *  uStateIn        UINT containing the state index for the button and the
                    587:  *                  color control bits.
                    588:  *  pTDD            LPTOOLDISPLAYDATA containing display configuration.
                    589:  *                  Can be NULL if hBmp is non-NULL.
                    590:  *
                    591:  * Return Value:
                    592:  *  BOOL            TRUE if drawing succeeded, FALSE otherwise meaning that
                    593:  *                  hDC is NULL or hBmp is NULL and iImage is not a valid
                    594:  *                  index for a standard image.
                    595:  */
                    596: 
                    597: BOOL WINAPI UIToolButtonDrawTDD(HDC hDC, int x, int y, int dx, int dy
                    598:     , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn
                    599:     , LPTOOLDISPLAYDATA pTDD)
                    600:     {
                    601:     static COLORREF crSys[5];  //Avoid stack arrays in DLLs: use static
                    602:     UINT            uState=(UINT)LOBYTE((WORD)uStateIn);
                    603:     UINT            uColors=(UINT)HIBYTE((WORD)uStateIn & PRESERVE_ALL);
                    604:     int             xOffsetGlyph, yOffsetGlyph;
                    605:     int             i, iSaveDC;
                    606:     HDC             hMemDC;
                    607:     HGDIOBJ         hObj;
                    608:     HBRUSH          hBR;
                    609:     HBITMAP         hBmpT;
                    610:     HBITMAP         hBmpMono;
                    611:     HBITMAP         hBmpMonoOrg;
                    612:     HBITMAP         hBmpSave=NULL;
                    613: 
                    614:     if (NULL==hDC)
                    615:         return FALSE;
                    616: 
                    617:     /*
                    618:      * If we're given no image bitmap, then use the standard and validate the
                    619:      * image index.  We also enforce the standard bitmap size and the size of
                    620:      * the button (as requested by User Interface designers).
                    621:      */
                    622:     if (NULL==hBmp && !(uState & BUTTONGROUP_BLANK))
                    623:         {
                    624:         hBmp=rghBmpStandardImages[pTDD->uIDImages-IDB_STANDARDIMAGESMIN];
                    625: 
                    626:         bmx=pTDD->cxImage;            //Force bitmap dimensions
                    627:         bmy=pTDD->cyImage;
                    628: 
                    629:         dx=pTDD->cxButton;            //Force button dimensions
                    630:         dy=pTDD->cyButton;
                    631: 
                    632:         if (iImage > TOOLIMAGE_MAX)
                    633:             return FALSE;
                    634: 
                    635:         /*
                    636:          * If we are using a standard command button, verify that the state
                    637:          * does not contain the LIGHTFACE group which only applies to
                    638:          * attribute buttons.
                    639:          */
                    640:         if (BUTTONTYPE_COMMAND==mpButtonType[iImage]
                    641:             && (uState & BUTTONGROUP_LIGHTFACE))
                    642:             return FALSE;
                    643:         }
                    644: 
                    645:     //Create a dithered bitmap.
                    646:     hBmpMono=CreateBitmap(dx-2, dy-2, 1, 1, NULL);
                    647: 
                    648:     if (NULL==hBmpMono)
                    649:         return FALSE;
                    650: 
                    651:     hBmpMonoOrg=(HBITMAP)SelectObject(hDCMono,  hBmpMono);
                    652: 
                    653: 
                    654:     //Save the DC state before we munge on it.
                    655:     iSaveDC=SaveDC(hDC);
                    656: 
                    657:     /*
                    658:      * Draw a button sans image.  This also fills crSys with the system
                    659:      * colors for us which has space for five colors.  We don't use the
                    660:      * fifth, the frame color, in this function.
                    661:      */
                    662:     DrawBlankButton(hDC, x, y, dx, dy, (BOOL)(uState & BUTTONGROUP_DOWN), crSys);
                    663: 
                    664:     //Shift coordinates to account for the button's border
                    665:     x++;
                    666:     y++;
                    667:     dx-=2;
                    668:     dy-=2;
                    669: 
                    670:     /*
                    671:      * Determine the offset necessary to center the image but also reflect
                    672:      * the pushed-in state, which means just adding 1 to the up state.
                    673:      */
                    674:     i=(uState & BUTTONGROUP_DOWN) ? 1 : 0;
                    675:     xOffsetGlyph=((dx-bmx) >> 1)+i;
                    676:     yOffsetGlyph=((dy-bmy) >> 1)+i;
                    677: 
                    678: 
                    679:     //Select the given image bitmap into the glyph DC before calling MaskCreate
                    680:     if (NULL!=hBmp)
                    681:         hBmpSave=(HBITMAP)SelectObject(hDCGlyphs, hBmp);
                    682: 
                    683: 
                    684:     /*
                    685:      * Draw the face on the button.  If we have an up or [mouse]down
                    686:      * button then we can just draw it as-is.  For indeterminate,
                    687:      * disabled, or down disabled we have to gray the image and possibly
                    688:      * add a white shadow to it (disabled/down disabled).
                    689:      *
                    690:      * Also note that for the intermediate state we first draw the normal
                    691:      * up state, then proceed to add disabling looking highlights.
                    692:      */
                    693: 
                    694:     //Up, mouse down, down, indeterminate
                    695:     if ((uState & BUTTONGROUP_ACTIVE) && !(uState & BUTTONGROUP_BLANK))
                    696:         {
                    697:         BOOL            fColorsSame=TRUE;
                    698: 
                    699:         /*
                    700:          * In here we pay close attention to the system colors.  Where
                    701:          * the source image is black, we paint COLOR_BTNTEXT.  Where
                    702:          * light gray, we paint COLOR_BTNFACE.  Where dark gray we paint
                    703:          * COLOR_BTNSHADOW, and where white we paint COLOR_BTNHILIGHT.
                    704:          *
                    705:          * The uColors variable contains flags to prevent color
                    706:          * conversion.  To do a little optimization, we just do a
                    707:          * single BitBlt if we're preserving all colors or if no colors
                    708:          * are different than the standards, which is by far the most
                    709:          * common case.  Otherwise, cycle through the four colors we can
                    710:          * convert and do a BitBlt that converts it to the system color.
                    711:          */
                    712: 
                    713:         //See what colors are different.
                    714:         for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++)
                    715:             fColorsSame &= (crSys[i]==crStandard[i]);
                    716: 
                    717:         if (PRESERVE_ALL==uColors || fColorsSame)
                    718:             {
                    719:             BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, bmx, bmy
                    720:                    , hDCGlyphs, iImage*bmx, 0, SRCCOPY);
                    721:             }
                    722:         else
                    723:             {
                    724:             /*
                    725:              * Cycle through hard-coded colors and create a mask that has all
                    726:              * regions of that color in white and all other regions black.
                    727:              * Then we select a pattern brush of the color to convert to:
                    728:              * if we aren't converting the color then we use a brush of
                    729:              * the standard hard-coded color, otherwise we use the actual
                    730:              * system color.  The ROP_DSPDxax means that anything that's
                    731:              * 1's in the mask get the pattern, anything that's 0 is unchanged
                    732:              * in the destination.
                    733:              *
                    734:              * To prevent too many Blts to the screen, we use an intermediate
                    735:              * bitmap and DC.
                    736:              */
                    737: 
                    738:             hMemDC=CreateCompatibleDC(hDC);
                    739: 
                    740:             //Make sure conversion of monochrome to color stays B&W
                    741:             SetTextColor(hMemDC, 0L);                     //0's in mono -> 0
                    742:             SetBkColor(hMemDC, (COLORREF)0x00FFFFFF);     //1's in mono -> 1
                    743: 
                    744:             hBmpT=CreateCompatibleBitmap(hDC, bmx, bmy);
                    745:             SelectObject(hMemDC, hBmpT);
                    746: 
                    747:             //Copy the unmodified bitmap to the temporary bitmap
                    748:             BitBlt(hMemDC, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
                    749: 
                    750:             for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++)
                    751:                 {
                    752:                 //Convert pixels of the color to convert to 1's in the mask
                    753:                 SetBkColor(hDCGlyphs, crStandard[i]);
                    754:                 BitBlt(hDCMono, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
                    755: 
                    756:                 //Preserve or modify the color depending on the flag.
                    757:                 hBR=CreateSolidBrush((uColors & (1 << i))
                    758:                                      ? crStandard[i] : crSys[i]);
                    759: 
                    760:                 if (NULL!=hBR)
                    761:                     {
                    762:                     hObj=SelectObject(hMemDC, hBR);
                    763: 
                    764:                     if (NULL!=hObj)
                    765:                         {
                    766:                         BitBlt(hMemDC, 0, 0, dx-1, dy-1, hDCMono, 0, 0, ROP_DSPDxax);
                    767:                         SelectObject(hMemDC, hObj);
                    768:                         }
                    769: 
                    770:                     DeleteObject(hBR);
                    771:                     }
                    772:                 }
                    773: 
                    774:             //Now put the final version on the display and clean up
                    775:             BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, dx-1, dy-1
                    776:                    , hMemDC, 0, 0, SRCCOPY);
                    777: 
                    778:             DeleteDC(hMemDC);
                    779:             DeleteObject(hBmpT);
                    780: 
                    781:             }
                    782:         }
                    783: 
                    784: 
                    785:     //Disabled and indeterminate states (unless we're blank)
                    786:     if ((uState & BUTTONGROUP_DISABLED || ATTRIBUTEBUTTON_INDETERMINATE==uState)
                    787:         && !(uState & BUTTONGROUP_BLANK))
                    788:         {
                    789:         //Grayed state (up or down, no difference)
                    790:         MaskCreate(iImage, dx, dy, bmx, bmy, xOffsetGlyph, yOffsetGlyph, 0);
                    791: 
                    792:         //Make sure conversion of monochrome to color stays B&W
                    793:         SetTextColor(hDC, 0L);                     //0's in mono -> 0
                    794:         SetBkColor(hDC, (COLORREF)0x00FFFFFF);     //1's in mono -> 1
                    795: 
                    796:         //If we're disabled, up or down, draw the highlighted shadow.
                    797:         if (uState & BUTTONGROUP_DISABLED)
                    798:             {
                    799:             hBR=CreateSolidBrush(crSys[SYSCOLOR_HILIGHT]);
                    800: 
                    801:             if (NULL!=hBR)
                    802:                 {
                    803:                 hObj=SelectObject(hDC, hBR);
                    804: 
                    805:                 if (NULL!=hObj)
                    806:                     {
                    807:                     //Draw hilight color where we have 0's in the mask
                    808:                     BitBlt(hDC, x+1, y+1, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax);
                    809:                     SelectObject(hDC, hObj);
                    810:                     }
                    811:                 DeleteObject(hBR);
                    812:                 }
                    813:             }
                    814: 
                    815:         //Draw the gray image.
                    816:         hBR=CreateSolidBrush(crSys[SYSCOLOR_SHADOW]);
                    817: 
                    818:         if (NULL!=hBR)
                    819:             {
                    820:             hObj=SelectObject(hDC, hBR);
                    821: 
                    822:             if (NULL!=hObj)
                    823:                 {
                    824:                 //Draw the shadow color where we have 0's in the mask
                    825:                 BitBlt(hDC, x, y, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax);
                    826:                 SelectObject(hDC, hObj);
                    827:                 }
                    828: 
                    829:             DeleteObject(hBR);
                    830:             }
                    831:         }
                    832: 
                    833:     //If the button is selected do the dither brush avoiding the glyph
                    834:     if (uState & BUTTONGROUP_LIGHTFACE)
                    835:         {
                    836:         HBRUSH      hBRDither;
                    837: 
                    838:         /*
                    839:          * Get the dither brush.  This function will recreate it if
                    840:          * necessary or return the global one if the colors already match.
                    841:          */
                    842:         hBRDither=HBrushDitherCreate(crSys[SYSCOLOR_FACE], crSys[SYSCOLOR_HILIGHT]);
                    843:         hObj=SelectObject(hDC, hBRDither);
                    844: 
                    845:         if (NULL!=hObj)
                    846:             {
                    847:             /*
                    848:              * The mask we create now determines where the dithering
                    849:              * ends up.  In the down disabled state, we have to preserve
                    850:              * the highlighted shadow, so the mask we create must have
                    851:              * two masks of the original glyph, one of them offset by
                    852:              * one pixel in both x & y.  For the indeterminate state,
                    853:              * we have to mask all highlighted areas.  The state passed
                    854:              * to MaskCreate matters here (we've used zero before).
                    855:              */
                    856:             MaskCreate(iImage, dx, dy, bmx, bmy
                    857:                        , xOffsetGlyph-1, yOffsetGlyph-1, uState);
                    858: 
                    859:             //Convert monochrome masks to B&W color bitmap in the BitBlt.
                    860:             SetTextColor(hDC, 0L);
                    861:             SetBkColor(hDC, (COLORREF)0x00FFFFFF);
                    862: 
                    863:             /*
                    864:              * Only draw the dither brush where the mask is 1's.  For
                    865:              * the indeterminate state we have to not overdraw the
                    866:              * shadow highlight so we use dx-3, dy-3 instead of dx-1
                    867:              * and dy-1.  We do this whether or not we're blank.
                    868:              */
                    869:             i=(ATTRIBUTEBUTTON_INDETERMINATE==uState
                    870:                || BLANKBUTTON_INDETERMINATE==uState) ? 3 : 1;
                    871: 
                    872:             BitBlt(hDC, x+1, y+1, dx-i, dy-i, hDCMono, 0, 0, ROP_DSPDxax);
                    873:             SelectObject(hDC, hObj);
                    874:             }
                    875: 
                    876:         //DO NOT delete hBRDither!  It's a reference to a shared global.
                    877:         }
                    878: 
                    879:     //Cleanup hDCGlyphs:  Must do AFTER calling MaskCreate
                    880:     if (NULL!=hBmpSave)
                    881:         SelectObject(hDCGlyphs, hBmpSave);
                    882: 
                    883:     SelectObject(hDCMono,   hBmpMonoOrg);
                    884:     DeleteObject(hBmpMono);
                    885: 
                    886:     //Restore everything in the DC.
                    887:     RestoreDC(hDC, iSaveDC);
                    888:     return TRUE;
                    889:     }
                    890: 
                    891: 
                    892: 
                    893: 
                    894: 
                    895: 
                    896: /*
                    897:  * DrawBlankButton
                    898:  *
                    899:  * Purpose:
                    900:  *  Draws a button with no face using the current system colors in either
                    901:  *  an up or down state.
                    902:  *
                    903:  * Parameters:
                    904:  *  hDC             HDC on which to draw
                    905:  *  x, y            int coordinates where we start drawing
                    906:  *  dx,dy           int size of the button
                    907:  *  fDown           BOOL indicating the up or down state of the button
                    908:  *  pcr             COLORREF FAR * to five colors in which we store text,
                    909:  *                  shadow, face, highlight, and frame colors.  This is
                    910:  *                  a matter of convenience for the caller, since we have
                    911:  *                  to load these colors anyway we might as well send them
                    912:  *                  back.
                    913:  *
                    914:  * Return Value:
                    915:  *  None
                    916:  */
                    917: 
                    918: static void DrawBlankButton(HDC hDC, int x, int y, int dx, int dy
                    919:     , BOOL fDown, COLORREF FAR *pcr)
                    920:     {
                    921:     //Get the current system colors for buttons.
                    922:     pcr[0]=GetSysColor(COLOR_BTNTEXT);
                    923:     pcr[1]=GetSysColor(COLOR_BTNSHADOW);
                    924:     pcr[2]=GetSysColor(COLOR_BTNFACE);
                    925: 
                    926:     //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white.
                    927:     if (0x0300 < (UINT)GetVersion())
                    928:         pcr[3]=GetSysColor(COLOR_BTNHIGHLIGHT);
                    929:     else
                    930:         pcr[3]=crStandard[STDCOLOR_WHITE];
                    931: 
                    932:     pcr[4]=GetSysColor(COLOR_WINDOWFRAME);
                    933: 
                    934:     //Draw the border around the button.
                    935:     PatB(hDC, x+1,    y,      dx-2, 1,    pcr[4]);
                    936:     PatB(hDC, x+1,    y+dy-1, dx-2, 1,    pcr[4]);
                    937:     PatB(hDC, x,      y+1,    1,    dy-2, pcr[4]);
                    938:     PatB(hDC, x+dx-1, y+1,    1,    dy-2, pcr[4]);
                    939: 
                    940:     //Shift coordinates to account for the border we just drew
                    941:     x++;
                    942:     y++;
                    943:     dx-=2;
                    944:     dy-=2;
                    945: 
                    946:     //Paint the interior grey as a default.
                    947:     PatB(hDC, x, y, dx, dy, pcr[2]);
                    948: 
                    949:     /*
                    950:      * Draw shadows and highlights.  The DOWN grouping that contains
                    951:      * down, mouse down, and down disabled are drawn depressed.  Up,
                    952:      * indeterminate, and disabled are drawn up.
                    953:      */
                    954: 
                    955:     if (fDown)
                    956:         {
                    957:         PatB(hDC, x, y, 1,  dy, pcr[1]);
                    958:         PatB(hDC, x, y, dx, 1,  pcr[1]);
                    959:         }
                    960:     else
                    961:         {
                    962:         //Normal button look.
                    963:         PatB(hDC, x, y, 1,    dy-1, pcr[3]);
                    964:         PatB(hDC, x, y, dx-1, 1,    pcr[3]);
                    965: 
                    966:         PatB(hDC, x+dx-1, y,      1,  dy, pcr[1]);
                    967:         PatB(hDC, x,      y+dy-1, dx, 1,  pcr[1]);
                    968: 
                    969:         PatB(hDC, x+1+dx-3, y+1,    1,    dy-2, pcr[1]);
                    970:         PatB(hDC, x+1,      y+dy-2, dx-2, 1,    pcr[1]);
                    971:         }
                    972: 
                    973:     return;
                    974:     }
                    975: 
                    976: 
                    977: 
                    978: 
                    979: 
                    980: 
                    981: /*
                    982:  * PatB
                    983:  * Internal
                    984:  *
                    985:  * Purpose:
                    986:  *  A more convenient PatBlt operation for drawing button borders and
                    987:  *  highlights.
                    988:  *
                    989:  * Parameters:
                    990:  *  hDC             HDC on which to paint.
                    991:  *  x, y            int coordinates at which to paint.
                    992:  *  dx, dy          int dimensions of rectangle to paint.
                    993:  *  rgb             COLORREF to use as the background color.
                    994:  *
                    995:  * Return Value:
                    996:  *  None
                    997:  */
                    998: 
                    999: static void PatB(HDC hDC, int x, int y, int dx, int dy, COLORREF rgb)
                   1000:     {
                   1001:     RECT        rc;
                   1002: 
                   1003:     SetBkColor(hDC, rgb);
                   1004:     SetRect(&rc, x, y, x+dx, y+dy);
                   1005:     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
                   1006:     }
                   1007: 
                   1008: 
                   1009: 
                   1010: 
                   1011: /*
                   1012:  * MaskCreate
                   1013:  * Internal
                   1014:  *
                   1015:  * Purpose:
                   1016:  *  Creates a monochrome mask bitmap of the given image at the given offset
                   1017:  *  in the global hDCMono.  Anywhere in the image that you have the light
                   1018:  *  gray (STDCOLOR_LTGRAY) or the white highlight (STDCOLOR_WHITE) you get
                   1019:  *  get 1's.  All other pixels are 0's
                   1020:  *
                   1021:  * Parameters:
                   1022:  *  iImage          UINT index of the image for which to create a mask.
                   1023:  *  dx, dy          int dimensions of the button.
                   1024:  *  bmx, bmy        int dimensions of the bitmap to use.
                   1025:  *  xOffset         int offset for x inside hDCMono where we paint.
                   1026:  *  yOffset         int offset for y inside hDCMono where we paint.
                   1027:  *  uState          UINT state of the image.  Special cases are made
                   1028:  *                  for ATTRIBUTEBUTTON_DOWNDISABLED and
                   1029:  *                  ATTRIBUTEBUTTON_INDETERMINATE.  In any case where you
                   1030:  *                  do not want a special case, pass zero here, regardless
                   1031:  *                  of the true button state.
                   1032:  *
                   1033:  * Return Value:
                   1034:  *  None
                   1035:  */
                   1036: 
                   1037: static void MaskCreate(UINT iImage, int dx, int dy, int bmx, int bmy
                   1038:     ,int xOffset, int yOffset, UINT uState)
                   1039:     {
                   1040:     //Initalize whole area with zeros
                   1041:     PatBlt(hDCMono, 0, 0, dx, dy, WHITENESS);
                   1042: 
                   1043:     if (uState & BUTTONGROUP_BLANK)
                   1044:         return;
                   1045: 
                   1046:     //Convert face colored pixels to 1's. all others to black.
                   1047:     SetBkColor(hDCGlyphs, crStandard[STDCOLOR_LTGRAY]);
                   1048:     BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
                   1049: 
                   1050:     //In the indeterminate state, don't turn highlight's to 1's. Leave black.
                   1051:     if (ATTRIBUTEBUTTON_INDETERMINATE!=uState)
                   1052:         {
                   1053:         //Convert highlight colored pixels to 1's and OR them with the previous.
                   1054:         SetBkColor(hDCGlyphs, crStandard[STDCOLOR_WHITE]);
                   1055:         BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCPAINT);
                   1056:         }
                   1057: 
                   1058:     /*
                   1059:      * For the down disabled state, AND this same mask with itself at an
                   1060:      * offset of 1, which accounts for the highlight shadow.
                   1061:      */
                   1062:     if (ATTRIBUTEBUTTON_DOWNDISABLED==uState)
                   1063:         BitBlt(hDCMono, 1, 1, dx-1, dy-1, hDCMono,  0, 0, SRCAND);
                   1064: 
                   1065:     return;
                   1066:     }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.