MFC自定义控件.docx

上传人:b****6 文档编号:13450447 上传时间:2023-06-14 格式:DOCX 页数:17 大小:39.15KB
下载 相关 举报
MFC自定义控件.docx_第1页
第1页 / 共17页
MFC自定义控件.docx_第2页
第2页 / 共17页
MFC自定义控件.docx_第3页
第3页 / 共17页
MFC自定义控件.docx_第4页
第4页 / 共17页
MFC自定义控件.docx_第5页
第5页 / 共17页
MFC自定义控件.docx_第6页
第6页 / 共17页
MFC自定义控件.docx_第7页
第7页 / 共17页
MFC自定义控件.docx_第8页
第8页 / 共17页
MFC自定义控件.docx_第9页
第9页 / 共17页
MFC自定义控件.docx_第10页
第10页 / 共17页
MFC自定义控件.docx_第11页
第11页 / 共17页
MFC自定义控件.docx_第12页
第12页 / 共17页
MFC自定义控件.docx_第13页
第13页 / 共17页
MFC自定义控件.docx_第14页
第14页 / 共17页
MFC自定义控件.docx_第15页
第15页 / 共17页
MFC自定义控件.docx_第16页
第16页 / 共17页
MFC自定义控件.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

MFC自定义控件.docx

《MFC自定义控件.docx》由会员分享,可在线阅读,更多相关《MFC自定义控件.docx(17页珍藏版)》请在冰点文库上搜索。

MFC自定义控件.docx

MFC自定义控件

关于CustomControl自定义控件的介绍,有一篇文章感觉不错,不过是英文的,英语不好的也没关系,不是有“有道”吗?

再说了,我们只要看代码就行了,而且步骤也就那么几步,结合教程图片稍微猜一下也就知道了。

原文地址:

接下来我把上面教程的操作步骤简单描述一下:

1、首先往对话框添加一个“自定义控件”,然后右击该控件选择“建立类向导”,在弹出的对话框点击“AddClass...”,选择“New...",

之后“Name"项填CMyCustomControl,“BaseClass"选择genericCWnd,点确定。

在MyCustomControl.h

添加函数声明BOOLRegisterWndClass();

给CMyCustomControl类添加如下函数:

BOOLCMyCustomControl:

:

RegisterWndClass()

{

 WNDCLASSwindowclass;

 HINSTANCEhInst=AfxGetInstanceHandle();

 if(!

:

:

GetClassInfo(hInst,"MyDrawPad",&windowclass))

 {

  windowclass.style=CS_DBLCLKS;

  windowclass.lpfnWndProc=:

:

DefWindowProc;

  windowclass.cbClsExtra=windowclass.cbWndExtra=0;

  windowclass.hInstance=hInst;

  windowclass.hIcon=NULL;

  windowclass.hCursor=AfxGetApp()->LoadStandardCursor(IDC_ARROW);

  windowclass.hbrBackground=:

:

GetSysColorBrush(COLOR_WINDOW);

  windowclass.lpszMenuName=NULL;

  windowclass.lpszClassName="MyDrawPad";

  if(!

AfxRegisterClass(&windowclass))

  {

   AfxThrowResourceException();

   returnFALSE;

  }

 }

returnTRUE;

}

在MyCustomControl类构造函数中调用RegisterWndClass函数,如下:

CMyCustomControl:

:

CMyCustomControl()

{

 RegisterWndClass();

}

接着右击对话框里“自定义控件”,选择属性,“种类”框里填上MyDrawPad(窗口类)。

给对话框类添加一个CMyCustomControl类对象(是在*Dlg.h)。

如:

CMyCustomControlm_drawpad;(记得包含头文件)。

#include"MyCustomControl.h"

对话框类的DoDataExchange函数里添加如下语句:

voidCThirdDlg:

:

DoDataExchange(CDataExchange*pDX)

{

 CDialog:

:

DoDataExchange(pDX);

 //{{AFX_DATA_MAP(CThirdDlg)

  //NOTE:

theClassWizardwilladdDDXandDDVcallshere

 //}}AFX_DATA_MAP

 DDX_Control(pDX,IDC_CUSTOM1,m_drawpad);//IDC_CUSTOM1为自定义控件的ID号

}

到了这里,自定义控件的基本问题算是解决了。

可自行给CMyCustomControl类添加消息响应函数,运行一下吧。

自定义控件仿工具栏

标题名是仿工具栏控件,其实也只是仿下工具栏那个模式而已,想一下,工具栏类里有那么多个函数,能仿得过来吗?

如果有谁觉得用自定义控件模仿这个太麻烦的话,也可直接从按钮控件(CButton)派生出类来代替“自定义控件”类。

