duilib可编辑下拉选择框

这篇博客介绍了如何使用duilib库创建一个可编辑的下拉选择框。作者指出,用户在输入文本后,下拉选项会自动匹配显示。尽管存在窗口移动时下拉窗口不自动关闭的问题,作者提供了内部实现的CComboEditUI类,包括其头文件和源文件,并分享了一个演示链接。
摘要由CSDN通过智能技术生成

标题duilib ComboEdit

可编辑下拉选择框

可编辑下拉选择框,输入文本后,下拉选择框会自动显示相关的选项;
自己根据EditUI、ComboUI、ListUI自己弄出来的;
缺陷:
当窗口移动的时候(拖住窗口标题移动),combo窗口不会主动关闭,也不会主动跟着窗口移动,需要在窗口的WM_NCLBUTTONDOWN消息设置焦点到窗口或其他控件,使得CEditWnd收到KillFocus消息,从而把自己(CEditWnd)关闭,关闭时也把CComboWnd关闭;
但这样控件需要外部来控制,破坏控件的封装,且移动后焦点就不在ComboEdit上了;

LRESULT CMainFrame::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
   
	switch (uMsg)
	{
   
	case WM_TIMER:
		{
   
			OnTimer(uMsg, wParam, lParam, bHandled);
		}
		break;
	case WM_NCLBUTTONDOWN:
		{
   
			ShowMsg(_T("非客户区单击"));

			SetFocus(GetHWND());
		}
		break;
	default:
		{
   

		}
		break;
	}
	return 0;
}
void CEditCombo_EditWnd::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_pEditWindow = NULL;
	m_pOwner->EditDestroy();  // 告诉父亲自己destroy
	delete this;
}

LRESULT CEditCombo_EditWnd::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;
}

void CEditComboUI::EditDestroy()
{
   
	if (NULL != m_pComboWindow)
	{
   
		m_pComboWindow->PostMessage(WM_CLOSE);
		Invalidate();
	}
}

CComboEditUI

1. UIComboEdit.h


#pragma once

#define  DUI_CTR_EDITCOMBOELEMENT  (_T("EditComboElement"))
#define  DUI_CTR_EDITCOMBO  (_T("EditCombo"))

class CEditCombo_EditWnd;
class CEditCombo_ComboWnd;

class IEditCombo_ControlUI
{
   
public:
	virtual int GetWindowStyls() const = 0;
	virtual CPaintManagerUI* GetManager() const = 0;
	virtual CControlUI* GetParent() const = 0;
	virtual LPVOID GetInterface(LPCTSTR pstrName) = 0;
	virtual void Invalidate() = 0;

	virtual bool IsEnabled() const = 0;
	virtual CDuiString GetText() const = 0;
	virtual void SetPos(RECT rc, bool bNeedInvalidate) = 0;
	virtual const RECT& GetPos() const = 0;
	virtual RECT GetRelativePos() const = 0;
	virtual RECT GetClientPos() const = 0;
	virtual bool IsVisible() const = 0;
	virtual void DoEvent(TEventUI &event) = 0;
protected:
	virtual void _SetText(LPCTSTR pstrText) = 0;  // 仅仅设置m_sText
};

class IEditCombo_EditUI : public IEditCombo_ControlUI
{
   
	friend class CEditCombo_EditWnd;

protected:
	CEditCombo_EditWnd *m_pEditWindow;  // Edit框

public:
	IEditCombo_EditUI() : m_pEditWindow(NULL){
   }
	virtual int GetFont() const = 0;
	virtual UINT GetTextStyle() const = 0;
	virtual RECT GetTextPadding() const = 0;
	virtual bool IsPasswordMode() const = 0;
	virtual TCHAR GetPasswordChar() const = 0;
	virtual bool IsReadOnly() const = 0;
	virtual bool IsAutoSelAll() const = 0;
	virtual UINT GetMaxChar() const = 0;
	virtual DWORD GetTextColor() const = 0;
	virtual DWORD GetNativeEditBkColor() const = 0;
	virtual DWORD GetNativeEditTextColor() const = 0;
	virtual void TextChange() = 0;
	virtual void EditDestroy() = 0;
};
class IEditCombo_ComboUI : public IEditCombo_ControlUI
{
   
