问一个关于按钮的问题 一个按钮,上面既有图标又有文字请问如何改变这个按钮的背景色以及该按钮上文字的颜色? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 在樣式里選擇owner draw ,處理WM_MEASUREITEM和WM_DRAWITEM消息.自已在里面繪圖. 在樣式里選擇owner draw ,處理WM_MEASUREITEM和WM_DRAWITEM消息.自已在里面繪圖.哦, 谢谢啊. 制作风格独特的按钮—用VC6扩展CButton类 (本文给你提供了文字的方法,位图的方法类似)-------------------------------------------------------------------------------- 一、 本文介绍一个CButton的派生类CLinkButton,用此派生类制作的按钮具有以下特点: 1、按钮的外观类似静态控件类CStatic 产生的对象。(参见图一) (图一) 2、当鼠标的光标移到按钮上,但并未按下时,光标改变形状,字体改变形状;按钮类似应用在工具条和菜单上的扁平钮效果。(参见图二) (图二) 3、当按钮按下的情形:(参见图三) (图三) 二、下面具体描述这种按钮的实现方法和步骤: 1. 在VC6的IDE环境中,生成一个基于对话框的PROJECT。 2. 将对话框资源中按钮的属性页打开,在“Style”标签页中选取按钮的“Owner Draw”(自绘)属性。 3. 将光标引入到应用程序的资源中。 4. 利用CLASSWIZARD,用CButton为基类,派生一个新类:CLinkButton。 5. 在派生类中重载基类CButton的虚函数: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 之所以要重载这个函数是因为选择了按钮的 “Owner Draw”属性后,当按钮的可视行为发生变化时,应用程序的框架要调用这个函数来重新绘制按钮。 6. 定制以下的消息处理: afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg BOOL OnEraseBkgnd(CDC* pDC); 7. 声明类成员变量定义: //定义字体变量 CFont fUnderline; //定义光标变量 HCURSOR hHand; //决定按钮是否按下 bool bLBtnDown; //决定鼠标是否在按钮上 bool bHighlight; 二、 派生类CLinkButton 的具体实现: 1.重载函数 DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。 void CLinkButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // 获取一个CDC指针 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //定义按钮区域并初始化 CRect rect(lpDrawItemStruct->rcItem); //设置背景模式 COLORREF oc = pDC->GetTextColor(); int iObk = pDC->SetBkMode(TRANSPARENT); //初始化按钮状态 UINT state = lpDrawItemStruct->itemState; CFont * pOldFont = NULL; int iYOffset = 0, iXOffset = 0; CString strText; GetWindowText(strText); rect.top += iYOffset; rect.left += iXOffset; if (state & ODS_DISABLED) { //按钮置灰状态(DISABLED) CBrush grayBrush; grayBrush.CreateSolidBrush (GetSysColor (COLOR_GRAYTEXT)); CSize sz = pDC->GetTextExtent(strText); int x = rect.left + (rect.Width() - sz.cx)/2; int y = rect.top + (rect.Height() - sz.cy)/2; rect.top += 2; rect.left += 2; pDC->SetTextColor(GetSysColor(COLOR_3DHIGHLIGHT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); rect.top -= 2; rect.left -= 2; pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } else { if (bHighlight)//光标在按钮上 { if (state & ODS_SELECTED) { //按下按钮 pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT)); } else {//未按下按钮 pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW)); } //字体颜色 pDC->SetTextColor(RGB(0,0,255)); //加下画线(也可以用其他字体) if (fUnderline.GetSafeHandle() == NULL) { CFont * pFont = GetFont(); ASSERT(pFont); LOGFONT lf; pFont->GetLogFont(&lf); lf.lfUnderline = TRUE; fUnderline.CreateFontIndirect(&lf); } pOldFont = pDC->SelectObject(&fUnderline); } else pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); if (pOldFont) pDC->SelectObject(pOldFont); } } 2.定制的消息处理函数 void OnMouseMove(UINT nFlags, CPoint point) { //设置一个定时器 SetTimer(1,10,NULL); // ... } 当鼠标光标移到按钮上时,执行此函数,定时器将发送一个 WM_TIMER消息到消息队列。 由OnTimer(UINT nIDEvent)函数处理这个消息。 void OnTimer(UINT nIDEvent) { //处理WM_TIMER消息 static bool pPainted = false; POINT pt; GetCursorPos(&pt); CRect rect; GetWindowRect (rect); if (bLBtnDown) { KillTimer (1); if (pPainted) InvalidateRect (NULL); pPainted = FALSE; return; } if (!rect.PtInRect (pt)) { bHighlight = false; KillTimer (1); if (pPainted) InvalidateRect(NULL); pPainted = false; return; } else { bHighlight = true; if (!pPainted) { pPainted = true; InvalidateRect(NULL); } } // CButton::OnTimer(nIDEvent); } BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { //当鼠标光标移到按钮上时,改变光标的形象 if (bHighlight) { ::SetCursor(hHand); return true; } // ... } int OnCreate(LPCREATESTRUCT lpCreateStruct) { ... CFont * pFont = GetFont(); ASSERT(pFont); LOGFONT lf; pFont->GetLogFont(&lf); lf.lfUnderline = TRUE; fUnderline.CreateFontIndirect(&lf); ... } 这个函数由框架在显示出按钮之前自动调用,我在这里初始化在按钮上显示的字体。 void OnLButtonUp(UINT nFlags, CPoint point) { bLBtnDown = false; if (bHighlight) { bHighlight = false; InvalidateRect(NULL); } ... } 当按下按钮又放开时调用这个函数。 void OnLButtonDown(UINT nFlags, CPoint point) { bLBtnDown = true; ... } 当按下按钮时调用这个函数。 BOOL OnEraseBkgnd(CDC* pDC) { COLORREF cr = GetSysColor(COLOR_3DFACE); int r = GetRValue(cr); int g = GetGValue(cr); int b = GetBValue(cr); if (r > 1) r -= 2; if (g > 1) g -= 2; if (r < 3 && g < 3 && b < 253) b += 2; COLORREF cr1 = RGB(r,g,b); CRect rc; GetClientRect(rc); pDC->FillSolidRect(rc, cr1); ... } 当按钮的背景需要重画时,应用程序框架调用此函数。编译并运行PROJECT LinkBtn, 效果与本文的图一、图二、图三一样。 先定义一个CIEButton类class CIEButton : public CButton{// Constructionpublic: CIEButton();// Attributespublic:// Operationspublic:// Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CIEButton) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); //}}AFX_VIRTUAL// Implementationpublic: //设置状态,查看鼠标是否位于按钮之上 BOOL IsMouseOn; virtual ~CIEButton(); // Generated message map functionsprotected: //{{AFX_MSG(CIEButton) afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnClicked(); //}}AFX_MSG DECLARE_MESSAGE_MAP()};按钮上绘图的主要函数:void CIEButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: Add your code to draw the specified item CDC ButtonDC; CBitmap bitmapTrans; BITMAP bmp; CDC mem; CRect rc,rc2; //得到用于绘制按钮的DC ButtonDC.Attach( lpDrawItemStruct->hDC ); //准备用于向按钮区域传输位图 mem.CreateCompatibleDC(&ButtonDC); //获取按钮所占的矩形大小 rc=lpDrawItemStruct->rcItem; rc2=rc; //在任何状态下,图片是首先要绘绘制的 bitmapTrans.LoadBitmap(IDB_IE);//IDB_IE为你的资源位图标识符 bitmapTrans.GetBitmap(&bmp); CBitmap *old=mem.SelectObject(&bitmapTrans); int x,y; x=rc.Width()/2-bmp.bmWidth/2; y=rc.Height()/2-bmp.bmHeight/2; //向按钮中心点传输位图 ButtonDC.BitBlt(x,y,rc.right,rc.bottom,&mem, 0, 0, SRCCOPY); mem.SelectObject(old); //获取按钮目前所处的状态,根据不同的状态绘制不同的按钮 //如果鼠标移入按钮,绘制浮起状态 if (IsMouseOn ) { //为按钮绘制立体效果 rc.top=rc.top+1;rc.bottom=rc.bottom-1; rc.left=rc.left+1;rc.right=rc.right-1; //绘制立体边框 ButtonDC.Draw3dRect(&rc,RGB(255,255,255),RGB(0,0,0)); } //如果按钮被按下,绘制下沉立体效果 if(lpDrawItemStruct->itemAction &ODA_SELECT) { rc2.top=rc2.top+1;rc2.bottom=rc2.bottom-1; rc2.left=rc2.left+1;rc2.right=rc2.right-1; //绘制立体边框 ButtonDC.Draw3dRect(&rc2,RGB(0,0,0),RGB(255,255,255)); } }void CIEButton::OnMouseMove(UINT nFlags, CPoint point) { //如果鼠标移入按钮 if(!IsMouseOn) { this->IsMouseOn=TRUE; //重绘整个控件 this->Invalidate(); } CButton::OnMouseMove(nFlags, point);}void CIEButton::OnClicked() { AfxMessageBox("测试信息"); }其他的就不用再讲了吧!^_^^_^ 这个控件叫什么名字? 解决了问题,松口气 消息映射 一个非常简单的串口通信的问题!!!!! 一个非常简单的问题请高手们帮忙看看..... 急. 中秋快乐 各位高手,有没有用过类似于windows的搜索图标? 不明白new 这样的东东如何实现好????? DLL中能不能导出重载函数,怎么做? 有符号十六进制"0xFFEA"如何快速计算得到"-22",是否有相关函数? 为何选用Multithreaded DLL编译程序出错
(本文给你提供了文字的方法,位图的方法类似)--------------------------------------------------------------------------------
一、 本文介绍一个CButton的派生类CLinkButton,用此派生类制作的按钮具有以下特点: 1、按钮的外观类似静态控件类CStatic 产生的对象。(参见图一) (图一) 2、当鼠标的光标移到按钮上,但并未按下时,光标改变形状,字体改变形状;按钮类似应用在工具条和菜单上的扁平钮效果。(参见图二) (图二) 3、当按钮按下的情形:(参见图三) (图三) 二、下面具体描述这种按钮的实现方法和步骤: 1. 在VC6的IDE环境中,生成一个基于对话框的PROJECT。 2. 将对话框资源中按钮的属性页打开,在“Style”标签页中选取按钮的“Owner Draw”(自绘)属性。 3. 将光标引入到应用程序的资源中。 4. 利用CLASSWIZARD,用CButton为基类,派生一个新类:CLinkButton。 5. 在派生类中重载基类CButton的虚函数: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 之所以要重载这个函数是因为选择了按钮的 “Owner Draw”属性后,当按钮的可视行为发生变化时,应用程序的框架要调用这个函数来重新绘制按钮。 6. 定制以下的消息处理: afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg BOOL OnEraseBkgnd(CDC* pDC); 7. 声明类成员变量定义: //定义字体变量 CFont fUnderline; //定义光标变量 HCURSOR hHand; //决定按钮是否按下 bool bLBtnDown; //决定鼠标是否在按钮上 bool bHighlight; 二、 派生类CLinkButton 的具体实现: 1.重载函数 DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。 void CLinkButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // 获取一个CDC指针 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //定义按钮区域并初始化 CRect rect(lpDrawItemStruct->rcItem); //设置背景模式 COLORREF oc = pDC->GetTextColor(); int iObk = pDC->SetBkMode(TRANSPARENT); //初始化按钮状态 UINT state = lpDrawItemStruct->itemState; CFont * pOldFont = NULL; int iYOffset = 0, iXOffset = 0; CString strText; GetWindowText(strText); rect.top += iYOffset; rect.left += iXOffset; if (state & ODS_DISABLED) { //按钮置灰状态(DISABLED) CBrush grayBrush; grayBrush.CreateSolidBrush (GetSysColor (COLOR_GRAYTEXT)); CSize sz = pDC->GetTextExtent(strText); int x = rect.left + (rect.Width() - sz.cx)/2; int y = rect.top + (rect.Height() - sz.cy)/2; rect.top += 2; rect.left += 2; pDC->SetTextColor(GetSysColor(COLOR_3DHIGHLIGHT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); rect.top -= 2; rect.left -= 2; pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } else { if (bHighlight)//光标在按钮上 { if (state & ODS_SELECTED) { //按下按钮 pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT)); } else {//未按下按钮 pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW)); } //字体颜色 pDC->SetTextColor(RGB(0,0,255)); //加下画线(也可以用其他字体) if (fUnderline.GetSafeHandle() == NULL) { CFont * pFont = GetFont(); ASSERT(pFont); LOGFONT lf; pFont->GetLogFont(&lf); lf.lfUnderline = TRUE; fUnderline.CreateFontIndirect(&lf); } pOldFont = pDC->SelectObject(&fUnderline); } else pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT)); pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); if (pOldFont) pDC->SelectObject(pOldFont); } } 2.定制的消息处理函数 void OnMouseMove(UINT nFlags, CPoint point) { //设置一个定时器 SetTimer(1,10,NULL); // ... } 当鼠标光标移到按钮上时,执行此函数,定时器将发送一个 WM_TIMER消息到消息队列。 由OnTimer(UINT nIDEvent)函数处理这个消息。 void OnTimer(UINT nIDEvent) { //处理WM_TIMER消息 static bool pPainted = false; POINT pt; GetCursorPos(&pt); CRect rect; GetWindowRect (rect); if (bLBtnDown) { KillTimer (1); if (pPainted) InvalidateRect (NULL); pPainted = FALSE; return; } if (!rect.PtInRect (pt)) { bHighlight = false; KillTimer (1); if (pPainted) InvalidateRect(NULL); pPainted = false; return; } else { bHighlight = true; if (!pPainted) { pPainted = true; InvalidateRect(NULL); } } // CButton::OnTimer(nIDEvent); } BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { //当鼠标光标移到按钮上时,改变光标的形象 if (bHighlight) { ::SetCursor(hHand); return true; } // ... } int OnCreate(LPCREATESTRUCT lpCreateStruct) { ... CFont * pFont = GetFont(); ASSERT(pFont); LOGFONT lf; pFont->GetLogFont(&lf); lf.lfUnderline = TRUE; fUnderline.CreateFontIndirect(&lf); ... } 这个函数由框架在显示出按钮之前自动调用,我在这里初始化在按钮上显示的字体。 void OnLButtonUp(UINT nFlags, CPoint point) { bLBtnDown = false; if (bHighlight) { bHighlight = false; InvalidateRect(NULL); } ... } 当按下按钮又放开时调用这个函数。 void OnLButtonDown(UINT nFlags, CPoint point) { bLBtnDown = true; ... } 当按下按钮时调用这个函数。 BOOL OnEraseBkgnd(CDC* pDC) { COLORREF cr = GetSysColor(COLOR_3DFACE); int r = GetRValue(cr); int g = GetGValue(cr); int b = GetBValue(cr); if (r > 1) r -= 2; if (g > 1) g -= 2; if (r < 3 && g < 3 && b < 253) b += 2; COLORREF cr1 = RGB(r,g,b); CRect rc; GetClientRect(rc); pDC->FillSolidRect(rc, cr1); ... } 当按钮的背景需要重画时,应用程序框架调用此函数。编译并运行PROJECT LinkBtn, 效果与本文的图一、图二、图三一样。
先定义一个CIEButton类
class CIEButton : public CButton
{
// Construction
public:
CIEButton();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CIEButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL// Implementation
public:
//设置状态,查看鼠标是否位于按钮之上
BOOL IsMouseOn;
virtual ~CIEButton(); // Generated message map functions
protected:
//{{AFX_MSG(CIEButton)
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnClicked();
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};按钮上绘图的主要函数:
void CIEButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
CDC ButtonDC;
CBitmap bitmapTrans;
BITMAP bmp;
CDC mem;
CRect rc,rc2;
//得到用于绘制按钮的DC
ButtonDC.Attach( lpDrawItemStruct->hDC );
//准备用于向按钮区域传输位图
mem.CreateCompatibleDC(&ButtonDC);
//获取按钮所占的矩形大小
rc=lpDrawItemStruct->rcItem;
rc2=rc;
//在任何状态下,图片是首先要绘绘制的
bitmapTrans.LoadBitmap(IDB_IE);//IDB_IE为你的资源位图标识符
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
int x,y;
x=rc.Width()/2-bmp.bmWidth/2;
y=rc.Height()/2-bmp.bmHeight/2;
//向按钮中心点传输位图
ButtonDC.BitBlt(x,y,rc.right,rc.bottom,&mem, 0, 0, SRCCOPY);
mem.SelectObject(old);
//获取按钮目前所处的状态,根据不同的状态绘制不同的按钮
//如果鼠标移入按钮,绘制浮起状态
if (IsMouseOn )
{
//为按钮绘制立体效果
rc.top=rc.top+1;rc.bottom=rc.bottom-1;
rc.left=rc.left+1;rc.right=rc.right-1;
//绘制立体边框
ButtonDC.Draw3dRect(&rc,RGB(255,255,255),RGB(0,0,0));
}
//如果按钮被按下,绘制下沉立体效果
if(lpDrawItemStruct->itemAction &ODA_SELECT)
{
rc2.top=rc2.top+1;rc2.bottom=rc2.bottom-1;
rc2.left=rc2.left+1;rc2.right=rc2.right-1;
//绘制立体边框
ButtonDC.Draw3dRect(&rc2,RGB(0,0,0),RGB(255,255,255));
}
}void CIEButton::OnMouseMove(UINT nFlags, CPoint point)
{
//如果鼠标移入按钮
if(!IsMouseOn)
{
this->IsMouseOn=TRUE;
//重绘整个控件
this->Invalidate();
}
CButton::OnMouseMove(nFlags, point);
}void CIEButton::OnClicked()
{
AfxMessageBox("测试信息");
}
其他的就不用再讲了吧!^_^^_^