异形图片问题,有点难。

afhel 2009-04-02 07:37:59
开始LoadImage(...)大小设置为0,0,然后SetupRegion(.,.,.),最后在onpaint中作为背景图,可以显示正常。
当loadImage(....)大小设置缩小一些179,126,然后SetupRegion(.,.,.),最后在onpaint中作为背景图,则最上面的一行就没有去掉,怎么回事呢。

void 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();
}
...全文
247 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
mirlemon 2010-12-13
  • 打赏
  • 举报
回复
好东西啊~~
非常感谢!
Fireway2008 2009-04-03
  • 打赏
  • 举报
回复
补充一下,退出程序之前,在对话框的析构函数里边,
记得把HBITMAP m_hBmp; 释放掉。
DeleteObject(m_hBmp); 防资源泄露
ssli 2009-04-03
  • 打赏
  • 举报
回复
Tinary3v0 这么快,就贴出来了。
ssli 2009-04-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cnzdgs 的回复:]
把 <=都改成 <。
另外再提一下,GetPixel效率较低,最好改成直接处理图象数据。
[/Quote]
但是这样不能根据图片及其透明色来设置不规则窗口。
楼主如果是要实现这样的功能,我能提供给你一个函数。
请告诉你的QQ或MSN
xghuzd 2009-04-03
  • 打赏
  • 举报
回复
up
Tinary3v0 2009-04-03
  • 打赏
  • 举报
回复
另外有这样一个函数可以不适用GetPexil 从图像中得到透明色除外的区域 有点长:
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);
}

}
Tinary3v0 2009-04-03
  • 打赏
  • 举报
回复
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( );
}

的确是cnzdgs说的一样 原因是应该是因为如果图像宽度是bmWidth 而起始是从0记数的话 只需要记数到bmWidth-1 就可以了
也就是while和for循环界限没有设定好。
jlj84237485 2009-04-02
  • 打赏
  • 举报
回复
帮顶一下
allenhiman 2009-04-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cnzdgs 的回复:]
把 <=都改成 <。
另外再提一下,GetPixel效率较低,最好改成直接处理图象数据。
[/Quote]

这样就好了吗?请稍微解释下 :>
cnzdgs 2009-04-02
  • 打赏
  • 举报
回复
另外再提一下,你可以给窗口加上WS_EX_LAYERED扩展风格,用SetLayeredWindowAttributes设置透明色,然后直接贴图就可以了,这样处理比较简单。
cnzdgs 2009-04-02
  • 打赏
  • 举报
回复
把<=都改成<。
另外再提一下,GetPixel效率较低,最好改成直接处理图象数据。
allenhiman 2009-04-02
  • 打赏
  • 举报
回复
你是说假设图片实际高度为h,你loadimg实际设置高度为h-1?
函数利用CBitmap &cBitmap,一般用HBITMAP比较合适吧
你这个cBitmap得来的代码是怎样的
怀疑你这个cBitmap本来第一行就是实色
allenhiman 2009-04-02
  • 打赏
  • 举报
回复
开始LoadImage(...)大小设置为0,0
loadImage(....)大小设置缩小一些179,126
把什么设置缩小一些?

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