Как мы можем выровнять текст по вертикали в окне редактирования?
Я создал поле для редактирования как:
m_EditWnd.Create(m_hWnd, rect, NULL, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD |
WS_OVERLAPPED | WS_VISIBLE,
WS_EX_CLIENTEDGE | WS_EX_LEFT | WS_EX_LTRREADING);
Для горизонтального выравнивания существует стиль ES_CENTER для горизонтального выравнивания текста, но можем ли мы выровнять текст по центру?
3 ответа
Вот класс, который наследует CEdit и позволяет вертикальное выравнивание
/// HEADER //////////////////////////////////////////
class CEditVC : public CEdit
{
public:
CEditVC();
protected:
CRect m_rectNCBottom;
CRect m_rectNCTop;
public:
virtual ~CEditVC();
protected:
afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
afx_msg void OnNcPaint();
afx_msg UINT OnGetDlgCode();
DECLARE_MESSAGE_MAP()
};
/// IMPLEMENTATION /////////////////////////////////////////
CEditVC::CEditVC()
: m_rectNCBottom(0, 0, 0, 0)
, m_rectNCTop(0, 0, 0, 0)
{
}
CEditVC::~CEditVC()
{
}
BEGIN_MESSAGE_MAP(CEditVC, CEdit)
ON_WM_NCCALCSIZE()
ON_WM_NCPAINT()
ON_WM_GETDLGCODE()
END_MESSAGE_MAP()
void CEditVC::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
CRect rectWnd, rectClient;
//calculate client area height needed for a font
CFont *pFont = GetFont();
CRect rectText;
rectText.SetRectEmpty();
CDC *pDC = GetDC();
CFont *pOld = pDC->SelectObject(pFont);
pDC->DrawText("Ky", rectText, DT_CALCRECT | DT_LEFT);
UINT uiVClientHeight = rectText.Height();
pDC->SelectObject(pOld);
ReleaseDC(pDC);
//calculate NC area to center text.
GetClientRect(rectClient);
GetWindowRect(rectWnd);
ClientToScreen(rectClient);
UINT uiCenterOffset = (rectClient.Height() - uiVClientHeight) / 2;
UINT uiCY = (rectWnd.Height() - rectClient.Height()) / 2;
UINT uiCX = (rectWnd.Width() - rectClient.Width()) / 2;
rectWnd.OffsetRect(-rectWnd.left, -rectWnd.top);
m_rectNCTop = rectWnd;
m_rectNCTop.DeflateRect(uiCX, uiCY, uiCX, uiCenterOffset + uiVClientHeight + uiCY);
m_rectNCBottom = rectWnd;
m_rectNCBottom.DeflateRect(uiCX, uiCenterOffset + uiVClientHeight + uiCY, uiCX, uiCY);
lpncsp->rgrc[0].top +=uiCenterOffset;
lpncsp->rgrc[0].bottom -= uiCenterOffset;
lpncsp->rgrc[0].left +=uiCX;
lpncsp->rgrc[0].right -= uiCY;
}
void CEditVC::OnNcPaint()
{
Default();
CWindowDC dc(this);
CBrush Brush(GetSysColor(COLOR_WINDOW));
dc.FillRect(m_rectNCBottom, &Brush);
dc.FillRect(m_rectNCTop, &Brush);
}
UINT CEditVC::OnGetDlgCode()
{
if(m_rectNCTop.IsRectEmpty())
{
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
}
return CEdit::OnGetDlgCode();
}
У меня недостаточно репутации, чтобы комментировать, поэтому, возможно, полезный фрагмент очень старого вопроса!
Если вы поставите WS_BORDER
стиль, тогда текст автоматически центрируется по запросу. Поскольку ОП использует WS_EX_CLIENTEDGE
в любом случае граница рисуется, поэтому добавление в этом стиле не должно быть проблемой.
Тем не мение, WS_BORDER | WS_EX_CLIENTEDGE
достигается только "частичное" вертикальное центрирование.
С помощью WS_BORDER | WS_EX_STATICEDGE
достигается правильное вертикальное центрирование, хотя, очевидно, тогда у нас немного отличается визуальный стиль от стиля, ориентированного на клиента. Для меня, я мог бы жить с этим небольшим компромиссом, а не писать пользовательский элемент управления редактирования.
Я попробовал решение от @Aidan Ryan с небольшой поправкой, чтобы избежать еще одной проблемы, связанной с пользовательским интерфейсом. Я перемещаю "SetWindowPos" в OnNCPaint() и вызываю функцию только один раз.
Насколько я знаю, это невозможно. Но вы можете реализовать свой собственный контроль, чтобы сделать это возможным.
Посмотрите на эту статью.
Надеюсь, поможет.
Кстати, это тот вопрос, который стоит написать в Google перед публикацией. Вы можете найти много такого рода вещей уже в Интернете.