博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
不规则按钮,支持普通Button,Radio Button, Check Button
阅读量:4314 次
发布时间:2019-06-06

本文共 25539 字,大约阅读时间需要 85 分钟。

使用白色作为透明色Mask创建不规则region

发几张图片(程序以bmp做例子,但是论坛不能传bmp)上来做个具体例子:

normal

down

focus

diable

mask

1 //Header File 2  3 #pragma once 4  5  6 // CRgnButton 7  8 #define WM_CXSHADE_RADIO    WM_USER+0x100 9 #define ALLOC_UNIT  10010 11 class CRgnButton : public CButton12 {13     DECLARE_DYNAMIC(CRgnButton)14 15 public:16     CRgnButton();17     virtual ~CRgnButton();18 19     enum DRAW_MODE { DRAW_NORMAL, DRAW_STRETCH, DRAW_TILED };20 public:21     void SetToolTipText(const CString &strTip);22     COLORREF SetTextColor(COLORREF colorNew);23     void SetSkin(UINT normal, UINT down, UINT over=0, UINT disabled=0, UINT focus=0,UINT mask=0,24         DRAW_MODE drawmode=DRAW_NORMAL,short border=0,short margin=0);25 public:26     virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);27 protected:28     virtual void PreSubclassWindow();29 30     afx_msg BOOL OnEraseBkgnd(CDC* pDC);31     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);32     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);33     afx_msg void OnMouseMove(UINT nFlags, CPoint point);34     afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);35     afx_msg void OnKillFocus(CWnd* pNewWnd);36     afx_msg BOOL OnBnClicked();37     afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);38 39     afx_msg HRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);40     afx_msg HRESULT OnRadioInfo(WPARAM wParam, LPARAM lParam);41     afx_msg HRESULT OnBMSetCheck(WPARAM wParam, LPARAM lParam);42     afx_msg HRESULT OnBMGetCheck(WPARAM wParam, LPARAM lParam);43     DECLARE_MESSAGE_MAP()44 45 protected:46     HRGN    CreateRgnFromBitmap(CBitmap &bmp, COLORREF cTransColor);47     void    FillWithBitmap(CDC* dc, CBitmap &bmp, RECT rc);48     void    DrawBitmap(CDC* dc, CBitmap &bmp, RECT rc, DRAW_MODE DrawMode);49     int        GetBitmapWidth (CBitmap *bmp);50     int        GetBitmapHeight (CBitmap *bmp);51     void    RelayEvent(UINT message, WPARAM wParam, LPARAM lParam);52 private:53     bool            m_bCheck;54     DWORD        m_Style;55     bool            m_bTrack;56     bool            m_bBtnDown;57     CToolTipCtrl    m_Tooltip;58     CBitmap        m_bNormal, m_bDown, m_bDisable, m_bMask, m_bOver, m_bFocus;59     short            m_nFocusRectMargin;60     COLORREF    m_cTextColor;61     HRGN            m_hClipRgn;62     bool            m_bHasBorder;63     DRAW_MODE    m_DrawMode;64 65     BYTE MinByte(BYTE a, BYTE b) { return (0xff < (a + b) )? 0xff : (a + b); }66 };
1 //Source Code  2 // RgnButton.cpp : 实现文件  3 //  4   5 #include "stdafx.h"  6 #include "RegionWnd.h"  7 #include "RgnButton.h"  8   9  10 // CRgnButton 11  12 IMPLEMENT_DYNAMIC(CRgnButton, CButton) 13  14 CRgnButton::CRgnButton() 15 : m_bCheck(false), m_bBtnDown(false), m_bTrack(false) 16 , m_DrawMode(DRAW_STRETCH) 17 , m_hClipRgn(NULL), m_nFocusRectMargin(0) 18 { 19     m_cTextColor = GetSysColor(COLOR_BTNTEXT); 20 } 21  22 CRgnButton::~CRgnButton() 23 { 24     if(m_hClipRgn) 25         DeleteObject(m_hClipRgn); 26 } 27  28  29 BEGIN_MESSAGE_MAP(CRgnButton, CButton) 30     ON_WM_ERASEBKGND() 31     ON_WM_LBUTTONDOWN() 32     ON_WM_LBUTTONUP() 33     ON_WM_MOUSEMOVE() 34     ON_WM_LBUTTONDBLCLK() 35     ON_WM_KILLFOCUS() 36 //    ON_CONTROL_REFLECT_EX(BN_CLICKED, &CRgnButton::OnBnClicked) 37     ON_WM_KEYDOWN() 38  39     ON_MESSAGE(WM_MOUSELEAVE,  OnMouseLeave) 40     ON_MESSAGE(WM_CXSHADE_RADIO,  OnRadioInfo) 41     ON_MESSAGE(BM_SETCHECK,  OnBMSetCheck) 42     ON_MESSAGE(BM_GETCHECK,  OnBMGetCheck) 43 END_MESSAGE_MAP() 44  45  46  47 // CRgnButton 消息处理程序 48  49  50  51 void CRgnButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 52 { 53     ASSERT(lpDrawItemStruct); 54  55     //Check if the button state is not in inconsistent mode... 56     POINT mouse_position; 57     if ( (m_bBtnDown) && (::GetCapture() == m_hWnd) && (::GetCursorPos(&mouse_position))) { 58         if (::WindowFromPoint(mouse_position) == m_hWnd){ 59             if ((GetState() & BST_PUSHED) != BST_PUSHED) { 60                 SetState(TRUE); 61                 return; 62             } 63         } else { 64             if ((GetState() & BST_PUSHED) == BST_PUSHED) { 65                 SetState(FALSE); 66                 return; 67             } 68         } 69     } 70  71     CString strCaption; 72     CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); 73     CRect rc=lpDrawItemStruct->rcItem; 74     int cx = rc.Width(); 75     int cy = rc.Height(); 76     // get text box position 77     RECT tr={ rc.left + m_nFocusRectMargin +2, rc.top, rc.right - m_nFocusRectMargin -2, rc.bottom }; 78  79     GetWindowText(strCaption);                            // get button text 80     pDC->SetBkMode(TRANSPARENT); 81  82     // Select the correct skin  83     if (lpDrawItemStruct->itemState & ODS_DISABLED){    // DISABLED BUTTON 84         if(m_bDisable.m_hObject == NULL) 85             // no skin selected for disabled state -> standard button 86             pDC->FillSolidRect(&rc, GetSysColor(COLOR_BTNFACE)); 87         else // paint the skin 88             DrawBitmap(pDC, m_bDisable, rc, m_DrawMode); 89         // if needed, draw the standard 3D rectangular border 90         if (m_bHasBorder)  91             pDC->DrawEdge(&rc, EDGE_RAISED, BF_RECT); 92         // paint the etched button text 93         pDC->SetTextColor(GetSysColor(COLOR_3DHILIGHT)); 94         pDC->DrawText(strCaption, &tr, DT_SINGLELINE|DT_VCENTER|DT_CENTER); 95         pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); 96         OffsetRect(&tr, -1, -1); 97         pDC->DrawText(strCaption, &tr, DT_SINGLELINE|DT_VCENTER|DT_CENTER); 98     } else {                                        // SELECTED (DOWN) BUTTON 99         if ( (lpDrawItemStruct->itemState & ODS_SELECTED) || m_bCheck ) {100             if(m_bDown.m_hObject==NULL) // no skin selected for selected state -> standard button101                 pDC->FillSolidRect(&rc, GetSysColor(COLOR_BTNFACE));102             else { // paint the skin103                 DrawBitmap(pDC, m_bDown, rc, m_DrawMode);104             }105             OffsetRect(&tr, 1, 1);  //shift text106             // if needed, draw the standard 3D rectangular border107             if (m_bHasBorder) 108                 pDC->DrawEdge(&rc, EDGE_SUNKEN, BF_RECT);109         } else {                                            // DEFAULT BUTTON110             if(m_bNormal.m_hObject==NULL) // no skin selected for normal state -> standard button                111             {112                 CString strRect;113                 strRect.Format(L"Rect: %d, %d, %d, %d\n", rc.left, rc.top, rc.right, rc.bottom);114                 OutputDebugString(strRect);115                 pDC->FillSolidRect(&rc, GetSysColor(COLOR_BTNFACE));116             }117             else if ( (m_bTrack) && (m_bOver.m_hObject != NULL)) { // paint the skin118                     DrawBitmap(pDC, m_bOver, rc, m_DrawMode);119             } else {120                 if ((lpDrawItemStruct->itemState & ODS_FOCUS)&&(m_bFocus.m_hObject != NULL)) {121                     DrawBitmap(pDC, m_bFocus, rc, m_DrawMode);122                 } else {123                     DrawBitmap(pDC, m_bNormal, rc, m_DrawMode);124                 }125             }126             // if needed, draw the standard 3D rectangular border127             if (m_bHasBorder) 128                 pDC->DrawEdge(&rc, EDGE_RAISED,BF_RECT);129         }130         // paint the focus rect131         if ((lpDrawItemStruct->itemState & ODS_FOCUS) && (m_nFocusRectMargin > 0)){132             rc.left   += m_nFocusRectMargin ;133             rc.top    += m_nFocusRectMargin ;134             rc.right  -= m_nFocusRectMargin ;135             rc.bottom -= m_nFocusRectMargin ;136             DrawFocusRect (lpDrawItemStruct->hDC, &rc) ;137         }138         // paint the enabled button text139         pDC->SetTextColor(m_cTextColor);140         pDC->DrawText(strCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER);141     }142 }143 144 int CRgnButton::GetBitmapWidth(CBitmap *bmp)145 {146     if(!bmp)147         return -1;148 149     BITMAP bm;150     bmp->GetBitmap(&bm);151 152     return bm.bmWidth;153 }154 155 int CRgnButton::GetBitmapHeight(CBitmap *bmp)156 {157     if(!bmp)158         return -1;159 160     BITMAP bm;161     bmp->GetBitmap(&bm);162 163     return bm.bmHeight;164 }165 166 void CRgnButton::DrawBitmap(CDC* dc, CBitmap &bmp, RECT rc, DRAW_MODE DrawMode)167 {168     if(DrawMode == DRAW_TILED){169         FillWithBitmap(dc, bmp, rc);170         return;171     }172     if(!bmp.GetSafeHandle()) 173         return;    //safe check174 175     CRect cr = rc;176     int cx=cr.Width();177     int cy=cr.Height();178     CDC dcBmp,dcMask;179     dcBmp.CreateCompatibleDC(dc);180     dcBmp.SelectObject(bmp);181 182     if (m_bMask.m_hObject!=NULL){183         dcMask.CreateCompatibleDC(dc);184         dcMask.SelectObject(m_bMask);185 186         CDC dcMem;187         dcMem.CreateCompatibleDC(dc);188         CBitmap bmpMem;189         bmpMem.CreateCompatibleBitmap(dc,cx,cy);190         CBitmap *oldBmp = dcMem.SelectObject(&bmpMem);191 192         dcMem.BitBlt(cr.left, cr.top, cx, cy, dc, 0, 0, SRCCOPY);193         if(DrawMode == DRAW_NORMAL){194             dcMem.BitBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, SRCINVERT);195             dcMem.BitBlt(cr.left, cr.top, cx, cy, &dcMask, 0, 0, SRCAND);196             dcMem.BitBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, SRCINVERT);197         } else {198             int bx=GetBitmapWidth(&bmp);199             int by=GetBitmapHeight(&bmp);200             dcMem.StretchBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, bx, by, SRCINVERT);201             dcMem.StretchBlt(cr.left, cr.top, cx, cy, &dcMask, 0, 0, bx, by, SRCAND);202             dcMem.StretchBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, bx, by, SRCINVERT);203         }204         dc->BitBlt(cr.left, cr.top, cx, cy, &dcMem, 0, 0, SRCCOPY);205 206         dcMem.SelectObject(oldBmp);207         dcMem.DeleteDC();208         bmpMem.DeleteObject();209 210         DeleteDC(dcMask);211     } else {212         if( DrawMode == DRAW_NORMAL){213             dc->BitBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, SRCCOPY);214         } else {215             int bx=GetBitmapWidth(&bmp);216             int by=GetBitmapHeight(&bmp);217             dc->StretchBlt(cr.left, cr.top, cx, cy, &dcBmp, 0, 0, bx, by, SRCCOPY);218         }219     }220     dcBmp.DeleteDC();221 }222 223 void CRgnButton::FillWithBitmap(CDC* dc, CBitmap &bmp, RECT rc)224 {225     if(!bmp.GetSafeHandle()) 226         return;227 228     CDC dcMem;229     dcMem.CreateCompatibleDC(dc);230     CBitmap *oldBmp = dcMem.SelectObject(&bmp);231 232     int w = rc.right - rc.left;233     int    h = rc.bottom - rc.top;234     int x, y, z;235     int    bx=GetBitmapWidth(&bmp);236     int    by=GetBitmapHeight(&bmp);237 238     for (y = rc.top ; y < h ; y += by){239         if ( (y + by) > h) 240             by = h - y;241         z=bx;242         for (x = rc.left ; x < w ; x += z){243             if ( (x + z) > w) 244                 z = w - x;245             dc->BitBlt(x, y, z, by, &dcMem, 0, 0, SRCCOPY);246         }247     }248 249     dcMem.SelectObject(oldBmp);250     dcMem.DeleteDC();251 }252 253 void CRgnButton::PreSubclassWindow()254 {255     m_Style=GetButtonStyle();    ///get specific BS_ styles256     if ( (m_Style & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX)257         m_Style=BS_CHECKBOX;258     else if ((m_Style & BS_AUTORADIOBUTTON)==BS_AUTORADIOBUTTON)259         m_Style=BS_RADIOBUTTON;260     else { m_Style=BS_PUSHBUTTON; }261 262     CButton::PreSubclassWindow();263     ModifyStyle(0, BS_OWNERDRAW);264 }265 266 BOOL CRgnButton::OnEraseBkgnd(CDC* pDC)267 {268     return TRUE;269 270 //    return CButton::OnEraseBkgnd(pDC);271 }272 273 void CRgnButton::OnLButtonDown(UINT nFlags, CPoint point)274 {275     RelayEvent(WM_LBUTTONDOWN, (WPARAM)nFlags, MAKELPARAM(LOWORD(point.x), LOWORD(point.y)));276 277     //If we are tracking this button, cancel it278     if (m_bTrack) {279         TRACKMOUSEEVENT t = {280             sizeof(TRACKMOUSEEVENT),281             TME_CANCEL | TME_LEAVE,282             m_hWnd,283             0 284         };285         if (::_TrackMouseEvent(&t)) {286             m_bTrack = false;287         }288     }289 290     CButton::OnLButtonDown(nFlags, point);291     m_bBtnDown = true;292 }293 294 void CRgnButton::OnLButtonUp(UINT nFlags, CPoint point)295 {296     if (m_Style){ //track mouse for radio & check buttons297         POINT p2 = point;298         ::ClientToScreen(m_hWnd, &p2);299         HWND mouse_wnd = ::WindowFromPoint(p2);300         if (mouse_wnd == m_hWnd){ // mouse is in button301             if (m_Style==BS_CHECKBOX) 302                 SetCheck(m_bCheck ? 0 : 1);303             if (m_Style==BS_RADIOBUTTON) 304                 SetCheck(1);305         }306     }307     //Pass this message to the ToolTip control308     RelayEvent(WM_LBUTTONUP,(WPARAM)nFlags,MAKELPARAM(LOWORD(point.x),LOWORD(point.y)));309 310     //Default-process the message311     m_bBtnDown = false;312     CButton::OnLButtonUp(nFlags, point);313 }314 315 void CRgnButton::OnMouseMove(UINT nFlags, CPoint point)316 {317     RelayEvent(WM_MOUSEMOVE,(WPARAM)nFlags,MAKELPARAM(LOWORD(point.x),LOWORD(point.y)));318 319     if ( (m_bBtnDown) && (::GetCapture() == m_hWnd)) {320         POINT p2 = point;321         ::ClientToScreen(m_hWnd, &p2);322         HWND mouse_wnd = ::WindowFromPoint(p2);323 324         bool bPressed = ((GetState() & BST_PUSHED) == BST_PUSHED);325         bool bNeedPressed = (mouse_wnd == m_hWnd);326         if (bPressed != bNeedPressed) {327             SetState(bNeedPressed ? TRUE : FALSE);328             Invalidate();329         }330     } else {331         if (!m_bTrack) {332             TRACKMOUSEEVENT t = {333                 sizeof(TRACKMOUSEEVENT),334                 TME_LEAVE,335                 m_hWnd,336                 0337             };338             if (::_TrackMouseEvent(&t)) {339                 m_bTrack = true;340                 Invalidate();341             }342         }343     }344 345     CButton::OnMouseMove(nFlags, point);346 }347 348 void CRgnButton::OnLButtonDblClk(UINT nFlags, CPoint point)349 {350     SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));351 352 //    CButton::OnLButtonDblClk(nFlags, point);353 }354 355 void CRgnButton::OnKillFocus(CWnd* pNewWnd)356 {357     if (::GetCapture() == m_hWnd) {358         ::ReleaseCapture();359         ASSERT (!m_bTrack);360         m_bBtnDown = false;361     }362 363     CButton::OnKillFocus(pNewWnd);364 }365 366 BOOL CRgnButton::OnBnClicked()367 {368     if (::GetCapture() == m_hWnd) {369         ::ReleaseCapture();370         ASSERT (!m_bTrack);371     }372 373     m_bBtnDown = false;374     return FALSE;375 }376 377 void CRgnButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)378 {379     if ( (m_Style) && (nChar==' ') ){ //needed stuff for check & radio buttons380         if (m_Style == BS_CHECKBOX) 381             SetCheck(m_bCheck ? 0 : 1);382         if (m_Style == BS_RADIOBUTTON) 383             SetCheck(1);384     }385 386     CButton::OnKeyDown(nChar, nRepCnt, nFlags);387 }388 389 HRESULT CRgnButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)390 {391     ASSERT(m_bTrack);392 393     m_bTrack = false;394     Invalidate();395 396     return 0;397 }398 399 HRESULT CRgnButton::OnRadioInfo(WPARAM wParam, LPARAM lParam)400 {401     if (m_bCheck){    //only checked buttons need to be unchecked402         m_bCheck = false;403         Invalidate();404     }405     return 0;406 }407 408 HRESULT CRgnButton::OnBMSetCheck(WPARAM wParam, LPARAM lParam)409 {410     m_bCheck = (wParam != 0);411 412     switch (m_Style)413     {414     case BS_RADIOBUTTON:415         if (m_bCheck) { //uncheck the other radio buttons (in the same group)416             HWND hthis,hwnd2,hpwnd;417             hpwnd=GetParent()->GetSafeHwnd();    //get button parent handle418             hwnd2=hthis=GetSafeHwnd();            //get this button handle419             if (hthis && hpwnd){                //consistency check420                 for( ; ; ){    //scan the buttons within the group421                     hwnd2=::GetNextDlgGroupItem(hpwnd, hwnd2, 0);422                     //until we reach again this button423                     if ( (hwnd2 == hthis) || (hwnd2 == NULL) ) 424                         break;425                     //post the uncheck message426                     ::PostMessage(hwnd2, WM_CXSHADE_RADIO, 0, 0);427                 }428             }429         }430         break;431     case BS_PUSHBUTTON:432         m_bCheck=false;433         ASSERT(false); // Must be a Check or Radio button to use this function434     }435 436     Invalidate();437     return 0;438 }439 440 HRESULT CRgnButton::OnBMGetCheck(WPARAM wParam, LPARAM lParam)441 {442     return m_bCheck;443 }444 445 void CRgnButton::SetSkin(UINT normal, UINT down, UINT over/* =0 */, 446              UINT disabled/* =0 */, UINT focus/* =0 */,UINT mask/* =0 */, 447              DRAW_MODE drawmode/* =1 */,short border/* =1 */,short margin/* =4 */)448 {449     m_bNormal.DeleteObject();    //free previous allocated bitmap450     m_bDown.DeleteObject();451     m_bOver.DeleteObject();452     m_bDisable.DeleteObject();453     m_bMask.DeleteObject();454     m_bFocus.DeleteObject();455 456     if (normal>0) m_bNormal.LoadBitmap(normal);457     if (down>0)      m_bDown.LoadBitmap(down);458     if (over>0)      m_bOver.LoadBitmap(over);459     if (focus>0)  m_bFocus.LoadBitmap(focus);460 461     if (disabled>0) 462         m_bDisable.LoadBitmap(disabled);463     else if (normal>0) 464         m_bDisable.LoadBitmap(normal);465 466     m_DrawMode = (DRAW_MODE)max(0,min(drawmode, DRAW_TILED));467     m_bHasBorder = (border > 0);468     m_nFocusRectMargin = max(0, margin);469 470     if (mask>0){471         m_bMask.LoadBitmap(mask);472         if (m_hClipRgn) 473             DeleteObject(m_hClipRgn);474         m_hClipRgn = CreateRgnFromBitmap(m_bMask, RGB(255,255,255));475         if (m_hClipRgn){476             SetWindowRgn(m_hClipRgn, TRUE);477             GetDC()->SelectClipRgn(CRgn::FromHandle(m_hClipRgn));478         }479         if (m_DrawMode == 0){480             SetWindowPos(NULL, 0, 0, GetBitmapWidth(&m_bMask),481                 GetBitmapHeight(&m_bMask), SWP_NOZORDER|SWP_NOMOVE);482         }483     }484 }485 486 HRGN CRgnButton::CreateRgnFromBitmap(CBitmap &bmp, COLORREF cTransColor)487 {488     HRGN hRgn = NULL;489     COLORREF cTolerance = RGB(0, 0, 0);490     BITMAP bm;491 492     bmp.GetBitmap(&bm);493     CDC dcMem;494     dcMem.CreateCompatibleDC(NULL);495 496     BITMAPINFOHEADER bInfoHead;497     bInfoHead.biSize = sizeof(BITMAPINFOHEADER);498     bInfoHead.biWidth = bm.bmWidth;499     bInfoHead.biHeight = bm.bmHeight; 500     bInfoHead.biPlanes = 1; 501     bInfoHead.biBitCount = 32; 502     bInfoHead.biCompression = BI_RGB; 503     bInfoHead.biSizeImage = 0; 504     bInfoHead.biXPelsPerMeter = 0; 505     bInfoHead.biYPelsPerMeter = 0; 506     bInfoHead.biClrUsed = 0; 507     bInfoHead.biClrImportant = 0; 508 509     void *pBit32 = NULL;510     HBITMAP hBmp32 = CreateDIBSection(dcMem.GetSafeHdc(), (BITMAPINFO *)&bInfoHead, DIB_RGB_COLORS, &pBit32, NULL, 0);511     if(hBmp32) {512         CBitmap *pBmp32 = CBitmap::FromHandle(hBmp32);513         BITMAP bm32;514         pBmp32->GetBitmap(&bm32);515         while(bm32.bmWidthBytes % 4)    //round to even516             bm32.bmWidthBytes++;517 518         CBitmap *oldBmp1 = dcMem.SelectObject(pBmp32);519         CDC dcTmp;520         dcTmp.CreateCompatibleDC(&dcMem);521         CBitmap *oldBmp2 = dcTmp.SelectObject(&bmp);522 523         dcMem.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcTmp, 0, 0, SRCCOPY);524 525         DWORD maxRects = ALLOC_UNIT;  526         HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));  527         RGNDATA *pData = (RGNDATA *)GlobalLock(hData);  528         pData->rdh.dwSize = sizeof(RGNDATAHEADER);  529         pData->rdh.iType = RDH_RECTANGLES;  530         pData->rdh.nCount = pData->rdh.nRgnSize = 0;  531         SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);532 533         BYTE lr = GetRValue(cTransColor);534         BYTE lg = GetGValue(cTransColor);535         BYTE lb = GetBValue(cTransColor);536         BYTE hr = MinByte(lr, GetRValue(cTolerance));537         BYTE hg = MinByte(lg, GetGValue(cTolerance));538         BYTE hb = MinByte(lb, GetBValue(cTolerance));539 540         BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;  541         for (int y = 0; y < bm.bmHeight; y++)  542         {  543             // Scan each bitmap pixel from left to right  544             for (int x = 0; x < bm.bmWidth; x++)  545             {  546                 // Search for a continuous range of "non transparent pixels"  547                 int x0 = x;  548                 LONG *p = (LONG *)p32 + x;  549                 while (x < bm.bmWidth)  550                 {  551                     BYTE b = GetRValue(*p);  552                     if (b >= lr && b <= hr)  553                     {  554                         b = GetGValue(*p);  555                         if (b >= lg && b <= hg)  556                         {  557                             b = GetBValue(*p);  558                             if (b >= lb && b <= hb)  559                                 // This pixel is "transparent"  560                                 break;  561                         }  562                     }  563                     p++;  564                     x++;  565                 }  566 567                 if (x > x0)  568                 {569                     // Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region  570                     if (pData->rdh.nCount >= maxRects)  571                     {  572                         GlobalUnlock(hData);  573                         maxRects += ALLOC_UNIT;  574                         hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);  575                         pData = (RGNDATA *)GlobalLock(hData);  576                     }  577                     RECT *pr = (RECT *)&pData->Buffer;  578                     SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);  579                     if (x0 < pData->rdh.rcBound.left)  580                         pData->rdh.rcBound.left = x0;  581                     if (y < pData->rdh.rcBound.top)  582                         pData->rdh.rcBound.top = y;  583                     if (x > pData->rdh.rcBound.right)  584                         pData->rdh.rcBound.right = x;  585                     if (y+1 > pData->rdh.rcBound.bottom)  586                         pData->rdh.rcBound.bottom = y+1;  587                     pData->rdh.nCount++;  588 589                     // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too  590                     // large (ie: > 4000). Therefore, we have to create the region by multiple steps.  591                     if (pData->rdh.nCount == 2000)  592                     {  593                         HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);  594                         if (hRgn)  595                         {  596                             CombineRgn(hRgn, hRgn, h, RGN_OR);  597                             DeleteObject(h);  598                         }  599                         else 600                             hRgn = h;  601                         pData->rdh.nCount = 0;  602                         SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);  603                     }  604                 }  605             }  606 607             // Go to next row (remember, the bitmap is inverted vertically)  608             p32 -= bm32.bmWidthBytes;  609         }  610 611         HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);  612         if (hRgn)  613         {  614             CombineRgn(hRgn, hRgn, h, RGN_OR);  615             DeleteObject(h);  616         }  617         else 618             hRgn = h;  619 620         // Clean up  621         GlobalFree(hData);622         dcMem.SelectObject(oldBmp1);623         DeleteObject(hBmp32);624         dcTmp.SelectObject(oldBmp2);625         dcTmp.DeleteDC();626     }627     dcMem.DeleteDC();628 629     return hRgn;630 }631 632 COLORREF CRgnButton::SetTextColor(COLORREF colorNew)633 {634     COLORREF colorTmp = m_cTextColor;635     m_cTextColor = colorNew;636 637     return colorTmp;638 }639 640 void CRgnButton::SetToolTipText(const CString &strTip)641 {642     if(m_Tooltip.m_hWnd==NULL){643         if(m_Tooltip.Create(this))    //first assignment644             if(m_Tooltip.AddTool(this, strTip))645                 m_Tooltip.Activate(1);646     } else {647         m_Tooltip.UpdateTipText(strTip,this);648     }649 }650 651 void CRgnButton::RelayEvent(UINT message, WPARAM wParam, LPARAM lParam)652 {653     if(NULL != m_Tooltip.m_hWnd){654         MSG msg;655         msg.hwnd = m_hWnd;656         msg.message = message;657         msg.wParam = wParam;658         msg.lParam = lParam;659         msg.time = 0;660         msg.pt.x = LOWORD(lParam);661         msg.pt.y = HIWORD(lParam);662 663         m_Tooltip.RelayEvent(&msg);664     }665 }

转载于:https://www.cnblogs.com/jojodru/archive/2012/08/23/2652856.html

你可能感兴趣的文章
MyBatis使用懒加载mybatis-config.xml配置
查看>>
《C++ Primer》第五版课后习题解答_第六章(2)(08-15)
查看>>
c语言第五次作业
查看>>
多线程执行显示进度条的实例
查看>>
【总结】 NOIp2018考时经历记
查看>>
DIY远程控制开关(tiny6410+LED+yeelink+curl)
查看>>
SGU[130] CIrcle
查看>>
深入V8引擎-Time核心方法之win篇(1)
查看>>
指令操作码与地址码
查看>>
Bogo排序
查看>>
字节对齐
查看>>
基于JavaConfig配置的拦截器使用
查看>>
HTML 个人资料框
查看>>
Selenium+IDEA+Maven+TestNG环境搭建
查看>>
Tyvj1057
查看>>
bzoj2463谁能赢呢?
查看>>
Java复习-arraylist和vector
查看>>
【单镜头反光相机】简介
查看>>
HTTP 之 Content-Type
查看>>
R聚类分析
查看>>