home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / route.cli / bitmap.c next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  17.1 KB  |  669 lines

  1. /*
  2.  -  B I T M A P . C
  3.  -
  4.  *  Purpose:
  5.  *      Bitmap and Listbox support functions for InBox in sample mail client.
  6.  *
  7.  *  Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
  8.  */
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #ifdef _WIN32
  15. #include <objerror.h>
  16. #include <objbase.h>
  17. #endif
  18. #ifdef WIN16
  19. #include <compobj.h>
  20. #endif
  21. #include <mapiwin.h>
  22. #include <mapidbg.h>
  23. #include <mapi.h>
  24. #include <mapix.h>
  25. #include "bitmap.h"
  26. #include "client.h"
  27.  
  28. // Fonts to use in dialogs
  29.  
  30. #ifdef _WIN32
  31. #define SHELL_FONT "MS Shell Dlg"
  32. #define SHELL_FONT_SIZE 8
  33. #else
  34. #define SHELL_FONT "MS Sans Serif"
  35. #define SHELL_FONT_SIZE 8
  36. #endif
  37.  
  38. /*
  39.  *  globals
  40.  */
  41.  
  42. DWORD   rgbWindowColor = 0xFF000000;    // variables for the current
  43. DWORD   rgbHiliteColor = 0xFF000000;    // system color settings.
  44. DWORD   rgbWindowText  = 0xFF000000;    // on a WM_SYSCOLORCHANGE
  45. DWORD   rgbHiliteText  = 0xFF000000;    // we check to see if we need
  46. DWORD   rgbGrayText    = 0xFF000000;    // to reload our bitmap.
  47. DWORD   rgbDDWindow    = 0xFF000000;    //
  48. DWORD   rgbDDHilite    = 0xFF000000;    // 0xFF000000 is an invalid RGB
  49.  
  50. // an array of integers containing the tab stops, in pixels. The tab 
  51. // stops must be sorted in ascending order; back tabs are not allowed. 
  52.  
  53. int     rgTabs[] = { 2, 28, 135, 292 };
  54. int     dxbmpLB, dybmpLB;   // dx and dy of listbox bmps
  55.  
  56. HDC     hdcMemory = 0;      // hdc to hold listbox bitmaps (for speed)
  57. HBITMAP hbmpOrigMemBmp = 0; // original null bitmap in hdcMemory
  58. HBITMAP hbmpLB = 0;         // cached listbox bitmaps
  59. HFONT   hfontLB = 0;        // hfont of LB
  60. HWND    hwndLB = 0;         // hwnd of LB
  61.  
  62. FONTSTYLE fontStyle = { SHELL_FONT_SIZE, FW_NORMAL, 0, TEXT(SHELL_FONT) };
  63.  
  64. extern HANDLE hInst;
  65.  
  66.  
  67. /*
  68.  -  DeInitBmps
  69.  -  
  70.  *  Purpose:
  71.  *      cleans up LB hfonts, hdc, and hbmps
  72.  */
  73.  
  74. VOID DeInitBmps(VOID)
  75. {
  76.     DeleteBitmapLB();
  77.     if(hdcMemory)
  78.     {
  79.         DeleteDC(hdcMemory);
  80.         hdcMemory = 0;
  81.     }
  82.  
  83.     if(hfontLB)
  84.     {
  85.         SetWindowFont(hwndLB, GetStockObject(SYSTEM_FONT), FALSE);
  86.         DeleteObject(hfontLB);
  87.         hfontLB = 0;
  88.     }
  89. }
  90.  
  91.  
  92. /*
  93.  -  SetLBFont
  94.  -  
  95.  *  Purpose:
  96.  *      creates a font from the global fontStyle
  97.  *      sets global hfontLB to new font and WM_SETFONTs
  98.  *      the hwndLB to the new font
  99.  */
  100.  
  101. VOID SetLBFont(VOID)
  102. {
  103.     LOGFONT lf;
  104.  
  105.     lf.lfHeight = fontStyle.lfHeight;
  106.     lf.lfWidth = 0;
  107.     lf.lfEscapement = 0;
  108.     lf.lfOrientation = 0;
  109.     lf.lfWeight = fontStyle.lfWeight;
  110.     lf.lfItalic = fontStyle.lfItalic;
  111.     lf.lfUnderline = 0;
  112.     lf.lfStrikeOut = 0;
  113.     lf.lfCharSet = ANSI_CHARSET;
  114.     lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  115.     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  116.     lf.lfQuality = DEFAULT_QUALITY;
  117.     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
  118.     lstrcpy(lf.lfFaceName, fontStyle.lfFaceName);
  119.  
  120.     hfontLB = CreateFontIndirect(&lf);
  121.     if(hfontLB)
  122.         SetWindowFont(hwndLB, hfontLB, FALSE);        
  123. }
  124.  
  125.  
  126. /*
  127.  -  InitBmps
  128.  -  
  129.  *  Purpose:
  130.  *      inits listbox globals, creates listbox
  131.  *  
  132.  *  Arguments:
  133.  *      HWND    main hwnd of app (parent of LB)
  134.  *  
  135.  *  Returns:
  136.  *      TRUE - success; FALSE - failed
  137.  */
  138.  
  139. BOOL InitBmps(HWND hwnd, int idLB)
  140. {
  141.     HDC     hdcScreen;
  142.     HBITMAP hbmpTemp;
  143.  
  144.     hdcScreen = GetDC(0);
  145.     if(!hdcScreen)
  146.         goto CantInit;
  147.     hdcMemory = CreateCompatibleDC(hdcScreen);
  148.     if(!hdcMemory)
  149.         goto ReleaseScreenDC;
  150.  
  151.     hbmpTemp = CreateCompatibleBitmap(hdcMemory, 1, 1);
  152.     if(!hbmpTemp)
  153.         goto ReleaseMemDC;
  154.     hbmpOrigMemBmp = SelectObject(hdcMemory, hbmpTemp); // get hbmp of NULL
  155.     if(!hbmpOrigMemBmp)                                 // bmp for hdcMemory
  156.         goto ReleaseMemDC;                              // for when we delete
  157.     SelectObject(hdcMemory, hbmpOrigMemBmp);            // it later in life
  158.     DeleteObject(hbmpTemp);
  159.     ReleaseDC(0, hdcScreen);
  160.  
  161.     SetRGBValues();     // set the global RGB values
  162.     LoadBitmapLB();     // load the bmps into hdcMemory
  163.  
  164.     hwndLB = GetDlgItem(hwnd, idLB);
  165.     
  166.     SetLBFont();    // set the font of our listbox
  167.     return TRUE;
  168.  
  169. /* Error recovery exits */
  170. ReleaseMemDC:
  171.     DeleteDC(hdcMemory);
  172.     hdcMemory = 0;
  173.  
  174. ReleaseScreenDC:
  175.     ReleaseDC(0, hdcScreen);
  176.  
  177. CantInit:
  178.     return FALSE;
  179. }
  180.  
  181.  
  182. /*
  183.  -  SetRGBValues
  184.  -  
  185.  *  Purpose:
  186.  *      To set various system colors in static variables.  Called at
  187.  *      init time and when system colors change.
  188.  */
  189.  
  190. VOID SetRGBValues(VOID)
  191. {
  192.     rgbWindowColor = GetSysColor(COLOR_WINDOW);
  193.     rgbHiliteColor = GetSysColor(COLOR_HIGHLIGHT);
  194.     rgbWindowText  = GetSysColor(COLOR_WINDOWTEXT);
  195.     rgbHiliteText  = GetSysColor(COLOR_HIGHLIGHTTEXT);
  196.     rgbGrayText    = GetSysColor(COLOR_GRAYTEXT);
  197. }
  198.  
  199.  
  200. /*
  201.  -  MeasureItem
  202.  -  
  203.  *  Purpose:
  204.  *      called from msg WM_MEASUREITEM: returns max dy of listbox items
  205.  *  
  206.  *  Arguments:
  207.  *      HWND        hwnd of main window
  208.  *      pmis        measureitemstruct from WM_MEASUREITEM call
  209.  */
  210.  
  211. VOID MeasureItem(HANDLE hwnd, LPMEASUREITEMSTRUCT pmis)
  212. {
  213.     HDC        hDC = GetDC(hwnd);
  214.     HANDLE     hFont = hfontLB;
  215.     TEXTMETRIC TM;
  216.  
  217.     if(!hFont)
  218.         hFont = GetStockObject(SYSTEM_FONT);
  219.     hFont = SelectObject(hDC, hFont);
  220.     GetTextMetrics(hDC, &TM);
  221.     SelectObject(hDC, hFont);
  222.     ReleaseDC(hwnd, hDC);
  223.  
  224.     // set the height to be max of (dyfont or dybitmap)
  225.     pmis->itemHeight = max(dybmpLB, TM.tmHeight);
  226. }
  227.  
  228.  
  229. /*
  230.  -  OutTextFormat
  231.  -  
  232.  *  Purpose:
  233.  *      to parse the string in the listbox and draw it accordingly:
  234.  *      first char == chBOLD: line is bold
  235.  *      first char == chUNDERLINE: line is underlined (can follow chBOLD)
  236.  *      char == chTAB: go to next column in rgTabs
  237.  *      '/001#': bitblt that numbered bitmap.
  238.  *      otherwise, outtext the line
  239.  *  
  240.  *  Arguments:
  241.  *      pDI     from DrawItem from WM_DRAWITEM msg
  242.  */
  243.  
  244. VOID OutTextFormat(LPDRAWITEMSTRUCT pDI)
  245. {
  246.     TCHAR   szDateRec[32];
  247.     TCHAR   szItem[256];
  248.     TCHAR   szTemp[4];
  249.     TCHAR   szDots[4] = {"..."};
  250.     TCHAR   *pch;
  251.     INT     nT;
  252.     INT     nTab = 0;           // current tab we is on
  253.     INT     nBmp;               // index of envelope bitmap
  254.     HFONT   hfDef = 0;
  255.     HFONT   hfOld = 0;          // bold or underlined font
  256.     TCHAR   *pchBuff = NULL;
  257.     LPMSGID lpMsgId = (LPMSGID)pDI->itemData;
  258.  
  259.     pch = szItem;
  260.  
  261.     // Format a string from the info in lpMsgNode
  262.     // First, calculate the index to the desired bitmap
  263.     
  264.     nBmp = ((!lpMsgId->fUnRead) * 2) + ((!!lpMsgId->fHasAttach) * 1 );
  265.  
  266.     // Convert our received date and build string
  267.     
  268.     ConvertDateRec (lpMsgId->lpszDateRec, szDateRec);
  269.  
  270.     // Limit our subject size
  271.     
  272.     szTemp[0] = '\0';
  273.     
  274.     if(lpMsgId->lpszSubject && (lstrlen(lpMsgId->lpszSubject) > 32))
  275.     {
  276.         memcpy(szTemp, &lpMsgId->lpszSubject[28], 4);
  277.         memcpy(&lpMsgId->lpszSubject[28], szDots, 4);
  278.     }
  279.     
  280.     wsprintf(szItem, "\001%d\t%s\t%s\t%s", nBmp, 
  281.             (lpMsgId->lpszFrom ? lpMsgId->lpszFrom : ""),
  282.             (lpMsgId->lpszSubject ? lpMsgId->lpszSubject : ""),
  283.             szDateRec);
  284.  
  285.     // erase background
  286.     ExtTextOut(pDI->hDC, 0, 0, ETO_OPAQUE, &pDI->rcItem, NULL, 0, NULL);
  287.  
  288.     // underline or bold this line?  Only check first & second char
  289.     if(*pch == chBOLD || *pch == chUNDERLINE)
  290.     {
  291.         LOGFONT     lf;
  292.  
  293.         hfOld = GetWindowFont(pDI->hwndItem);
  294.         if(!hfOld)
  295.             hfOld = GetStockObject(SYSTEM_FONT);
  296.         GetObject(hfOld, sizeof(lf), &lf);
  297.  
  298.         if(*pch == chBOLD)
  299.         {
  300.             lf.lfWeight = FW_BOLD;
  301.             pch++;
  302.         }
  303.         if(*pch == chUNDERLINE)
  304.         {
  305.             lf.lfUnderline = TRUE;
  306.             pch++;
  307.         }
  308.  
  309.         hfDef = CreateFontIndirect(&lf);
  310.         if(hfDef)
  311.             SelectObject(pDI->hDC, hfDef);
  312.     }
  313.  
  314.     // selected or nonselected bmps?
  315.     nT = (ODS_SELECTED & pDI->itemState) ? (BMWIDTH * NUMBMPS) : 0;
  316.  
  317.     // parse the string
  318.     for(; *pch; pch++)
  319.     {
  320.         TCHAR   *pchT;
  321.         RECT    rc;
  322.  
  323.         if(*pch == chBITMAP)     // do we have a bitmap?
  324.         {
  325.             ++pch;
  326.             // draw the bitmap
  327.             BitBlt(pDI->hDC, pDI->rcItem.left + rgTabs[nTab],
  328.                 pDI->rcItem.top, BMWIDTH, BMHEIGHT, hdcMemory,
  329.                 nT + (int)(*pch - TEXT('0')) * BMWIDTH, 0, SRCCOPY);
  330.             continue;
  331.         }
  332.  
  333.         if(*pch == chTAB)    // move to next tabstop?
  334.         {
  335.             nTab++;
  336.             continue;
  337.         }
  338.  
  339.         pchT = pch;     // find end of the column of text
  340.         while(*pchT && (*pchT != chTAB))
  341.             pchT++;
  342.  
  343.         // set rect to drawtext in
  344.         SetRect(&rc, pDI->rcItem.left + rgTabs[nTab], pDI->rcItem.top, 
  345.             pDI->rcItem.right, pDI->rcItem.bottom);
  346.  
  347.         // draw the text
  348.         ExtTextOut(pDI->hDC, rc.left, rc.top + 1, ETO_OPAQUE | ETO_CLIPPED,
  349.             &rc, pch, pchT - pch, NULL);
  350.         pch = pchT - 1; // move to end of this column
  351.     }
  352.  
  353.     if(hfDef)   // delete underline or bold font if we created it
  354.     {
  355.         SelectObject(pDI->hDC, hfOld);
  356.         DeleteObject(hfDef);
  357.     }
  358.  
  359.     if(szTemp[0] != '\0')
  360.     {
  361.         memcpy(&lpMsgId->lpszSubject[28], szTemp, 4);
  362.     }
  363. }
  364.  
  365.  
  366. /*
  367.  -  DrawItem
  368.  -
  369.  *  Purpose:
  370.  *      Handles WM_DRAWITEM for both drive and directory listboxes.
  371.  *
  372.  *  Parameters:
  373.  *      pDI     LPDRAWITEMSTRUCT passed from the WM_DRAWITEM message.
  374.  */
  375.  
  376. VOID DrawItem(LPDRAWITEMSTRUCT pDI)
  377. {
  378.     COLORREF    crText, crBack;
  379.  
  380.     if((int)pDI->itemID < 0)
  381.         return;
  382.  
  383.     if((ODA_DRAWENTIRE | ODA_SELECT) & pDI->itemAction)
  384.     {
  385.         if(pDI->itemState & ODS_SELECTED)
  386.         {
  387.             // Select the appropriate text colors
  388.             crText = SetTextColor(pDI->hDC, rgbHiliteText);
  389.             crBack = SetBkColor(pDI->hDC, rgbHiliteColor);
  390.         }
  391.  
  392.         // parse and spit out bmps and text
  393.         OutTextFormat(pDI);
  394.  
  395.         // Restore original colors if we changed them above.
  396.         if(pDI->itemState & ODS_SELECTED)
  397.         {
  398.             SetTextColor(pDI->hDC, crText);
  399.             SetBkColor(pDI->hDC,   crBack);
  400.         }
  401.     }
  402.  
  403.     if((ODA_FOCUS & pDI->itemAction) || (ODS_FOCUS & pDI->itemState))
  404.         DrawFocusRect(pDI->hDC, &pDI->rcItem);
  405. }
  406.  
  407.  
  408. /*
  409.  -  ConvertDateRec
  410.  -
  411.  *  Purpose:
  412.  *      To convert the lpszDateReceived field of a message to a
  413.  *      more paletable display format; namely: mm/dd/yy hh:mmAM.
  414.  *
  415.  *  Parameters:
  416.  *      lpszDateRec         - Original format
  417.  *      lpszDateDisplay     - Display format
  418.  */
  419.  
  420. VOID ConvertDateRec (LPSTR lpszDateRec, LPSTR lpszDateDisplay)
  421. {
  422.     char  szDateTmp[32];
  423.     LPSTR lpszYear;
  424.     LPSTR lpszMonth;
  425.     LPSTR lpszDay;
  426.     LPSTR lpszHour;
  427.     LPSTR lpszMinute;
  428.     int nHour;
  429.     static char szFoo[2][3] =
  430.     {"AM", "PM"};
  431.  
  432.     *lpszDateDisplay = 0;
  433.     if (!lpszDateRec || !*lpszDateRec)
  434.         return;
  435.  
  436.     lstrcpy(szDateTmp, lpszDateRec);
  437.  
  438.     lpszYear = strtok (szDateTmp, "/ :");
  439.     lpszMonth = strtok (NULL, "/ :");
  440.     lpszDay = strtok (NULL, "/ :");
  441.     lpszHour = strtok (NULL, "/ :");
  442.     lpszMinute = strtok (NULL, "/ :");
  443.  
  444.     if(lpszHour)
  445.         nHour = atoi (lpszHour);
  446.     else
  447.         nHour = 0;
  448.  
  449.     if (nHour > 12)
  450.         wsprintf (lpszHour, "%d", nHour - 12);
  451.  
  452.     wsprintf (lpszDateDisplay, "%s/%s/%s %s:%s%s", lpszMonth,
  453.         (lpszDay ? lpszDay : ""),
  454.         (lpszYear ? lpszYear : ""),
  455.         (lpszHour ? lpszHour : ""),
  456.         (lpszMinute ? lpszMinute : ""),
  457.         szFoo[(nHour > 11 ? 1 : 0)]);
  458. }
  459.  
  460.  
  461. /*
  462.  *  RgbInvertRgb
  463.  *  
  464.  *  Purpose:
  465.  *      To reverse the byte order of the RGB value (for file format
  466.  *  
  467.  *  Arguments:
  468.  *  
  469.  *  Returns:
  470.  *      New color value (RGB to BGR)
  471.  */
  472.  
  473. #define RgbInvertRgb(_rgbOld) \
  474.     (DWORD)RGB(GetBValue(_rgbOld), GetGValue(_rgbOld), GetRValue(_rgbOld))
  475.  
  476.  
  477. /*
  478.  *  LoadAlterBitmap (mostly stolen from commdlg)
  479.  *  
  480.  *  Purpose:
  481.  *      Loads the IDB_ENVELOPE bitmap and gives all the pixels that are
  482.  *      RGBREPLACE a new color.
  483.  *
  484.  *  Assumption:
  485.  *      This function will work on one bitmap during it's lifetime.
  486.  *      (Due to the fact that it finds RGBREPLACE once and then
  487.  *      operates on that offset whenever called again because under NT,
  488.  *      it appears that the bitmap is cached, so the second time you go
  489.  *      looking for RGBREPLACE, it won't be found.) You could load the
  490.  *      resource, copy it, then modify the copy as a workaround. But I
  491.  *      chose the cheap way out as I will only ever modify one bmp.
  492.  *  
  493.  *  Arguments:
  494.  *      rgbInstead  rgb value to replace defined RGBREPLACE with
  495.  *  
  496.  *  Returns:
  497.  *      NULL - failed or hbmp of new modified bitmap
  498.  */
  499.  
  500. HBITMAP LoadAlterBitmap(DWORD rgbInstead)
  501. {
  502.     HANDLE              hbmp = 0;
  503.     LPBITMAPINFOHEADER  qbihInfo;
  504.     HDC                 hdcScreen;
  505.     HRSRC               hresLoad;
  506.     HGLOBAL             hres;
  507.     LPBYTE              qbBits;
  508.     DWORD               rgbReplace = 0;
  509.     DWORD               *rgdw = NULL;
  510.     DWORD               *lpdw = NULL;
  511.     ULONG               cb = 0;
  512.     
  513.     if (rgbInstead)
  514.         rgbReplace = RGBREPLACE;
  515.  
  516.     // load our listbox bmps resource
  517.     hresLoad = FindResource(hInst, MAKEINTRESOURCE(IDB_ENVELOPE), RT_BITMAP);
  518.     if(hresLoad == 0)
  519.         return 0;
  520.     hres = LoadResource(hInst, hresLoad);
  521.     if(hres == 0)
  522.         return 0;
  523.  
  524.     rgbReplace = RgbInvertRgb(rgbReplace);
  525.     rgbInstead = RgbInvertRgb(rgbInstead);
  526.     qbihInfo = (LPBITMAPINFOHEADER)LockResource(hres);
  527.  
  528.     // Skip over the header structure
  529.     qbBits = (LPBYTE)(qbihInfo + 1);
  530.  
  531.     // Skip the color table entries, if any
  532.     qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD);
  533.  
  534.     // Copy the resource into writable memory so we can
  535.     // munge the color table to set our background color
  536.     cb = (ULONG)(qbBits - (LPBYTE)qbihInfo) + qbihInfo->biSizeImage;
  537.     rgdw = (DWORD *)GlobalAllocPtr(GMEM_MOVEABLE, cb);
  538.     
  539.     CopyMemory((LPVOID)rgdw, (LPVOID)qbihInfo, cb);
  540.     
  541.     // find the color to replace in the color table
  542.     for(lpdw = (DWORD *)((LPBYTE)rgdw + qbihInfo->biSize); ; lpdw++)
  543.     {
  544.         if(*lpdw == rgbReplace)
  545.             break;
  546.     }
  547.  
  548.     // replace that color value with our new one
  549.     *lpdw = (DWORD)rgbInstead;
  550.  
  551.     // Create a color bitmap compatible with the display device
  552.     hdcScreen = GetDC(0);
  553.     if(hdcScreen != 0)
  554.     {
  555.         hbmp = CreateDIBitmap(hdcScreen, (LPBITMAPINFOHEADER)rgdw, 
  556.                 (LONG)CBM_INIT, qbBits, (LPBITMAPINFO) rgdw, DIB_RGB_COLORS);
  557.         ReleaseDC(0, hdcScreen);
  558.     }
  559.  
  560.     UnlockResource(hres);
  561.     FreeResource(hres);
  562.  
  563.     GlobalFreePtr(rgdw);
  564.     
  565.     return hbmp;
  566. }
  567.  
  568.  
  569. /*
  570.  *  DeleteBitmapLB
  571.  *  
  572.  *  Purpose:
  573.  *      Get rid of hbmpLB, if it exists
  574.  */
  575.  
  576. VOID DeleteBitmapLB(VOID)
  577. {
  578.     if(hbmpOrigMemBmp)
  579.     {
  580.         SelectObject(hdcMemory, hbmpOrigMemBmp);
  581.         if(hbmpLB != 0)
  582.         {
  583.             DeleteObject(hbmpLB);
  584.             hbmpLB = 0;
  585.         }
  586.     }
  587. }
  588.  
  589.  
  590. /*
  591.  *  LoadBitmapLB (mostly stolen from commdlg)
  592.  *  
  593.  *  Purpose:
  594.  *      Creates the listbox bitmap. If an appropriate bitmap
  595.  *      already exists, it just returns immediately.  Otherwise, it
  596.  *      loads the bitmap and creates a larger bitmap with both regular
  597.  *      and highlight colors.
  598.  *
  599.  *  Returns:
  600.  *      TRUE - success; FALSE - failure
  601.  */
  602.  
  603. BOOL LoadBitmapLB(VOID)
  604. {
  605.     BITMAP  bmp;
  606.     HANDLE  hbmp, hbmpOrig;
  607.     HDC     hdcTemp;
  608.     BOOL    bWorked = FALSE;
  609.  
  610.     // check for existing bitmap and validity
  611.     if( (hbmpLB != 0) &&
  612.         (rgbWindowColor == rgbDDWindow) &&
  613.         (rgbHiliteColor == rgbDDHilite))
  614.     {
  615.         if(SelectObject(hdcMemory, hbmpLB))
  616.             return TRUE;
  617.     }
  618.  
  619.     DeleteBitmapLB();
  620.  
  621.     rgbDDWindow = rgbWindowColor;
  622.     rgbDDHilite = rgbHiliteColor;
  623.  
  624.     if(!(hdcTemp = CreateCompatibleDC(hdcMemory)))
  625.         goto LoadExit;
  626.  
  627.     if(!(hbmp = LoadAlterBitmap(rgbWindowColor)))
  628.         goto DeleteTempDC;
  629.  
  630.     GetObject(hbmp, sizeof(BITMAP), (LPBYTE) &bmp);
  631.     dybmpLB = bmp.bmHeight;
  632.     dxbmpLB = bmp.bmWidth;
  633.  
  634.     hbmpOrig = SelectObject(hdcTemp, hbmp);
  635.  
  636.     hbmpLB = CreateDiscardableBitmap(hdcTemp, dxbmpLB*2, dybmpLB);
  637.     if(!hbmpLB)
  638.         goto DeleteTempBmp;
  639.  
  640.     if(!SelectObject(hdcMemory, hbmpLB))
  641.     {
  642.         DeleteBitmapLB();
  643.         goto DeleteTempBmp;
  644.     }
  645.  
  646.     BitBlt(hdcMemory, 0, 0, dxbmpLB, dybmpLB,   // copy unhighlited bmps
  647.            hdcTemp, 0, 0, SRCCOPY);             // into hdcMemory
  648.     SelectObject(hdcTemp, hbmpOrig);
  649.  
  650.     DeleteObject(hbmp);
  651.  
  652.     if(!(hbmp = LoadAlterBitmap(rgbHiliteColor)))
  653.         goto DeleteTempDC;
  654.  
  655.     hbmpOrig = SelectObject(hdcTemp, hbmp);
  656.     BitBlt(hdcMemory, dxbmpLB, 0, dxbmpLB, dybmpLB, // copy highlited bmps
  657.         hdcTemp, 0, 0, SRCCOPY);                    // into hdcMemory
  658.     SelectObject(hdcTemp, hbmpOrig);
  659.  
  660.     bWorked = TRUE;
  661.  
  662. DeleteTempBmp:
  663.     DeleteObject(hbmp);
  664. DeleteTempDC:
  665.     DeleteDC(hdcTemp);
  666. LoadExit:
  667.     return bWorked;
  668. }
  669.