home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / C / MRCE / SOURCE.ZIP / BMPBTN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-14  |  11.0 KB  |  372 lines

  1. // MRCEXT: Micro Focus Extension DLL for MFC 2.1+
  2. // Copyright (C)1994-5    Micro Focus Inc, 2465 East Bayshore Rd, Palo Alto, CA 94303.
  3. // 
  4. //  This program is free software; you can redistribute it and/or modify
  5. //  it under the terms of the GNU General Public License as published by
  6. //  the Free Software Foundation. In addition, you may also charge for any
  7. //  application    using MRCEXT, and are under no obligation to supply source
  8. //  code. You must accredit Micro Focus Inc in the "About Box", or banner
  9. //  of your application. 
  10. //
  11. //  This program is distributed in the hope that it will be useful,
  12. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. //  GNU General Public License for more details.
  15. //
  16. //  You should also have received a copy of the GNU General Public License with this
  17. //  software, also indicating additional rights you have when using MRCEXT.  
  18. //
  19. //
  20. // mrcbmpbtn.cpp : implementation file
  21. // $Date:   28 Dec 1995 18:59:24  $
  22. // $Revision:   1.1  $
  23. // $Author:   MRC  $
  24.  
  25. #include "mrcstafx.h"
  26. #include "mrcpriv.h"
  27.  
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32.  
  33. extern MRC_AUX_DATA afxData;
  34.  
  35. static HDC hDCGlyphs = NULL;
  36. static HDC hDCMono = NULL;
  37. static HBRUSH hbrDither = NULL;
  38.  
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CMRCBitmapButton
  41. IMPLEMENT_DYNAMIC(CMRCBitmapButton, CButton)
  42.  
  43. BEGIN_MESSAGE_MAP(CMRCBitmapButton, CButton)
  44.     //{{AFX_MSG_MAP(CMRCBitmapButton)
  45.     ON_WM_SYSCOLORCHANGE()
  46.     //}}AFX_MSG_MAP
  47. END_MESSAGE_MAP()
  48.  
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CMRCBitmapButton message handlers
  52.  
  53. //------------------------------------------------------------------------------------
  54. CMRCBitmapButton::CMRCBitmapButton()
  55. //------------------------------------------------------------------------------------
  56. {
  57.     m_hBitmap = NULL;
  58. }
  59.  
  60. CMRCBitmapButton::~CMRCBitmapButton()
  61. {
  62. }
  63.  
  64.  
  65. //----------------------------------------------------------------------------------------
  66. BOOL CMRCBitmapButton::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
  67. //----------------------------------------------------------------------------------------
  68. {
  69.     dwStyle |= BS_OWNERDRAW;
  70.     return CButton::Create(NULL, dwStyle, rect, pParentWnd, nID);
  71. }
  72.  
  73.  
  74. //----------------------------------------------------------------------------------------
  75. BOOL CMRCBitmapButton::LoadBitmap(LPCTSTR lpszResource)
  76. // Load the specified bitmap. Note this function is virtual, so you can override it,
  77. // either to turn off the coloring, or change the way the bitmap is loaded.
  78. //----------------------------------------------------------------------------------------
  79. {
  80.     if (m_hBitmap != NULL)
  81.         ::DeleteObject(m_hBitmap);
  82.  
  83.     m_hInst = AfxFindResourceHandle(lpszResource, RT_BITMAP);
  84.     m_hRsrc = ::FindResource(m_hInst, lpszResource, RT_BITMAP);
  85.     if (m_hRsrc == NULL)
  86.     {
  87.         TRACE("CMRCBitapButton failed to load bitmap\n");
  88.         return FALSE;
  89.     }
  90.  
  91.     m_hBitmap = LoadRecolorBitmap(m_hInst, m_hRsrc);
  92.  
  93.     BITMAP bm;
  94.     ::GetObject(m_hBitmap, sizeof(bm), &bm);    
  95.      m_sizeImage.cx = bm.bmWidth;
  96.      m_sizeImage.cy = bm.bmHeight;
  97.     return TRUE;
  98. }
  99.  
  100.  
  101.  
  102. //----------------------------------------------------------------------------------------
  103. BOOL CMRCBitmapButton::AutoLoad(UINT nID, CWnd * pParent, BOOL bSetSize)
  104. //----------------------------------------------------------------------------------------
  105. {
  106.     // first attach to the dialog control
  107.     if (!SubclassDlgItem(nID, pParent))
  108.         return FALSE;
  109.  
  110.     CString buttonName;
  111.     GetWindowText(buttonName);
  112.     ASSERT(!buttonName.IsEmpty());      // must provide a title
  113.  
  114.     if (!LoadBitmap(buttonName))
  115.     {                                          
  116.         return FALSE;
  117.     }
  118.     
  119.     if (bSetSize == TRUE)
  120.     {
  121.         AutoSize();
  122.     }
  123.     return TRUE;
  124. }
  125.  
  126.  
  127. //----------------------------------------------------------------------------------------
  128. BOOL CMRCBitmapButton::AutoSize()
  129. // sets the size of the button to match the loaded bitmap
  130. //----------------------------------------------------------------------------------------
  131. {
  132.     if (m_hBitmap == NULL) 
  133.         return FALSE;
  134.     SetWindowPos(NULL, 0, 0, m_sizeImage.cx + 6, m_sizeImage.cy + 6,
  135.                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);        
  136.     return TRUE;
  137. }
  138.  
  139.  
  140. //----------------------------------------------------------------------------------------
  141. void CMRCBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
  142. //----------------------------------------------------------------------------------------
  143. {
  144. //    itemAction:
  145. //        ODA_DRAWENTIRE
  146. //        ODA_FOCUS
  147. //        ODA_SELECT:    
  148. //    itemState: ODS_DISABLED, ODS_FOCUS ODS_SELECTED (=down) 
  149.  
  150.     CRect rcClient;
  151.     GetClientRect(&rcClient);
  152.     m_sizeButton = rcClient.Size();
  153.     int dx = m_sizeButton.cx;
  154.     int dy = m_sizeButton.cy;
  155.  
  156.     CDC dc;
  157.     dc.Attach(lpDIS->hDC);
  158.  
  159.     // interior grey
  160.     dc.FillSolidRect(&rcClient, afxData.clrBtnFace);
  161.     
  162.     // determine offset of bitmap (centered within button)
  163.     CPoint ptOffset;
  164.     ptOffset.x = (dx - m_sizeImage.cx - 1) / 2;
  165.     ptOffset.y = (dy - m_sizeImage.cy) / 2;
  166.  
  167.     if (lpDIS->itemState & ODS_SELECTED)
  168.     {
  169.         // pressed in or checked
  170.         dc.Draw3dRect(0, 0, dx, dy,
  171.             afxData.bWin4 ? afxData.clrWindowFrame : afxData.clrBtnShadow,
  172.             afxData.bWin4 ? afxData.clrBtnHilite : afxData.clrBtnFace);
  173.  
  174.         if (afxData.bWin4)
  175.         {
  176.             dc.Draw3dRect(1, 1, dx - 2, dy - 2,
  177.                 afxData.clrBtnShadow, afxData.clrBtnFace);
  178.         }
  179.  
  180.         // for any depressed button, add one to the offsets.
  181.         ptOffset.x += 1;
  182.         ptOffset.y += 1;
  183.     }
  184.     else
  185.     {
  186.         // regular button look
  187.         dc.Draw3dRect(0, 0, dx, dy, afxData.clrBtnHilite,
  188.             afxData.bWin4 ? afxData.clrWindowFrame : afxData.clrBtnShadow);
  189.         dc.Draw3dRect(1, 1, dx - 2, dy - 2,
  190.             afxData.clrBtnFace, afxData.clrBtnShadow);
  191.     }
  192.  
  193.     //if (lpDIS->itemAction & ODA_DRAWENTIRE)
  194.     {
  195.         // create bitmap for item
  196.         CDC SrcDC;
  197.         SrcDC.CreateCompatibleDC(&dc);
  198.         SrcDC.SelectObject(CBitmap::FromHandle(m_hBitmap));
  199.  
  200.         // normal image version
  201.         dc.BitBlt(ptOffset.x, ptOffset.y,
  202.                 m_sizeImage.cx, m_sizeImage.cy,
  203.                 &SrcDC,
  204.                 0 ,0, SRCCOPY);
  205.     }
  206.  
  207.     // indicate focus by drawing a rectangle inside the button - done after the bitmap so it's
  208.     // visible
  209.     if (lpDIS->itemState & ODS_FOCUS)
  210.     {
  211.          dc.SetBkColor(afxData.clrBtnFace);
  212.            CRect rect = rcClient;
  213.         rect.InflateRect(-3,-3);
  214.         dc.DrawFocusRect(&rect);
  215.     }
  216.  
  217.     dc.Detach();
  218.  
  219. }
  220.  
  221.  
  222. void CMRCBitmapButton::OnSysColorChange() 
  223. {
  224.     CButton::OnSysColorChange();
  225.     
  226.     if (m_hBitmap != NULL)
  227.     {
  228.         ::DeleteObject(m_hBitmap);
  229.         m_hBitmap = LoadRecolorBitmap(m_hInst, m_hRsrc);
  230.     }
  231. }
  232.  
  233.  
  234.  
  235. // routine to handle recoloring of bitmaps to fit standard colors. This really just the
  236. // code from MFC, with the addition that you can specify your own color table mapping, and 
  237. // it'll handle 256-color as well as 16-color bitmaps 
  238. // Hey, why write your own routines from scratch, when Microsoft have provided a ready-working
  239. // one for you ?
  240.  
  241. #ifndef _MAC
  242. #define RGB_TO_RGBQUAD(r,g,b)   (RGB(b,g,r))
  243. #define CLR_TO_RGBQUAD(clr)     (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)))
  244. #else
  245. #define RGB_TO_RGBQUAD(r,g,b)   (RGB(r,g,b) << 8)
  246. #define CLR_TO_RGBQUAD(clr)     (clr << 8)
  247. #endif
  248.  
  249. //-----------------------------------------------------------------------------
  250. HBITMAP LoadRecolorBitmap(LPCTSTR lpszResourceName, const BITMAPCOLORMAP * pColorMap, int nMaps)
  251. //-----------------------------------------------------------------------------
  252. {
  253.     HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
  254.     HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_BITMAP);
  255.     if (hRsrc == NULL)
  256.         return NULL;
  257.     return LoadRecolorBitmap(hInst, hRsrc, pColorMap, nMaps);
  258.  
  259. }    
  260.  
  261.  
  262. //-----------------------------------------------------------------------------
  263. HBITMAP LoadRecolorBitmap(UINT nID, const BITMAPCOLORMAP * pColorMap, int nMaps)
  264. //-----------------------------------------------------------------------------
  265.     return LoadRecolorBitmap(MAKEINTRESOURCE(nID), pColorMap, nMaps);
  266. }
  267.  
  268.  
  269. //-----------------------------------------------------------------------------
  270. HBITMAP LoadRecolorBitmap(HINSTANCE hInst, HRSRC hRsrc, const BITMAPCOLORMAP * pColorMap, int nMaps)
  271. // Create a bitmap with a modified color table. This routine only handles 16-color bitmaps
  272. //-----------------------------------------------------------------------------
  273. {
  274.     ASSERT(hRsrc != NULL);
  275.  
  276.     // system color maps (same as MFC uses for toolbars, if user doesn't specify one)
  277.     static const BITMAPCOLORMAP sysColorMap[] =
  278.     {
  279.         // mapping from color in DIB to system color
  280.         { RGB_TO_RGBQUAD(0x00, 0x00, 0x00),  COLOR_BTNTEXT },       // black
  281.         { RGB_TO_RGBQUAD(0x80, 0x80, 0x80),  COLOR_BTNSHADOW },     // dark grey
  282.         { RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0),  COLOR_BTNFACE },       // bright grey
  283.         { RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF),  COLOR_BTNHIGHLIGHT }   // white
  284.     };
  285.     
  286.     if (pColorMap == NULL)
  287.     {
  288.         pColorMap = sysColorMap;
  289.         nMaps = 4;
  290.     }
  291.  
  292.     HGLOBAL hglb;
  293.     if ((hglb = ::LoadResource(hInst, hRsrc)) == NULL)
  294.         return NULL;
  295.  
  296.     LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  297.     if (lpBitmap == NULL)
  298.         return NULL;
  299.  
  300.     // make copy of BITMAPINFOHEADER so we can modify the color table
  301.     int nColorTableSize = lpBitmap->biClrUsed;
  302.     if (nColorTableSize == 0)
  303.     {
  304.         switch (lpBitmap->biBitCount)
  305.         {
  306.             case 4:
  307.                 nColorTableSize = 16;
  308.                 break;
  309.             case 8:
  310.                 nColorTableSize = 256;
  311.                 break;
  312.             default:
  313.                 return NULL;
  314.         }
  315.     }
  316.     
  317.     UINT nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
  318.     LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize);
  319.     if (lpBitmapInfo == NULL)
  320.         return NULL;
  321.     memcpy(lpBitmapInfo, lpBitmap, nSize);
  322.  
  323.     // color table is in RGBQUAD DIB format
  324.     DWORD* pColorTable =
  325.         (DWORD*)(((LPBYTE)lpBitmapInfo) + (UINT)lpBitmapInfo->biSize);
  326.  
  327.     HDC hDCScreen = ::GetDC(HWND_DESKTOP);
  328.     
  329.     for (int iColor = 0; iColor < nColorTableSize; iColor++)
  330.     {
  331.         // look for matching RGBQUAD color in original
  332.         for (int i = 0; i < nMaps; i++)
  333.         {
  334.             if (pColorTable[iColor] == pColorMap[i].rgbqFrom)
  335.             {
  336.                 COLORREF clrNew = CLR_TO_RGBQUAD(::GetSysColor(pColorMap[i].iSysColorTo));
  337.                 clrNew = ::GetNearestColor(hDCScreen, clrNew);        // map to solid colors only
  338.                 pColorTable[iColor] = clrNew;
  339.                 break;
  340.             }
  341.         }
  342.     }
  343.  
  344.     int nWidth = (int)lpBitmapInfo->biWidth;
  345.     int nHeight = (int)lpBitmapInfo->biHeight;
  346.     HBITMAP hbm = ::CreateCompatibleBitmap(hDCScreen, nWidth, nHeight);
  347.     ::ReleaseDC(NULL, hDCScreen);
  348.     if (hbm != NULL)
  349.     {
  350.         HDC hDCGlyphs = CreateCompatibleDC(NULL);
  351.     
  352.         HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm);
  353.  
  354.         LPBYTE lpBits;
  355.         lpBits = (LPBYTE)(lpBitmap + 1);
  356.         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  357.  
  358.         StretchDIBits(hDCGlyphs, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
  359.             lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  360.         SelectObject(hDCGlyphs, hbmOld);
  361.        ::DeleteDC(hDCGlyphs);
  362.     }
  363.     
  364.     // free copy of bitmap info struct and resource itself
  365.     ::free(lpBitmapInfo);
  366.     ::FreeResource(hglb);
  367.  
  368.     return hbm;
  369. }
  370.  
  371.