15,979
社区成员
发帖
与我相关
我的任务
分享
HRGN C**Dlg ::DIBToRgn(HBITMAP hBmp, COLORREF BkColor, BOOL Direct)
{
// use to return the handle of the HGRN
HRGN hRgn = NULL;
#define MAX_ALLOC_RECTS 100
//the difference of the color
COLORREF Tolerance=0x00101010;
if (hBmp)
{
//creat the dib to save the dc
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC)
{
BITMAP bm;
//get the info of the bitmap
GetObject(hBmp, sizeof(bm), &bm);
BITMAPINFOHEADER BmpInfoh = { //the struct of the bitmap
sizeof(BITMAPINFOHEADER), // biSize
bm.bmWidth, // biWidth;
bm.bmHeight, // biHeight;
1, // biPlanes;
32, // biBitCount
BI_RGB, // biCompression;
0, // biSizeImage;
0, // biXPelsPerMeter;
0, // biYPelsPerMeter;
0, // biClrUsed;
0 // biClrImportant;
};
//design a void point to point to the bitmap
LPVOID pBit32;
//creat a DIB
HBITMAP hDib32 = CreateDIBSection(hMemDC,
(BITMAPINFO *)&BmpInfoh,
DIB_RGB_COLORS, &pBit32, NULL, 0);
if (hDib32)
{
//copy dib to DC
HBITMAP hOldib32 = (HBITMAP)SelectObject(hMemDC, hDib32);
// create a DC to save orgin bitmap
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
BITMAP bm32;
// get the new 34 bit Dib size
GetObject(hDib32, sizeof(bm32), &bm32);
//make sure the 32Dib's every line pilex's is 4 's times
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
//copy the orginal dib to DC
HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
//copy dib to memory DC
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
DWORD MaxRects = MAX_ALLOC_RECTS;
SYSTEM_INFO Sysinfo;
//get memory size
GetSystemInfo(&Sysinfo);
//make a stack which can chang big
//alloct memory
HANDLE hRcData=HeapCreate(HEAP_GENERATE_EXCEPTIONS,Sysinfo.dwPageSize, 0);
RGNDATA * pRcData=(RGNDATA*)HeapAlloc(hRcData,HEAP_ZERO_MEMORY,
sizeof(RGNDATAHEADER)+sizeof(RECT)*MaxRects);
//fill the the RGNDATA struck
pRcData->rdh.dwSize = sizeof(RGNDATAHEADER);
pRcData->rdh.iType = RDH_RECTANGLES;
pRcData->rdh.nCount = pRcData->rdh.nRgnSize = 0;
SetRect(&pRcData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
BYTE hr,hg,hb,lr,lg,lb;
switch(BkColor)
{
case RGB(255,255,255): //if the bkcolor is white
hr = GetRValue(BkColor);
hg = GetGValue(BkColor);
hb = GetBValue(BkColor);
lr = min(0xff, hr - GetRValue(Tolerance));
lg = min(0xff, hg - GetGValue(Tolerance));
lb = min(0xff, hb - GetBValue(Tolerance));
break;
case RGB(0,0,0): //if the bkcolor is black
lr = GetRValue(BkColor);
lg = GetGValue(BkColor);
lb = GetBValue(BkColor);
hr = min(0xff, lr + GetRValue(Tolerance));
hg = min(0xff, lg + GetGValue(Tolerance));
hb = min(0xff, lb + GetBValue(Tolerance));
break;
default: //if the bkcolor is other color
Tolerance=0x111111;
lr =max(0, GetRValue(BkColor)-GetRValue(Tolerance));
lg = max(0,GetGValue(BkColor)-GetGValue(Tolerance));
lb = max(0,GetBValue(BkColor)-GetBValue(Tolerance));
hr=min(0xff,GetRValue(BkColor)+GetRValue(Tolerance));
hg=min(0xff,GetGValue(BkColor)+GetGValue(Tolerance));
hb=min(0xff,GetBValue(BkColor)+GetBValue(Tolerance));
break;
}
// Get the bit point and do the search
BYTE *pBits = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
for (int y = 0; y < bm.bmHeight; y++)
{
for (int x = 0; x < bm.bmWidth; x++)
{
int x0 = x;
DWORD *pColor = (DWORD *)pBits + x;
BYTE dr,dg,db;
while (x < bm.bmWidth)
{
dr=GetRValue(*pColor);
dg=GetGValue(*pColor);
db=GetBValue(*pColor);
if ((dr>= lr && dr<= hr)&&(dg>=lg&&dg<=hg)&&(db>=lb&&db<=hb))
{
if(Direct)
break;
else
{
pColor++;
x++;
}
}
else if(Direct)
{
pColor++;
x++;
}
else
break;
}
if (x > x0)
{
if (pRcData->rdh.nCount >= MaxRects)
{
MaxRects += MAX_ALLOC_RECTS;
//re alloc the stack
pRcData=(RGNDATA*)HeapReAlloc(
hRcData,HEAP_ZERO_MEMORY,pRcData,
sizeof(RGNDATAHEADER)+sizeof(RECT)*MaxRects);
}
RECT *pr = (RECT *)&pRcData->Buffer;
SetRect(&pr[pRcData->rdh.nCount], x0, y, x, y+1);
pRcData->rdh.rcBound.left = x0;
pRcData->rdh.rcBound.top = y;
pRcData->rdh.rcBound.right = x;
pRcData->rdh.rcBound.bottom = y+1;
pRcData->rdh.nCount++;
if (pRcData->rdh.nCount == 3000)
{
HRGN tmphRgn = ExtCreateRegion(NULL,
sizeof(RGNDATAHEADER) + (sizeof(RECT) * MaxRects),
pRcData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, tmphRgn, RGN_OR);
DeleteObject(tmphRgn);
}
else
hRgn = tmphRgn;
pRcData->rdh.nCount = 0;
SetRect(&pRcData->rdh.rcBound,
MAXLONG, MAXLONG, 0, 0);
}
}
}
// search next line
pBits -= bm32.bmWidthBytes;
}
HRGN tmphRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * MaxRects), pRcData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, tmphRgn, RGN_OR);
DeleteObject(tmphRgn);
}
else
hRgn = tmphRgn;
// make a rect ,use this rect xor to the BkColor
//then we can get the rect we want
if(!Direct)
{
HRGN hRect=CreateRectRgn(0,0,bm.bmWidth,bm.bmHeight);
if(hRect)
{
CombineRgn(hRgn,hRgn,hRect,RGN_XOR);
DeleteObject(hRect);
}
else
return NULL;
}
//release the memory
HeapFree(hRcData,HEAP_NO_SERIALIZE,pRcData);
SelectObject(hDC, holdBmp);
DeleteDC(hDC);
DeleteObject(holdBmp);
}
SelectObject(hMemDC,hOldib32);
DeleteDC(hMemDC);
DeleteObject(hOldib32);
DeleteObject(hDib32);
}
else
DeleteDC(hMemDC);
}
}
return hRgn;
}
HBITMAP m_hBmp;
HRGN m_hClientRgn;
HRGN m_hWndRgn;//头文件中定义变量
CSkinDlg::CSkinDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSkinDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_hBmp=(HBITMAP)LoadImage(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
m_hClientRgn=CreateEllipticRgn(33,34,34,35);
m_hWndRgn=DIBToRgn(m_hBmp,0xffffff,TRUE );
}
BOOL CSkinDlg::OnInitDialog()
{
CDialog::OnInitDialog();
if( m_hWndRgn )
{
SetWindowRgn(m_hWndRgn,TRUE);
}
}
void C**::SetupRegion( CDC *pDC, CBitmap &cBitmap, COLORREF TransColor )
{
CDC memDC;
//创建与传入DC兼容的临时DC
memDC.CreateCompatibleDC( pDC );
CBitmap *pOldMemBmp = NULL;
//将位图选入临时DC
pOldMemBmp=memDC.SelectObject( &cBitmap );
CRgn wndRgn;
//创建总的窗体区域,初始region为0
wndRgn.CreateRectRgn( 0, 0, 0, 0 );
BITMAP bit;
cBitmap.GetBitmap ( &bit );//取得位图参数,这里要用到位图的长和宽
int y;
for( y = 0; y < bit.bmHeight; y ++ )
{
CRgn rgnTemp; //保存临时region
int iX = 0;
do
{
//跳过透明色找到下一个非透明色的点.
while ( iX < bit.bmWidth && memDC.GetPixel( iX, y ) == TransColor )
iX++;
//记住这个起始点
int iLeftX = iX;
//寻找下个透明色的点
while ( iX < bit.bmWidth && memDC.GetPixel( iX, y ) != TransColor )
++iX;
//创建一个包含起点与重点间高为1像素的临时“region”
rgnTemp.CreateRectRgn( iLeftX, y, iX, y + 1 );
//合并到主"region".
wndRgn.CombineRgn( &wndRgn, &rgnTemp, RGN_OR );
//删除临时"region",否则下次创建时和出错
rgnTemp.DeleteObject();
}while( iX < bit.bmWidth );
iX = 0;
}
if( pOldMemBmp )
{
memDC.SelectObject( pOldMemBmp );
}
CWnd * pWnd = pDC->GetWindow( );
pWnd->SetWindowRgn( wndRgn, TRUE );
pWnd->SetForegroundWindow( );
}