动态提示框最好能有三个功能:1.动态地改变大小 2.支持多种颜色 3.能有个确定按钮
1.用xml给提示框来个布局。
<layer> <header class="msgboxhead" width="full" height="31"> <icon src="100" pos="5,9"/> <text id="60004" class="dlgtitle" pos="25,10">%str1%</text> <imgbtn id="60001" class="linkimage" skin="closeonlybtn" pos="-43,0"/> </header> <footer class="msgboxfoot" width="full" height="55"> <dlg id="60008" pos="0,0,-0,-10" class="client"/> </footer> <body class="msgboxbody" width="full" height="full"> <dlg pos="0,0,-0,-0"> <dlg pos="0,0,-0,-20"> <icon id="60005" pos="20,20" src="32516" oem="1" size="32"/> <richtext id="60006" pos="70,20,-0,-0" /> </dlg> </dlg> </body> </layer>
首先是大小,如果能确定变换文字的大小(richtext)就可以用richtext的大小+header+footer+按钮+空行 来确定对话框的大小。
通过DrawText(...DT_CALCRECT)来计算宽度。
list<LISTITEM> ::iterator pos; for (pos = m_lstMsg.begin(); pos != m_lstMsg.end(); ++pos) { LISTITEM item = (*pos); dc.DrawText(item.strText, item.strText.GetLength(), rcText, textStyle.m_nTextAlign | DT_CALCRECT); if (nWidth < rcText.Width()) nWidth = rcText.Width(); }
其次,我们来确定对话框的高度,我们用一个list来存贮提示信息,其中每个元素是一句话,占一行。
我们用确定一下没行的高度(行高),用 行高*行数 +header+footer+按钮+空行 即可算出提示框的高度。
void CColorMsgBox::CalcRect(CRect &rc1) { int nHeight = m_lstMsg.size() * 18;; int nWidth = 418; CWindowDC dc(::GetDesktopWindow()); CRect rcText(0, 0, 1000, 1000); const BkStyle& textStyle = BkStyle::GetStyle("msgtext"); dc.SelectFont(textStyle.m_ftText); list<LISTITEM> ::iterator pos; for (pos = m_lstMsg.begin(); pos != m_lstMsg.end(); ++pos) { LISTITEM item = (*pos); dc.DrawText(item.strText, item.strText.GetLength(), rcText, textStyle.m_nTextAlign | DT_CALCRECT); if (nWidth < rcText.Width()) nWidth = rcText.Width(); } rc1.left = 0; rc1.top = 0; rc1.right = nWidth+10; rc1.bottom = nHeight+135; } 3.增加按钮。void CColorMsgBox::AddButton() { CString strButtonXmlFormat, strButtons, strButtonDiv; CString strText = "确定"; CWindowDC dc(::GetDesktopWindow()); CRect rcText(0, 0, 1000, 1000); const BkStyle& btnStyle = BkStyle::GetStyle("normalbtn"); HFONT hftOld = dc.SelectFont(btnStyle.m_ftText); dc.DrawText(strText, strText.GetLength(), rcText, btnStyle.m_nTextAlign | DT_CALCRECT); rcText.InflateRect(btnStyle.m_nMarginX, btnStyle.m_nMarginY); dc.SelectFont(hftOld); int uWidth = max(80, rcText.Width()); strButtonXmlFormat = BkString::Get(IDS_MSGBOX_BUTTON_XML); UINT uLeft = 0; strButtons.AppendFormat(strButtonXmlFormat, IDC_BTN_SYS_CLOSE, uLeft, uLeft + uWidth,_T("确定")); uLeft += uWidth; strButtonDiv.Format(BkString::Get(IDS_MSGBOX_BUTTON_DIV), uWidth / 2, uWidth / 2, strButtons); SetPanelXml(IDC_DIV_MSGBOX_BUTTONS, CT2A(strButtonDiv, CP_UTF8)); }
其中,BkString::Get(IDS_MSGBOX_BUTTON_XML);中的IDS_MSGBOX_BUTTON_XML对应着一个字符串
<s id="17"><button id=%d pos="%d,5,%d,-5" class=normalbtn>%s</button></s>格式化后就可动态产生一个“确定”按钮了。4.提示框的颜色,我们利用了richtext对应类CBkRichText,其中有对颜色的绘制。
else if (0 == stricmp(pElemChild->Value(), "c")) { COLORREF clrText = CBkObject::HexStringToColor(pElemChild->Attribute("color")); crTextOld = dc.SetTextColor( clrText ); if( crTextOld == CLR_INVALID ) { crTextOld = 0; } }
5,上总的代码。ColorMsgBox.h
#pragma once #include <atlcoll.h> #include <wtlhelper/whwindow.h> enum TextColor { enRed = 1, //已安装 enGreen = 2, //更新服务器配置文件状态 enBlue = 3, //版本已更新,请通过软件小管家下载 }; typedef struct listItem { CString strText; TextColor clr; }LISTITEM; class CColorMsgBox : public CBkDialogImpl<CColorMsgBox> , public CWHRoundRectFrameHelper<CColorMsgBox> { public: CColorMsgBox(); ~CColorMsgBox(); void AppendMsg(TextColor textClr,LPCWSTR lpszText); void ShowMsg(); protected: list<LISTITEM> m_lstMsg; BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/); void OnBkBtnClose(); void OnSize(UINT nType, CSize size); void AddButton(); void CalcRect(CRect &rc); BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) BK_NOTIFY_ID_COMMAND(IDC_BTN_SYS_CLOSE,OnBkBtnClose) //BK_NOTIFY_COMMAND(OnBkCommand) BK_NOTIFY_MAP_END() BEGIN_MSG_MAP_EX(CColorMsgBox) MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) CHAIN_MSG_MAP(CBkDialogImpl<CColorMsgBox>) CHAIN_MSG_MAP(CWHRoundRectFrameHelper<CColorMsgBox>) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_SIZE(OnSize) END_MSG_MAP() };
ColorMsgBox.cpp
#include "stdafx.h" #include "ColorMsgBox.h" CColorMsgBox::CColorMsgBox() : CBkDialogImpl<CColorMsgBox>(IDR_BK_MSGBOX4) { } CColorMsgBox::~CColorMsgBox() { m_lstMsg.clear(); } void CColorMsgBox::ShowMsg() { this->DoModal(); } void CColorMsgBox::AppendMsg(TextColor textClr,LPCWSTR lpszText) { LISTITEM item; item.clr = textClr; item.strText = lpszText; m_lstMsg.push_back(item); } void CColorMsgBox::AddButton() { CString strButtonXmlFormat, strButtons, strButtonDiv; CString strText = "确定"; CWindowDC dc(::GetDesktopWindow()); CRect rcText(0, 0, 1000, 1000); const BkStyle& btnStyle = BkStyle::GetStyle("normalbtn"); HFONT hftOld = dc.SelectFont(btnStyle.m_ftText); dc.DrawText(strText, strText.GetLength(), rcText, btnStyle.m_nTextAlign | DT_CALCRECT); rcText.InflateRect(btnStyle.m_nMarginX, btnStyle.m_nMarginY); dc.SelectFont(hftOld); int uWidth = max(80, rcText.Width()); strButtonXmlFormat = BkString::Get(IDS_MSGBOX_BUTTON_XML); UINT uLeft = 0; strButtons.AppendFormat(strButtonXmlFormat, IDC_BTN_SYS_CLOSE, uLeft, uLeft + uWidth,_T("确定")); uLeft += uWidth; strButtonDiv.Format(BkString::Get(IDS_MSGBOX_BUTTON_DIV), uWidth / 2, uWidth / 2, strButtons); SetPanelXml(IDC_DIV_MSGBOX_BUTTONS, CT2A(strButtonDiv, CP_UTF8)); } BOOL CColorMsgBox::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { CString strMsg; list<LISTITEM> ::iterator pos; for (pos = m_lstMsg.begin(); pos != m_lstMsg.end(); ++pos) { LISTITEM item = (*pos); CString strTmp; if (item.clr == enRed) { strTmp = "a31515"; } else if (item.clr == enGreen) { strTmp = "008000"; } else if (item.clr == enBlue) { strTmp = "0000ff"; } strMsg += "<c color='"+strTmp+"'>" + item.strText +"</c><br/>";; } SetRichText(60006,strMsg); CRect thisRect; // 根据提示信息的内容,动态计算提示框大小 CalcRect(thisRect); // 增加“确定”按钮 AddButton(); CRect rc; CRect rcClient; SystemParametersInfo(SPI_GETWORKAREA,0,&rc,0); rcClient.left = ((rc.Width() - thisRect.Width()) >> 1); rcClient.right = rcClient.left + thisRect.Width(); rcClient.top = ((rc.Height() - thisRect.Height()) >> 1); rcClient.bottom= rcClient.top + thisRect.Height(); MoveWindow(&rcClient,FALSE); ShowWindow(SW_SHOW); return TRUE; } void CColorMsgBox::OnSize(UINT nType, CSize size) { } void CColorMsgBox::OnBkBtnClose() { EndDialog(IDCANCEL); } void CColorMsgBox::CalcRect(CRect &rc1) { int nHeight = m_lstMsg.size() * 18;; int nWidth = 418; CWindowDC dc(::GetDesktopWindow()); CRect rcText(0, 0, 1000, 1000); const BkStyle& textStyle = BkStyle::GetStyle("msgtext"); dc.SelectFont(textStyle.m_ftText); list<LISTITEM> ::iterator pos; for (pos = m_lstMsg.begin(); pos != m_lstMsg.end(); ++pos) { LISTITEM item = (*pos); dc.DrawText(item.strText, item.strText.GetLength(), rcText, textStyle.m_nTextAlign | DT_CALCRECT); if (nWidth < rcText.Width()) nWidth = rcText.Width(); } rc1.left = 0; rc1.top = 0; rc1.right = nWidth+10; rc1.bottom = nHeight+135; }
6.用法CColorMsgBox clrMsg; clrMsg.AppendMsg(enBlue,strMsg); ... clrMsg.ShowMsg();