	friend class CEditCombo_ComboWnd;
protected:
	CEditCombo_ComboWnd *m_pComboWindow;  // Combo弹窗
	UINT m_uButtonState;  // 状态

public:
	IEditCombo_ComboUI() : m_pComboWindow(NULL), m_uButtonState(0){
   }
	virtual LPCTSTR GetClass() const = 0;
	virtual bool IsFloat() const = 0;
	virtual int GetCurSel() const = 0;
	virtual int GetCount() const = 0;
	virtual void SetManager(CPaintManagerUI* pManager, CControlUI* pParent, bool bInit = true) = 0;
	virtual CControlUI* GetItemAt(int id) = 0;
	virtual void SetFocus() = 0;

	virtual SIZE GetDropBoxSize() const = 0;
	virtual CDuiString GetDropBoxAttributeList() = 0;
	virtual TListInfoUI* GetListInfo() = 0;

	virtual bool SelectItem(int iIndex, bool bTakeFocus = false, bool bTriggerEvent=true, bool bMutil = false) = 0;
};


class CEditComboElementUI : public CListLabelElementUI
{
   
public:
	CEditComboElementUI() : CListLabelElementUI(){
   }
	LPCTSTR GetClass() const
	{
   
		return DUI_CTR_EDITCOMBOELEMENT;
	}
	LPVOID GetInterface(LPCTSTR pstrName)
	{
   
		if (0 == _tcscmp(pstrName, DUI_CTR_EDITCOMBOELEMENT))
		{
   
			return static_cast<CEditComboElementUI*>(this);
		}

		return CListLabelElementUI::GetInterface(pstrName);
	}

	void SetFocus() override{
   }
};

class CEditComboUI : public CContainerUI, public IEditCombo_EditUI, public IEditCombo_ComboUI, public IListOwnerUI
{
   
public:
	CEditComboUI(void);
	virtual ~CEditComboUI(void);

	LPCTSTR GetClass() const;
	LPVOID GetInterface(LPCTSTR pstrName);
	UINT GetControlFlags() const;
	HWND GetNativeWindow() const;
	HWND GetNativeEditHWND() const;

	int GetWindowStyls() const;
	UINT GetTextStyle() const;
	int GetFont() const;
	CPaintManagerUI* GetManager() const;
	CControlUI* GetParent() const;
	void Invalidate();

	bool IsEnabled() const;
	void SetEnabled(bool bEnable);
	CDuiString GetText() const;
	void _SetText(LPCTSTR pstrtext);
	void SetText(LPCTSTR pstrText);
	RECT GetTextPadding() const;
	void SetTextPadding(RECT rc);
	void SetTextPadding(LPCTSTR pstrValue);
	bool IsVisible() const;
	void TextChange();
	void EditDestroy();

	void SetPasswordMode(bool bPasswordMode);
	bool IsPasswordMode() const;
	void SetPasswordChar(TCHAR szChar);
	TCHAR GetPasswordChar() const;
	void SetMaxChar(UINT uMax);
	UINT GetMaxChar() const;
	void SetReadOnly(bool bReadOnly);
	bool IsReadOnly() const;
	void SetNumberOnly(bool bNumberOnly);
	bool IsNumberOnly() const;
	void SetAutoSelAll(bool bAuto);
	bool IsAutoSelAll() const;
	void SetReplaceSel(LPCTSTR lpszReplace);

	void SetFont(int index);
	void SetPos(RECT rc, bool bNeedInvalidate);
	const RECT& GetPos() const;
	RECT GetRelativePos() const;
	RECT GetClientPos() const;
	void Move(SIZE szOffset, bool bNeedInvalidate);
	void SetVisible(bool bVisible);
	void SetInternVisible(bool bVisible);
	SIZE EstimateSize(SIZE szAvailable);
	void PaintStatusImage(HDC hDC);
	void PaintText(HDC hDC);

	LPCTSTR GetNormalImage();
	void SetNormalImage(LPCTSTR pStrImage);
	LPCTSTR GetHotImage();
	void SetHotImage(LPCTSTR pStrImage);
	LPCTSTR GetPushedImage() const;
	void SetPushedIMage(LPCTSTR pStrImage);
	LPCTSTR GetFocusedImage();
	void SetFocusedImage(LPCTSTR pStrImage);
	LPCTSTR GetDisabledImage();
	void SetDisabledImage(LPCTSTR pStrImage);
	DWORD GetTextColor() const;
	void SetNativeEditBkColor(LPCTSTR pStrColor);
	DWORD GetNativeEditBkColor() const;
	void SetNativeEditTextColor(LPCTSTR pStrColor);
	DWORD GetNativeEditTextColor() const;
	void SetTipValue(LPCTSTR pStrTipValue);
	void SetTipValueColor(LPCTSTR pStrColor);
	DWORD GetTipValueColor();
	CDuiString GetTipValue();
	LPCTSTR GetSrcTipValue();

