home *** CD-ROM | disk | FTP | other *** search
/ PC Administrator / spravce.iso / TaskModule / src / ButtonImage.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-08  |  24.8 KB  |  851 lines

  1. // ButtonImage.cpp: implementation of the CButtonImage class.
  2. //
  3. /*
  4. Copyright 2001 Anish Mistry. All rights reserved.
  5.  
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8.  
  9.    1. Redistributions of source code must retain the above copyright notice, 
  10.    this list of conditions and the following disclaimer.
  11.    2. Redistributions in binary form must reproduce the above copyright notice,
  12.    this list of conditions and the following disclaimer in the documentation 
  13.    and/or other materials provided with the distribution.
  14.  
  15. THIS SOFTWARE IS PROVIDED BY ANISH MISTRY ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  16. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
  17. AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 
  18. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  19. OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  20. GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  21. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  22. TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24.  
  25. The views and conclusions contained in the software and documentation are those
  26. of the authors and should not be interpreted as representing official policies,
  27. either expressed or implied, of Anish Mistry or AM Productions.
  28.  
  29. * Variation of the FreeBSD License. http://www.freebsd.org/copyright/freebsd-license.html
  30. */
  31. //////////////////////////////////////////////////////////////////////
  32.  
  33. #include "stdafx.h"
  34. #include "ButtonImage.h"
  35.  
  36. //////////////////////////////////////////////////////////////////////
  37. // Construction/Destruction
  38. //////////////////////////////////////////////////////////////////////
  39.  
  40. CButtonImage::CButtonImage()
  41. {
  42.     ThunkInit(m_Thunk,this);
  43. }
  44.  
  45. CButtonImage::~CButtonImage()
  46. {
  47.     Cleanup();
  48. }
  49. bool CButtonImage::LoadCtrlImage(UINT iconID)
  50. {
  51.     // determine what type of resource the user wants to load
  52.     if((m_nStyles & BS_BITMAP) == BS_BITMAP)
  53.         imageType = IMAGE_BITMAP;
  54.     else if((m_nStyles & BS_ICON) == BS_ICON)
  55.         imageType = IMAGE_ICON;
  56.     else
  57.         return false;
  58.  
  59.     // Load image from resource
  60.     HGDIOBJ hIcon = LoadImage(appInstance, MAKEINTRESOURCE(iconID),imageType, imageSize.cx, imageSize.cy, LR_DEFAULTCOLOR);
  61.     SetButtonImage(imageType,hIcon);
  62. /*    HGDIOBJ oldObject = buttonImage;
  63.     
  64.     // destroy the image
  65.     if(imageType == IMAGE_BITMAP)
  66.         DeleteObject(oldObject);
  67.     else if(imageType == IMAGE_ICON)
  68.         DestroyIcon((HICON)oldObject);
  69.     else if(imageType == IMAGE_CURSOR)
  70.         DestroyCursor((HCURSOR)oldObject);
  71.     else
  72.         return false;*/
  73.     return true;
  74. }
  75.  
  76. void CButtonImage::Create(UINT ID,HWND parent,HINSTANCE parentInstance,BYTE imageFlags,SIZE imgSz)
  77. {
  78.     Setup();
  79.     // assign values
  80.     appInstance = parentInstance;
  81.     flags = imageFlags;
  82.     ctrlID = ID;
  83.     parentWnd = parent;
  84.     if((flags & BI_SIZE) == BI_SIZE)
  85.     {// begin user want custon size
  86.         imageSize = imgSz;
  87.     }// end user want custom size
  88.     else
  89.     {// begin use default
  90.         imageSize.cx = 32;
  91.         imageSize.cy = 32;
  92.     }// end use default
  93.     m_hWnd = ctrlWnd = GetDlgItem(parent,ID);
  94.     // subclass owner's window message function
  95.     oldWndProc = (WNDPROC)::SetWindowLong(ctrlWnd,GWL_WNDPROC,(LONG)(void *)m_Thunk);
  96.  
  97.     // set the button colors to the default ones
  98.     buttonColor = GetSysColor(COLOR_BTNFACE);
  99.     fontColor = GetSysColor(COLOR_BTNTEXT);
  100.  
  101.     // get button styles
  102.     m_nStyles = GetWindowLong(ctrlWnd,GWL_STYLE);
  103.  
  104. //    SetOffset();
  105. }
  106.  
  107. LRESULT CButtonImage::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  108. {
  109.     switch(message)
  110.     { // begin switch
  111.     case BM_SETIMAGE:
  112.         SetButtonImage((unsigned int)wParam,(HANDLE)lParam);
  113.         break;
  114.     case BM_GETIMAGE:
  115.         return (LRESULT)GetButtonImage();
  116.     case BM_SETSTATE:
  117.         return OnSetState(wParam);
  118.     case BM_GETSTATE:
  119.     case BM_GETCHECK:
  120.         return (LRESULT)OnGetState();
  121.     case BM_SETCHECK:
  122.     case BM_SETSTYLE:
  123.         return (bool)OnSetStyle((unsigned long int)wParam,(LPARAM)(bool)lParam);
  124.     case WM_SETFOCUS:
  125.         hasFocus = true;
  126.         SendMessage(hwnd,WM_PAINT,0,0);
  127.         break;
  128.     case WM_KILLFOCUS:
  129.         hasFocus = false;
  130.         SendMessage(hwnd,WM_PAINT,0,0);
  131.         break;
  132.     case WM_LBUTTONDBLCLK:
  133.     case WM_LBUTTONDOWN:
  134.         if((m_nStyles & BS_GROUPBOX) == BS_GROUPBOX)
  135.             return 0;
  136.         SetCapture(hwnd);
  137.         SetFocus(hwnd);
  138.         IsDown = true;
  139.         SendMessage(hwnd,WM_PAINT,0,0);
  140.         return 0;//break;
  141.     case WM_MOUSEMOVE:
  142.         OnMouseMove(lParam);
  143.         break;
  144.     case WM_LBUTTONUP:
  145.         if(IsDown)
  146.         {
  147.             OnClick(hwnd,lParam);
  148.         }
  149.         break;
  150.     case WM_ENABLE:
  151.         SendMessage(hwnd,WM_PAINT,0,0);
  152.         return 0;
  153.     case WM_PAINT:
  154.         return OnPaint();
  155.     case WM_DESTROY:
  156.         OnDestroy();
  157.         break;
  158. //    case WM_SETTEXT:
  159. //        return OnSetText(wParam,lParam);
  160.     } // end switch
  161.  
  162.     // pass the message to the owner window's WndProc function
  163.     return CallWindowProc(oldWndProc,hwnd,message,wParam,lParam);
  164. }
  165.  
  166. SIZE CButtonImage::SetImageSize(SIZE newImageSize)
  167. // precondition: newImageSize is a valid new image size
  168. // postcondition: the previous image size is returned
  169. {// begin SetImageSize
  170.     SIZE oldSize = imageSize;
  171.     imageSize = newImageSize;
  172.     return oldSize;
  173. }// end SetImageSize
  174.  
  175. bool CButtonImage::Draw(HDC originalButtonDC)
  176. {// begin Draw
  177.  
  178.     // get button info
  179.     RECT buttonRect = {NULL};
  180.     GetClientRect(ctrlWnd,&buttonRect);
  181.     unsigned long int nExStyles = (unsigned long int)GetWindowLong(ctrlWnd,GWL_EXSTYLE);
  182. //    m_nStyles = (unsigned long int)GetWindowLong(ctrlWnd,GWL_STYLE);
  183.     SetOffset();
  184.  
  185.     SIZE buttonEdge = GetButtonEdgeSize(nExStyles);
  186.  
  187.     buttonRect.left += buttonEdge.cx;
  188.     buttonRect.top += buttonEdge.cy;
  189.     buttonRect.right += buttonEdge.cx;
  190.     buttonRect.bottom += buttonEdge.cy;
  191.     buttonTopLeft.x = buttonEdge.cx;
  192.     buttonTopLeft.y = buttonEdge.cy;
  193.  
  194.     SIZE buttonSize = {buttonRect.right-buttonRect.left,buttonRect.bottom-buttonRect.top};
  195.  
  196.     if(imageTopLeft.x < buttonEdge.cx)
  197.         imageTopLeft.x = buttonEdge.cx;
  198.  
  199.  
  200.     HDC buttonDC = CreateCompatibleDC(originalButtonDC);
  201.     HBITMAP buttonBitmap = CreateCompatibleBitmap(originalButtonDC,buttonRect.right,buttonRect.bottom);
  202.     HGDIOBJ oldButtonBitmap = SelectObject(buttonDC,buttonBitmap);
  203.     if(buttonDC != NULL)
  204.     {// begin draw image
  205.         POINT tempPoint = imageTopLeft;
  206.         if(IsDown)
  207.         {// begin draw in down pos
  208.             tempPoint.x += 1;
  209.             tempPoint.y += 1;
  210.         }// end draw in down pos
  211.  
  212.         unsigned long int tempStyles = 0;//m_nStyles;
  213.  
  214.         tempStyles |= DFCS_BUTTONPUSH;
  215.         if(IsDown)
  216.             tempStyles |= DFCS_PUSHED;
  217.  
  218.         // select the default button color brush to draw area with
  219.         HBRUSH brush = CreateSolidBrush(buttonColor);
  220.         HGDIOBJ oldBrush = SelectObject(buttonDC,brush);
  221.         // select the default button color pen to draw area with
  222.         HPEN pen = CreatePen(PS_SOLID,1,buttonColor);
  223.         HGDIOBJ oldPen = SelectObject(buttonDC,pen);
  224.         // draw face
  225.         RECT tempRectangle = buttonRect;
  226.         tempRectangle.left -= 1;
  227.         tempRectangle.top -= 1;
  228.         FillRect(buttonDC,&tempRectangle,brush);
  229.         // draw frame
  230.         DrawButtonFrame(buttonDC,&buttonRect);
  231.  
  232.         if(GetFocus() == ctrlWnd)
  233.         {
  234.             ExpandRectangle(1,&buttonRect);
  235.         }
  236.         // draw image
  237.         tempPoint.x += borderSize.cx;//*2;
  238.         DrawButtonImage(buttonDC,tempPoint);
  239.         // draw the text
  240.         DrawButtonText(buttonDC,tempPoint,buttonRect);
  241.         
  242.         // draw focus rect if the button is active
  243.         if(GetFocus() == ctrlWnd)
  244.         {// begin draw focus
  245.             RECT temp = buttonRect;
  246.             ContractRectangle(4,&temp);
  247.             DrawFocusRect(buttonDC,&temp);
  248.         }// end draw focus
  249.  
  250.         // copy to originalButtonDC
  251.         BitBlt(originalButtonDC,buttonTopLeft.x,buttonTopLeft.y,buttonSize.cx,buttonSize.cy,buttonDC,buttonTopLeft.x,buttonTopLeft.y,SRCCOPY);
  252.  
  253.         // clean up
  254.         SelectObject(buttonDC,oldButtonBitmap);
  255.         SelectObject(buttonDC,oldBrush);
  256.         SelectObject(buttonDC,oldPen);
  257.         DeleteObject(pen);
  258.         DeleteObject(brush);
  259.         DeleteObject(buttonBitmap);
  260.         DeleteObject(oldButtonBitmap);
  261.         DeleteDC(buttonDC);
  262.  
  263.         return true;
  264.     }// end draw image
  265.     return false;
  266. }// end Draw
  267.  
  268. bool CButtonImage::CleanUpImage()
  269. {// begin CleanUpImage
  270.     // determine image type
  271.     if((m_nStyles & BS_BITMAP) == BS_BITMAP)
  272.         imageType = IMAGE_BITMAP;
  273.     else if((m_nStyles & BS_ICON) == BS_ICON)
  274.         imageType = IMAGE_ICON;
  275.     else
  276.         return false;
  277.     // destroy the image
  278.     if((m_nStyles & BS_BITMAP) == BS_BITMAP)
  279.         DeleteObject(buttonImage);
  280.     else if((m_nStyles & BS_ICON) == BS_ICON)
  281.         DestroyIcon((HICON)buttonImage);
  282.     else
  283.         return false;
  284.     return true;
  285. }// end CleanUpImage
  286.  
  287. void CButtonImage::SetOffset()
  288. {// begin SetOffset
  289.     // calculate image position
  290.     if((m_nStyles & BS_GROUPBOX) != BS_GROUPBOX && m_nStyles & BS_VCENTER)
  291.     {
  292.         RECT rButton = {NULL};
  293.         GetWindowRect(ctrlWnd,&rButton);
  294.         imageTopLeft.y = ((rButton.bottom-rButton.top)/2)-(imageSize.cy/2);
  295.     }
  296.     else
  297.         imageTopLeft.y = 0;
  298.     if((flags & BI_CENTERIMAGE) == BI_CENTERIMAGE)
  299.     {// begin center image
  300.         char string[1024] = {NULL};
  301.         SIZE fontSize = {NULL};
  302.         // get info for GetTextExtentPoint32
  303.         GetWindowText(ctrlWnd,string,1023);
  304.         HDC buttonDC = GetWindowDC(ctrlWnd);
  305.         int stringLength = lstrlen(string);
  306.  
  307.         // get the font dimentions
  308.         GetTextExtentPoint32(buttonDC,string,stringLength,&fontSize);
  309.         // get the control dimentions
  310.         RECT buttonRect = {NULL};
  311.         GetClientRect(ctrlWnd,&buttonRect);
  312.         imageTopLeft.x = ((buttonRect.right-buttonRect.left)/2)-(fontSize.cx+imageSize.cx+borderSize.cx)/2;
  313.         if(imageTopLeft.x < borderSize.cx)
  314.         {
  315.             imageTopLeft.x = borderSize.cx;
  316.         }
  317.  
  318.         // clean up
  319.         ReleaseDC(ctrlWnd,buttonDC);
  320.     }// end center image
  321.     else
  322.     {// left justify image
  323.         imageTopLeft.x = 0;
  324.     }// left justify image
  325. }// end SetOffset
  326.  
  327. void CButtonImage::ContractRectangle(unsigned int num, RECT *rect)
  328. {
  329.     rect->top += num;
  330.     rect->left += num;
  331.     rect->right -= num;
  332.     rect->bottom -= num;
  333. }
  334.  
  335. void CButtonImage::ContractRectangle(SIZE size,RECT *rect)
  336. {
  337.     rect->top += size.cy;
  338.     rect->left += size.cx;
  339.     rect->right -= size.cx;
  340.     rect->bottom -= size.cy;
  341. }
  342.  
  343. void CButtonImage::ExpandRectangle(unsigned int num, RECT *rect)
  344. {
  345.     rect->top -= num;
  346.     rect->left -= num;
  347.     rect->right += num;
  348.     rect->bottom += num;
  349. }
  350.  
  351. void CButtonImage::ExpandRectangle(SIZE size,RECT *rect)
  352. {
  353.     rect->top -= size.cy;
  354.     rect->left -= size.cx;
  355.     rect->right += size.cx;
  356.     rect->bottom += size.cy;
  357. }
  358.  
  359. RECT CButtonImage::DrawButtonText(const    HDC buttonDC, POINT &textPos, const RECT buttonRect)
  360. {
  361.     char buttonText[MAX_PATH] = {NULL};
  362.     GetWindowText(ctrlWnd,buttonText,MAX_PATH-1);
  363.     RECT buttonTextRect = buttonRect;
  364.     if(IsDown)
  365.     {// begin set pushed offset
  366.         buttonTextRect.top += 1;
  367.         buttonTextRect.bottom += 1;
  368.         buttonTextRect.left += 1;
  369.         buttonTextRect.right += 1;
  370.     }// end set pushed offset
  371.  
  372.     ContractRectangle(borderSize,&buttonTextRect);
  373.  
  374.     buttonTextRect.left = textPos.x+imageSize.cx+borderSize.cx;
  375.     buttonTextRect.top -= borderSize.cy;
  376.  
  377.     DrawControlText(buttonDC,buttonText,buttonTextRect);
  378.  
  379.     return buttonTextRect;
  380. }
  381.  
  382. void CButtonImage::DrawButtonImage(const HDC buttonDC,const POINT imagePos)
  383. {
  384.     // draw image
  385.     if(!IsWindowEnabled(ctrlWnd))
  386.     {
  387.         // the button is disabled monochrome the image
  388.         HICON icon = (HICON)::CopyImage( buttonImage, IMAGE_ICON, imageSize.cx, imageSize.cy, LR_MONOCHROME );
  389.         DrawImage(buttonDC,&imagePos,icon);
  390. //        DrawIconEx(buttonDC,imagePos.x,imagePos.y,(HICON)icon,imageSize.cx,imageSize.cy,NULL,NULL,DI_NORMAL);
  391.         DestroyIcon(icon);
  392.     }
  393.     else
  394.         DrawImage(buttonDC,&imagePos);
  395.         //DrawIconEx(buttonDC,imagePos.x,imagePos.y,(HICON)buttonImage,imageSize.cx,imageSize.cy,NULL,NULL,DI_NORMAL);
  396. }
  397.  
  398. void CButtonImage::DrawButtonFrame(const HDC buttonDC,RECT *buttonRect)
  399. {
  400.     // adjust for focused button
  401.     if(GetFocus() == ctrlWnd)
  402.     {
  403.         // draw border
  404.         HBRUSH borderBrush = CreateSolidBrush(fontColor);
  405.         FrameRect(buttonDC,buttonRect,borderBrush);
  406.         DeleteObject(borderBrush);
  407.  
  408.         // shrink 3D rect to not cover border
  409.         ContractRectangle(1,buttonRect);
  410.     }
  411.  
  412. //    DrawFrameControl(buttonDC,buttonRect,DFC_BUTTON,drawStyles );
  413.  
  414.     RECT tempRect = *buttonRect;
  415.     tempRect.right -= 1;
  416.     tempRect.bottom -= 1;
  417.     COLORREF topLeftColor = NULL;
  418.     COLORREF bottomRightColor = NULL;
  419.     if(IsDown)
  420.     {
  421.         topLeftColor = GetShadowColor(buttonColor);
  422.         bottomRightColor = GetHiliteColor(buttonColor);
  423.     }
  424.     else
  425.     {
  426.         topLeftColor = GetHiliteColor(buttonColor);
  427.         bottomRightColor = GetShadowColor(buttonColor);
  428.     }
  429.  
  430.     Draw3dRect(buttonDC,&tempRect,topLeftColor,RGB(0,0,0));
  431.     ContractRectangle(1,&tempRect);
  432.     Draw3dRect(buttonDC,&tempRect,buttonColor,bottomRightColor);
  433.  
  434. }
  435.  
  436. void CButtonImage::OnMouseMove(LPARAM lParam)
  437. {
  438.     if(IsDown)
  439.     {
  440.         POINT cursorPos = {LOWORD(lParam),HIWORD(lParam)};
  441.         ClientToScreen(ctrlWnd,&cursorPos);
  442.         RECT buttonRect = {NULL};
  443.         GetWindowRect(ctrlWnd,&buttonRect);
  444.         if(!PtInRect(&buttonRect,lastPoint) && PtInRect(&buttonRect,cursorPos))
  445.         {// begin mouse now over button
  446.             // draw the button
  447.                 IsDown = true;
  448.                 SendMessage(ctrlWnd,WM_PAINT,0,0);
  449.         }// end mouse now over button
  450.         else if(PtInRect(&buttonRect,lastPoint) && !PtInRect(&buttonRect,cursorPos))
  451.         {// begin mouse now out of button
  452.             // draw the button
  453.                 IsDown = false;
  454.                 SendMessage(ctrlWnd,WM_PAINT,0,0);
  455.         }// end mouse now out of button
  456.         IsDown = true;
  457.         lastPoint = cursorPos;
  458.     }
  459.  
  460. }
  461.  
  462. void CButtonImage::SetButtonImage(unsigned int type, HANDLE image)
  463. {
  464.     if(buttonImage != NULL)
  465.         CleanUpImage();
  466.     buttonImage = image;  // handle to the image 
  467.     imageType = type;
  468. }
  469.  
  470.  
  471.  
  472. void CButtonImage::OnClick(HWND hWnd, LPARAM lParam)
  473. {
  474.     if(GetCapture() == hWnd)
  475.         ReleaseCapture();
  476.     IsDown = false;
  477.     POINT pt = {LOWORD(lParam),HIWORD(lParam)};
  478.     RECT buttonRect = {NULL};
  479.     GetClientRect(hWnd,&buttonRect);
  480.     if(PtInRect(&buttonRect,pt))
  481.     {
  482.         ToggleButtonState();
  483.         // notify parent of button click
  484.         WORD loword = (WORD)ctrlID;
  485.         WORD hiword = 0;
  486.         SendMessage(parentWnd,WM_COMMAND,MAKEWPARAM(loword,hiword),(LPARAM)hWnd);
  487.     }
  488.     // paint in new state
  489.     SendMessage(hWnd,WM_PAINT,0,0);
  490. }
  491.  
  492. HANDLE CButtonImage::GetButtonImage()
  493. {
  494.     return (HANDLE)buttonImage;
  495. }
  496.  
  497. unsigned int CButtonImage::OnGetState()
  498. {
  499.     unsigned int states = 0;
  500.     states = states|buttonState;
  501.     if(GetFocus() == ctrlWnd)
  502.         states = states|BST_FOCUS;
  503.     if(IsDown)
  504.         states = states|BST_PUSHED;
  505.     return states;
  506. }
  507.  
  508. int CButtonImage::OnSetStyle(unsigned long int styles, bool redraw)
  509. {
  510.     SetWindowLong(ctrlWnd,GWL_STYLE,(LONG)styles);
  511.     m_nStyles = styles;
  512.     SetOffset();
  513.     if(redraw)
  514.         SendMessage(ctrlWnd,WM_PAINT,0,0);
  515.     return 0;
  516. }
  517.  
  518. COLORREF CButtonImage::SetColor(COLORREF color)
  519. {
  520.     COLORREF oldButtonColor = buttonColor;
  521.     buttonColor = color;
  522.     return oldButtonColor;
  523. }
  524.  
  525. COLORREF CButtonImage::SetFontColor(COLORREF color)
  526. {
  527.     COLORREF oldFontColor = fontColor;
  528.     fontColor = color;
  529.     return oldFontColor;
  530. }
  531.  
  532.  
  533.  
  534.  
  535. int CButtonImage::LevelColorTop(int color)
  536. {
  537.     if(color > 255)
  538.         color = 255;
  539.     return color;
  540. }
  541.  
  542. int CButtonImage::LevelColorBottom(int color)
  543. {
  544.     if(color < 0)
  545.         color = 0;
  546.     return color;
  547. }
  548.  
  549. LRESULT CButtonImage::OnPaint()
  550. {
  551.     // initilize paintStruct
  552.     PAINTSTRUCT paintStruct = {NULL};
  553.     BeginPaint(ctrlWnd,&paintStruct);
  554.     HDC drawDC = GetWindowDC(ctrlWnd);
  555.     if(drawDC)
  556.     {
  557.         Draw(drawDC);
  558.         ReleaseDC(ctrlWnd,drawDC);
  559.     }
  560.     EndPaint(ctrlWnd,&paintStruct);
  561.     return 0;
  562. }
  563.  
  564. void CButtonImage::SetTextStyles(unsigned int styles)
  565. {
  566.     m_nTextStyles = styles;
  567.     SetOffset();
  568. }
  569.  
  570. void CButtonImage::DrawControlText(HDC buttonDC,char *buttonText,RECT &buttonTextRect)
  571. {// begin DrawControlText
  572.     // set and save text background color
  573.     COLORREF oldBkColor = SetBkColor(buttonDC,buttonColor);
  574.     COLORREF oldFontColor = SetTextColor(buttonDC,fontColor);
  575.     HFONT font = (HFONT)SendMessage(ctrlWnd,WM_GETFONT,0,0);
  576.     HFONT oldFont = (HFONT)SelectObject(buttonDC,font);
  577.     if(!IsWindowEnabled(ctrlWnd))
  578.     {// begin draw disabled text
  579.         //COLORREF hiliteColor = RGB(LevelColorTop(GetRValue(fontColor)+216),LevelColorTop(GetGValue(fontColor)+216),LevelColorTop(GetBValue(fontColor)+216));
  580.         SetTextColor(buttonDC,GetHiliteColor(buttonColor));
  581.         RECT tempRect = buttonTextRect;
  582.         tempRect.bottom += 1;
  583.         tempRect.left += 1;
  584.         tempRect.right += 1;
  585.         tempRect.top += 1;
  586.         DrawTextEx(buttonDC,buttonText,-1,&tempRect,m_nTextStyles,NULL);
  587.         SetTextColor(buttonDC,GetShadowColor(buttonColor));
  588. //        SetTextColor(buttonDC,RGB(LevelColorTop(GetRValue(fontColor)+128),LevelColorTop(GetGValue(fontColor)+128),LevelColorTop(GetBValue(fontColor)+128)));
  589.     }// end draw disabled text
  590.     SetBkMode(buttonDC,TRANSPARENT); 
  591.     DrawTextEx(buttonDC,buttonText,-1,&buttonTextRect,m_nTextStyles,NULL);
  592.     SetBkMode(buttonDC,OPAQUE); 
  593.     SelectObject(buttonDC,oldFont);
  594.     // set the old text background color back in case it is needed else where
  595.     SetTextColor(buttonDC,oldFontColor);
  596.     SetBkColor(buttonDC,oldBkColor);
  597. }// end DrawControlText
  598.  /*
  599. void CButtonImage::DrawControlText(HDC buttonDC,char *buttonText,RECT &buttonTextRect)
  600. {// begin DrawControlText
  601.     // set and save text background color
  602.     COLORREF oldBkColor = SetBkColor(buttonDC,buttonColor);
  603.     COLORREF oldFontColor = SetTextColor(buttonDC,fontColor);
  604.     HFONT font = (HFONT)SendMessage(ctrlWnd,WM_GETFONT,0,0);
  605.     HFONT oldFont = (HFONT)SelectObject(buttonDC,font);
  606.     if(!IsWindowEnabled(ctrlWnd))
  607.     {// begin draw disabled text
  608.         COLORREF hiliteColor = RGB(LevelColorTop(GetRValue(fontColor)+216),LevelColorTop(GetGValue(fontColor)+216),LevelColorTop(GetBValue(fontColor)+216));
  609.         SetTextColor(buttonDC,hiliteColor);
  610.         RECT tempRect = buttonTextRect;
  611.         tempRect.bottom += 1;
  612.         tempRect.left += 1;
  613.         tempRect.right += 1;
  614.         tempRect.top += 1;
  615.         DrawTextEx(buttonDC,buttonText,-1,&tempRect,m_nTextStyles,NULL);
  616.         SetTextColor(buttonDC,RGB(LevelColorTop(GetRValue(fontColor)+128),LevelColorTop(GetGValue(fontColor)+128),LevelColorTop(GetBValue(fontColor)+128)));
  617.     }// end draw disabled text
  618.     SetBkMode(buttonDC,TRANSPARENT); 
  619.     DrawTextEx(buttonDC,buttonText,-1,&buttonTextRect,m_nTextStyles,NULL);
  620.     SetBkMode(buttonDC,OPAQUE); 
  621.     SelectObject(buttonDC,oldFont);
  622.     // set the old text background color back in case it is needed else where
  623.     SetTextColor(buttonDC,oldFontColor);
  624.     SetBkColor(buttonDC,oldBkColor);
  625. }// end DrawControlText
  626. */
  627.  
  628. void CButtonImage::ToggleButtonState()
  629. {
  630.     switch(buttonState)
  631.     {
  632.     case BST_UNCHECKED:
  633.         OnSetState(BST_CHECKED);
  634.         break;
  635.     case BST_CHECKED:
  636.         OnSetState(BST_UNCHECKED);
  637.         break;
  638.     default:
  639.         OnSetState(BST_UNCHECKED);
  640.     }
  641. }
  642.  
  643. SIZE CButtonImage::GetButtonEdgeSize(unsigned long int extendedStyles)
  644. {
  645.         SIZE buttonEdge = {0,0};
  646.         if((extendedStyles & WS_EX_STATICEDGE) == WS_EX_STATICEDGE)
  647.         {
  648.             buttonEdge.cx += GetSystemMetrics(SM_CXBORDER);
  649.             buttonEdge.cy += GetSystemMetrics(SM_CYBORDER);
  650.         }
  651.         else
  652.         {
  653.             if((extendedStyles & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE)
  654.             {
  655.                 buttonEdge.cx += GetSystemMetrics(SM_CXEDGE);
  656.                 buttonEdge.cy += GetSystemMetrics(SM_CYEDGE);
  657.             }
  658.             if((extendedStyles & WS_EX_DLGMODALFRAME) == WS_EX_DLGMODALFRAME)
  659.             {
  660.                 buttonEdge.cx += GetSystemMetrics(SM_CXDLGFRAME);
  661.                 buttonEdge.cy += GetSystemMetrics(SM_CYDLGFRAME);
  662.             }
  663.         }
  664.         return buttonEdge;
  665. }
  666.  
  667. int CButtonImage::OnSetState(WPARAM state)
  668. {
  669.     buttonState = state;
  670.     return 0;
  671. }
  672.  
  673.  
  674.  
  675. COLORREF CButtonImage::GetHiliteColor(COLORREF color)
  676. {
  677.     double alpha = 0;
  678.     return RGB((1-alpha)*LevelColorTop(GetRValue(color)+128) + (alpha*GetRValue(color)),
  679.         (1-alpha)*LevelColorTop(GetGValue(color)+128) + (alpha*GetGValue(color)),
  680.         (1-alpha)*LevelColorTop(GetBValue(color)+128) + (alpha*GetBValue(color)));
  681. /*    return RGB((1-alpha)*LevelColorTop(GetRValue(color)+196) + (alpha*GetRValue(color)),
  682.         (1-alpha)*LevelColorTop(GetGValue(color)+196) + (alpha*GetGValue(color)),
  683.         (1-alpha)*LevelColorTop(GetBValue(color)+196) + (alpha*GetBValue(color)));*/
  684. }
  685.  
  686. COLORREF CButtonImage::GetShadowColor(COLORREF color)
  687. {
  688.     // avoid using floating point numbers so that _ftol() is not needed
  689.     int whole = 1000000000; // 1,000,000,000
  690.     int alpha = 333333333;    // 333,333,333
  691.     return RGB((whole-alpha)*LevelColorBottom(GetRValue(color)-128) + (alpha*GetRValue(color)/100),
  692.         (whole-alpha)*LevelColorBottom(GetGValue(color)-128) + (alpha*GetGValue(color)/100),
  693.         (whole-alpha)*LevelColorBottom(GetBValue(color)-128) + (alpha*GetBValue(color)/100));
  694.  
  695. }
  696.  
  697. void CButtonImage::Draw3dRect(HDC destDC,RECT *rect, COLORREF topLeftColor, COLORREF bottomRightColor)
  698. {
  699.     POINT leftTopArray[3] = {NULL};
  700.     leftTopArray[0].x = rect->left;
  701.     leftTopArray[0].y = rect->bottom;
  702.     leftTopArray[1].x = rect->left;
  703.     leftTopArray[1].y = rect->top;
  704.     leftTopArray[2].x = rect->right;
  705.     leftTopArray[2].y = rect->top;
  706.  
  707.     HPEN topLeftPen = CreatePen(PS_SOLID,1,topLeftColor);
  708.     HGDIOBJ oldTopLeftPen = SelectObject(destDC,topLeftPen);
  709.     Polyline(destDC,leftTopArray,3); 
  710.     SelectObject(destDC,oldTopLeftPen);
  711.     DeleteObject(topLeftPen);
  712.  
  713.     POINT bottomRightArray[3] = {NULL};
  714.     bottomRightArray[0].x = rect->right;
  715.     bottomRightArray[0].y = rect->top;
  716.     bottomRightArray[1].x = rect->right;
  717.     bottomRightArray[1].y = rect->bottom;
  718.     bottomRightArray[2].x = rect->left-1;
  719.     bottomRightArray[2].y = rect->bottom;
  720.  
  721.     HPEN bottomRightPen = CreatePen(PS_SOLID,1,bottomRightColor);
  722.     HGDIOBJ oldBottomRightPen = SelectObject(destDC,bottomRightPen);
  723.     Polyline(destDC,bottomRightArray,3); 
  724.     SelectObject(destDC,oldBottomRightPen);
  725.     DeleteObject(bottomRightPen);
  726. }
  727.  
  728. void CButtonImage::DrawImage(const HDC hDC,const POINT *pLeftTop,HANDLE hImage)
  729. {// begin DrawImage
  730.     if(hImage == NULL)
  731.         hImage = buttonImage;
  732.     switch(imageType)
  733.     {// begin imageType switch
  734.     case IMAGE_ICON:
  735.         DrawIconEx(hDC,pLeftTop->x,pLeftTop->y,(HICON)hImage,imageSize.cx,imageSize.cy,NULL,NULL,DI_NORMAL);
  736.         break;
  737.     case IMAGE_BITMAP:
  738.         DrawTransparentBitmap(hDC,(HBITMAP)hImage,pLeftTop->x,pLeftTop->y,cTransparentColor);
  739.         break;
  740.     }// end imageType switch
  741. }// end DrawImage
  742.  
  743. void CButtonImage::DrawTransparentBitmap(HDC hDC, HBITMAP hBitmap, int x, int y, COLORREF crColour)
  744. // written by Paul Reynolds: Paul.Reynolds@cmgroup.co.uk
  745. // CodeGuru article: "Transparent Bitmap - True Mask Method"
  746. // http://codeguru.earthweb.com/bitmap/CISBitmap.shtml
  747. {
  748.     COLORREF crOldBack = SetBkColor(hDC,RGB(255,255,255));
  749.     COLORREF crOldText = SetTextColor(hDC,RGB(0,0,0));
  750.     HDC dcImage, dcTrans;
  751.  
  752.     // Create two memory dcs for the image and the mask
  753.     dcImage = CreateCompatibleDC(hDC);
  754.     dcTrans = CreateCompatibleDC(hDC);
  755.  
  756.     // Select the image into the appropriate dc
  757.     HGDIOBJ hOldBitmapImage = SelectObject(dcImage,hBitmap);
  758.  
  759.     // Create the mask bitmap
  760.     HBITMAP bitmapTrans = NULL;
  761.     // get the image dimensions
  762.     BITMAP bm = {NULL};
  763.     GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  764.     int nWidth = bm.bmWidth;
  765.     int nHeight = bm.bmHeight;
  766.     bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
  767.  
  768.     // Select the mask bitmap into the appropriate dc
  769.     HGDIOBJ hOldBitmapTrans = SelectObject(dcTrans,bitmapTrans);
  770.  
  771.     // Build mask based on transparent colour
  772.     SetBkColor(dcImage,crColour);
  773.     BitBlt(dcTrans, 0, 0, nWidth, nHeight, dcImage, 0, 0, SRCCOPY);
  774.  
  775.     // Do the work - True Mask method - cool if not actual display
  776.     BitBlt(hDC,x, y, nWidth, nHeight, dcImage, 0, 0, SRCINVERT);
  777.     BitBlt(hDC,x, y, nWidth, nHeight, dcTrans, 0, 0, SRCAND);
  778.     BitBlt(hDC,x, y, nWidth, nHeight, dcImage, 0, 0, SRCINVERT);
  779.  
  780.     // Restore settings
  781.     // don't delete this, since it is the bitmap
  782.     SelectObject(dcImage,hOldBitmapImage);
  783.     // delete bitmapTrans
  784.     DeleteObject(SelectObject(dcTrans,hOldBitmapTrans));
  785.     SetBkColor(hDC,crOldBack);
  786.     SetTextColor(hDC,crOldText);
  787.     // clean up
  788.     DeleteDC(dcImage);
  789.     DeleteDC(dcTrans);
  790. }
  791.  
  792. void CButtonImage::SetTransparentColor(COLORREF cColor)
  793. {// begin SetTransparentColor
  794.     cTransparentColor = cColor;
  795. }// end SetTransparentColor
  796.  
  797. void CButtonImage::Cleanup()
  798. {// begin Cleanup
  799.     CleanUpImage();
  800. }// end Cleanup
  801.  
  802. void CButtonImage::Setup()
  803. {// begin Setup
  804.     // initilize variables
  805.     appInstance = NULL;
  806.     ctrlWnd = NULL;
  807.     m_hWnd = NULL;
  808.     oldWndProc = NULL;
  809.     flags = NULL;
  810.     imageSize.cx = 0;
  811.     imageSize.cy = 0;
  812.     imageTopLeft.x = 0;
  813.     imageTopLeft.y = 0;
  814.     IsDown = false;
  815.     borderSize.cx = GetSystemMetrics(SM_CXEDGE);
  816.     borderSize.cy = GetSystemMetrics(SM_CYEDGE);
  817.     m_nTextStyles = DT_LEFT|DT_WORDBREAK|DT_NOCLIP;
  818.     m_nStyles = 0;
  819.     lastPoint.x = 0;
  820.     buttonState = BST_CHECKED;
  821.     lastPoint.y = 0;
  822.     buttonImage = NULL;
  823.     hasFocus = false;
  824.     firstDraw = true;
  825.     ctrlID = 0;
  826.     parentWnd = NULL;
  827.     buttonTopLeft.x = 0;
  828.     buttonTopLeft.y = 0;
  829.     cTransparentColor = RGB(255,0,255);
  830. }// end Setup
  831.  
  832. bool CButtonImage::OnDestroy()
  833. {// begin OnDestroy
  834.     // remove subclass of owner's window message function
  835.     ::SetWindowLong(ctrlWnd,GWL_WNDPROC,(DWORD)oldWndProc);
  836.     Cleanup();
  837.     return true;
  838. }// end OnDestroy
  839.  
  840. HWND CButtonImage::GetSafeHwnd(void)
  841. {// begin GetSafeHwnd
  842.     return ctrlWnd;
  843. }// end GetSafeHwnd
  844. /*
  845. LRESULT CButtonImage::OnSetText(WPARAM wParam,LPARAM lParam)
  846. {// begin OnSetText
  847.     LRESULT lResult = CallWindowProc(oldWndProc,ctrlWnd,WM_SETTEXT,wParam,lParam);
  848.     SetOffset();
  849.     return lResult;
  850. }// end OnSetText
  851. */