BTTNCUR.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:31k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * BTTNCUR.C
- * Buttons & Cursors Version 1.1, March 1993
- *
- * Public functions to generate different states of toolbar buttons from
- * a single bitmap. States are normal, pressed, checked, and disabled.
- *
- * Copyright (c)1992-1996 Microsoft Corporation, All Rights Reserved,
- * as applied to redistribution of this source code in source form
- * License is granted to use of compiled code in shipped binaries.
- */
- #define STRICT
- #include <windows.h>
- #include <memory.h>
- #include "bttncur.h"
- #include "bttncuri.h"
- //Display sensitive information
- TOOLDISPLAYDATA tdd;
- //Library instance
- HINSTANCE ghInst;
- /*
- 23/1/94 (kerenm)
- Add intance count for 32bit dll
- */
- int cInstances = 0;
- //Cache GDI objects to speed drawing.
- HDC hDCGlyphs = NULL;
- HDC hDCMono = NULL;
- HBRUSH hBrushDither = NULL;
- //Standard images to use in case caller doesn't provide them
- HBITMAP rghBmpStandardImages[3];
- //Standard button colors.
- const COLORREF crStandard[4]={ RGB(0, 0, 0) //STDCOLOR_BLACK
- , RGB(128, 128, 128) //STDCOLOR_DKGRAY
- , RGB(192, 192, 192) //STDCOLOR_LTGRAY
- , RGB(255, 255, 255)}; //STDCOLOR_WHITE
- /*
- * Mapping from image identifier to button type (command/attribute).
- * Version 1.00 of this DLL has no attribute images defined, so
- * the code will only support three states for each command
- * button. Any state is, however, valid for an application
- * defined image.
- */
- UINT mpButtonType[TOOLIMAGE_MAX-TOOLIMAGE_MIN+1]=
- {
- BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND,
- BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND,
- BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND, BUTTONTYPE_COMMAND
- };
- /*
- * LibMain
- *
- * Purpose:
- * DLL-specific entry point called from LibEntry. Initializes
- * global variables and loads standard image bitmaps.
- *
- * Parameters:
- * hInstance HANDLE instance of the DLL.
- * wDataSeg WORD segment selector of the DLL's data segment.
- * wHeapSize WORD byte count of the heap.
- * lpCmdLine LPSTR to command line used to start the module.
- *
- * Return Value:
- * HANDLE Instance handle of the DLL.
- */
- BOOL xxxLibMain(HINSTANCE hInstance)
- {
- int i;
- /*
- 23/1/94 (kerenm)
- For WIN32S - should done only once. On NT ghInst is instance dataso it will
- always be zero.
- */
- #ifdef WIN32
- if (ghInst) {
- return(TRUE);
- }
- #endif
- ghInst=hInstance;
- tdd.uDPI =96;
- tdd.cyBar =CYBUTTONBAR96;
- tdd.cxButton =TOOLBUTTON_STD96WIDTH;
- tdd.cyButton =TOOLBUTTON_STD96HEIGHT;
- tdd.cxImage =TOOLBUTTON_STD96IMAGEWIDTH;
- tdd.cyImage =TOOLBUTTON_STD96IMAGEHEIGHT;
- tdd.uIDImages=IDB_STANDARDIMAGES96;
- for (i=0; i < 3; i++)
- {
- rghBmpStandardImages[i]=LoadBitmap(hInstance
- , MAKEINTRESOURCE(IDB_STANDARDIMAGESMIN+i));
- if (NULL==rghBmpStandardImages[i])
- return FALSE;
- }
- //Perform global initialization.
- if (ToolButtonInit())
- {
- CursorsCache(hInstance);
- return TRUE;
- }
- return FALSE;
- }
- #ifdef WIN32
- void FAR PASCAL WEP(int);
- BOOL WINAPI DllMain
- (
- HINSTANCE hInstance,
- ULONG Reason,
- PCONTEXT Context
- )
- {
- OutputDebugString("bttncur LibMain: bttncur.dll loadedrn");
- UNREFERENCED_PARAMETER(Context);
- if (Reason == DLL_PROCESS_DETACH) {
- #ifdef WIN32
- if (!--cInstances) {
- WEP(0);
- }
- #else
- WEP(0);
- #endif
- return TRUE;
- }
- else if (Reason != DLL_PROCESS_ATTACH)
- return TRUE;
- /* 1/23/94 */
- #ifdef WIN32
- cInstances++;
- #endif
- return xxxLibMain(hInstance);
- }
- #else
- HANDLE FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg
- , WORD cbHeapSize, LPSTR lpCmdLine)
- {
- //Perform global initialization.
- if (xxxLibMain(hInstance))
- if (0!=cbHeapSize)
- UnlockData(0);
- return hInstance;
- }
- #endif
- /*
- * WEP
- *
- * Purpose:
- * Required DLL Exit function. Does nothing.
- *
- * Parameters:
- * bSystemExit BOOL indicating if the system is being shut
- * down or the DLL has just been unloaded.
- *
- * Return Value:
- * void
- *
- */
- void FAR PASCAL WEP(int bSystemExit)
- {
- /*
- * **Developers: Note that WEP is called AFTER Windows does any
- * automatic task cleanup. You may see warnings for
- * that two DCs, a bitmap, and a brush, were not
- * deleted before task termination. THIS IS NOT A
- * PROBLEM WITH THIS CODE AND IT IS NOT A BUG. This
- * WEP function is properly called and performs the
- * cleanup as appropriate. The fact that Windows is
- * calling WEP after checking task cleanup is not
- * something we can control. Just to prove it, the
- * OutputDebugStrings in this and ToolButtonFree
- * show that the code is exercised.
- */
- #ifdef DEBUG
- OutputDebugString ("BttnCur WEP Entryrn");
- #endif
- CursorsFree();
- ToolButtonFree();
- #ifdef DEBUG
- OutputDebugString ("BttnCur WEP Exitrn");
- #endif
- return;
- }
- /*
- * UIToolConfigureForDisplay
- * Public API
- *
- * Purpose:
- * Initializes the library to scale button images for the display type.
- * Without calling this function the library defaults to 96 DPI (VGA).
- * By calling this function an application acknowledges that it must
- * use the data returned from this function to configure itself for
- * the display.
- *
- * Parameters:
- * lpDD LPTOOLDISPLAYDATA to fill with the display-sensitive
- * size values.
- *
- * Return Value:
- * BOOL TRUE if the sizes were obtained, FALSE otherwise.
- */
- BOOL WINAPI UIToolConfigureForDisplay(LPTOOLDISPLAYDATA lpDD)
- {
- int cy;
- HDC hDC;
- if (NULL==lpDD || IsBadWritePtr(lpDD, sizeof(TOOLDISPLAYDATA)))
- return FALSE;
- /*
- * Determine the aspect ratio of the display we're currently
- * running on and calculate the necessary information.
- *
- * By retrieving the logical Y extent of the display driver, you
- * only have limited possibilities:
- * LOGPIXELSY Display
- * ----------------------------------------
- * 48 CGA (unsupported)
- * 72 EGA
- * 96 VGA
- * 120 8514/a (i.e. HiRes VGA)
- */
- hDC=GetDC(NULL);
- if (NULL==hDC)
- return FALSE;
- cy=GetDeviceCaps(hDC, LOGPIXELSY);
- ReleaseDC(NULL, hDC);
- /*
- * Instead of single comparisons, check ranges instead, so in case
- * we get something funky, we'll act reasonable.
- */
- if (72 >=cy)
- {
- lpDD->uDPI =72;
- lpDD->cyBar =CYBUTTONBAR72;
- lpDD->cxButton =TOOLBUTTON_STD72WIDTH;
- lpDD->cyButton =TOOLBUTTON_STD72HEIGHT;
- lpDD->cxImage =TOOLBUTTON_STD72IMAGEWIDTH;
- lpDD->cyImage =TOOLBUTTON_STD72IMAGEHEIGHT;
- lpDD->uIDImages=IDB_STANDARDIMAGES72;
- }
- else
- {
- if (72 < cy && 120 > cy)
- {
- lpDD->uDPI =96;
- lpDD->cyBar =CYBUTTONBAR96;
- lpDD->cxButton =TOOLBUTTON_STD96WIDTH;
- lpDD->cyButton =TOOLBUTTON_STD96HEIGHT;
- lpDD->cxImage =TOOLBUTTON_STD96IMAGEWIDTH;
- lpDD->cyImage =TOOLBUTTON_STD96IMAGEHEIGHT;
- lpDD->uIDImages=IDB_STANDARDIMAGES96;
- }
- else
- {
- lpDD->uDPI =120;
- lpDD->cyBar =CYBUTTONBAR120;
- lpDD->cxButton =TOOLBUTTON_STD120WIDTH;
- lpDD->cyButton =TOOLBUTTON_STD120HEIGHT;
- lpDD->cxImage =TOOLBUTTON_STD120IMAGEWIDTH;
- lpDD->cyImage =TOOLBUTTON_STD120IMAGEHEIGHT;
- lpDD->uIDImages=IDB_STANDARDIMAGES120;
- }
- }
- return TRUE;
- }
- /*
- * ToolButtonInit
- * Internal
- *
- * Purpose:
- * Initializes GDI objects for drawing images through UIToolButtonDraw.
- * If the function fails, the function has already performed proper
- * cleanup.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * BOOL TRUE if initialization succeeded. FALSE otherwise.
- */
- static BOOL ToolButtonInit(void)
- {
- COLORREF rgbHi;
- //DC for BitBltting the image (the glyph)
- hDCGlyphs=CreateCompatibleDC(NULL);
- //Create a monochrome DC and a brush for doing pattern dithering.
- hDCMono=CreateCompatibleDC(NULL);
- //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white.
- if (0x0300 < (UINT)GetVersion())
- rgbHi=GetSysColor(COLOR_BTNHIGHLIGHT);
- else
- rgbHi=crStandard[STDCOLOR_WHITE];
- hBrushDither=HBrushDitherCreate(GetSysColor(COLOR_BTNFACE), rgbHi);
- if (NULL==hDCGlyphs || NULL==hDCMono || NULL==hBrushDither)
- {
- //On failure, cleanup whatever might have been allocated.
- ToolButtonFree();
- return FALSE;
- }
- return TRUE;
- }
- /*
- * ToolButtonFree
- * Internal
- *
- * Purpose:
- * Free all GDI allocations made during initialization. Note that the
- * DEBUG output included here shows that WEP is called and cleanup actually
- * occurs. However, if you watch debug output in DBWIN or on a terminal,
- * the debugging version of Windows does automatic app cleanup before WEP
- * is called, leading some to believe that this code is buggy. The
- * debug output below shows that we do perform all necessary cleanup.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * None
- */
- static void ToolButtonFree(void)
- {
- UINT i;
- if (NULL!=hDCMono)
- DeleteDC(hDCMono);
- hDCMono=NULL;
- if (NULL!=hDCGlyphs)
- DeleteDC(hDCGlyphs);
- hDCGlyphs=NULL;
- if (NULL!=hBrushDither)
- DeleteObject(hBrushDither);
- hBrushDither=NULL;
- for (i=0; i < 3; i++)
- {
- if (NULL!=rghBmpStandardImages[i])
- DeleteObject(rghBmpStandardImages[i]);
- rghBmpStandardImages[i]=NULL;
- }
- return;
- }
- /*
- * HBrushDitherCreate
- * Internal
- *
- * Purpose:
- * Creates and returns a handle to a pattern brush created from
- * an 8*8 monochrome pattern bitmap. We use the button face and
- * highlight colors to indicate the resulting colors of a PatBlt
- * using this brush.
- *
- * Parameters:
- * rgbFace COLORREF of the button face color.
- * rgbHilight COLORREF of the button highlight color.
- *
- * Return Value:
- * HBITMAP Handle to the dither bitmap.
- */
- static HBRUSH HBrushDitherCreate(COLORREF rgbFace, COLORREF rgbHilight)
- {
- struct //BITMAPINFO with 16 colors
- {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[16];
- } bmi;
- HBRUSH hBrush=NULL;
- DWORD patGray[8];
- HDC hDC;
- HBITMAP hBmp;
- static COLORREF rgbFaceOld =0xFFFFFFFF; //Initially an impossible color
- static COLORREF rgbHilightOld=0xFFFFFFFF; //so at first we always create
- /*
- * If the colors haven't changed from last time, just return the
- * existing brush.
- */
- if (rgbFace==rgbFaceOld && rgbHilight==rgbHilightOld)
- return hBrushDither;
- rgbFaceOld=rgbFace;
- rgbHilightOld=rgbHilight;
- /*
- * We're going to create an 8*8 brush for PatBlt using the
- * button face color and button highlight color. We use this
- * brush to affect the pressed state and the disabled state.
- */
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = 8;
- bmi.bmiHeader.biHeight = 8;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 1;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = 0;
- bmi.bmiHeader.biXPelsPerMeter= 0;
- bmi.bmiHeader.biYPelsPerMeter= 0;
- bmi.bmiHeader.biClrUsed = 0;
- bmi.bmiHeader.biClrImportant = 0;
- bmi.bmiColors[0].rgbBlue = GetBValue(rgbFace);
- bmi.bmiColors[0].rgbGreen = GetGValue(rgbFace);
- bmi.bmiColors[0].rgbRed = GetRValue(rgbFace);
- bmi.bmiColors[0].rgbReserved = 0;
- bmi.bmiColors[1].rgbBlue = GetBValue(rgbHilight);
- bmi.bmiColors[1].rgbGreen = GetGValue(rgbHilight);
- bmi.bmiColors[1].rgbRed = GetRValue(rgbHilight);
- bmi.bmiColors[1].rgbReserved = 0;
- //Create the byte array for CreateDIBitmap.
- patGray[6]=patGray[4]=patGray[2]=patGray[0]=0x5555AAAAL;
- patGray[7]=patGray[5]=patGray[3]=patGray[1]=0xAAAA5555L;
- //Create the bitmap
- hDC=GetDC(NULL);
- hBmp=CreateDIBitmap(hDC, &bmi.bmiHeader, CBM_INIT, patGray
- , (LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
- ReleaseDC(NULL, hDC);
- //Create the brush from the bitmap
- if (NULL!=hBmp)
- {
- hBrush=CreatePatternBrush(hBmp);
- DeleteObject(hBmp);
- }
- /*
- * If we could recreate a brush, clean up and make it the current
- * pattern. Otherwise the best we can do it return the old one,
- * which will be colored wrong, but at least it works.
- */
- if (NULL!=hBrush)
- {
- if (NULL!=hBrushDither)
- DeleteObject(hBrushDither);
- hBrushDither=hBrush;
- }
- return hBrushDither;
- }
- /*
- * UIToolButtonDraw
- * Public API
- *
- * Purpose:
- * Draws the complete image of a toolbar-style button with a given
- * image in the center and in a specific state. The button is drawn
- * on a specified hDC at a given location, so this function is useful
- * on standard owner-draw buttons as well as on toolbar controls that
- * have only one window but show images of multiple buttons.
- *
- * Parameters:
- * hDC HDC on which to draw.
- * x, y int coordinates at which to draw.
- * dx, dy int dimensions of the *button*, not necessarily the image.
- * hBmp HBITMAP from which to draw the image.
- * bmx, bmy int dimensions of each bitmap in hBmp. If hBmp is NULL
- * then these are forced to the standard sizes.
- * iImage int index to the image to draw in the button
- * uStateIn UINT containing the state index for the button and the
- * color control bits.
- *
- * Return Value:
- * BOOL TRUE if drawing succeeded, FALSE otherwise meaning that
- * hDC is NULL or hBmp is NULL and iImage is not a valid
- * index for a standard image.
- */
- BOOL WINAPI UIToolButtonDraw(HDC hDC, int x, int y, int dx, int dy
- , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn)
- {
- return UIToolButtonDrawTDD(hDC, x, y, dx, dy, hBmp, bmx, bmy, iImage
- , uStateIn, &tdd);
- }
- /*
- * UIToolButtonDrawTDD
- * Public API
- *
- * Purpose:
- * Draws the complete image of a toolbar-style button with a given
- * image in the center and in a specific state. The button is drawn
- * on a specified hDC at a given location, so this function is useful
- * on standard owner-draw buttons as well as on toolbar controls that
- * have only one window but show images of multiple buttons.
- *
- * This is the same as UIToolButtonDraw but adds the pTDD configuration
- * structure. UIToolButtonDraw calls us with that pointing to the
- * default 96dpi structure.
- *
- * Parameters:
- * hDC HDC on which to draw.
- * x, y int coordinates at which to draw.
- * dx, dy int dimensions of the *button*, not necessarily the image.
- * hBmp HBITMAP from which to draw the image.
- * bmx, bmy int dimensions of each bitmap in hBmp. If hBmp is NULL
- * then these are forced to the standard sizes.
- * iImage int index to the image to draw in the button
- * uStateIn UINT containing the state index for the button and the
- * color control bits.
- * pTDD LPTOOLDISPLAYDATA containing display configuration.
- * Can be NULL if hBmp is non-NULL.
- *
- * Return Value:
- * BOOL TRUE if drawing succeeded, FALSE otherwise meaning that
- * hDC is NULL or hBmp is NULL and iImage is not a valid
- * index for a standard image.
- */
- BOOL WINAPI UIToolButtonDrawTDD(HDC hDC, int x, int y, int dx, int dy
- , HBITMAP hBmp, int bmx, int bmy, int iImage, UINT uStateIn
- , LPTOOLDISPLAYDATA pTDD)
- {
- static COLORREF crSys[5]; //Avoid stack arrays in DLLs: use static
- UINT uState=(UINT)LOBYTE((WORD)uStateIn);
- UINT uColors=(UINT)HIBYTE((WORD)uStateIn & PRESERVE_ALL);
- int xOffsetGlyph, yOffsetGlyph;
- int i, iSaveDC;
- HDC hMemDC;
- HGDIOBJ hObj;
- HBRUSH hBR;
- HBITMAP hBmpT;
- HBITMAP hBmpMono;
- HBITMAP hBmpMonoOrg;
- HBITMAP hBmpSave=NULL;
- if (NULL==hDC)
- return FALSE;
- /*
- * If we're given no image bitmap, then use the standard and validate the
- * image index. We also enforce the standard bitmap size and the size of
- * the button (as requested by User Interface designers).
- */
- if (NULL==hBmp && !(uState & BUTTONGROUP_BLANK))
- {
- hBmp=rghBmpStandardImages[pTDD->uIDImages-IDB_STANDARDIMAGESMIN];
- bmx=pTDD->cxImage; //Force bitmap dimensions
- bmy=pTDD->cyImage;
- dx=pTDD->cxButton; //Force button dimensions
- dy=pTDD->cyButton;
- if (iImage > TOOLIMAGE_MAX)
- return FALSE;
- /*
- * If we are using a standard command button, verify that the state
- * does not contain the LIGHTFACE group which only applies to
- * attribute buttons.
- */
- if (BUTTONTYPE_COMMAND==mpButtonType[iImage]
- && (uState & BUTTONGROUP_LIGHTFACE))
- return FALSE;
- }
- //Create a dithered bitmap.
- hBmpMono=CreateBitmap(dx-2, dy-2, 1, 1, NULL);
- if (NULL==hBmpMono)
- return FALSE;
- hBmpMonoOrg=(HBITMAP)SelectObject(hDCMono, hBmpMono);
- //Save the DC state before we munge on it.
- iSaveDC=SaveDC(hDC);
- /*
- * Draw a button sans image. This also fills crSys with the system
- * colors for us which has space for five colors. We don't use the
- * fifth, the frame color, in this function.
- */
- DrawBlankButton(hDC, x, y, dx, dy, (BOOL)(uState & BUTTONGROUP_DOWN), crSys);
- //Shift coordinates to account for the button's border
- x++;
- y++;
- dx-=2;
- dy-=2;
- /*
- * Determine the offset necessary to center the image but also reflect
- * the pushed-in state, which means just adding 1 to the up state.
- */
- i=(uState & BUTTONGROUP_DOWN) ? 1 : 0;
- xOffsetGlyph=((dx-bmx) >> 1)+i;
- yOffsetGlyph=((dy-bmy) >> 1)+i;
- //Select the given image bitmap into the glyph DC before calling MaskCreate
- if (NULL!=hBmp)
- hBmpSave=(HBITMAP)SelectObject(hDCGlyphs, hBmp);
- /*
- * Draw the face on the button. If we have an up or [mouse]down
- * button then we can just draw it as-is. For indeterminate,
- * disabled, or down disabled we have to gray the image and possibly
- * add a white shadow to it (disabled/down disabled).
- *
- * Also note that for the intermediate state we first draw the normal
- * up state, then proceed to add disabling looking highlights.
- */
- //Up, mouse down, down, indeterminate
- if ((uState & BUTTONGROUP_ACTIVE) && !(uState & BUTTONGROUP_BLANK))
- {
- BOOL fColorsSame=TRUE;
- /*
- * In here we pay close attention to the system colors. Where
- * the source image is black, we paint COLOR_BTNTEXT. Where
- * light gray, we paint COLOR_BTNFACE. Where dark gray we paint
- * COLOR_BTNSHADOW, and where white we paint COLOR_BTNHILIGHT.
- *
- * The uColors variable contains flags to prevent color
- * conversion. To do a little optimization, we just do a
- * single BitBlt if we're preserving all colors or if no colors
- * are different than the standards, which is by far the most
- * common case. Otherwise, cycle through the four colors we can
- * convert and do a BitBlt that converts it to the system color.
- */
- //See what colors are different.
- for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++)
- fColorsSame &= (crSys[i]==crStandard[i]);
- if (PRESERVE_ALL==uColors || fColorsSame)
- {
- BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, bmx, bmy
- , hDCGlyphs, iImage*bmx, 0, SRCCOPY);
- }
- else
- {
- /*
- * Cycle through hard-coded colors and create a mask that has all
- * regions of that color in white and all other regions black.
- * Then we select a pattern brush of the color to convert to:
- * if we aren't converting the color then we use a brush of
- * the standard hard-coded color, otherwise we use the actual
- * system color. The ROP_DSPDxax means that anything that's
- * 1's in the mask get the pattern, anything that's 0 is unchanged
- * in the destination.
- *
- * To prevent too many Blts to the screen, we use an intermediate
- * bitmap and DC.
- */
- hMemDC=CreateCompatibleDC(hDC);
- //Make sure conversion of monochrome to color stays B&W
- SetTextColor(hMemDC, 0L); //0's in mono -> 0
- SetBkColor(hMemDC, (COLORREF)0x00FFFFFF); //1's in mono -> 1
- hBmpT=CreateCompatibleBitmap(hDC, bmx, bmy);
- SelectObject(hMemDC, hBmpT);
- //Copy the unmodified bitmap to the temporary bitmap
- BitBlt(hMemDC, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
- for (i=STDCOLOR_BLACK; i<=STDCOLOR_WHITE; i++)
- {
- //Convert pixels of the color to convert to 1's in the mask
- SetBkColor(hDCGlyphs, crStandard[i]);
- BitBlt(hDCMono, 0, 0, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
- //Preserve or modify the color depending on the flag.
- hBR=CreateSolidBrush((uColors & (1 << i))
- ? crStandard[i] : crSys[i]);
- if (NULL!=hBR)
- {
- hObj=SelectObject(hMemDC, hBR);
- if (NULL!=hObj)
- {
- BitBlt(hMemDC, 0, 0, dx-1, dy-1, hDCMono, 0, 0, ROP_DSPDxax);
- SelectObject(hMemDC, hObj);
- }
- DeleteObject(hBR);
- }
- }
- //Now put the final version on the display and clean up
- BitBlt(hDC, x+xOffsetGlyph, y+yOffsetGlyph, dx-1, dy-1
- , hMemDC, 0, 0, SRCCOPY);
- DeleteDC(hMemDC);
- DeleteObject(hBmpT);
- }
- }
- //Disabled and indeterminate states (unless we're blank)
- if ((uState & BUTTONGROUP_DISABLED || ATTRIBUTEBUTTON_INDETERMINATE==uState)
- && !(uState & BUTTONGROUP_BLANK))
- {
- //Grayed state (up or down, no difference)
- MaskCreate(iImage, dx, dy, bmx, bmy, xOffsetGlyph, yOffsetGlyph, 0);
- //Make sure conversion of monochrome to color stays B&W
- SetTextColor(hDC, 0L); //0's in mono -> 0
- SetBkColor(hDC, (COLORREF)0x00FFFFFF); //1's in mono -> 1
- //If we're disabled, up or down, draw the highlighted shadow.
- if (uState & BUTTONGROUP_DISABLED)
- {
- hBR=CreateSolidBrush(crSys[SYSCOLOR_HILIGHT]);
- if (NULL!=hBR)
- {
- hObj=SelectObject(hDC, hBR);
- if (NULL!=hObj)
- {
- //Draw hilight color where we have 0's in the mask
- BitBlt(hDC, x+1, y+1, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax);
- SelectObject(hDC, hObj);
- }
- DeleteObject(hBR);
- }
- }
- //Draw the gray image.
- hBR=CreateSolidBrush(crSys[SYSCOLOR_SHADOW]);
- if (NULL!=hBR)
- {
- hObj=SelectObject(hDC, hBR);
- if (NULL!=hObj)
- {
- //Draw the shadow color where we have 0's in the mask
- BitBlt(hDC, x, y, dx-2, dy-2, hDCMono, 0, 0, ROP_PSDPxax);
- SelectObject(hDC, hObj);
- }
- DeleteObject(hBR);
- }
- }
- //If the button is selected do the dither brush avoiding the glyph
- if (uState & BUTTONGROUP_LIGHTFACE)
- {
- HBRUSH hBRDither;
- /*
- * Get the dither brush. This function will recreate it if
- * necessary or return the global one if the colors already match.
- */
- hBRDither=HBrushDitherCreate(crSys[SYSCOLOR_FACE], crSys[SYSCOLOR_HILIGHT]);
- hObj=SelectObject(hDC, hBRDither);
- if (NULL!=hObj)
- {
- /*
- * The mask we create now determines where the dithering
- * ends up. In the down disabled state, we have to preserve
- * the highlighted shadow, so the mask we create must have
- * two masks of the original glyph, one of them offset by
- * one pixel in both x & y. For the indeterminate state,
- * we have to mask all highlighted areas. The state passed
- * to MaskCreate matters here (we've used zero before).
- */
- MaskCreate(iImage, dx, dy, bmx, bmy
- , xOffsetGlyph-1, yOffsetGlyph-1, uState);
- //Convert monochrome masks to B&W color bitmap in the BitBlt.
- SetTextColor(hDC, 0L);
- SetBkColor(hDC, (COLORREF)0x00FFFFFF);
- /*
- * Only draw the dither brush where the mask is 1's. For
- * the indeterminate state we have to not overdraw the
- * shadow highlight so we use dx-3, dy-3 instead of dx-1
- * and dy-1. We do this whether or not we're blank.
- */
- i=(ATTRIBUTEBUTTON_INDETERMINATE==uState
- || BLANKBUTTON_INDETERMINATE==uState) ? 3 : 1;
- BitBlt(hDC, x+1, y+1, dx-i, dy-i, hDCMono, 0, 0, ROP_DSPDxax);
- SelectObject(hDC, hObj);
- }
- //DO NOT delete hBRDither! It's a reference to a shared global.
- }
- //Cleanup hDCGlyphs: Must do AFTER calling MaskCreate
- if (NULL!=hBmpSave)
- SelectObject(hDCGlyphs, hBmpSave);
- SelectObject(hDCMono, hBmpMonoOrg);
- DeleteObject(hBmpMono);
- //Restore everything in the DC.
- RestoreDC(hDC, iSaveDC);
- return TRUE;
- }
- /*
- * DrawBlankButton
- *
- * Purpose:
- * Draws a button with no face using the current system colors in either
- * an up or down state.
- *
- * Parameters:
- * hDC HDC on which to draw
- * x, y int coordinates where we start drawing
- * dx,dy int size of the button
- * fDown BOOL indicating the up or down state of the button
- * pcr COLORREF FAR * to five colors in which we store text,
- * shadow, face, highlight, and frame colors. This is
- * a matter of convenience for the caller, since we have
- * to load these colors anyway we might as well send them
- * back.
- *
- * Return Value:
- * None
- */
- static void DrawBlankButton(HDC hDC, int x, int y, int dx, int dy
- , BOOL fDown, COLORREF FAR *pcr)
- {
- //Get the current system colors for buttons.
- pcr[0]=GetSysColor(COLOR_BTNTEXT);
- pcr[1]=GetSysColor(COLOR_BTNSHADOW);
- pcr[2]=GetSysColor(COLOR_BTNFACE);
- //Windows 3.0 doesn't support COLOR_BTNHIGHLIGHT, so leave it white.
- if (0x0300 < (UINT)GetVersion())
- pcr[3]=GetSysColor(COLOR_BTNHIGHLIGHT);
- else
- pcr[3]=crStandard[STDCOLOR_WHITE];
- pcr[4]=GetSysColor(COLOR_WINDOWFRAME);
- //Draw the border around the button.
- PatB(hDC, x+1, y, dx-2, 1, pcr[4]);
- PatB(hDC, x+1, y+dy-1, dx-2, 1, pcr[4]);
- PatB(hDC, x, y+1, 1, dy-2, pcr[4]);
- PatB(hDC, x+dx-1, y+1, 1, dy-2, pcr[4]);
- //Shift coordinates to account for the border we just drew
- x++;
- y++;
- dx-=2;
- dy-=2;
- //Paint the interior grey as a default.
- PatB(hDC, x, y, dx, dy, pcr[2]);
- /*
- * Draw shadows and highlights. The DOWN grouping that contains
- * down, mouse down, and down disabled are drawn depressed. Up,
- * indeterminate, and disabled are drawn up.
- */
- if (fDown)
- {
- PatB(hDC, x, y, 1, dy, pcr[1]);
- PatB(hDC, x, y, dx, 1, pcr[1]);
- }
- else
- {
- //Normal button look.
- PatB(hDC, x, y, 1, dy-1, pcr[3]);
- PatB(hDC, x, y, dx-1, 1, pcr[3]);
- PatB(hDC, x+dx-1, y, 1, dy, pcr[1]);
- PatB(hDC, x, y+dy-1, dx, 1, pcr[1]);
- PatB(hDC, x+1+dx-3, y+1, 1, dy-2, pcr[1]);
- PatB(hDC, x+1, y+dy-2, dx-2, 1, pcr[1]);
- }
- return;
- }
- /*
- * PatB
- * Internal
- *
- * Purpose:
- * A more convenient PatBlt operation for drawing button borders and
- * highlights.
- *
- * Parameters:
- * hDC HDC on which to paint.
- * x, y int coordinates at which to paint.
- * dx, dy int dimensions of rectangle to paint.
- * rgb COLORREF to use as the background color.
- *
- * Return Value:
- * None
- */
- static void PatB(HDC hDC, int x, int y, int dx, int dy, COLORREF rgb)
- {
- RECT rc;
- SetBkColor(hDC, rgb);
- SetRect(&rc, x, y, x+dx, y+dy);
- ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
- }
- /*
- * MaskCreate
- * Internal
- *
- * Purpose:
- * Creates a monochrome mask bitmap of the given image at the given offset
- * in the global hDCMono. Anywhere in the image that you have the light
- * gray (STDCOLOR_LTGRAY) or the white highlight (STDCOLOR_WHITE) you get
- * get 1's. All other pixels are 0's
- *
- * Parameters:
- * iImage UINT index of the image for which to create a mask.
- * dx, dy int dimensions of the button.
- * bmx, bmy int dimensions of the bitmap to use.
- * xOffset int offset for x inside hDCMono where we paint.
- * yOffset int offset for y inside hDCMono where we paint.
- * uState UINT state of the image. Special cases are made
- * for ATTRIBUTEBUTTON_DOWNDISABLED and
- * ATTRIBUTEBUTTON_INDETERMINATE. In any case where you
- * do not want a special case, pass zero here, regardless
- * of the true button state.
- *
- * Return Value:
- * None
- */
- static void MaskCreate(UINT iImage, int dx, int dy, int bmx, int bmy
- ,int xOffset, int yOffset, UINT uState)
- {
- //Initalize whole area with zeros
- PatBlt(hDCMono, 0, 0, dx, dy, WHITENESS);
- if (uState & BUTTONGROUP_BLANK)
- return;
- //Convert face colored pixels to 1's. all others to black.
- SetBkColor(hDCGlyphs, crStandard[STDCOLOR_LTGRAY]);
- BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCCOPY);
- //In the indeterminate state, don't turn highlight's to 1's. Leave black.
- if (ATTRIBUTEBUTTON_INDETERMINATE!=uState)
- {
- //Convert highlight colored pixels to 1's and OR them with the previous.
- SetBkColor(hDCGlyphs, crStandard[STDCOLOR_WHITE]);
- BitBlt(hDCMono, xOffset, yOffset, bmx, bmy, hDCGlyphs, iImage*bmx, 0, SRCPAINT);
- }
- /*
- * For the down disabled state, AND this same mask with itself at an
- * offset of 1, which accounts for the highlight shadow.
- */
- if (ATTRIBUTEBUTTON_DOWNDISABLED==uState)
- BitBlt(hDCMono, 1, 1, dx-1, dy-1, hDCMono, 0, 0, SRCAND);
- return;
- }