	void SetTextStyle(UINT uStyle);
	void SetTextColor(DWORD dwTextColor);
	void SetDisabledTextColor(DWORD dwTextColor);
	DWORD GetDisabledTextColor() const;

	DWORD StringToColor(LPCTSTR pstrColor);
	void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);

	void DoEvent(TEventUI& event) override;

protected:
	int m_iWindowStyls;  // 类型
	int m_iFont;  // 字体
	bool m_bReadOnly;  // 是否只读
	bool m_bPasswordMode;  // 密码模式
	TCHAR m_szPasswordChar;  // 密码显示的字符
	UINT m_uMaxChar;  // 最大个数
	bool m_bAutoSelAll;  // 自动全选
	UINT m_uButtonState;  // 按钮状态
	RECT m_rcTextPadding;  // 文本间隔
	DWORD m_dwEditBkColor;  // Edit背景颜色
	DWORD m_dwEditTextColor;  // Edit文本颜色
	DWORD m_dwTipValueColor;  // 提示颜色

	CDuiString m_sTipValue;	 // 提示的值
	CDuiString m_sSrcTipValue;  // 

	UINT m_uTextStyle;
	DWORD m_dwTextColor;
	DWORD m_dwDisabledTextColor;

	TDrawInfo m_diNormal;
	TDrawInfo m_diHot;
	TDrawInfo m_diPushed;
	TDrawInfo m_diFocused;
	TDrawInfo m_diDisabled;


public:
	bool IsFloat() const;
	int GetCurSel() const;
	int GetCount() const;
	void SetManager(CPaintManagerUI* pManager, CControlUI* pParent, bool bInit = true);
	CControlUI* GetItemAt(int id);
	void SetFocus();

	void SetDropBoxSize(SIZE szSize);
	void SetDropBoxSize(LPCTSTR pstrValue);
	SIZE GetDropBoxSize() const;
	void SetDropBoxAttributeList(LPCTSTR pstrList);
	CDuiString GetDropBoxAttributeList();
	TListInfoUI* GetListInfo();

	bool SelectItem(int iIndex, bool bTakeFocus = false, bool bTriggerEvent=true, bool bMutil = false);
	bool SelectRange(int iIndex, bool bTakeFocus = false, bool bTriggerEvent=true, bool bMutil = false);
	bool ExpandItem(int iIndex, bool bExpand = true);
	int GetExpandedItem() const;

	bool SetItemIndex(CControlUI* pControl, int iNewIndex);
	bool SetMultiItemIndex(CControlUI* pStartControl, int iCount, int iNewStartIndex);
	bool Add(CControlUI* pControl);
	bool AddAt(CControlUI* pControl, int iIndex);
	bool Remove(CControlUI* pControl, bool bDoNotDestroy =false);
	bool RemoveAt(int iIndex, bool bDoNotDestroy =false);
	void RemoveAll();


	void SetShowText(bool bShow);
	bool GetShowText() const;
	void SetSelectCloseFlag(bool flag);
	bool GetSelectCloseFlag() const;
	UINT GetItemFixedHeight();
	void SetItemFixedHeight(UINT nHeight);
	int GetItemFont(int index);
	void SetItemFont(int index);
	void SetItemAlign(LPCTSTR pstrValue);
	UINT GetItemTextStyle();
	void SetItemTextStyle(UINT uStyle);
	RECT GetItemTextPadding() const;
	void SetItemTextPadding(RECT rc);
	void SetItemTextPadding(LPCTSTR pstrValue);
	DWORD GetItemTextColor() const;
	void SetItemTextColor(DWORD dwTextColor);
	DWORD GetItemBkColor() const;
	void SetItemBkColor(DWORD dwBkColor);
	LPCTSTR GetItemBkImage() const;
	void SetItemBkImage(LPCTSTR pStrImage);
	bool IsItemAlternateBk() const;
	void SetItemAlternateBk(bool bAlternateBk);
	DWORD GetSelectedItemTextColor() const;
	void SetSelectedItemTextColor(DWORD dwTextColor);
	DWORD GetSelectedItemBkColor() const;
	void SetSelectedItemBkColor(DWORD dwBkColor);
	LPCTSTR GetSelectedItemImage() const;
	void SetSelectedItemImage(LPCTSTR pStrImage);
	DWORD GetHotItemTextColor() const;
	void SetHotItemTextColor(DWORD dwTextColor);
	DWORD GetHotItemBkColor() const;
	void SetHotItemBkColor(DWORD dwBkColor);
	LPCTSTR GetHotItemImage() const;
	void SetHotItemImage(LPCTSTR pStrImage);
	DWORD GetDisabledItemTextColor() const;
	void SetDisabledItemTextColor(DWORD dwTextColor);
	DWORD GetDisabledItemBkColor() const;
	void SetDisabledItemBkColor(DWORD dwBkColor);
	LPCTSTR GetDisabledItemImage() const;
	void SetDisabledItemImage(LPCTSTR pStrImage);
	int GetItemHLineSize() const;
	void SetItemHLineSize(int iSize);
	DWORD GetItemHLineColor() const;
	void SetItemHLineColor(DWORD dwLineColor);
	int GetItemVLineSize() const;
	void SetItemVLineSize(int iSize);
	DWORD GetItemVLineColor() const;
	void SetItemVLineColor(DWORD dwLineColor);
	bool IsItemShowHtml();
	void SetItemShowHtml(bool bShowHtml = true);
