左边可以简单地使用一个组框,贴上背景图。当然,也可以使用新的对话框。
图形按钮类
1、类向导-》添加类-》选择MFC-》填入新类名称-》选择父类为 CButton
2、添加消息响应函数和虚函数:
消息响应mouse leave (离开) mouse move (移动)
虚函数:DrawItem(绘制按钮)
代码如下:
头文件
#pragma once
// CPicButton
class CPicButton : public CButton
{
DECLARE_DYNAMIC(CPicButton)
public:
CPicButton();
virtual ~CPicButton();
void LoadImage(UINT nResID,int _nStyleNum = 1);
void ChangeButtonStyle(int _style);
void MoveButtonTo(int left,int top);
protected:
int m_Width;
int m_Height;
CDC *m_lpMemoryDC;
CBitmap *m_lpBackgroundBitmap;
bool m_IsMoveOn;
TRACKMOUSEEVENT tme;
void Init();
void ClearUp();
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
afx_msg void OnMouseLeave();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
CPP文件
// PicButton.cpp : 实现文件
//
#include "stdafx.h"
#include "MFC09.h"
#include "PicButton.h"
// CPicButton
IMPLEMENT_DYNAMIC(CPicButton, CButton)
CPicButton::CPicButton()
{
m_lpMemoryDC = NULL;
m_lpBackgroundBitmap = NULL;
m_Width = 0;
m_Height = 0;
m_IsMoveOn = false;
}
CPicButton::~CPicButton()
{
}
BEGIN_MESSAGE_MAP(CPicButton, CButton)
ON_WM_MOUSELEAVE()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
// CPicButton 消息处理程序
void CPicButton::LoadImage(UINT nResID,int _nStyleNum )
{
Init();
m_lpBackgroundBitmap->LoadBitmap(nResID);
m_lpMemoryDC->SelectObject(m_lpBackgroundBitmap);
BITMAP bm;
m_lpBackgroundBitmap->GetBitmap(&bm);
m_Height = bm.bmHeight;
m_Width = bm.bmWidth / _nStyleNum;
SetWindowPos(this,0,0,m_Width,m_Height, SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE);
}
void CPicButton::ChangeButtonStyle(int _style)
{
CClientDC dc(this);
dc.SetStretchBltMode(COLORONCOLOR);
dc.StretchBlt(0,0,m_Width,m_Height,m_lpMemoryDC,_style * m_Width,0, m_Width,m_Height,SRCCOPY);
}
void CPicButton::Init()
{
ClearUp();
CDC *dc = this->GetDC();
m_lpMemoryDC = new CDC();
m_lpBackgroundBitmap = new CBitmap();
m_lpMemoryDC->CreateCompatibleDC(dc);
this->ReleaseDC(dc);
this->ModifyStyle(0,BS_OWNERDRAW|WS_CLIPSIBLINGS|WS_CHILD|WS_VISIBLE);
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = this->m_hWnd;
}
void CPicButton::ClearUp()
{
if (m_lpBackgroundBitmap != NULL) delete m_lpBackgroundBitmap;
if (m_lpMemoryDC != NULL) delete m_lpMemoryDC;
}
void CPicButton::MoveButtonTo(int _Left,int _Top)
{
this->MoveWindow(_Left, _Top, m_Width , m_Height);
}
void CPicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
if (lpDrawItemStruct->itemState & ODS_DISABLED) //按钮不可用状态
{
this->ChangeButtonStyle(0);
}
else if (lpDrawItemStruct->itemState & ODS_SELECTED) //按钮按下状态
{
this->ChangeButtonStyle(1);
}
else if(m_IsMoveOn)
{
this->ChangeButtonStyle(1);
}
else
this->ChangeButtonStyle(0);
}
void CPicButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_IsMoveOn = false;
Invalidate(0);
CButton::OnMouseLeave();
}
void CPicButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_IsMoveOn = true;
Invalidate(FALSE);
::_TrackMouseEvent(&tme);
CButton::OnMouseMove(nFlags, point);
}
左边对话框的实现
首先添加对话框资源
对话框添加四个按钮,大小位置可以任意,设置对话框的属性为Child
并且取消对话框的标题栏等。
使用类向导给对话框添加四个按钮对象:
手动修改成上面新建的CPicButton。
代码如下:
#pragma once
#include "PicButton.h"
// CLeftDlg 对话框
class CLeftDlg : public CDialogEx
{
DECLARE_DYNAMIC(CLeftDlg)
public:
CLeftDlg(CWnd* pParent = NULL); // 标准构造函数
CBitmap m_BackGround;
CDC *mdc;
virtual ~CLeftDlg();
// 对话框数据
enum { IDD = IDD_LEFTDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
CPicButton m_Start;
CPicButton m_Stop;
CPicButton m_Save;
CPicButton m_Exit;
};
// LeftDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "MFC09.h"
#include "LeftDlg.h"
#include "afxdialogex.h"
// CLeftDlg 对话框
IMPLEMENT_DYNAMIC(CLeftDlg, CDialogEx)
CLeftDlg::CLeftDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CLeftDlg::IDD, pParent)
{
}
CLeftDlg::~CLeftDlg()
{
}
void CLeftDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_Start);
DDX_Control(pDX, IDC_BUTTON2, m_Stop);
DDX_Control(pDX, IDC_BUTTON3, m_Save);
DDX_Control(pDX, IDC_BUTTON4, m_Exit);
}
BEGIN_MESSAGE_MAP(CLeftDlg, CDialogEx)
ON_WM_PAINT()
END_MESSAGE_MAP()
// CLeftDlg 消息处理程序
BOOL CLeftDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加额外的初始化
m_BackGround.LoadBitmap(IDB_LEFT);
BITMAP bm;
m_BackGround.GetBitmap(&bm);
int cx = bm.bmWidth;
int cy = bm.bmHeight + 30;
this->MoveWindow(0,0,cx,cy);
mdc = new CDC;
CDC *dc = this->GetDC();
mdc->CreateCompatibleDC(dc);
mdc->SelectObject(&m_BackGround);
m_Exit.LoadImage(IDB_EXIT,2);
m_Save.LoadImage(IDB_SAVE,2);
m_Stop.LoadImage(IDB_STOP,2);
m_Start.LoadImage(IDB_START,2);
int h = 65;
m_Start.MoveButtonTo(22,h);
m_Stop.MoveButtonTo(22,h*2);
m_Save.MoveButtonTo(22,h *3);
m_Exit.MoveButtonTo(22,h*4);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CLeftDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialogEx::OnPaint()
CRect rect;
this->GetClientRect(&rect);
dc.SetStretchBltMode(STRETCH_HALFTONE);
// TODO: Add your message handler code here
dc.StretchBlt(0,0,rect.right,rect.bottom,mdc,0,0,336,435,SRCCOPY);
}
响应资源:(可以用画图简单完成,两个图片分别是鼠标进入和离开的切换效果)
在主对话框里也添加任意一个Button,按照上面的方法,同样添加一个按钮到主对话框类,然后修改OnInitDialog函数,代码如下:
// MFC09Dlg.h : 头文件
//
#pragma once
#include "LeftDlg.h"
#include "picbutton.h"
// CMFC09Dlg 对话框
class CMFC09Dlg : public CDialogEx
{
// 构造
public:
CMFC09Dlg(CWnd* pParent = NULL); // 标准构造函数
CBitmap m_BackGround;
CBitmap m_top;
CDC *mdc;
CLeftDlg leftDlg;
void InitDlg();
// 对话框数据
enum { IDD = IDD_MFC09_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CPicButton m_close;
};
// MFC09Dlg.cpp : 实现文件
//
#include "stdafx.h"
#include "MFC09.h"
#include "MFC09Dlg.h"
#include "afxdialogex.h"
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFC09Dlg 对话框
CMFC09Dlg::CMFC09Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMFC09Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFC09Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_close);
}
BEGIN_MESSAGE_MAP(CMFC09Dlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
// CMFC09Dlg 消息处理程序
BOOL CMFC09Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_top.LoadBitmap(IDB_TOP);
m_BackGround.LoadBitmap(IDB_BK);
mdc = new CDC;
CDC *dc = this->GetDC();
mdc->CreateCompatibleDC(dc);
this->ReleaseDC(dc);
int cxIcon = GetSystemMetrics(SM_CXFULLSCREEN);
int cyIcon = GetSystemMetrics(SM_CYFULLSCREEN);
BITMAP bm;
m_BackGround.GetBitmap(&bm);
int cx = bm.bmWidth;
int cy = bm.bmHeight + 30;
int x = (cxIcon - cx ) / 2;
int y = (cyIcon - cy ) / 2;
this->MoveWindow(x,y,cx,cy);
leftDlg.Create(IDD_LEFTDLG);
leftDlg.MoveWindow(0 , 30, 180, cy - 30, 0);
leftDlg.ShowWindow(SW_SHOW);
m_close.LoadImage(IDB_CLOSE,5);
m_close.MoveButtonTo(cx - 35,5);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMFC09Dlg::InitDlg()
{
BITMAP bm;
m_BackGround.LoadBitmap(IDB_BK);
m_top.LoadBitmap(IDB_TOP);
m_BackGround.GetBitmap(&bm);
int cxIcon = GetSystemMetrics(SM_CXFULLSCREEN);
int cyIcon = GetSystemMetrics(SM_CYFULLSCREEN);
int cx = bm.bmWidth;
int cy = bm.bmHeight + 30;
int x = (cxIcon - cx ) / 2;
int y = (cyIcon - cy ) / 2;
this->MoveWindow(x,y,cx,cy);
leftDlg.Create(IDD_LEFTDLG);
leftDlg.MoveWindow(0 , 30, 180, cy - 30, 0);
leftDlg.ShowWindow(SW_SHOW);
mdc = new CDC;
CDC *dc = this->GetDC();
mdc->CreateCompatibleDC(dc);
this->ReleaseDC(dc);
}
void CMFC09Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
mdc->SelectObject(&m_top);
dc.SetStretchBltMode(STRETCH_HALFTONE);
dc.StretchBlt(0,0,rect.right,30,mdc,0,0,2,29,SRCCOPY);
mdc->SelectObject(&m_BackGround);
dc.StretchBlt(180,30,rect.right - 150,rect.bottom - 30,mdc,0,0,735,549,SRCCOPY);
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFC09Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
退出按钮图片,放左上角:
运行后界面:
以上资源可以自由编辑,注意添加到工程后修改相应的ID即可。
总结:
1、对话框可以作为主窗口,也可以作为子窗口,成为其他窗口的一部分;可以对MFC提供的按钮等类进行派生,增加功能;
2、按钮可以利用资源视图直接添加到对话框,添加变量的时候修改成指定的类即可,也可以动态生成,类似在主对话框中添加CLeftDlg,这时候,资源类(按钮、列表、文本框等等)需要手动Create创建。
3、总的来说,一种方法资源视图和类向导中添加窗口资源类的控件,不需要创建,直接使用,另外一种方法,则需要 定义对象-》创建窗口-》显示窗口的步骤来完成添加。如以下CLeftDlg的使用(很容易漏掉Create):
CLeftDlg leftDlg; -》 leftDlg.Create(IDD_LEFTDLG); -》 设置窗口大小等等 -》leftDlg.ShowWindow(SW_SHOW);