我这里就直接以上面工程的CMyCustomControl类为例。

1、首先往工程里引三张图片如下:

2、再引入六个图标,用于项显示图标,ID号保持默认不变,

3、CMyCustomControl添加如下成员变量(私有变量)

4、响应自定义控件(CMyCustomControl)WM_ERASEBKGND、WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_PAINT、WM_TIMER消息

5、添加如下成员函数

6、构造函数中初始化部分成员变量(私有变量初始化)

7、添加各函数代码

8、成员函数要在.h中的public中声明

voidSetBitmapIDs(UINTBKID,UINTitemMOverID,UINTitemPushID);

BOOLSetItemSize(intWidth,intHeight,intitemSpacing=5);

BOOLSetImageList(CImageList*pImageList);

BOOLAddItem(UINTnID);

9、在*Dlg.h中定义一个需要用到的变量

CImageListm_ImageList;

10、在*.cpp中添加初始化响应函数

m_ImageList.Create(32,32,ILC_COLOR32|ILC_MASK,1,0);

for(inti=0;i<6;i++)

m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1+i));

m_drawpad.SetImageList(&m_ImageList);

m_drawpad.SetBitmapIDs(IDB_BK,IDB_ITEMOVER,IDB_ITEMPUSH);

m_drawpad.SetItemSize(38,40,3);

for(i=0;i<6;i++)

m_drawpad.AddItem(1001+i);

11、如果要处理项按钮单击消息的话,需手动添加消息映射,方法跟添加工具栏控件项单击消息映射一样。

前面给第一项设置ID号为1001,那么添加这个项单击消息映射就是:

在*Dlg.cpp中的BEGIN_MESSAGE_MAP(CThirdDlg,CDialog)函数下添加

ON_COMMAND(1001,OnItem1)//OnItem1为消息处理函数

BEGIN_MESSAGE_MAP(CThirdDlg,CDialog)

END_MESSAGE_MAP()为消息映射区域

如何获知ID号:

查看Resource.h

成员变量的初始化可以再构造函数中进行。

存在分配相同ID的可能。

详情见下:

ID的分配是通过头文件控制的。

你看你的resource.h的最后几行(注释是我加的,源文件里没有):

#ifndefAPSTUDIO_READONLY_SYMBOLS

#define_APS_NEXT_RESOURCE_VALUE2000//下一个资源的ID,比如字符串资源,位图资源等

#define_APS_NEXT_COMMAND_VALUE40001//下一个command的ID,这个一般是作为WM_COMMAND消息的参数用的。

#define_APS_NEXT_CONTROL_VALUE1001//下一个控件的ID

#define_APS_NEXT_SYMED_VALUE101//下一个符号的ID

#endif

比如,如果这个时候你用VC的对话框插入一个字符串,那么这个字符串的ID就会自动被分配成2000,同时_APS_NEXT_RESOURCE_VALUE会被改成2001。

其他几个值也是以类似方式工作的。

所以其实VC自动分配的ID号,跟你自己定义的是有可能重复的。

你必须自己保证没有重复,而不是依赖于VC帮你检查。

一个办法是,比如你要新加一个控件,你可以用_APS_NEXT_CONTROL_VALUE的值作为这个控件的ID,然后自己手动把_APS_NEXT_CONTROL_VALUE的值加1,这样就能保持跟VC的ID分配机制一致。

全文复制如下:

关于CustomControl自定义控件的介绍,有一篇文章感觉不错,不过是英文的,英语不好的也没关系,不是有“有道”吗?

再说了,我们只要看代码就行了,而且步骤也就那么几步,结合教程图片稍微猜一下也就知道了。

原文地址:

接下来我把上面教程的操作步骤简单描述一下:

首先往对话框添加一个“自定义控件”,然后右击该控件选择“建立类向导”,在弹出的对话框点击“AddClass...”,选择“New...",

之后“Name"项填CMyCustomControl,“BaseClass"选择genericCWnd,点确定。

给CMyCustomControl类添加如下函数:

BOOLCMyCustomControl:

:

RegisterWndClass()

{

 WNDCLASSwindowclass;

 HINSTANCEhInst=AfxGetInstanceHandle();

 if(!

:

:

GetClassInfo(hInst,"MyDrawPad",&windowclass))

 {

  windowclass.style=CS_DBLCLKS;

  windowclass.lpfnWndProc=:

:

DefWindowProc;

  windowclass.cbClsExtra=windowclass.cbWndExtra=0;

  windowclass.hInstance=hInst;

  windowclass.hIcon=NULL;

  windowclass.hCursor=AfxGetApp()->LoadStandardCursor(IDC_ARROW);

  windowclass.hbrBackground=:

:

GetSysColorBrush(COLOR_WINDOW);

  windowclass.lpszMenuName=NULL;

  windowclass.lpszClassName="MyDrawPad";

  if(!

AfxRegisterClass(&windowclass))

  {

   AfxThrowResourceException();

   returnFALSE;

  }

 }

returnTRUE;

}