private:
	int m_iCurSel;  // 当前选择的item
	bool m_bShowText;  // 不显示文本
	bool m_bSelectCloseFlag;  // (下拉框)关闭
	SIZE m_szDropBox;  // 下拉框大小
	CDuiString m_sDropBoxAttributes;  // 下拉框设置

	// 列表设置
	TListInfoUI m_ListInfo;
};

2. UIComboEdit.cpp


#include "stdafx.h"
#include "UIEditCombo.h"

//
class CEditCombo_EditWnd : public CWindowWnd
{
   
public:
	CEditCombo_EditWnd();

	void Init(IEditCombo_EditUI* 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,
	};

	IEditCombo_EditUI* m_pOwner;
	HBRUSH m_hBkBrush;
	bool m_bInit;
	bool m_bDrawCaret;
};


CEditCombo_EditWnd::CEditCombo_EditWnd() : m_pOwner(NULL), m_hBkBrush(NULL), m_bInit(false), m_bDrawCaret(false)
{
   
}

void CEditCombo_EditWnd::Init(IEditCombo_EditUI* pOwner)
{
   
	m_pOwner = pOwner;
	RECT rcPos = CalPos();
	UINT uStyle = WS_CHILD | ES_AUTOHSCROLL | pOwner->GetWindowStyls();
	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;
	if( m_pOwner->IsPasswordMode() ) uStyle |= ES_PASSWORD;
	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());
	if( m_pOwner->IsPasswordMode() ) Edit_SetPasswordChar(m_hWnd, m_pOwner->GetPasswordChar());
	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);
	Edit_SetReadOnly(m_hWnd, m_pOwner->IsReadOnly() == true);

	//Styls
	::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE);
	::SetFocus(m_hWnd);
	if (m_pOwner->IsAutoSelAll()) {
   
		int nSize = GetWindowTextLength(m_hWnd);
		if( nSize == 0 ) nSize = 1;
		Edit_SetSel(m_hWnd, 0, nSize);
	}
	else {
   
		int nSize = GetWindowTextLength(m_hWnd);
		Edit_SetSel(m_hWnd, nSize, nSize);
	}

	m_bInit = true;    
}

RECT CEditCombo_EditWnd::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 = static_cast<CControlUI*>(m_pOwner->GetInterface(DUI_CTR_CONTROL));
	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 CEditCombo_EditWnd::GetWindowClassName() const
{
   
	return _T("EditCombo_EditWnd");
}

LPCTSTR CEditCombo_EditWnd::GetSuperClassName() const
{
   
	return WC_EDIT;
}

void CEditCombo_EditWnd::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_pEditWindow = NULL;
	m_pOwner->EditDestroy();
	delete this;
}

LRESULT CEditCombo_EditWnd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值