有时候会遇到一个控件想要多个控件的功能,这时候就需要自己封装控件。或者在一个或多个界面中会有相同的多个控件组合在一起的时候,也可以将这些控件封装到一起。
一、目标实现效果
二、实现
1、XML配置
<?xml version="1.0" encoding="UTF-8"?>
<Window size="367,290">
<HorizontalLayout bkimage="skin/card_normal.png" selectedimage="skin/card_selected.png">
<Button name="btnPatSelected" width="367" height="290" bkimage="skin/card_man_normal.png" hotimage="skin/card_man_selected.png"></Button>
<Label name="PatIcon" text="" float="true" pos="21,21,0,0" width="124" height="124" ></Label>
<Label name="" text="姓名" float="true" font="4" pos="171,54,0,0" width="55" height="22" align="center" ></Label>
<Label name="" text="年龄" float="true" font="4" pos="230,54,0,0" width="55" height="22" align="center" ></Label>
<Label name="" text="性别" float="true" font="4" pos="292,54,0,0" width="55" height="22" align="center" ></Label>
<Label name="PatName" text="罗文" float="true" font="4" pos="171,90,0,0" width="55" height="22" align="center" ></Label>
<Label name="PatAge" text="22" float="true" font="4" pos="230,90,0,0" width="55" height="22" align="center" ></Label>
<Label name="PatSex" text="男" float="true" font="4" pos="292,90,0,0" width="55" height="22" align="center" ></Label>
<Label align="left" name="PatBornDate" text="2018-04-01" font="4" float="true" pos="250,175,0,0" width="120" height="17" ></Label>
<Label align="left" name="PatTel" text="18627293017" font="4" float="true" pos="250,212,0,0" width="120" height="17" ></Label>
<Label align="left" name="PatCreateDate" text="2018-04-14" font="4" float="true" pos="250,248,0,0" width="120" height="17" ></Label>
<Label name="" text="ID" font="4" float="true" pos="21,190,0,0" width="124" height="24" align="center" ></Label>
<Label name="PatID" font="4" text="212121" float="true" pos="21,228,0,0" width="124" height="34" align="center" ></Label>
<Label name="" text="出生日期:" font="2" float="true" pos="175,175,0,0" width="70" height="17" ></Label>
<Label name="" text="联系电话:" font="2" float="true" pos="175,212,0,0" width="70" height="17" ></Label>
<Label name="" text="创建时间:" font="2" float="true" pos="175,248,0,0" width="70" height="17" ></Label>
</HorizontalLayout>
</Window>
C++代码
CPatInfoCardUI.h文件
#ifndef _CPATINFO_CARD_UI_H__
#define _CPATINFO_CARD_UI_H__
namespace DuiLib
{
typedef struct DuiPatinfo //定义结构体保存需要设置的病人信息(卡片上需要显示的)
{
DuiPatinfo()
{
ZeroMemory(this, sizeof(DUIPATINFO));
}
CDuiString strPatID; //病人ID
CDuiString strPatName;//病人姓名
CDuiString strPatSex;//病人性别
CDuiString strBornDate;//出生日期
CDuiString strPatTel;//电话号码
CDuiString strCreateDate;//创建时间
CDuiString strPatAge;//病人年龄
} DUIPATINFO, *PDUIPATINFO;
class CPatinfoCardUI : public CContainerUI, INotifyUI
{
public:
CPatinfoCardUI();
~CPatinfoCardUI();
private:
LPCTSTR GetClass() const;
LPVOID GetInterface(LPCTSTR pstrName);
UINT GetControlFlags() const;
void DoInit();
void Notify(TNotifyUI& msg);
//重写设置属性
virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
void SetHotImage(LPCTSTR pstrValue);//暂且没有用啊
void SetNormalImage(LPCTSTR pstrValue);//暂且没有用啊
void SetSelectedImage(LPCTSTR pstrValue);//暂且没有用啊
void PaintStatusImage(HDC hDC);//暂且没有用啊
//设置病人参数
void SetPatInfo(DUIPATINFO &duipatinfo);
private:
UINT m_bButtonState; //选中状态
CLabelUI* m_pPatName; //病人姓名显示
CLabelUI* m_pPatAge; //病人年龄
CLabelUI* m_pPatSex; //病人性别
CLabelUI* m_pPatBornDate; //病人出生日期
CLabelUI* m_pPatTel; //创建时间显示
CLabelUI* m_pPatCreateDate; //创建时间显示
CLabelUI* m_pPatID; //病人ID显示位置
CButtonUI * m_pSelectBtn; //背景按钮(本来准备自定义属性,先用这个解决,这样不用写代码)
CDuiString m_sNormalImage;//正常状态的背景图片
CDuiString m_sHotImage;//正常状态的背景图片
CDuiString m_sSelectedImage;//正常状态的背景图片
PDUIPATINFO m_PatInfo;//保存显示病人信息参数
bool m_select; //是否选中
};
}
#endif
CPatInfoCardUI.cpp
#include "stdafx.h"
#include "CPatInfoCardUI.h"
namespace DuiLib
{
CPatinfoCardUI::CPatinfoCardUI()
{
}
CPatinfoCardUI::~CPatinfoCardUI()
{
}
LPCTSTR CPatinfoCardUI::GetClass()const
{
return _T("CPatInfoCard");
}
LPVOID CPatinfoCardUI::GetInterface(LPCTSTR pstrName)
{
if( _tcscmp(pstrName, _T("CPatInfoCard")) == 0 ) return static_cast<CPatinfoCardUI*>(this);
return CContainerUI::GetInterface(pstrName);
}
UINT CPatinfoCardUI::GetControlFlags()const
{
return CContainerUI::GetControlFlags();
}
void CPatinfoCardUI::DoInit()
{
CDialogBuilder builder;
CContainerUI* pChildWindow = static_cast<CHorizontalLayoutUI*>(builder.Create(_T("ControlCard.xml"), (UINT)0, NULL, m_pManager));
if (pChildWindow)
{
this->Add(pChildWindow);
//m_pManager->AddNotifier(this); //可能是因为我参考的另一个人的东西;他是用class CMainWnd : public CWindowWnd, p
//public INotifyUI,public IDialogBuilderCallback;这种方式加载主窗口的,他的不会在分发消息
//时崩溃;我是用的windowimpbase,所以此处不能添加这行代码, 如果需要用到这个控件的消息,还是在使用控件的位置处理,让控件自己处理会导致崩溃
}
else
{
this->RemoveAll();
}
m_pPatName = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatName")));
m_pPatAge = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatAge")));
m_pPatBornDate = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatBornDate")));
m_pPatSex = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatSex")));
m_pPatID = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatID")));
m_pPatCreateDate = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatCreateDate")));
m_pPatTel = static_cast<CLabelUI*>(m_pManager->FindControl(_T("PatTel")));
m_pSelectBtn = static_cast<CButtonUI*>(m_pManager->FindControl(_T("btnPatSelected")));
}
void CPatinfoCardUI::Notify(TNotifyUI& msg)
{
if (msg.sType == DUI_MSGTYPE_SELECTCHANGED)
{
if (msg.pSender == m_pSelectBtn)
{
//m_pSelectBtn->Selected(true); //导致死循环崩溃
m_select = true;
}
}
}
}
void CPatinfoCardUI::SetHotImage(LPCTSTR pstrValue)
{
m_sHotImage = pstrValue;
}
void CPatinfoCardUI::SetNormalImage(LPCTSTR pstrValue)
{
m_sNormalImage = pstrValue;
}
void CPatinfoCardUI::SetSelectedImage(LPCTSTR pstrValue)
{
m_sSelectedImage = pstrValue;
}
void CPatinfoCardUI::PaintStatusImage(HDC hDC)
{
}
void CPatinfoCardUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
if( _tcscmp(pstrName, _T("normalimage")) == 0 )
{
// if (m_PatInfo->strPatSex == _T("男"))
// {
// m_pSelectBtn->SetHotImage(pstrValue);
// }
// else
// {
// m_pSelectBtn->SetHotImage(pstrValue);
// }
}
else if (_tcscmp(pstrName, _T("hotimage")) == 0 )
{
}
else if (_tcscmp(pstrName, _T("selectedimage")) == 0)
{
//m_pSelectBtn->SetPushedImage(pstrValue);
//SetSelectedImage(pstrValue);
}
else
{
CContainerUI::SetAttribute(pstrName, pstrValue);
}
}
void CPatinfoCardUI::SetPatInfo(DUIPATINFO &duipatinfo)
{
m_pPatName->SetText(duipatinfo.strPatName);
m_pPatSex->SetText(duipatinfo.strPatSex);
if (m_PatInfo->strPatSex == _T("女"))
{
m_pSelectBtn->SetBkImage(_T("skin/card_man_normal.png"));
m_pSelectBtn->SetHotImage(_T("skin/card_man_selected.png"));
}
else
{
m_pSelectBtn->SetBkImage(_T("skin/card_woman_normal.png"));
m_pSelectBtn->SetHotImage(_T("skin/card_woman_selected.png"));
}
m_pPatTel->SetText(duipatinfo.strPatTel);
m_pPatID->SetText(duipatinfo.strPatID);
m_pPatCreateDate->SetText(duipatinfo.strCreateDate);
m_pPatBornDate->SetText(duipatinfo.strBornDate);
m_pPatAge->SetText(duipatinfo.strPatAge);
}
主窗口代码
CControlUI * CEtcdMainWnd::CreateControl(LPCTSTR pstrClass)
{
CControlUI* pControl = NULL;//= new CControl;
if (_tcsicmp(pstrClass, _T("ControlCard")) == 0)
{
pControl = new CPatinfoCardUI();
}
return pControl;
}
主窗口xml配置
<?xml version="1.0" encoding="UTF-8"?>
<HorizontalLayout size="1600,900" >
<ControlCard width="380" height="300" bkimage="skin/card_normal.png" selectedimage="skin/card_selected.png"></ControlCard>
</HorizontalLayout>
由于我的是在tablayout中的某一个界面,所以不是用的Window,而是用的HorizontalLayout ;
效果图:
右上角就是自己定义的组合的那一个控件;
三、核心类容是Doinit()函数,CreateControl()函数,基类CContainerUI, INotifyUI
2018多看源码,多研究原理!为自己加油!