CEdit with an ellipsis
Sometimes developers are devoted to absolutely rediculous tasks. Like having an established conception broken for some reason. You spend a lot of time cracking things up to acomplish your mission. Recently I was working on an edit control with an ellipsis if the text does not fit.
I came up with painting the edit in case it's not focused:
class CEllipsisEdit : public CEdit { DECLARE_DYNAMIC(CEllipsisEdit) protected: COLORREF GetBkColor() const; protected: CBrush m_bkBrush; protected: DECLARE_MESSAGE_MAP() afx_msg void OnPaint(); };
#include "EllipsisEdit.h" IMPLEMENT_DYNAMIC(CEllipsisEdit, CEdit) // CEllipsisEdit message map BEGIN_MESSAGE_MAP(CEllipsisEdit, CEdit) ON_WM_PAINT() END_MESSAGE_MAP() // CEllipsisEdit message handlers COLORREF CEllipsisEdit::GetBkColor() const { if (m_hWnd) { const HWND hParentWnd = GetParent()->GetSafeHwnd(); if (::GetWindowThreadProcessId(hParentWnd, NULL) == ::GetWindowThreadProcessId(m_hWnd, NULL)) { CDC dc; dc.CreateCompatibleDC(NULL); const bool enabled = (GetStyle() & WS_DISABLED) == 0; const UINT colorMsg = enabled ? WM_CTLCOLOREDIT : WM_CTLCOLORSTATIC; ::SendMessage(hParentWnd, colorMsg, reinterpret_cast<WPARAM>(dc.m_hDC), reinterpret_cast<LPARAM>(m_hWnd)); return dc.GetBkColor(); } } return ::GetSysColor(COLOR_WINDOW); } void CEllipsisEdit::OnPaint() { if (::GetFocus() == m_hWnd) { __super::OnPaint(); return; } CString text; GetWindowText(text); if (!m_bkBrush.m_hObject) m_bkBrush.CreateSolidBrush(GetBkColor()); CPaintDC dc(this); RECT rc = { 0, 0, 0, 0 }; GetClientRect(&rc); dc.FillRect(&rc, &m_bkBrush); GetRect(&rc); dc.SetBkMode(TRANSPARENT); dc.SelectObject(GetFont()); dc.DrawText(text, text.GetLength(), &rc, DT_SINGLELINE | DT_NOPREFIX | DT_WORD_ELLIPSIS); }
There were several problems:
- Edit control would paint itself synchronously. No WM_PAINT message is sent, just GetDC(hwnd) and the paint code, no way to sabstitute painting.
- Edit control doesn't have non-client area, borders are drawn in client area.
- Have to somehow determine text background color.
Synchronous paint seems to be an issue only with focused control. Borders are drawn as usual for unknown reason. Background color shall be determined by sending WM_CTLCOLOREDIT
or WM_CTLCOLORSTATIC
to parent or just a COLOR_WINDOW
system color as a fallback.
Please note that WM_CTLCOLOR
-related messages are not sent to parent widows in different threads! Also don't forget to add DT_NOPREFIX
flag when invoking DrawText
method.