以前也是对windows有些研究的,只是近来搞C#把底层的东西忘了不少,现在连windows都有哪些消息都不知道了,以前能够娴熟的利用windows消息写出奇妙的东西,现在用mfc都不清楚mfc的消息路由有谁到谁了,这几天又做C++开发,原来的是wxWidgets用着不是很爽,基本都很多和mfc的一样,有点就是开源跨平台,缺点是资料太少,特别是中文的.所以就想把那些代码转成中文的.
现在也想预热下,温习下用mfc来开发东西,就把自己经过的点滴记下,一来自己日后忘了可以直接看,二来也可以为新手朋友们提供点有点用的东西吧.
按钮是比较常用的控件了,几乎每个windows桌面的窗口中都有,所以就先看看按钮怎么来美化下,其实美化下也就是添加点颜色、图片和效果。
当然了mfc中CBitmapButton已经可以做到好的效果,但是可能会不知道其中的实现的原理,为了能够为以后做点铺垫,所以自己动手来写个类似于CBitmapButton的类来
我这里命名CDynamicButton从CButton继承而来.记得好像以前美化是从DrawItem中来的,于是就重载了CButton的DrawItem方法,然后就如下来创建一个按钮:
为了测试先建一个基于对话框的工程,我在对话框的OnInitDialog中创建了pButton按钮
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
CDynamicButton * pButton = new CDynamicButton(IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4);
pButton -> Create(TEXT( " My Button " ),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | WS_TABSTOP,CRect(CPoint( 10 , 10 ),CSize( 200 , 200 )), this , 601 );
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
因为要给不同的状态给按钮不同图片,所以这个
CDynamicButton的构造函数中获取四个图片的资源ID,从而来设置不同状态下的图片.一定要给按钮设为BS_OWNERDRAW样式才可以的,这样父窗口在重新绘制前就会给按钮发送重绘消息的.
如果在窗口中直接添加按钮控件,直接把按钮ID与按钮变量关联起来,把变量类型声明为 CDynamicButton,然后可以通过CDynamicButton中的几个设置bmp的方法,设置不同状态下的图片
也是为了能够直接在其他窗口中直接添加控件来使用这个类,所以这个类定义如下:
// CDynamicButton
class CDynamicButton : public CButton
{
DECLARE_DYNAMIC(CDynamicButton)
public :
CDynamicButton();
CDynamicButton(UINT nNormalResourceId,UINT nOverResourceI,UINT nDownResourceId,UINT nDisalbeResourceId);
virtual ~ CDynamicButton();
void SetNormalBmp(UINT nNormalResourceId);
void SetOverBmp(UINT nNormalResourceId);
void SetDownBmp(UINT nNormalResourceId);
void SetDisableBmp(UINT nNormalResourceId);
protected :
void DrawBitmap(CDC * pDC,CRect & rect,CBitmap * pBmp);
private :
CBitmap * m_pNormalBmp;
CBitmap * m_pOverBmp;
CBitmap * m_pDownBmp;
CBitmap * m_pDisableBmp;
protected :
DECLARE_MESSAGE_MAP()
public :
afx_msg void OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual void DrawItem(LPDRAWITEMSTRUCT /* lpDrawItemStruct */ );
afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
afx_msg void OnBnKillfocus();
};
而相应的cpp文件我也一下贴出来再做说明了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//
#include " stdafx.h "
#include " Button.h "
#include " DynamicButton.h "
// CDynamicButton
IMPLEMENT_DYNAMIC(CDynamicButton, CButton)
CDynamicButton::CDynamicButton()
{
}
CDynamicButton::CDynamicButton(UINT nNormalResourceId,UINT nOverResourceI,UINT nDownResourceId,UINT nDisalbeResourceId)
{
m_pNormalBmp = new CBitmap();
m_pNormalBmp -> LoadBitmapW( nNormalResourceId);
m_pOverBmp = new CBitmap();
m_pOverBmp -> LoadBitmapW( nOverResourceI);
m_pDownBmp = new CBitmap();
m_pDownBmp -> LoadBitmapW( nDownResourceId);
m_pDisableBmp = new CBitmap();
m_pDisableBmp -> LoadBitmapW( nDisalbeResourceId);
}
CDynamicButton:: ~ CDynamicButton()
{
m_pNormalBmp -> DeleteObject();
delete m_pNormalBmp;
}
BEGIN_MESSAGE_MAP(CDynamicButton, CButton)
ON_WM_DRAWITEM()
ON_WM_MBUTTONDOWN()
ON_CONTROL_REFLECT(BN_KILLFOCUS, & CDynamicButton::OnBnKillfocus)
END_MESSAGE_MAP()
// CDynamicButton 消息处理程序
void CDynamicButton::SetNormalBmp(UINT nNormalResourceId)
{
m_pNormalBmp = new CBitmap();
m_pNormalBmp -> LoadBitmapW( nNormalResourceId);
}
void CDynamicButton::SetOverBmp(UINT nNormalResourceId)
{
m_pOverBmp = new CBitmap();
m_pOverBmp -> LoadBitmapW( nNormalResourceId);
}
void CDynamicButton::SetDownBmp(UINT nNormalResourceId)
{
m_pDownBmp = new CBitmap();
m_pDownBmp -> LoadBitmapW( nNormalResourceId);
}
void CDynamicButton::SetDisableBmp(UINT nNormalResourceId)
{
m_pDisableBmp = new CBitmap();
m_pDisableBmp -> LoadBitmapW( nNormalResourceId);
}
void CDynamicButton::OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
// HBITMAP bmp = (HBITMAP)LoadImage(NULL, strFileName.GetBuffer(), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
// ULONG_PTR btnState = lpDrawItemStruct->itemState;
// CString s;
// s.Format(_T("%d"),ODS_DEFAULT);
// MessageBox(s);
// if( btnState & ODS_DEFAULT ) // 默认的
// {
// CDC *pDC = new CDC();
// pDC->Attach(lpDrawItemStruct->hDC);
// CDC mDC;
// mDC.CreateCompatibleDC(pDC);
// BITMAP bmpInfo;
// m_pNormalBmp->GetBitmap(&bmpInfo);
// mDC.SelectObject(*m_pNormalBmp);
// CRect rect(lpDrawItemStruct->rcItem);
// pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&mDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);
// mDC.Detach();
// mDC.DeleteDC();
// }
//
// CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
void CDynamicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
ULONG_PTR btnState = lpDrawItemStruct -> itemState;
/* CString s;
s.Format(_T("%d"),btnState);
MessageBox(s); */
CDC * pDC = new CDC();
CRect rect(lpDrawItemStruct -> rcItem);
pDC -> Attach(lpDrawItemStruct -> hDC);
if ( btnState == 0 ) // 默认的
{
DrawBitmap(pDC,rect,m_pNormalBmp);
}
// else if(btnState & ODS_FOCUS)
// {
// DrawBitmap(pDC,rect,m_pDownBmp);
// }
// else if(btnState & ODS_DEFAULT)
// {
// DrawBitmap(pDC,rect,m_pNormalBmp);
// }
// else if(btnState & ODS_SELECTED)
// {
// DrawBitmap(pDC,rect,m_pOverBmp);
// }
}
void CDynamicButton::DrawBitmap(CDC * pDC,CRect & rect,CBitmap * pBmp)
{
CDC mDC;
mDC.CreateCompatibleDC(pDC);
BITMAP bmpInfo;
pBmp -> GetBitmap( & bmpInfo);
mDC.SelectObject( * pBmp);
pDC -> StretchBlt( 0 , 0 ,rect.Width(),rect.Height(), & mDC, 0 , 0 ,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);
mDC.Detach();
mDC.DeleteDC();
}
void CDynamicButton::OnMButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDC * pDC = GetWindowDC();
CRect rect;
GetClientRect( & rect);
DrawBitmap(pDC,rect,m_pDownBmp);
// MessageBox(_T("aaa"));
// CButton::OnMButtonDown(nFlags, point);
}
void CDynamicButton::OnBnKillfocus()
{
CDC * pDC = GetWindowDC();
CRect rect;
GetClientRect( & rect);
(pDC,rect,m_pNormalBmp);
// TODO: 在此添加控件通知处理程序代码
}
其中其实DrawBitmap的作用很大,每次都是它在画图,才是按钮显示不同的图片
我当初才接触的时候,就是对画图的这部门不够明白,现在其实想想,好看的界面都是画图画出来的,CDC这个设备上下文类,用几次就明白其中的东东了
由于好久没有弄这个mfc了,这个CDynamicButton并没有成功的,因为现在根本就不反应,只是能够简单的换下图片而已,背景效果还有待改进,明天还要上班,现在已经不早了,明晚有时间再搞吧
如果是新手看的,就看DrawBitmap就可以了,把这个搞懂,就可以画图,再个就是搞懂消息了,在哪个消息向应里画呢.这两样搞懂了,搞出好的界面就不难了
给我这个难看的东西截个图留念下,哈:
不早了睡觉觉了~~~~~~