动态创建控件支持事件响应并可保存与读取
http://tech.ddvip.com 2007年12月30日 社区交流
内容摘要:动态控件是比较繁杂的一个工作 这里演示了从在一个窗体上分别动态创建按钮、文本框、标签框的例子,当然,你还可以直接再添加其它的控件是很容易的.并且它是可以响应动态控件的事件的,你还可以用类向导生成事件,不必再手动添加消息。我还使这些控件的信息保存为文件并可以随时读取。
我们要做的不止这些,因为我说过,只有当动态控件能响应几乎所有事件的话,整个工程才算完整。所以接下来我们将要把控件对事件的响应完成掉。
动态控件的事件响应,两种最为常用(也许只是我) 一种是在PreTranslateMessage中判断消息的ID是否是控件ID,然后再判断事件消息来操作。一种就是使用自己的控件类,在类中添加好控件对消息的事件处理。有人会使用 ON_COMMAND_RANGE,但不总是太好也不能实现大多数消息功能。
因为在一开始,我们使用了系统向导来生成继承的控件类,所以,它是能够得到六个文件(三个.h三个.cpp),也就意味着,它是能够使用ctrl+w类向导来生成事件。你可以试一下? 呵,是的,就是这么简单,直接添加事件的响应就可以了,不如在按钮类里面来个单击事件?void CMyButton::OnClicked()噢,真的能响应,似乎太简单了!? 也许,任何方法都是不止你所能看到的数量,而只是你我都未发现而已。
{
AfxMessageBox("你单击了我!(BN_CLICKED)");
}
到此,动态控件的添加与事件响应已经能够完成了,我还说过要将它能保存与读取,所以,下面的代码将完成它。把下面这些代码都写到global文件中://////////////////////////在任何地方调用:
//取得控件在窗体中的坐标与大小(根据控件 窗体相对屏幕的坐标)
//////////////////////////
template<class T,class B>
static CRect getRect(T& myControl,B& obj)
{
CRect _rect,_rect2,_rect3;
int _right,_bottom;//用于保存控件大小
//获取控件所在父窗体坐标
obj.GetClientRect(&_rect);
obj.ClientToScreen(&_rect);
//获取自身坐标
myControl.GetClientRect(&_rect2);
_right=_rect2.right;
_bottom=_rect2.bottom;
myControl.ClientToScreen(&_rect2);
_rect3.left=_rect2.left-_rect.left;//控件left值等于自身的left减去父窗体的left
_rect3.top=_rect2.top-_rect.top;//控件top值等于自身的top减去父窗体的top
_rect3.right=_rect3.left+_right;//这是控件的right值 等于left坐标+大小
_rect3.bottom=_rect3.top+_bottom;//这是控件的bottom值 等于top坐标+大小
return _rect3;
}
//////////////////////////
//重新计算控件坐标
//////////////////////////
template<class T>
static void getGUIData(T& obj)
{
CWnd* _wnd;
//重新计算控件坐标信息
for (int i=1;i<=globalData.count;i++) {
switch(globalData.myControl[i]->type) {
case MYBUTTON:
{
_wnd=CWnd::FromHandle(globalData.myControl[i]->myButton.m_hWnd);
}
break;
case MYEDIT:
{
_wnd=CWnd::FromHandle(globalData.myControl[i]->myEdit.m_hWnd);
}
break;
case MYLABEL:
{
_wnd=CWnd::FromHandle(globalData.myControl[i]->myLabel.m_hWnd);
}break;
default:;
}
globalData.myControl[i]->rect=getRect(*_wnd,*obj);
}
}
// **********************************************
//数据保存
// **********************************************
template<class T>
static void saveFile(T& object)
{
getGUIData(object);//重新计算控件坐标及大小
//共用变量
CString _str;
//清空文件
CFile _file(globalData.appAllPath,CFile::modeCreate);//清空文件先CFile::Remove
_file.Close();
//DeleteFile(globalData.appAllPath);//删除整个文件
//清除
//WritePrivateProfileString(APPINFO,NULL,NULL,globalData.appAllPath);
//保存数量
_str.Format("%d",globalData.count);
WritePrivateProfileString(APPINFO,"count",_str,globalData.appAllPath);
//保存控件信息
//清除
//WritePrivateProfileString(CONTROL,NULL,NULL,globalData.appAllPath);
CString ITEM,_temp;
for (int i=1;i<=globalData.count;i++)
{
_str.Format("%d",i);
ITEM=CONTROL+_str;//项名
//公共属性
WritePrivateProfileString(ITEM,"caption",globalData.myControl[i]->caption,globalData.appAllPath);
_temp.Format("%d",globalData.myControl[i]->rect.left);
WritePrivateProfileString(ITEM,"left",_temp,globalData.appAllPath);
_temp.Format("%d",globalData.myControl[i]->rect.top);
WritePrivateProfileString(ITEM,"top",_temp,globalData.appAllPath);
_temp.Format("%d",globalData.myControl[i]->rect.right);
WritePrivateProfileString(ITEM,"right",_temp,globalData.appAllPath);
_temp.Format("%d",globalData.myControl[i]->rect.bottom);
WritePrivateProfileString(ITEM,"bottom",_temp,globalData.appAllPath);
_temp.Format("%d",globalData.myControl[i]->type);
WritePrivateProfileString(ITEM,"type",_temp,globalData.appAllPath);
}
}
// **********************************************
//数据读取
// **********************************************
template<class T>
void readFile(T& object)
{
//清除资源
for (int j=1;j<=globalData.count;j++) {
delete globalData.myControl[j];
globalData.myControl[j]=new _myControl;
}
CString _str,ITEM;
char _buff[255];
globalData.count=GetPrivateProfileInt(APPINFO,"count",NULL,globalData.appAllPath);
for(int i=1;i<=globalData.count;i++)
{
_str.Format("%d",i);
ITEM=CONTROL+_str;//项名
GetPrivateProfileString(ITEM,"caption",NULL,_buff,256,globalData.appAllPath);
globalData.myControl[i]->caption.Format("%s",_buff);
globalData.myControl[i]->rect.left=GetPrivateProfileInt(ITEM,"left",NULL,globalData.appAllPath);
globalData.myControl[i]->rect.top=GetPrivateProfileInt(ITEM,"top",NULL,globalData.appAllPath);
globalData.myControl[i]->rect.right=GetPrivateProfileInt(ITEM,"right",NULL,globalData.appAllPath);
globalData.myControl[i]->rect.bottom=GetPrivateProfileInt(ITEM,"bottom",NULL,globalData.appAllPath);
globalData.myControl[i]->type=GetPrivateProfileInt(ITEM,"type",NULL,globalData.appAllPath);
//调用创建控件函数
addContorl(object,globalData.myControl[i]->type,i);
}
//获取屏幕分辩率
int nFullWidth=GetSystemMetrics(SM_CXSCREEN);
int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
} saveFile(this);//保存所有控件信息我在PreTranslateMessage还加入了对控件拖拽的处理:
readFile(this);//读取 //使用鼠标可以随意拖动控件 控件拖拽我研究了蛮久的时间。感觉使用这个消息方法是最为方便的,你可以再将它功能增加,比如说控件拖拽改变大小(SC_SIZE 可以做到),那岂不是做成界面设计器了 !
if (pMsg->message==WM_LBUTTONDOWN)
{
if (globalData.isDraw)//自己增加这个变量
{
FromHandle(pMsg->hwnd)->SendMessage( WM_SYSCOMMAND,SC_MOVE+1,0);
this->Invalidate(TRUE);
return true;
}
}
来源:vckbase 作者:天枫十一郎 责编:豆豆技术应用
- VC/VC++按钮设计专题
- VC/VC++ 菜单专题
- VC/VC++ 工具条专题
- VC/VC++ 对话框教程
- VC/VC++ 报表教程
- VC/VC++ 控件
- VC/VC++ GDI
- Visual Studio 2008
- VC/VC++ MFC教程
- VC/VC++ QQ
- VC/VC++ Socket编程
- VC/VC++ 钩子编程
- TangramMini组件应用教程
- VC/VC++ 窗体
- VC/VC++ ADO 教程
- Windows CE 教程
- VC/VC++ DLL(动态链接库)编程
- VC/VC++ PDFlib
- VC与MATLAB编程
- VC/VC++ DirectShow 教程
- VC++入门视频教程
- VC/VC++ COM组件设计与应用
- VC/VC++ ATL
- VC/VC++ WTL
- VC/VC++ 定制调试诊断工具和程序
- VC/VC++ 进程
- VC/VC++ Win32
- VC/VC++ WMI
- VC/VC++ 消息
- 更多VC/VC++专题……