9.VC(ui)-怎么让单行EDIT文本居中

利用多行文本框来模拟单行进行设置垂直居中

派生一个基于CEdit的类CEditEx,重载create函数,记住是create,不是WM_ONCREATE消息,重载的目的是为了保证起始光标位置就在竖直中间靠左位置,代码如下

BOOL CEditEx::Create(CString  strNc,DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
	dwStyle |= ES_MULTILINE | ES_AUTOHSCROLL;
   //不能加ES_AUTOVSCROLL | ES_WANTRETURN属性
 if(CEdit::Create(dwStyle, rect, pParentWnd, nID))
	{
		m_strNc=strNc;
		CRect rc ;
		GetClientRect(&rc) ;
		CDC* pDC = GetDC();
		TEXTMETRIC tm;
		pDC->GetTextMetrics(&tm);
		int nFontHeight = tm.tmHeight + tm.tmExternalLeading;
		int nMargin = (rc.Height() - nFontHeight) / 2;

		rc.DeflateRect(0,nMargin);
		SetRectNP(&rc);
		ReleaseDC(pDC) ;
		return true ;
	}
	else
		 return false ;
}

如果定义的CEditEx对象不会变换位置,那么上面代码就足够了,但是,CEditEx的对象如果变换了大小或位置,那么Create中的SetRectNP就无效了,所以我们还需要在WM_CHAR消息响应函数中加入代码:

void CEditEx::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect rc ;
	GetClientRect(&rc) ;
	CDC* pDC = GetDC();
	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);
	int nFontHeight = tm.tmHeight + tm.tmExternalLeading;
	int nMargin = (rc.Height() - nFontHeight) / 2;

	rc.DeflateRect(0,nMargin);
	SetRectNP(&rc);
	ReleaseDC(pDC) ;
	CEdit::OnChar(nChar, nRepCnt, nFlags);
}

其实也就是在每次变换了大小或位置都要重新设置下SetRectNP即可,是不是在WM_CHAR中设置都无所谓,你也可以在ONSIZE中设置,最后看下SetRectNP的MSDN解释吧:

CEdit::SetRectNP
void GetRectNP(LPRECT lpRect);
参数:
说明:
调用此成员函数用一个多行编辑控件设置格式化矩形。此格式化矩形为文本的边界矩形,与编辑控件窗口的大小无关。
除了编辑控件窗口不被重新设置外,SetRectNP与SetRect成员函数一致。
当编辑控件首次被创建时格式化矩形与用户的编辑控件窗口区一样。使用SetRect NP成员函数后,应用程序可以使格式化矩形大于或小于编辑控件窗口。
如果编辑控件没有滚动栏,在格式化矩形大于窗口时,文本将被剪切而不是被覆盖。
此成员函数仅对多行编辑控件有效。
要了解更多信息,请参阅Win32文档中的EM_SETRECTNP。

另一种写死的方法,重载WM_NCCALISIZE,通过把非客户区设宽,只给字体留居中的矩形做为客户区,那当然是字体绝对居中了

代码:

void CEditEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
	int height = lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top;
	int margin = 0;

	CDC* pDC = GetDC();
	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);
	int nFontHeight = tm.tmHeight + tm.tmExternalLeading;
	int nMargin = (height - nFontHeight) / 2;

	lpncsp->rgrc[0].left += 8;
	lpncsp->rgrc[0].top += nMargin;
	lpncsp->rgrc[0].right -= 8;
	lpncsp->rgrc[0].bottom -= (nMargin-1);

	CEdit::OnNcCalcSize(bCalcValidRects, lpncsp);
}

当然这时你也可以重绘NPPaint,来使用非客户区颜色和客户区一致,让人误以为那还是客户区。

随手写的,别拍砖,期待兄弟们更好的方法分享。----------hgy

你可能感兴趣的:(文档)