ComboEdit.h
#ifndef __UICOMBOEDIT_H__ #define __UICOMBOEDIT_H__ #pragma once namespace DuiLib { class CComboEditWnd; class DUILIB_API CComboEditUI:public CComboUI { public: CComboEditUI(); LPCTSTR GetClass() const; LPVOID GetInterface(LPCTSTR pstrName); CDuiString GetText() const; void DoEvent(TEventUI& event); int GetFont(); void SetFont(int iFont); UINT GetTextStyle(); void SetTextStyle(UINT iTextStyle); int GetMaxChar(); void SetMaxChar(int iMaxChar); DWORD GetNativeEditBkColor(); void SetNativeEditBkColor(DWORD dwColor); DWORD GetTextColor(); void SetTextColor(DWORD dwColor); CDuiString m_sText; CComboEditWnd* m_pEditWnd; BOOL SelectItem(int iIndex, BOOL bTakeFocus = FALSE, BOOL bTriggerEvent = TRUE); void PaintText(HDC hDC); private: int GetCurSel() const; int m_iMaxChar; int m_iFont; UINT m_uTextStyle; DWORD m_dwNativeEditBkColor; DWORD m_dwTextColor; DWORD m_dwDisabledTextColor; }; }// end Duilib #endif // __UICOMBOEDIT_H__
ComboEdit.cpp
#include "stdafx.h" #include "UIComboEdit.h" #include <olectl.h> namespace DuiLib { class DUILIB_API CComboEditWnd : public CWindowWnd { public: CComboEditWnd(); void Init(CComboEditUI* pOwner); RECT CalPos(); LPCTSTR GetWindowClassName() const; LPCTSTR GetSuperClassName() const; void OnFinalMessage(HWND hWnd); LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnEditChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); protected: enum { DEFAULT_TIMERID = 20, }; CComboEditUI* m_pOwner; HBRUSH m_hBkBrush; BOOL m_bInit; BOOL m_bDrawCaret; }; CComboEditWnd::CComboEditWnd() : m_pOwner(NULL), m_hBkBrush(NULL), m_bInit(FALSE), m_bDrawCaret(FALSE) { } void CComboEditWnd::Init(CComboEditUI* pOwner) { m_pOwner = pOwner; RECT rcPos = CalPos(); UINT uStyle = WS_CHILD | ES_AUTOHSCROLL ; UINT uTextStyle = m_pOwner->GetTextStyle(); if (uTextStyle & DT_LEFT) uStyle |= ES_LEFT; else if (uTextStyle & DT_CENTER) uStyle |= ES_CENTER; else if (uTextStyle & DT_RIGHT) uStyle |= ES_RIGHT; Create(m_pOwner->GetManager()->GetPaintWindow(), NULL, uStyle, 0, rcPos); HFONT hFont = NULL; int iFontIndex = m_pOwner->GetFont(); if (iFontIndex != -1) hFont = m_pOwner->GetManager()->GetFont(iFontIndex); if (hFont == NULL) hFont = m_pOwner->GetManager()->GetDefaultFontInfo()->hFont; SetWindowFont(m_hWnd, hFont, TRUE); Edit_LimitText(m_hWnd, m_pOwner->GetMaxChar()); Edit_SetText(m_hWnd, m_pOwner->GetText()); Edit_SetModify(m_hWnd, FALSE); SendMessage(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELPARAM(0, 0)); Edit_Enable(m_hWnd, m_pOwner->IsEnabled() == TRUE); //Styls ::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE); ::SetFocus(m_hWnd); int nSize = GetWindowTextLength(m_hWnd); Edit_SetSel(m_hWnd, nSize, nSize); m_bInit = TRUE; } RECT CComboEditWnd::CalPos() { CDuiRect rcPos = m_pOwner->GetPos(); RECT rcInset = m_pOwner->GetTextPadding(); rcPos.left += rcInset.left; rcPos.top += rcInset.top; rcPos.right -= rcInset.right; rcPos.bottom -= rcInset.bottom; LONG lEditHeight = m_pOwner->GetManager()->GetFontInfo(m_pOwner->GetFont())->tm.tmHeight; if (lEditHeight < rcPos.GetHeight()) { rcPos.top += (rcPos.GetHeight() - lEditHeight) / 2; rcPos.bottom = rcPos.top + lEditHeight; } CControlUI* pParent = m_pOwner; RECT rcParent; while (pParent = pParent->GetParent()) { if (!pParent->IsVisible()) { rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0; break; } rcParent = pParent->GetClientPos(); if (!::IntersectRect(&rcPos, &rcPos, &rcParent)) { rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0; break; } } return rcPos; } LPCTSTR CComboEditWnd::GetWindowClassName() const { return _T("ComboEditWnd"); } LPCTSTR CComboEditWnd::GetSuperClassName() const { return WC_EDIT; } void CComboEditWnd::OnFinalMessage(HWND hWnd) { m_pOwner->Invalidate(); // Clear reference and die if (m_hBkBrush != NULL) ::DeleteObject(m_hBkBrush); m_pOwner->GetManager()->RemoveNativeWindow(hWnd); m_pOwner->m_pEditWnd= NULL; delete this; } LRESULT CComboEditWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = TRUE; if (uMsg == WM_CREATE) { m_pOwner->GetManager()->AddNativeWindow(m_pOwner, m_hWnd); if (m_pOwner->GetManager()->IsLayered()) { ::SetTimer(m_hWnd, DEFAULT_TIMERID, ::GetCaretBlinkTime(), NULL); } bHandled = FALSE; } else if (uMsg == WM_KILLFOCUS) lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); else if (uMsg == OCM_COMMAND) { if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) lRes = OnEditChanged(uMsg, wParam, lParam, bHandled); else if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_UPDATE) { RECT rcClient; ::GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, FALSE); } } else if (uMsg == WM_KEYDOWN && TCHAR(wParam) == VK_RETURN) { m_pOwner->GetManager()->SendNotify(m_pOwner, DUI_MSGTYPE_RETURN); } else if (uMsg == OCM__BASE + WM_CTLCOLOREDIT || uMsg == OCM__BASE + WM_CTLCOLORSTATIC) { if (m_pOwner->GetManager()->IsLayered() && !m_pOwner->GetManager()->IsPainting()) { m_pOwner->GetManager()->AddNativeWindow(m_pOwner, m_hWnd); } DWORD clrColor = m_pOwner->GetNativeEditBkColor(); if (clrColor == 0xFFFFFFFF) return 0; ::SetBkMode((HDC)wParam, TRANSPARENT); DWORD dwTextColor = m_pOwner->GetTextColor(); ::SetTextColor((HDC)wParam, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor))); if (clrColor < 0xFF000000) { if (m_hBkBrush != NULL) ::DeleteObject(m_hBkBrush); RECT rcWnd = m_pOwner->GetManager()->GetNativeWindowRect(m_hWnd); HBITMAP hBmpEditBk = CRenderEngine::GenerateBitmap(m_pOwner->GetManager(), rcWnd, m_pOwner, clrColor); m_hBkBrush = ::CreatePatternBrush(hBmpEditBk); ::DeleteObject(hBmpEditBk); } else { if (m_hBkBrush == NULL) { m_hBkBrush = ::CreateSolidBrush(RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor))); } } return (LRESULT)m_hBkBrush; } else if (uMsg == WM_PAINT) { if (m_pOwner->GetManager()->IsLayered()) { m_pOwner->GetManager()->AddNativeWindow(m_pOwner, m_hWnd); } bHandled = FALSE; } else if (uMsg == WM_PRINT) { if (m_pOwner->GetManager()->IsLayered()) { lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam); if (m_pOwner->IsEnabled() && m_bDrawCaret) { // todo:判断是否enabled RECT rcClient; ::GetClientRect(m_hWnd, &rcClient); POINT ptCaret; ::GetCaretPos(&ptCaret); RECT rcCaret = { ptCaret.x, ptCaret.y, ptCaret.x, ptCaret.y + rcClient.bottom - rcClient.top }; CRenderEngine::DrawLine((HDC)wParam, rcCaret, 1, 0xFF000000); } return lRes; } bHandled = FALSE; } else if (uMsg == WM_TIMER) { if (wParam == DEFAULT_TIMERID) { m_bDrawCaret = !m_bDrawCaret; RECT rcClient; ::GetClientRect(m_hWnd, &rcClient); ::InvalidateRect(m_hWnd, &rcClient, FALSE); return 0; } bHandled = FALSE; } else bHandled = FALSE; if (!bHandled) return CWindowWnd::HandleMessage(uMsg, wParam, lParam); return lRes; } LRESULT CComboEditWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); if ((HWND)wParam != m_pOwner->GetManager()->GetPaintWindow()) { ::SendMessage(m_pOwner->GetManager()->GetPaintWindow(), WM_KILLFOCUS, wParam, lParam); } SendMessage(WM_CLOSE); return lRes; } LRESULT CComboEditWnd::OnEditChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { if (!m_bInit) return 0; if (m_pOwner == NULL) return 0; // Copy text back int cchLen = ::GetWindowTextLength(m_hWnd) + 1; LPTSTR pstr = static_cast<LPTSTR>(_alloca(cchLen * sizeof(TCHAR))); ASSERT(pstr); if (pstr == NULL) return 0; ::GetWindowText(m_hWnd, pstr, cchLen); m_pOwner->m_sText = pstr; m_pOwner->SetToolTip(pstr); m_pOwner->GetManager()->SendNotify(m_pOwner, DUI_MSGTYPE_TEXTCHANGED); if (m_pOwner->GetManager()->IsLayered()) m_pOwner->Invalidate(); return 0; } CComboEditUI::CComboEditUI() { m_iMaxChar = -1; m_pEditWnd = NULL; m_iFont = 1; m_uTextStyle = DT_VCENTER | DT_SINGLELINE; m_dwNativeEditBkColor = 0x00000000; m_dwTextColor = 0x00000000; m_dwDisabledTextColor = 0; } LPCTSTR CComboEditUI::GetClass() const { return DUI_CTR_COMBOEDIT; } LPVOID CComboEditUI::GetInterface(LPCTSTR pstrName) { if (_tcscmp(pstrName, DUI_CTR_COMBO) == 0) return static_cast<CComboEditUI*>(this); return CComboUI::GetInterface(pstrName); } DuiLib::CDuiString CComboEditUI::GetText() const { return m_sText; } void CComboEditUI::DoEvent(TEventUI& event) { if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND) { if (m_pParent != NULL) m_pParent->DoEvent(event); else CComboUI::DoEvent(event); return; } if (event.Type == UIEVENT_KILLFOCUS) { if (m_pEditWnd) { m_pEditWnd->ShowWindow(FALSE, FALSE); } return; } if ( event.Type == UIEVENT_DBLCLICK || event.Type== UIEVENT_RBUTTONDOWN) { if (m_pEditWnd) { m_pEditWnd->ShowWindow(TRUE, TRUE); } if (m_pEditWnd) return; m_pEditWnd = new CComboEditWnd(); ASSERT(m_pEditWnd); m_pEditWnd->Init(this); } CComboUI::DoEvent(event); } int CComboEditUI::GetFont() { return m_iFont; } void CComboEditUI::SetFont(int iFont) { m_iFont = iFont; } UINT CComboEditUI::GetTextStyle() { return m_uTextStyle; } void CComboEditUI::SetTextStyle(UINT iTextStyle) { m_uTextStyle = iTextStyle; } int CComboEditUI::GetMaxChar() { return m_iMaxChar; } void CComboEditUI::SetMaxChar(int iMaxChar) { m_iMaxChar = iMaxChar; } DWORD CComboEditUI::GetNativeEditBkColor() { return m_dwNativeEditBkColor; } void CComboEditUI::SetNativeEditBkColor(DWORD dwColor) { m_dwNativeEditBkColor = dwColor; } DWORD CComboEditUI::GetTextColor() { return m_dwTextColor; } void CComboEditUI::SetTextColor(DWORD dwColor) { m_dwTextColor = dwColor; } BOOL CComboEditUI::SelectItem(int iIndex, BOOL bTakeFocus /*= FALSE*/, BOOL bTriggerEvent /*= TRUE*/) { if (m_bSelectCloseFlag && m_pWindow != NULL) m_pWindow->Close(); if (iIndex == m_iCurSel) return TRUE; int iOldSel = m_iCurSel; if (m_iCurSel >= 0) { CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]); if (!pControl) return FALSE; IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(DUI_CTR_ILISTITEM)); if (pListItem != NULL) pListItem->Select(FALSE, bTriggerEvent); m_iCurSel = -1; } if (iIndex < 0) return FALSE; if (m_items.GetSize() == 0) return FALSE; if (iIndex >= m_items.GetSize()) iIndex = m_items.GetSize() - 1; CControlUI* pControl = static_cast<CControlUI*>(m_items[iIndex]); if (!pControl || !pControl->IsVisible() || !pControl->IsEnabled()) return FALSE; m_sText = pControl->GetText(); SetToolTip(m_sText); IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(DUI_CTR_ILISTITEM)); if (pListItem == NULL) return FALSE; m_iCurSel = iIndex; if (m_pWindow != NULL || bTakeFocus) pControl->SetFocus(); pListItem->Select(TRUE, bTriggerEvent); if (m_pManager != NULL && bTriggerEvent) m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMSELECT, m_iCurSel, iOldSel); Invalidate(); return TRUE; } void CComboEditUI::PaintText(HDC hDC) { if (!m_bShowText) { return; } if (m_pEditWnd && IsWindowVisible(m_pEditWnd->GetHWND())) { return; } RECT rcText = m_rcItem; rcText.left += m_rcTextPadding.left; rcText.right -= m_rcTextPadding.right; rcText.top += m_rcTextPadding.top; rcText.bottom -= m_rcTextPadding.bottom; if (m_iCurSel >= 0) { CListLabelElementUI* pControl = static_cast<CListLabelElementUI*>(m_items[m_iCurSel]); if (pControl) { CDuiString strIcon = pControl->GetIcon(); SIZE szIcon = pControl->GetIconSize(); if (strIcon != _T("")) { IListOwnerUI* pOwner = pControl->GetOwner(); if (pOwner == NULL) return; TListInfoUI* pInfo = pOwner->GetListInfo(); if (pInfo == NULL) return; int left, right; left =0; right = left + szIcon.cx; TDrawInfo diIcon; CDuiString pStrImage; int bottom, top = (rcText.bottom - rcText.top - szIcon.cy) / 2; bottom = top + szIcon.cy; pStrImage.SmallFormat(_T("file='%s' dest='%d,%d,%d,%d'"), strIcon.GetData(), left, top, right, bottom); diIcon.Clear(); diIcon.sDrawString = pStrImage; CRenderEngine::DrawImage(hDC, m_pManager, rcText, m_rcPaint, diIcon); m_uTextStyle |= pInfo->uTextStyle; } rcText.left += szIcon.cx; } } if (m_dwTextColor == 0) m_dwTextColor = m_pManager->GetDefaultFontColor(); if (m_dwDisabledTextColor == 0) m_dwDisabledTextColor = m_pManager->GetDefaultDisabledColor(); if (m_sText.IsEmpty()) return; if (IsEnabled()) { CRenderEngine::DrawText(hDC, m_pManager, rcText, m_sText, m_dwTextColor, m_iFont, DT_SINGLELINE | m_uTextStyle); } else { CRenderEngine::DrawText(hDC, m_pManager, rcText, m_sText, m_dwDisabledTextColor, m_iFont, DT_SINGLELINE | m_uTextStyle); } } int CComboEditUI::GetCurSel() const { return -1; } }// end duilib
效果,右键或者双击启动编辑功能
<Default name="ComboEdit" value="normalimage="file='resuttonscombo_normal.png' corner='20,0,20,0'" hotimage="file='resuttonscombo_down.png' corner='20,0,20,0'" pushedimage="file='resuttonscombo_down.png' corner='20,0,20,0'" vscrollbar="true" textpadding="6,0,20,0" itemtextpadding="6,0,0,0" " />