当前位置:网站首页>WTL 自绘控件库 (CQsCheckComboxBox)
WTL 自绘控件库 (CQsCheckComboxBox)
2022-04-23 05:16:00 【houxian1103】
概述:
CQsCheckComboxBox 继承与 CComboBox,通过自绘来背景的绘制,以及各种选中状态的的绘制。
代码实现如下:
****/
#pragma once;
#include "QsInclude.h"
#pragma warning(disable: 4312)
#pragma warning(disable: 4311)
extern WNDPROC m_pWndProc;
LRESULT ComboBoxListBoxProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
class CQsCheckComboxBox :
public CWindowImpl< CQsCheckComboxBox, CComboBox >, public COwnerDraw< CQsCheckComboxBox >
{
typedef CWindowImpl< CQsCheckComboxBox, CComboBox > theBaseClass;
public:
BEGIN_MSG_MAP(CQsCheckComboxBox)
MESSAGE_HANDLER( CB_ADDSTRING, OnAddString )
MESSAGE_HANDLER( CB_INSERTSTRING, OnInsertString )
MESSAGE_HANDLER( CB_DELETESTRING, OnDeleteString )
MESSAGE_HANDLER( WM_CTLCOLORLISTBOX, OnCtlColorListBox )
MESSAGE_HANDLER( CBN_DROPDOWN, OnCbnDropdown )
MESSAGE_HANDLER( WM_GETTEXT, OnGetText )
MESSAGE_HANDLER( WM_GETTEXTLENGTH, OnGetTextLength )
CHAIN_MSG_MAP_ALT( COwnerDraw< CQsCheckComboxBox >, 1 )
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
/** *@method CQsCheckComboxBox *@brief 构造函数 * *@param void *@return */
CQsCheckComboxBox( void )
{
m_hListBox = NULL;
m_bTextUpdated = FALSE;
m_strText = _T("");
m_strbkText = _T("");
}
/** *@method ~CQsCheckComboxBox *@brief 析构函数 * *@param void *@return */
~CQsCheckComboxBox( void )
{
}
/** *@method Create *@brief 通过Create来创建窗口。 * *@param HWND hWndParent parent window *@param _U_RECT rect = NULL create window rect *@param LPCTSTR szWindowName = NULL the window name *@param DWORD dwStyle = 0 base window style *@param DWORD dwExStyle = 0 extended window style *@param _U_MENUorID MenuOrID = 0U menu or ID *@param LPVOID lpCreateParam = NULL create param *@return HWND 非NULL success return TRUE, failed return NULL */
HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
// Remove the CBS_SIMPLE and CBS_DROPDOWN styles and add the one I'm designed for
dwStyle &= ~0xF;
dwStyle |= CBS_DROPDOWNLIST;
// Make sure to use the CBS_OWNERDRAWVARIABLE style
dwStyle |= CBS_OWNERDRAWVARIABLE;
// Use default strings. We need the itemdata to store checkmarks
dwStyle |= CBS_HASSTRINGS;
return theBaseClass::Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
}
/** *@method SubclassWindow *@brief 类对象关联 * *@param HWND hWnd 对象句柄 *@return BOOL 成功返回TRUE,失败返回FALSE */
BOOL SubclassWindow(HWND hWnd)
{
DWORD dwStyle = CBS_DROPDOWNLIST|CBS_OWNERDRAWVARIABLE|CBS_HASSTRINGS;
BOOL bRet = theBaseClass::SubclassWindow( hWnd );
ModifyStyle(0,dwStyle);
return bRet;
}
/** *@method SetBkText *@brief 设置背景Text * *@param CString & strBkText *@return void */
void SetBkText(CString& strBkText)
{
m_strbkText = strBkText;
}
/** *@method DrawItem *@brief 按钮重画函数 * *@param LPDRAWITEMSTRUCT lpDrawItemStruct 详见MSN *@return void */
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct )
{
HDC dc = lpDrawItemStruct->hDC;
CRect rcBitmap = lpDrawItemStruct->rcItem;
CRect rcText = lpDrawItemStruct->rcItem;
CString strText;
// 0 - No check, 1 - Empty check, 2 - Checked
bool bCheck = false;
// Check if we are drawing the static portion of the combobox
if ((LONG)lpDrawItemStruct->itemID < 0)
{
// Make sure the m_strText member is updated
RecalcText();
// Get the text
strText = m_strText;
}
// Otherwise it is one of the items
else
{
int nLen = GetLBTextLen( lpDrawItemStruct->itemID );
TCHAR *str = new TCHAR[nLen+1];
GetLBText(lpDrawItemStruct->itemID, str);
strText = str;
bCheck = m_vtChekcList[lpDrawItemStruct->itemID];
TEXTMETRIC metrics;
GetTextMetrics(dc, &metrics);
rcBitmap.left = 0;
rcBitmap.right = rcBitmap.left + metrics.tmHeight + metrics.tmExternalLeading + 6;
rcBitmap.top += 1;
rcBitmap.bottom -= 1;
rcText.left = rcBitmap.right;
UINT nState = DFCS_BUTTONCHECK;
if (bCheck)
{
nState |= DFCS_CHECKED;
}
// Draw the checkmark using DrawFrameControl
DrawFrameControl(dc, rcBitmap, DFC_BUTTON, nState);
delete [] str;
}
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
SetBkColor(dc, GetSysColor(COLOR_WINDOW));
SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
}
if(strText.GetLength()>0)
{
// Erase and draw
ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0);
DrawText(dc, ' ' + strText, strText.GetLength() + 1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS);
}
else
{
HWND hwnd = GetFocus();
if(hwnd!=m_hWnd)
{
CRect rectBk;
GetClientRect(&rectBk);
rectBk.left = rectBk.left+5;
DrawText(dc, m_strbkText, m_strbkText.GetLength() + 1, &rectBk, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS);
}
}
if ((lpDrawItemStruct->itemState & (ODS_FOCUS|ODS_SELECTED)) == (ODS_FOCUS|ODS_SELECTED))
{
DrawFocusRect(dc, &rcText);
}
}
/** *@method SetCheck *@brief 用来设置item的状态 * *@param int nIndex 设置状态的ID *@param bool bFlag 状态值,选中或非选中 *@return int */
int SetCheck( int nIndex, bool bFlag )
{
m_vtChekcList[(UINT)nIndex] = bFlag;
m_bTextUpdated = FALSE;
Invalidate(FALSE);
return 0;
}
/** *@method GetCheck *@brief 得到item的状态 * *@param int nIndex item标示(Id) *@return bool */
bool GetCheck( int nIndex )
{
return m_vtChekcList[(UINT)nIndex];
}
/** *@method SelectAll *@brief CQsCheckComboxBox控件Item全部check或全部Uncheck * *@param bool bFlag item的check状态,true为选中,false为未选中 *@return void */
void SelectAll( bool bFlag )
{
int nCount = GetCount();
for (int i = 0; i < nCount; i++)
{
SetCheck(i, bFlag);
}
}
/** *@method OnAddString *@brief CB_ADDSTRING消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为CB_ADDSTRING *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnAddString(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
m_vtChekcList.push_back( false );
bHandled = FALSE;
return 0;
}
/** *@method OnInsertString *@brief CB_INSERTSTRING消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为CB_ADDSTRING *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnInsertString(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
int nIndex = (int)wParam;
if ( -1 == nIndex )
{
m_vtChekcList.push_back( false );
}
else
{
std::vector<bool>::iterator it;
for ( int i = 0; i < nIndex; i++, it++ );
m_vtChekcList.insert( it, false );
}
bHandled = FALSE;
return 0;
}
/** *@method OnDeleteString *@brief CB_DELETESTRING消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为CB_DELETESTRING *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnDeleteString(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
int nIndex = (int)wParam;
std::vector<bool>::iterator it;
for ( int i = 0; i < nIndex; i++, it++ );
m_vtChekcList.erase( it );
bHandled = FALSE;
return 0;
}
/** *@method OnCtlColorListBox *@brief WM_CTLCOLORLISTBOX消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为WM_CTLCOLORLISTBOX *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnCtlColorListBox(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
// If the listbox hasn't been subclassed yet, do so...
if (m_hListBox == 0)
{
HWND hWnd = (HWND)lParam;
if (hWnd != 0 && hWnd != m_hWnd)
{
// Save the listbox handle
m_hListBox = hWnd;
// Do the subclassing
m_pWndProc = (WNDPROC)(::GetWindowLong(m_hListBox, GWL_WNDPROC));
::SetWindowLong(m_hListBox, GWL_WNDPROC, (LONG)ComboBoxListBoxProc);
::SetWindowLong(m_hListBox, GWL_USERDATA, (LONG)this);
}
}
return DefWindowProc(WM_CTLCOLORLISTBOX, wParam, lParam);
}
/** *@method RecalcText *@brief CQSCheckComboxBox控件重新计算Text函数 * *@return void */
void RecalcText()
{
if (!m_bTextUpdated)
{
CString strText;
// Get the list count
UINT nCount = (UINT)GetCount();
// Get the list separator
TCHAR szBuffer[10] = {
0};
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szBuffer, sizeof(szBuffer));
CString strSeparator = szBuffer;
// If none found, the the ';'
if (strSeparator.GetLength() == 0)
{
strSeparator = ';';
}
// Trim extra spaces
strSeparator.TrimRight();
// And one...
strSeparator += ' ';
for (UINT i = 0; i < nCount; i++)
{
if (m_vtChekcList[i])
{
//CString strItem;
int nLen = GetLBTextLen( i );
TCHAR *str = new TCHAR[nLen + 1];
GetLBText(i, str);
CString strItem( str );
if (!strText.IsEmpty())
{
strText += strSeparator;
}
strText += strItem;
delete [] str;
}
}
// Set the text
m_strText = strText;
m_bTextUpdated = TRUE;
}
}
/** *@method OnCbnDropdown *@brief CBN_DROPDOWN消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为WM_CTLCOLORLISTBOX *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnCbnDropdown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
return 0;
}
/** *@method OnGetText *@brief WM_GETTEXT消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为WM_GETTEXT *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnGetText(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// TODO: 在此添加控件通知处理程序代码
// Make sure the text is updated
RecalcText();
if (lParam == 0)
return 0;
// Copy the 'fake' window text
lstrcpyn((TCHAR *)lParam, m_strText, (INT)wParam);
return m_strText.GetLength();
}
/** *@method OnGetTextLength *@brief WM_GETTEXTLENGTH消息响应函数,详见MSDN * *@param UINT uMsg 消息ID,为WM_GETTEXTLENGTH *@param WPARAM wParam 未被使用 *@param LPARAM lParam 详见MSDN *@param BOOL& bHandled 详见MSDN *@return LRESULT */
LRESULT OnGetTextLength(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// Make sure the text is updated
RecalcText();
return m_strText.GetLength();
}
CString m_strText;
BOOL m_bTextUpdated;
HWND m_hListBox;
CString m_strbkText;
private:
std::vector<bool> m_vtChekcList; // list的item的checkbox选中标志向量
};
版权声明
本文为[houxian1103]所创,转载请带上原文链接,感谢
https://blog.csdn.net/houxian1103/article/details/124334779
边栏推荐
- Blender程序化地形制作
- At pgconf Asia Chinese technology forum, listen to Tencent cloud experts' in-depth understanding of database technology
- Knowledge points sorting: ES6
- 何时适合进行自动化测试?(下)
- 工具在数字化转型中扮演了什么样的角色?
- My old programmer's perception of the dangers and opportunities of the times?
- Interview summary
- Backup MySQL database with Navicat
- 开源规则引擎——ice:致力于解决灵活繁复的硬编码问题
- Deep learning notes - fine tuning
猜你喜欢
随机推荐
Summary of MySQL knowledge points
Docker installation and mysql5 7 installation
Master-slave replication of MariaDB database
2021 年 25 大 DevOps 工具(下)
Kubectl command automatic replenishment
JSP-----JSP简介
Flip coin (Blue Bridge Cup)
Independent station operation | Facebook marketing artifact - chat robot manychat
Live delivery form template - automatically display pictures - automatically associate series products
Use the built-in function of win to transfer files between two computers in the same LAN (the speed is the same as that between local disks)
多线程基本概念(并发与并行、线程与进程)和入门案例
Locks and transactions in MySQL
MySQL basics 3
Basic theory of Flink
Golang memory escape
《2021年IT行业项目管理调查报告》重磅发布!
如何在Word中添加漂亮的代码块 | 很全的方法整理和比较
什么是指令周期,机器周期,和时钟周期?
深度学习笔记 —— 物体检测和数据集 + 锚框
What are the redis data types