沧桑不尽
无穷的沧桑,不尽的落叶

以前也是对windows有些研究的,只是近来搞C#把底层的东西忘了不少,现在连windows都有哪些消息都不知道了,以前能够娴熟的利用windows消息写出奇妙的东西,现在用mfc都不清楚mfc的消息路由有谁到谁了,这几天又做C++开发,原来的是wxWidgets用着不是很爽,基本都很多和mfc的一样,有点就是开源跨平台,缺点是资料太少,特别是中文的.所以就想把那些代码转成中文的.

现在也想预热下,温习下用mfc来开发东西,就把自己经过的点滴记下,一来自己日后忘了可以直接看,二来也可以为新手朋友们提供点有点用的东西吧.

 

按钮是比较常用的控件了,几乎每个windows桌面的窗口中都有,所以就先看看按钮怎么来美化下,其实美化下也就是添加点颜色、图片和效果。

当然了mfc中CBitmapButton已经可以做到好的效果,但是可能会不知道其中的实现的原理,为了能够为以后做点铺垫,所以自己动手来写个类似于CBitmapButton的类来

我这里命名CDynamicButton从CButton继承而来.记得好像以前美化是从DrawItem中来的,于是就重载了CButton的DrawItem方法,然后就如下来创建一个按钮:

为了测试先建一个基于对话框的工程,我在对话框的OnInitDialog中创建了pButton按钮

代码
BOOL CButtonDlg::OnInitDialog()
{
    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的方法,设置不同状态下的图片

也是为了能够直接在其他窗口中直接添加控件来使用这个类,所以这个类定义如下:

 

#pragma once


// 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文件我也一下贴出来再做说明了

 

CDynamicButton.cpp
// DynamicButton.cpp : 实现文件
//

#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就可以了,把这个搞懂,就可以画图,再个就是搞懂消息了,在哪个消息向应里画呢.这两样搞懂了,搞出好的界面就不难了

给我这个难看的东西截个图留念下,哈:

不早了睡觉觉了~~~~~~

posted on 2009-12-03 23:08  沧桑不尽  阅读(2734)  评论(3编辑  收藏  举报