在MyCustomControl类构造函数中调用RegisterWndClass函数,如下:

CMyCustomControl:

:

CMyCustomControl()

{

 RegisterWndClass();

}

接着右击对话框里“自定义控件”,选择属性,“种类”框里填上MyDrawPad(窗口类)。

给对话框类添加一个CMyCustomControl类对象。

如:

CMyCustomControlm_drawpad;(记得包含头文件)。

对话框类的DoDataExchange函数里添加如下语句:

voidCThirdDlg:

:

DoDataExchange(CDataExchange*pDX)

{

 CDialog:

:

DoDataExchange(pDX);

 //{{AFX_DATA_MAP(CThirdDlg)

  //NOTE:

theClassWizardwilladdDDXandDDVcallshere

 //}}AFX_DATA_MAP

 DDX_Control(pDX,IDC_CUSTOM1,m_drawpad);//IDC_CUSTOM1为自定义控件的ID号

}

到了这里,自定义控件的基本问题算是解决了。

可自行给CMyCustomControl类添加消息响应函数,运行一下吧。

 自定义控件仿工具栏

标题名是仿工具栏控件,其实也只是仿下工具栏那个模式而已,想一下,工具栏类里有那么多个函数,能仿得过来吗?

如果有谁觉得用自定义控件模仿这个太麻烦的话,也可直接从按钮控件(CButton)派生出类来代替“自定义控件”类。

我这里就直接以上面工程的CMyCustomControl类为例。

首先往工程里引三张图片如下:

 自定义控件背景,ID号:

IDB_BK

鼠标停留时,项背景,ID号:

IDB_ITMEOVER

鼠标单击时,项背景,ID号:

IDB_ITEMPUSH

再引入六个图标,用于项显示图标,ID号保持默认不变,IDI_ICON1、IDI_ICON2。

IDI_ICON6

CMyCustomControl添加如下成员变量:

private:

 CRectm_itemRect[10];//各项区域

 UINTm_itemID[10];//各项ID号

 CImageList*m_pImageList;//各项图标

 intm_itemCount;//项数量

 UINTm_BKID;//控件背景位图ID号

 UINTm_itemMOverID;//项鼠标停留时的背景位图ID号

 UINTm_itemMPushID;//项鼠标按下时的背景位图ID号

 intm_itemWidth;//项宽

 intm_itemHeight;//项高

 intm_itemSpacing;//项区域间距,上下左右。

 intm_CurMouseItem;//记录当前鼠标位置所在项

 intm_TimerID;//计时器ID号

 BOOLm_MousePush;//鼠标是否在按下中

响应自定义控件(CMyCustomControl)WM_ERASEBKGND、WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_PAINT、WM_TIMER消息,各消息处理函数如下:

BOOLCMyCustomControl:

:

OnEraseBkgnd(CDC*pDC)

voidCMyCustomControl:

:

OnLButtonDown(UINTnFlags,CPointpoint)

voidCMyCustomControl:

:

OnLButtonUp(UINTnFlags,CPointpoint)

voidCMyCustomControl:

:

OnMouseMove(UINTnFlags,CPointpoint)

voidCMyCustomControl:

:

OnPaint()

voidCMyCustomControl:

:

OnTimer(UINTnIDEvent)

添加如下成员函数:

BOOLCMyCustomControl:

:

AddItem(UINTnID)//此函数添加项

//设置控件背景位图ID,项状态位图背景ID(鼠标停留,单击)

voidCMyCustomControl:

:

SetBitmapIDs(UINTBKID,UINTitemMOverID,UINTitemMPushID)

BOOLCMyCustomControl:

:

SetImageList(CImageList*pImageList)//设置图像列表

BOOLCMyCustomControl:

:

SetItemSize(intWidth,intHeight,intitemSpacing)//设置项宽高

构造函数中初始化部分成员变量:

CMyCustomControl:

:

CMyCustomControl()

{

 m_pImageList=NULL;

 m_itemCount=0;

 m_itemWidth=26;

 m_itemHeight=30;

 m_BKID=NULL;

 m_itemSpacing=5;

 m_CurMouseItem=-1;

 m_TimerID=1500;

 m_MousePush=FALSE;

 RegisterWndClass();//如果是从按钮控件(CButton)派生出的类,则不要调用此语句

}

