Как мы можем выровнять текст по вертикали в окне редактирования?

Я создал поле для редактирования как:

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 перед публикацией. Вы можете найти много такого рода вещей уже в Интернете.

Другие вопросы по тегам