扩展金山提示框,使之带颜色(二)

     动态提示框最好能有三个功能: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>

2.提示框大小和提示框位置个如何确定?

首先是大小,如果能确定变换文字的大小(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();



你可能感兴趣的:(xml,iterator,Class,扩展,button,金山)