为什么我用SetWindowRgn创建不规则按钮没效果

maomao85 2014-01-23 10:00:06
我想创建带圆角的按钮,然后按钮是半透明的,我在网上看说用CreateRoundRectRgn和SetWindowRgn就可以创建不规则按钮,可是我这样做却没有效果

void CMyButton::PreSubclassWindow()
{
this->ModifyStyle(0, BS_OWNERDRAW); //修改为自绘button
//设置按钮的有效区域
CRgn rgn;
CRect rc;
GetClientRect(&rc);
//有效区域为一个角半径为5的圆角矩形
rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,10,10);
SetWindowRgn(rgn,TRUE);
rgn.DeleteObject();
CButton::PreSubclassWindow();
}
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
HDC hdc=lpDrawItemStruct->hDC;
CDC *pDC=CDC::FromHandle(hdc);
DrawAlphaButton(pDC);
}
void CMyButton::DrawAlphaButton(CDC *pDC)
{
CRect parantrect;
CRect rect;
CRect winrect;
GetClientRect(&rect);
GetWindowRect(&winrect);
GetParent()->GetClientRect(¶ntrect);
GetParent()->ScreenToClient(&winrect);//获取button控件相对于父窗口的坐标位置
CDC dcMem;
CDC dcMem2;//绘制纯色位图的内存DC
CDC dcMem3;//获取父窗口背景的内存DC
dcMem.CreateCompatibleDC(pDC);
dcMem2.CreateCompatibleDC(pDC);
dcMem3.CreateCompatibleDC(pDC);
CBitmap bkimg;
CBitmap bkimg2;
CBitmap bkimg3;
bkimg.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
bkimg2.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
bkimg3.CreateCompatibleBitmap(pDC, parantrect.Width(), parantrect.Height());
CBitmap *pImgOld=dcMem.SelectObject(&bkimg);
CBitmap *pImgOld2=dcMem2.SelectObject(&bkimg2);
CBitmap *pImgOld3=dcMem3.SelectObject(&bkimg3);
HBRUSH hbr=CreateSolidBrush(RGB(255,0,0));
FillRect(dcMem2,&rect,hbr);
DeleteObject(hbr);
HRGN hRgn=CreateRectRgn(winrect.left, winrect.top,winrect.right,winrect.bottom);
SelectClipRgn (dcMem3.m_hDC,hRgn);
GetParent()->SendMessage( WM_ERASEBKGND, (WPARAM)dcMem3.m_hDC, 0);
dcMem.BitBlt(0, 0, rect.Width(), rect.Height(), &dcMem3, winrect.left, winrect.top, SRCCOPY);
//将内存DC上的图象拷贝到前台
BLENDFUNCTION blend;
memset( &blend, 0, sizeof( blend) );
blend.BlendOp= AC_SRC_OVER;
blend.SourceConstantAlpha= 150; // 透明度 最大255
AlphaBlend (dcMem.m_hDC,0,0,rect.Width(), rect.Height(),dcMem2.m_hDC, 0,0,rect.Width(), rect.Height(),blend);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dcMem, 0, 0, SRCCOPY);
CString strText;
GetWindowText(strText);
SetBkMode(pDC->m_hDC,TRANSPARENT);
if (isbuttondown)
{
CRect rectdown=rect;
rectdown.OffsetRect(0,1);
DrawText(pDC->m_hDC,strText,-1,&rectdown,DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_WORD_ELLIPSIS);
}
else
{
DrawText(pDC->m_hDC,strText,-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_WORD_ELLIPSIS);
}