各函数代码如下:

BOOLCMyCustomControl:

:

OnEraseBkgnd(CDC*pDC)

{

 //TODO:

Addyourmessagehandlercodehereand/orcalldefault

 returnTRUE;//直接返回真

 //returnCWnd:

:

OnEraseBkgnd(pDC);//禁止父类擦除背景,重画。

}

voidCMyCustomControl:

:

OnLButtonDown(UINTnFlags,CPointpoint)

{

 //TODO:

Addyourmessagehandlercodehereand/orcalldefault

  m_MousePush=TRUE;//鼠标左键处于按下状态

 this->Invalidate();//刷新控件窗口

 CWnd:

:

OnLButtonDown(nFlags,point);

}

 voidCMyCustomControl:

:

OnLButtonUp(UINTnFlags,CPointpoint)

{

 //TODO:

Addyourmessagehandlercodehereand/orcalldefault

 m_MousePush=FALSE;

 this->Invalidate();//刷新(控件)窗口

 if(m_CurMouseItem!

=-1)//给父窗口发送项被单击消息

 GetParent()->SendMessage(WM_COMMAND,

  MAKEWPARAM(m_itemID[m_CurMouseItem],0),LPARAM(GetSafeHwnd()));

 CWnd:

:

OnLButtonUp(nFlags,point);

}

 voidCMyCustomControl:

:

OnMouseMove(UINTnFlags,CPointpoint)

{

  if(m_CurMouseItem==-1)

 SetTimer(m_TimerID,50,NULL);//设置计时器

 CWnd:

:

OnMouseMove(nFlags,point);

}

voidCMyCustomControl:

:

OnPaint()

{

 CPaintDCdc(this);//devicecontextforpainting

 //先在内存DC里完成所有要进行的画图操作,然后再把内存DC里的画图(数据)一次性画上去。

 CDCmemDC;

 memDC.CreateCompatibleDC(&dc);

 CRectrect;

 GetClientRect(rect);

 CBitmapbmp;

 bmp.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());

 memDC.SelectObject(&bmp);

 if(m_BKID!

=NULL)//画位图背景

   {

  CDCbmpDC;

  bmpDC.CreateCompatibleDC(&memDC);

  CBitmapmBmp;

  mBmp.LoadBitmap(m_BKID);

  bmpDC.SelectObject(&mBmp);

  BITMAPbmpInfo;

  mBmp.GetBitmap(&bmpInfo);

  memDC.StretchBlt(0,0,rect.Width(),rect.Height(),&bmpDC,0,0,

             bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);

 }

 intspacing=0;

  if(m_CurMouseItem!

=-1)

 {

  

  CDCbmpDC;

  bmpDC.CreateCompatibleDC(&memDC);

  CBitmapmBmp;

  if(m_MousePush)

  {

  spacing=2;

  mBmp.LoadBitmap(m_itemMPushID);

  }

  elsemBmp.LoadBitmap(m_itemMOverID);

  bmpDC.SelectObject(&mBmp);

  BITMAPbmpInfo;

  mBmp.GetBitmap(&bmpInfo);

  memDC.StretchBlt(m_itemRect[m_CurMouseItem].left,m_itemRect[m_CurMouseItem].top,

   m_itemRect[m_CurMouseItem].Width(),m_itemRect[m_CurMouseItem].Height(),

   &bmpDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);

 }

 for(inti=0;i

 {

  POINTpt;

  pt.x=m_itemRect[i].left+2;

  pt.y=m_itemRect[i].top+2;

  if(i==m_CurMouseItem)

  {pt.x+=spacing;pt.y+=spacing;}

  m_pImageList->Draw(&memDC,i,pt,ILD_NORMAL);

 }

 dc.BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);

 //TODO:

Addyourmessagehandlercodehere

}

 voidCMyCustomControl:

:

OnTimer(UINTnIDEvent)

{

 intoldMouseItem=m_CurMouseItem;

 //TODO:

Addyourmessagehandlercodehereand/orcalldefault

 POINTpt;

 :

:

GetCursorPos(&pt);//获取鼠标当前位置

 ScreenToClient(&pt);//转换成相对于客户区坐标

 //判断当前鼠标是否在某一个项上

 for(m_CurMouseItem=0;m_CurMouseItem

  if(m_itemRect[m_CurMouseItem].PtInRect(pt))

   break;

 if(m_CurMouseItem==m_itemCount)//不在所有项上

 {

  m_CurMouseItem=-1;

  KillTimer(m_TimerID);

  m_MousePush=

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2