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='res\buttons\combo_normal.png' corner='20,0,20,0'" hotimage="file='res\buttons\combo_down.png' corner='20,0,20,0'" pushedimage="file='res\buttons\combo_down.png' corner='20,0,20,0'" vscrollbar="true" textpadding="6,0,20,0" itemtextpadding="6,0,0,0" " />