dcMem.DeleteDC();
dcMem2.DeleteDC();
dcMem3.DeleteDC();
bkimg.DeleteObject();
bkimg2.DeleteObject();
bkimg3.DeleteObject();

}
...全文
243 点赞 收藏 13
写回复
13 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
schlafenhamster 2014-01-27
创建 最大 30 个: void CDIDlg::OnBnClickedMyButton() { m_iBn++;// from -1 if(m_iBn >BUTTONS_MAX-1) //30 { m_iBn--; AfxMessageBox("Maximun arrived !"); return ; } pBn[m_iBn] = new MyButton; TCHAR ca[3];// '30' _itoa(m_iBn,ca,10); RECT rect; rect.top = BUTTONS_PER_ROW * (m_iBn/BUTTONS_PER_ROW+1) + m_iBn/BUTTONS_PER_ROW*CIRCLE_DIA; rect.left=(m_iBn%BUTTONS_PER_ROW)*CIRCLE_DIA; rect.bottom = rect.top+60; rect.right = rect.left+CIRCLE_DIA; pBn[m_iBn]->Create(ca,WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_OWNERDRAW, rect,this,WM_USER+m_iBn); pBn[m_iBn]->ShowWindow(SW_SHOW); pBn[m_iBn]->UpdateWindow(); pBn[m_iBn]->EnableWindow(); //circle CRgn rg; rg.CreateEllipticRgn(0,0,CIRCLE_DIA,CIRCLE_DIA); pBn[m_iBn]->SetWindowRgn(rg,TRUE); DeleteObject(rg); } BOOL MyButton::OnEraseBkgnd(CDC* pDC) { return TRUE; // return CButton::OnEraseBkgnd(pDC); } //#define PATTERN void MyButton::DrawItem(LPDRAWITEMSTRUCT lpDS) { CDC dc; dc.Attach(lpDS->hDC); CString text; this->GetWindowText(text); if(lpDS->itemState & ODS_SELECTED) color = RGB(255,1,1); else if(lpDS->itemState & ODS_FOCUS) color = RGB(1,255,1); else if(m_hover) color = RGB(188,50,99); else color = RGB(100,100,255); // RECT rect = lpDS->rcItem; CRgn rgn; rgn.CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom); int ret=::GetWindowRgn(lpDS->hwndItem,rgn); dc.SelectClipRgn(&rgn); #ifdef PATTERN dc.FillRect(&rect,&m_BackBr); #else dc.FillRect(&rect,&CBrush(color)); #endif DeleteObject(rgn); // SetBkMode(lpDS->hDC,TRANSPARENT); // HFONT oldFont=(HFONT)dc.SelectObject(m_font); ::DrawText(lpDS->hDC,text, text.GetLength(),&(lpDS->rcItem),DT_CENTER|DT_VCENTER|DT_SINGLELINE); dc.SelectObject(oldFont); dc.Detach(); }
回复
maomao85 2014-01-26
引用 11 楼 VisualEleven 的回复:
在CButton类的派生类中的DrawItem虚函数中自行绘制图形
不能自行绘制啊,我的按钮背景是一个位图啊~~
回复
Eleven 2014-01-26
引用 10 楼 maomao85 的回复:
[quote=引用 3 楼 schlafenhamster 的回复:] 对子控件 SetWindowRgn 不能 改变 窗口 外形。 需要 在 paint 时; pDC->SelectClipRgn
这样做果然是对的~~[/quote] 在CButton类的派生类中的DrawItem虚函数中自行绘制图形
回复
maomao85 2014-01-26
引用 3 楼 schlafenhamster 的回复:
对子控件 SetWindowRgn 不能 改变 窗口 外形。 需要 在 paint 时; pDC->SelectClipRgn
这样做果然是对的~~
回复
maomao85 2014-01-24
引用 5 楼 schlafenhamster 的回复:
“SetWindowRgn(rgn,TRUE);” 还是要的, 但 绘制时 要 pDC->SelectClipRgn
SetWindowRgn(rgn,TRUE); pDC->SelectClipRgn 一起用可以改变窗口外形?
回复
schlafenhamster 2014-01-24
“SetWindowRgn(rgn,TRUE);” 还是要的, 但 绘制时 要 pDC->SelectClipRgn
回复
maomao85 2014-01-24
引用 3 楼 schlafenhamster 的回复:
对子控件 SetWindowRgn 不能 改变 窗口 外形。 需要 在 paint 时; pDC->SelectClipRgn
你设置剪裁区,只是剪裁区以外的区域不会被绘制,可是这些不会被绘制的区域还是会被显示啊,那怎么搞?
回复
schlafenhamster 2014-01-24
对子控件 SetWindowRgn 不能 改变 窗口 外形。 需要 在 paint 时; pDC->SelectClipRgn
回复
快乐鹦鹉 2014-01-24
After a successful call to SetWindowRgn, the operating system owns the region specified by the region handle hRgn. The operating system does not make a copy of the region, so do not make any further function calls with this region handle, and do not close this region handle. 另外,该函数说明中强调,你给出的HRGN参数,必须长期保留,因为操作系统不会复制该区域。你的程序中,直接将该句柄delete了,所以不会起作用。可将HRGN定义为类成员变量,对话框析构时再删除。
回复
快乐鹦鹉 2014-01-24
The coordinates of a window’s window region are relative to the upper-left corner of the window, not the client area of the window. SetWindowRgn函数有说明,指定的坐标是相对窗口左上角的坐标,不是窗口客户区的坐标。你用GetClientRect得到的矩形坐标是不对的。
回复
maomao85 2014-01-24
引用 8 楼 allenhiman 的回复:
SetWindowRgn对具有WS_CHILD属性的窗口 不起作用
那怎么办?
回复
allenhiman 2014-01-24
SetWindowRgn对具有WS_CHILD属性的窗口 不起作用
回复
schlafenhamster 2014-01-24
可以 网上 有 “异形按钮”
回复
相关推荐
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2014-01-23 10:00
社区公告
暂无公告