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