有时候会遇到一个控件想要多个控件的功能,这时候就需要自己封装控件。或者在一个或多个界面中会有相同的多个控件组合在一起的时候,也可以将这些控件封装到一起。
一、目标实现效果
二、实现
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;//保存显示病人信息参数 }; } #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); } } } } 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多看源码,多研究原理!为自己加油!