2014년 10월 29일 수요일

다이얼로그를 비트맵 모양으로 자르기

/************************************************************************/
/* 윈도우를 그림 모양으로 자르기                                                              */
/************************************************************************/
void CDmbgDlg::SetShapeBitmap(HBITMAP hBitmap, COLORREF clrTransparent)
{
     CRgn rgnBitmap; // 비트맵에서 추출한 영역을 저장하는 변수

     if(hBitmap == NULL)
     {
          return;
     }
     if(rgnBitmap.m_hObject)
     {
          rgnBitmap.DeleteObject();
     }
     rgnBitmap.CreateRectRgn(0, 0, 0, 0);
     BITMAP bmpInfo;

     ::GetObject(hBitmap, sizeof(bmpInfo), &bmpInfo);
     BITMAPINFOHEADER Header32Bit;

     ::memset(&Header32Bit, 0, sizeof(Header32Bit));
     Header32Bit.biSize   = sizeof(BITMAPINFOHEADER);
     Header32Bit.biWidth   = bmpInfo.bmWidth;
     Header32Bit.biHeight  = bmpInfo.bmHeight;
     Header32Bit.biPlanes  = 1;
     Header32Bit.biBitCount  = 32;
     Header32Bit.biCompression = BI_RGB;

     HDC hScreenDC = ::GetDC(NULL);
     HDC hMemDC = ::CreateCompatibleDC(hScreenDC);

     void *pBmpBits = NULL;
     HBITMAP h32BitBmp = CreateDIBSection(hMemDC, (BITMAPINFO*)&Header32Bit,
                                                               DIB_RGB_COLORS, &pBmpBits, NULL, 0);
     if(h32BitBmp)
     {
          BITMAP bmpInfo32;
          ::GetObject(h32BitBmp, sizeof(bmpInfo32), &bmpInfo32);
       
          if(bmpInfo32.bmWidthBytes % 4 > 0)
               bmpInfo32.bmWidthBytes += (4 - (bmpInfo32.bmWidthBytes % 4));
       
         HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, h32BitBmp);
         HDC hBmpDC = ::CreateCompatibleDC(hMemDC);
       
         HBITMAP hOldBmp2 = (HBITMAP)::SelectObject(hBmpDC, hBitmap);
         ::BitBlt(hMemDC, 0, 0, bmpInfo32.bmWidth, bmpInfo32.bmHeight,
                   hBmpDC, 0, 0, SRCCOPY);
          ::SelectObject(hBmpDC, hOldBmp2);
          ::DeleteDC(hBmpDC);
         
          DWORD dwMaxRect = 100;
          HANDLE hRgnData = ::GlobalAlloc(GHND, sizeof(RGNDATAHEADER) + (sizeof(RECT) * dwMaxRect));
          RGNDATA *pRgnData = (RGNDATA*)::GlobalLock(hRgnData);
          pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
          pRgnData->rdh.iType  = RDH_RECTANGLES;
          pRgnData->rdh.nCount = 0;
          pRgnData->rdh.nRgnSize = 0;
          ::SetRect(&pRgnData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
          BYTE *pPixel = (BYTE*)bmpInfo32.bmBits + ((bmpInfo32.bmHeight - 1) * bmpInfo32.bmWidthBytes);
       
          int x, y, nStartX;
          long *pRGB;
          RECT *pRect;

         for(y = 0; y < bmpInfo32.bmHeight; y++)
         {
               for(x = 0; x < bmpInfo32.bmWidth; x++)
               {
                      nStartX = x;
                      pRGB = (long*)pPixel + x;
 
                     for(;x < bmpInfo32.bmWidth; x++, pRGB++)
                     {
                         if(::memcmp((char*)pRGB + 1, (char*)&clrTransparent + 1, 3) == 0)  break;
                     }
 
                     if(x > nStartX)
                     {
                             if(pRgnData->rdh.nCount >= dwMaxRect)
                             {
                                  ::GlobalUnlock(hRgnData);
                                  dwMaxRect += 100;
                                  hRgnData = ::GlobalReAlloc(hRgnData, sizeof(RGNDATAHEADER)
                                                                           + (sizeof(RECT) * dwMaxRect), GMEM_MOVEABLE);
                                  pRgnData = (RGNDATA*)::GlobalLock(hRgnData);    
                             }
 
                             pRect = (RECT*)&pRgnData->Buffer;
                             ::SetRect(pRect + pRgnData->rdh.nCount, nStartX, y, x, y + 1);
   
                             if(nStartX < pRgnData->rdh.rcBound.left)
                                      pRgnData->rdh.rcBound.left = nStartX;

                             if(y < pRgnData->rdh.rcBound.top)
                                      pRgnData->rdh.rcBound.top = y;

                             if(x > pRgnData->rdh.rcBound.right)
                                      pRgnData->rdh.rcBound.right = x;
   
                             if(y + 1 > pRgnData->rdh.rcBound.bottom)
                                      pRgnData->rdh.rcBound.bottom = y + 1;

                             pRgnData->rdh.nCount++;
       
                             if(pRgnData->rdh.nCount == 2000)
                             {
                                  CRgn NewRgn;
                                  if(NewRgn.CreateFromData(NULL, sizeof(RGNDATAHEADER)
                                                                        + (sizeof(RECT) * dwMaxRect), pRgnData))
                                  {
                                              rgnBitmap.CombineRgn(&rgnBitmap, &NewRgn, RGN_OR);
                                              NewRgn.DeleteObject();
                                  }
                                  pRgnData->rdh.nCount=0;
                                  SetRect(&pRgnData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
                             }
                      }
               }

               pPixel -= bmpInfo32.bmWidthBytes;
        }

        CRgn NewRgn;
 
        if(NewRgn.CreateFromData(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * dwMaxRect), pRgnData))
        {
               rgnBitmap.CombineRgn(&rgnBitmap, &NewRgn, RGN_OR);
               NewRgn.DeleteObject();
        }
 
         ::GlobalUnlock(hRgnData);
         ::GlobalFree(hRgnData);
 
         ::SelectObject(hMemDC, hOldBmp);
         ::DeleteObject(h32BitBmp);
     }
     ::DeleteDC(hMemDC);
     ::ReleaseDC(NULL, hScreenDC);
     SetWindowPos(NULL, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SWP_NOZORDER | SWP_NOMOVE);
     SetWindowRgn(rgnBitmap, ::IsWindowVisible(m_hWnd));
}

BOOL CDmbgDlg::OnInitDialog()
{
     CDialog::OnInitDialog();
     // Set the icon for this dialog.  The framework does this automatically
     //  when the application's main window is not a dialog
     SetIcon(m_hIcon, TRUE);   // Set big icon
     SetIcon(m_hIcon, FALSE);  // Set small icon

     // TODO: Add extra initialization here

     // 다이얼로그 그림 모양으로 자르기
     CBitmap m_bmpWindow;
     m_bmpWindow.LoadBitmap(IDB_BACKIMG);                    // 리소스에서 불러운 이미지 ID 입력
     SetShapeBitmap(m_bmpWindow, RGB(255,0,255));

     return TRUE;  // return TRUE  unless you set the focus to a control
}

댓글 없음: