2#include "control/SComboBase.h"
6const wchar_t *KStyle_Dropdown = L
"dropdownStyle";
7const wchar_t *KStyle_Edit = L
"editStyle";
21 SEdit::OnMouseHover((UINT)wParam, ptPos);
22 GetOwner()->SSendMessage(WM_MOUSEHOVER, wParam, MAKELPARAM(ptPos.x, ptPos.y));
27 __baseCls::OnMouseLeave();
28 GetOwner()->SSendMessage(WM_MOUSELEAVE);
34 if (pOwner && (nChar == VK_DOWN || nChar == VK_UP || nChar == VK_ESCAPE))
36 pOwner->
SSendMessage(WM_KEYDOWN, nChar, MAKELONG(nFlags, nRepCnt));
47 evt->SetIdFrom(GetOwner()->GetID());
48 evt->SetNameFrom(GetOwner()->GetName());
50 return SEdit::FireEvent(evt);
55 __baseCls::OnKillFocus(wndFocus);
56 GetOwner()->SSendMessage(WM_KILLFOCUS, wndFocus);
61BOOL SDropDownWnd_ComboBox::PreTranslateMessage(MSG *pMsg)
65 if (pMsg->message == WM_MOUSEWHEEL || ((pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) && (pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)))
75SComboBase::SComboBase(
void)
76 : m_pSkinBtn(GETBUILTINSKIN(SKIN_SYS_DROPBTN))
82 , m_pDropDownWnd(NULL)
84 , m_bAutoFitDropBtn(TRUE)
85 , m_crCue(RGBA(0xcc, 0xcc, 0xcc, 0xff))
89 , m_bAutoDropdown(FALSE)
93 m_style.SetAlign(SwndStyle::Align_Left);
94 m_style.SetVAlign(SwndStyle::VAlign_Middle);
96 m_evtSet.addEvent(EVENTID(EventCBSelChange));
97 m_evtSet.addEvent(EVENTID(EventRENotify));
98 m_evtSet.addEvent(EVENTID(EventCBDropdown));
99 m_evtSet.addEvent(EVENTID(EventCBBeforeCloseUp));
102SComboBase::~SComboBase(
void)
106BOOL SComboBase::CreateChildren(
SXmlNode xmlNode)
108 m_xmlDropdownStyle.root().append_copy(xmlNode.
child(KStyle_Dropdown));
110 SXmlNode xmlEditStyle = xmlNode.
child(KStyle_Edit);
111 SStringW strEditClass = xmlEditStyle.
attribute(L
"wndclass").
as_string(SComboEdit::GetClassName());
115 m_pEdit->SetOwner(
this);
117 m_pEdit->GetEventSet()->setMutedState(TRUE);
119 m_pEdit->InitFromXml(&xmlEditStyle);
121 m_pEdit->SSendMessage(WM_CREATE);
122 m_pEdit->GetEventSet()->setMutedState(FALSE);
124 m_pEdit->SetID(IDC_CB_EDIT);
125 m_pEdit->SSendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE);
126 m_pEdit->SetVisible(!m_bDropdown);
128 BOOL ret = CreateListBox(xmlNode);
133void SComboBase::GetDropBtnRect(LPRECT prc)
135 SIZE szBtn = m_pSkinBtn->GetSkinSize();
138 rcClient.DeflateRect(rcPadding);
141 int nHei = prc->bottom - prc->top;
142 prc->left = prc->right - nHei * szBtn.cx / szBtn.cy;
143 if (m_bAutoFitDropBtn && szBtn.cy < nHei)
145 prc->top += (prc->bottom - prc->top - szBtn.cy) / 2;
146 prc->left = prc->right - szBtn.cx;
147 prc->right = prc->left + szBtn.cx;
148 prc->bottom = prc->top + szBtn.cy;
152void SComboBase::GetTextRect(LPRECT pRect)
155 rc.DeflateRect(
GetStyle().GetPadding());
157 GetDropBtnRect(&rcBtn);
158 rc.right -= rcBtn.Width();
171 if (GetCurSel() != -1)
173 SStringT strText = GetWindowText();
178 SStringT strCue = GetCueText();
179 if (!strCue.IsEmpty())
194 GetDropBtnRect(&rcBtn);
195 m_pSkinBtn->DrawByState(pRT, rcBtn, m_dwBtnState);
198void SComboBase::OnLButtonDown(UINT nFlags, CPoint pt)
205void SComboBase::OnMouseMove(UINT nFlags, CPoint pt)
210 __baseCls::OnMouseHover(nFlags, pt);
212 GetDropBtnRect(&rcBtn);
213 if (rcBtn.PtInRect(pt))
225void SComboBase::OnMouseLeave()
231 __baseCls::OnMouseLeave();
236 GetDropBtnRect(&rcBtn);
241void SComboBase::OnKeyDown(TCHAR nChar, UINT nRepCnt, UINT nFlags)
249 int iSel = GetCurSel();
251 if (iSel < GetCount())
258 int iSel = GetCurSel();
260 if (iSel < GetCount() && iSel >= 0)
268 if ((GetTickCount() - m_LastPressTime) > 300)
272 m_LastPressTime = GetTickCount();
274 int iCurSel = GetCurSel();
275 int iStart = iCurSel + 1;
276 bool matched =
false;
277 while (iStart < GetCount())
279 SStringT itemText = GetLBText(iStart);
280 if (itemText.StartsWith(m_strMatch,
true))
291 while (iStart <= iCurSel)
293 SStringT itemText = GetLBText(iStart);
294 if (itemText.StartsWith(m_strMatch,
true))
308BOOL SComboBase::OnMouseWheel(UINT nFlags,
short zDelta, CPoint pt)
313 int iSel = GetCurSel();
315 if (iSel < GetCount() && iSel >= 0)
320 int iSel = GetCurSel();
322 if (iSel < GetCount())
328void SComboBase::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
332 SComboEdit *pEdit =
static_cast<SComboEdit *
>(
FindChildByID(IDC_CB_EDIT));
334 pEdit->SSendMessage(WM_CHAR, nChar, MAKELONG(nFlags, nRepCnt));
339UINT SComboBase::OnGetDlgCode()
const
341 return SC_WANTARROWS;
344BOOL SComboBase::IsFocusable()
const
351SWindow *SComboBase::GetDropDownOwner()
356static const wchar_t *KAttrTrCtx = L
"trCtx";
357void SComboBase::OnCreateDropDown(
SDropDownWnd *pDropDown)
360 SXmlNode xmlDropdownStyleNode = m_xmlDropdownStyle.root().child(KStyle_Dropdown);
361 if (xmlDropdownStyleNode)
363 if (!xmlDropdownStyleNode.
attribute(KAttrTrCtx))
376 GetDropBtnRect(&rcBtn);
380void SComboBase::OnDestroyDropDown(
SDropDownWnd *pDropDown)
388 m_pDropDownWnd = NULL;
390 GetDropBtnRect(&rcBtn);
404BOOL SComboBase::CalcPopupRect(
int nHeight, CRect &rcPopup)
416 MONITORINFO mi = {
sizeof(MONITORINFO) };
417 ::GetMonitorInfo(hMonitor, &mi);
418 rcMonitor = mi.rcMonitor;
422 rcMonitor.right = GetSystemMetrics(SM_CXSCREEN);
423 rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
425 if (rcWnd.bottom + nHeight <= rcMonitor.bottom)
427 rcPopup = CRect(rcWnd.left, rcWnd.bottom, rcWnd.right, rcWnd.bottom + nHeight);
432 rcPopup = CRect(rcWnd.left, rcWnd.top - nHeight, rcWnd.right, rcWnd.top);
437void SComboBase::DropDown()
444 m_pDropDownWnd =
new SDropDownWnd_ComboBox(
this);
447 EventCBDropdown evt(
this);
448 evt.pDropDown = m_pDropDownWnd;
449 SStringT strInput = GetWindowText(TRUE);
452 m_pDropDownWnd->Create(CRect(0, 0, 100, 100), 0);
453 m_pDropDownWnd->GetRoot()->SDispatchMessage(UM_SETSCALE,
GetScale(), 0);
455 CRect rcPadding = m_pDropDownWnd->GetRoot()->GetStyle().GetPadding();
456 CRect rcMargin = m_pDropDownWnd->GetRoot()->GetStyle().GetMargin();
457 int nDropHeight = GetListBoxHeight() + rcPadding.top + rcPadding.bottom + rcMargin.top + rcMargin.bottom;
460 BOOL bDown = CalcPopupRect(nDropHeight, rcPopup);
461 m_pDropDownWnd->MoveWindow(rcPopup.left, rcPopup.top, rcPopup.Width(), rcPopup.Height());
462 m_pDropDownWnd->GetRoot()->UpdateChildrenPosition();
466 m_pDropDownWnd->AnimateHostWindow(m_nAnimTime, AW_SLIDE | (bDown ? AW_VER_POSITIVE : AW_VER_NEGATIVE));
468 m_pDropDownWnd->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
470 m_pDropDownWnd->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
472 m_pDropDownWnd->SNativeWnd::SetCapture();
475void SComboBase::UpdateDropdown(
const SStringT &strInput)
479 m_pDropDownWnd =
new SDropDownWnd_ComboBox(
this);
480 m_pDropDownWnd->GetRoot()->SDispatchMessage(UM_SETSCALE,
GetScale(), 0);
483 EventCBDropdown evt(
this);
484 evt.pDropDown = m_pDropDownWnd;
485 evt.strInput = &strInput;
487 BOOL bNewPopup = !m_pDropDownWnd->IsWindow();
489 m_pDropDownWnd->Create(CRect(0, 0, 100, 100), 0);
491 CRect rcPadding = m_pDropDownWnd->GetRoot()->GetStyle().GetPadding();
492 CRect rcMargin = m_pDropDownWnd->GetRoot()->GetStyle().GetMargin();
493 int nDropHeight = GetListBoxHeight() + rcPadding.top + rcPadding.bottom + rcMargin.top + rcMargin.bottom;
496 BOOL bDown = CalcPopupRect(nDropHeight, rcPopup);
497 m_pDropDownWnd->MoveWindow(rcPopup.left, rcPopup.top, rcPopup.Width(), rcPopup.Height());
498 m_pDropDownWnd->GetRoot()->UpdateChildrenPosition();
501 if (m_nAnimTime > 0 && bNewPopup)
502 m_pDropDownWnd->AnimateHostWindow(m_nAnimTime, AW_SLIDE | (bDown ? AW_VER_POSITIVE : AW_VER_NEGATIVE));
504 m_pDropDownWnd->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
506 m_pDropDownWnd->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
508 m_pDropDownWnd->SNativeWnd::SetCapture();
511void SComboBase::CloseUp()
513 EventCBBeforeCloseUp evt(
this);
514 evt.bCloseBlock = FALSE;
517 if (!evt.bCloseBlock && m_pDropDownWnd)
519 m_pDropDownWnd->EndDropDown(IDCANCEL);
523void SComboBase::OnDestroy()
526 __baseCls::OnDestroy();
529int SComboBase::OnCreate(LPVOID)
531 int ret = __baseCls::OnCreate(NULL);
539void SComboBase::OnSelChanged()
541 EventCBSelChange evt(
this);
542 evt.nCurSel = GetCurSel();
546BOOL SComboBase::FireEvent(IEvtArgs *evt)
548 if (evt->GetID() == EventRENotify::EventID)
550 EventRENotify *evtRe = (EventRENotify *)evt;
551 if (evtRe->iNotify == EN_CHANGE && !m_pEdit->GetEventSet()->isMuted())
553 m_pEdit->GetEventSet()->setMutedState(
true);
554 SStringT strTxt = m_pEdit->GetWindowText();
557 if (strTxt.GetLength() > m_nTextLength)
559 int iItem = FindString(strTxt, -1, TRUE);
562 SStringT strItem = GetLBText(iItem);
563 m_pEdit->SetWindowText(strItem);
564 m_pEdit->SetSel(strTxt.GetLength(), strItem.GetLength(), TRUE);
567 m_nTextLength = strTxt.GetLength();
571 UpdateDropdown(strTxt);
577 m_pEdit->GetEventSet()->setMutedState(
false);
583int SComboBase::FindString(LPCTSTR pszFind,
int iFindAfter , BOOL bPartMatch )
587 int iStart = iFindAfter + 1;
588 for (
int i = 0; i < GetCount(); i++)
590 int iTarget = (i + iStart) % GetCount();
591 SStringT strItem = GetLBText(iTarget, TRUE);
594 if (strItem.StartsWith(pszFind))
599 if (strItem.Compare(pszFind) == 0)
606void SComboBase::GetDesiredSize(SIZE *psz,
int nParentWid,
int nParentHei)
615 szRet.cx = nParentWid;
624 szRet.cy = nParentHei;
627 if (szRet.cx != -1 && szRet.cy != -1)
632 int nTestDrawMode =
GetTextAlign() & ~(DT_CENTER | DT_RIGHT | DT_VCENTER | DT_BOTTOM);
636 CRect rcTest(0, 0, 100000, 100000);
638 SAutoRefPtr<IRenderTarget> pRT;
639 GETRENDERFACTORY->CreateRenderTarget(&pRT, 0, 0);
642 SStringT strText = GetWindowText(FALSE);
643 SStringT strForText = strText.
IsEmpty() ? SStringT(_T(
"A")) : strText;
644 DrawText(pRT, strForText, strForText.GetLength(), rcTest, nTestDrawMode | DT_CALCRECT);
645 if (strText.IsEmpty())
646 rcTest.right = rcTest.left;
648 SIZE szBtn = m_pSkinBtn->GetSkinSize();
649 rcTest.right += szBtn.cx;
650 rcTest.bottom = smax(rcTest.Height(), szBtn.cy);
652 rcTest.InflateRect(
m_style.GetMargin());
653 rcTest.InflateRect(rcPadding);
656 szRet.cx = rcTest.Width();
658 szRet.cy = rcTest.Height();
663SStringT SComboBase::GetWindowText(BOOL bRawText )
667 return GetEditText();
669 if (GetCurSel() == -1)
671 return GetLBText(GetCurSel(), bRawText);
674void SComboBase::SetWindowText(LPCTSTR pszText)
677 m_pEdit->SetWindowText(pszText);
678 m_nTextLength = (int)_tcslen(pszText);
681void SComboBase::OnKillFocus(SWND wndFocus)
683 __baseCls::OnKillFocus(wndFocus);
687HRESULT SComboBase::OnAttrDropDown(
const SStringW &strValue, BOOL bLoading)
689 m_bDropdown = STRINGASBOOL(strValue);
692 m_pEdit->SetVisible(!m_bDropdown, TRUE);
696void SComboBase::UpdateChildrenPosition()
698 __baseCls::UpdateChildrenPosition();
699 SIZE szBtn = m_pSkinBtn->GetSkinSize();
703 GetDropBtnRect(&rcBtn);
704 rcEdit.right = rcBtn.left;
705 m_pEdit->Move(rcEdit);
708void SComboBase::OnColorize(COLORREF cr)
710 __baseCls::OnColorize(cr);
712 m_pSkinBtn->OnColorize(cr);
715 m_pDropDownWnd->GetRoot()->SDispatchMessage(UM_SETCOLORIZE, cr, 0);
719HRESULT SComboBase::OnLanguageChanged()
721 HRESULT hr = __baseCls::OnLanguageChanged();
724 m_pDropDownWnd->GetRoot()->SDispatchMessage(UM_SETLANGUAGE, 0, 0);
729void SComboBase::OnScaleChanged(
int nScale)
731 __baseCls::OnScaleChanged(nScale);
734 m_pDropDownWnd->GetRoot()->SDispatchMessage(UM_SETSCALE, nScale, 0);
739BOOL SComboBase::IsDropdown()
const
744void SComboBase::SetDropdown(BOOL bDropdown)
746 m_bDropdown = bDropdown;
747 m_pEdit->SetVisible(!m_bDropdown, TRUE);
750SStringT SComboBase::GetCueText(BOOL bRawText)
const
752 return m_strCue.GetText(bRawText);
755void SComboBase::SetFocus()
760 __baseCls::SetFocus();
763SStringT SComboBase::GetLBText(
int iItem, BOOL bRawText )
766 GetItemText(iItem, bRawText, &str);
@ EVT_RE_NOTIFY
丰富编辑控件通知事件
virtual ~SComboEdit()
Destructor.
void OnMouseHover(WPARAM wParam, CPoint ptPos)
Handle mouse hover event.
void OnMouseLeave()
Handle mouse leave event.
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Notify event.
void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
Handle key down event.
void OnKillFocus(SWND wndFocus)
Handle kill focus event.
UINT GetExitCode() const
Get the exit code of the dropdown window.
virtual BOOL WINAPI PreTranslateMessage(MSG *pMsg)
Pre-translate messages.
void setMutedState(BOOL setting)
设置事件集的静音状态
void SetTrCtx(const SStringW &strTrCtx)
Sets the translation context.
BOOL InitFromXml(IXmlNode *pNode) OVERRIDE
Initializes the host window from an XML node.
SHostWndAttr & GetHostAttr()
Gets the host window attributes.
int toPixelSize(int scale) const
将大小转换为像素值
LRESULT SendMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0) OVERRIDE
Sends a message to the window.
BOOL IsEmpty() SCONST
Checks if the string is empty.
A class representing an ASCII string.
Base class for SOUI DUI windows.
virtual LPCWSTR GetTrCtx() const
Get translation context.
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
DWORD GetState() SCONST OVERRIDE
Retrieves the current state of the window.
UINT GetTextAlign() const
Retrieves the text alignment of the window.
int GetScale() SCONST OVERRIDE
Retrieves the scale factor of the window.
CRect GetWindowRect() const
Retrieves the bounding rectangle of the window.
ISwndContainer * GetContainer() OVERRIDE
Retrieves the container associated with this window.
BOOL IsFocused() SCONST OVERRIDE
Checks if the window has focus.
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
void InsertChild(SWindow *pNewChild, SWindow *pInsertAfter=NULL)
Inserts a child window into the window tree.
LRESULT SSendMessage(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0, BOOL *pbMsgHandled=NULL) OVERRIDE
Sends a message to the window.
virtual void BeforePaint(IRenderTarget *pRT, SPainter &painter)
Prepare rendering environment.
void InvalidateRect(LPCRECT lprect) OVERRIDE
Invalidates a specific rectangle area of the window.
virtual SWindow * CreateChildByName(LPCWSTR pszName)
Create child window by name.
virtual void DrawFocus(IRenderTarget *pRT)
Draw focus state.
virtual void AfterPaint(IRenderTarget *pRT, SPainter &painter)
Restore rendering environment.
ILayoutParam * GetLayoutParam() SCONST OVERRIDE
Retrieves the layout parameter object associated with the window.
virtual void DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)
Draw text content.
SEventSet * GetEventSet()
Retrieves the event set associated with the window.
void SetWindowText(LPCTSTR lpszText) OVERRIDE
Sets the window text.
void GetScaleSkin(SAutoRefPtr< ISkinObj > &pSkin, int nScale)
Retrieves a scaled skin object based on the current scale factor.
DWORD ModifyState(DWORD dwStateAdd, DWORD dwStateRemove, BOOL bUpdate=FALSE) OVERRIDE
Modifies the state of the window.
const SwndStyle & GetStyle() const
Retrieves the style of the window.
HWND GetHostHwnd() OVERRIDE
Retrieves the host window handle.
SWindow * FindChildByID(int nID, int nDeep=-1)
Finds a child window by its ID.
void BeforePaintEx(IRenderTarget *pRT)
Prepares the drawing environment for the current window's RenderTarget, starting from the top-level w...
bool set_value(const wchar_t *rhs)
Sets the attribute value.
const wchar_t * as_string(const wchar_t *def=L"") const
Gets the attribute value as a string.
Class representing an XML node.
SXmlAttr attribute(const wchar_t *name, bool bCaseSensitive=false) const
Gets the attribute with the specified name.
SXmlAttr append_attribute(const wchar_t *name)
Adds an attribute with the specified name.
SXmlNode child(const wchar_t *name, bool bCaseSensitive=false) const
Gets the child node, attribute, or next/previous sibling with the specified name.
CRect GetPadding() const
Retrieves the padding rectangle.
Interface for rendering target objects.
COLORREF SetTextColor(COLORREF color) PURE
Sets the current text color.
void FrameToHost(RECT *rc) SCONST PURE
Converts the rectangle coordinates of the current frame to the final host coordinates.
void EnableHostPrivateUiDef(BOOL bEnable) PURE
Enables or disables the host's private UI definitions.