MoveWindow CCombox重绘,list下拉框窗口闪烁,覆盖掉部分窗口

玉生香 2020-03-02 05:53:57
创建时大小,与move 到大小没有变化,只是位置发生变化了。下来部分一直在闪烁,求解答

截图部分,被覆盖了好多。

重绘代码,是使用别人源码。下面放置源码



//创建combox
BOOL CWorkFrame::CreateCombbox()
{
if (m_pCBox == NULL)
{

CWindowDC dc(this);
CFont *pFontDC = dc.SelectObject(&m_FontCombox);
CSize size = dc.GetTextExtent(_T("华"));
dc.SelectObject(pFontDC);

m_pCBox = new CMyComboBox();
m_pCBox->SetLHeight(m_nFontHeight);


int _10hscale = CScaleFactor::Instance()->Get10HPix();
int _30hscale = _10hscale * 3;

CRect comRect = CRect(0,0,1,_30hscale);
int nlen = (comRect.Height() - abs(m_nFontHeight)) / 2;
comRect.TopLeft() = CPoint(comRect.right + m_nColOffset, comRect.top + nlen - 3);
comRect.BottomRight() = CPoint(comRect.left + 5 * size.cx, comRect.top + 7 * abs(m_nFontHeight - 2));
m_pCBox->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL, comRect, this, IDC_COMBOBOX);
m_pCBox->SetFont(&m_FontCombox);

std::map<CString, int>::iterator iter;

std::map<int, CString> vmapCombox;
for (iter = m_MapCombox.begin(); iter != m_MapCombox.end(); ++iter)
{
vmapCombox.insert(std::make_pair(iter->second, iter->first));
}
for (size_t i = 0; i < vmapCombox.size(); ++i)
{
m_pCBox->InsertString(i, vmapCombox[i]);
}
}
return TRUE;
}

// 绘制的时候,移动

CFont *pFontDC = dc.SelectObject(&m_FontCombox);
CSize size = dc.GetTextExtent(_T("华"));
dc.SelectObject(pFontDC);
m_pCBox->SetLHeight(m_nFontHeight);
CRect comRect = m_AloneSeleRect;
int nlen = (m_AloneSeleRect.Height() - abs(m_nFontHeight)) / 2;
comRect.TopLeft() = CPoint(comRect.right + m_nColOffset, comRect.top + nlen - 3);
comRect.BottomRight() = CPoint(comRect.left + 5 * size.cx, comRect.top + 7 * abs(m_nFontHeight - 2));
m_pCBox->MoveWindow(comRect);
m_pCBox->ShowWindow(SW_SHOW);



...全文
858 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
zgl7903 2020-03-04
  • 打赏
  • 举报
回复
在MyComboBox的OnPaint中设置了一个断点, 看调用堆栈的时候发现之前有 WM_SIZE消息, 基本上可以断定是改变窗口大小或者移动窗口引起的,

void CComboxDlg::OnPaint()
{
  CPaintDC dc(this);

  if (m_bButtonClick)
  {
    CRect rect(10, 50, 150, 80);
    m_pComboBox->MoveWindow(rect);

    //加这一句
    m_bButtonClick = FALSE;
  }
}
玉生香 2020-03-04
  • 打赏
  • 举报
回复
引用 6 楼 zgl7903 的回复:
我的理解就是输入的时候也显示下列列表? 从 CComboBox 派生, 重载 PreTranslateMessage, 看看这个能满足要求不


BOOL CMyComboBox::PreTranslateMessage(MSG* pMsg)
{
  switch(pMsg->message)
  {
  case(WM_LBUTTONDOWN):
  case(WM_KEYDOWN):
    {
      COMBOBOXINFO cbInfo = {sizeof(COMBOBOXINFO)};
      if(GetComboBoxInfo(&cbInfo)
        && pMsg->hwnd == cbInfo.hwndItem
        && ::GetFocus() == pMsg->hwnd)
      {
        ShowDropDown(TRUE);
      }
      break;
    }
  }

  return __super::PreTranslateMessage(pMsg);
}



BOOL CComboxDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标
	m_pComboBox = new CMyComboBox();
	CRect rect(10, 30, 150, 60);
	m_pComboBox->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL, rect, this, 1000);
	m_pComboBox->InsertString(0, _T("测试MoveWindow"));
	m_pComboBox->InsertString(0, _T("Move后闪烁"));
	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


void CComboxDlg::OnPaint()
{
	CPaintDC dc(this);

	if (m_bButtonClick)
	{
		CRect rect(10, 50, 150, 80);
		m_pComboBox->MoveWindow(rect);
	}
}

这是我上传的一个例子,请帮忙看一下。 https://download.csdn.net/download/u010251009/12218019
zgl7903 2020-03-04
  • 打赏
  • 举报
回复
我的理解就是输入的时候也显示下列列表? 从 CComboBox 派生, 重载 PreTranslateMessage, 看看这个能满足要求不


BOOL CMyComboBox::PreTranslateMessage(MSG* pMsg)
{
  switch(pMsg->message)
  {
  case(WM_LBUTTONDOWN):
  case(WM_KEYDOWN):
    {
      COMBOBOXINFO cbInfo = {sizeof(COMBOBOXINFO)};
      if(GetComboBoxInfo(&cbInfo)
        && pMsg->hwnd == cbInfo.hwndItem
        && ::GetFocus() == pMsg->hwnd)
      {
        ShowDropDown(TRUE);
      }
      break;
    }
  }

  return __super::PreTranslateMessage(pMsg);
}

玉生香 2020-03-04
  • 打赏
  • 举报
回复
引用 8 楼 zgl7903 的回复:
在MyComboBox的OnPaint中设置了一个断点, 看调用堆栈的时候发现之前有 WM_SIZE消息, 基本上可以断定是改变窗口大小或者移动窗口引起的,

void CComboxDlg::OnPaint()
{
  CPaintDC dc(this);

  if (m_bButtonClick)
  {
    CRect rect(10, 50, 150, 80);
    m_pComboBox->MoveWindow(rect);

    //加这一句
    m_bButtonClick = FALSE;
  }
}
谢谢大神,明白了。不能多次移动控件。这样就会闪烁。 解决了。
玉生香 2020-03-02
  • 打赏
  • 举报
回复
自己顶上去,求解答
玉生香 2020-03-02
  • 打赏
  • 举报
回复
引用 3 楼 zgl7903 的回复:
先简单说一下 想把CComboBox 改造成啥样?
实现成图片这样。 没有3D效果。平滑。 我使用使用MoveWindow 一直在闪烁
zgl7903 2020-03-02
  • 打赏
  • 举报
回复
先简单说一下 想把CComboBox 改造成啥样?
玉生香 2020-03-02
  • 打赏
  • 举报
回复


}
	else
	{

		if (m_bMouseOverBox || bListDropped)
		{
			clrFrame = (m_bIsDropList || m_bIsEditFocused || bListDropped) ? COMBO_MOUSE_ON_FRAME_COLOR : COMBO_NORMAL_MOUSE_ON_EDIT_COLOR;
			clrText = COMBO_MOUSE_ON_TEXT_COLOR;
			clrBkground = m_bIsDropList ? COMBO_MOUSE_ON_BK_COLOR : COMBO_NORMAL_BK_COLOR;

			if (m_bMouseOverArrow && !m_bIsDropList)
			{
				bDrawArrowRect = TRUE;
			}
		}
		else
		{
			clrText = COMBO_NORMAL_TEXT_COLOR;
			clrFrame = RGB(0, 0, 0);// COMBO_NORMAL_FRAME_COLOR;
			clrBkground = m_bIsDropList ? COMBO_READONLY_BK_COLOR : COMBO_NORMAL_BK_COLOR;
		}
	}


	CFont *pOldFont;
	CPen *pOldPen;
	CPen penArrow;
	CBrush brushBkground;
	CBrush brushArrow;
	CString str;

	dc.SetBkMode(TRANSPARENT);
	dc.Draw3dRect(rect, clrFrame, clrFrame);//画边框
	rect.DeflateRect(1, 1, 1, 1);


	if (m_bIsDropList)
	{
		dc.FillSolidRect(rect, clrBkground);
	}
	else
	{
		CRgn rgnBox, rgnEdit;
		rgnBox.CreateRectRgnIndirect(rect);
		rgnEdit.CreateRectRgnIndirect(&cbi.rcItem);
		// 处理后的rgnBox只包括了Edit框之外的客户区域,这样,Edit将不会被我的背景覆盖而导致重画。 
		if (rgnBox.CombineRgn(&rgnBox, &rgnEdit, RGN_XOR) == ERROR)
		{
			ASSERT(FALSE);
		}
		if (IsWindowEnabled())
		{
			brushBkground.CreateSolidBrush(clrBkground);
		}
		else {
			brushBkground.CreateSolidBrush(COMBO_DISABLED_EDIT_OUTTER_COLOR);
		}
		dc.FillRgn(&rgnBox, &brushBkground);
	}

	if (bDrawArrowRect && IsWindowEnabled())
	{
		cbi.rcButton.right = rect.right + 1;
		cbi.rcButton.top = 0;
		cbi.rcButton.bottom = RECT_HEIGHT(rect) + 2;
		dc.Draw3dRect(&cbi.rcButton, COMBO_MOUSE_ON_FRAME_COLOR, COMBO_MOUSE_ON_FRAME_COLOR);
	}

	// Set Window Text
	{
		GetWindowText(str);
		pOldFont = dc.SelectObject(&m_fontText);
		dc.SetTextColor(clrText);

		if (!m_bIsDropList && IsWindowEnabled())
		{
			//
		}
		else
		{
			cbi.rcItem.left += 1;
			dc.DrawText(str, &cbi.rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE);//显示文本
		}

	}

	// Draw Button
	{
		penArrow.CreatePen(PS_DASH, 1, COMBO_ARROW_COLOR);
		pOldPen = dc.SelectObject(&penArrow);

		int x = ptArrowBeg.x + 1;
		int y = ptArrowBeg.y + 1;
		for (; x <= (ptArrowMid.x - 1); x++, y++)
		{
			dc.SetPixel(x, y, COMBO_ARROW_COLOR);
		}

		for (; x <= (ptArrowEnd.x - 1); x++, y--)
		{
			dc.SetPixel(x, y, COMBO_ARROW_COLOR);
		}


	}
	dc.SelectObject(pOldPen);
	dc.SelectObject(pOldFont);

#if USE_COMPATIBLE_DC
	parentDc.BitBlt(comboRect.left, comboRect.top, comboRect.Width(), comboRect.Height(), &dc, 0, 0, SRCCOPY);

	bmp.DeleteObject();
	dc.DeleteDC();
#endif

#endif
}



int CMyComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{

	// TODO:  Add your code to determine the sorting order of the specified items
	// return -1 = item 1 sorts before item 2
	// return 0 = item 1 and item 2 sort the same
	// return 1 = item 1 sorts after item 2

	LPCWSTR pStr1 = (LPCWSTR)lpCompareItemStruct->itemData1;
	LPCWSTR pStr2 = (LPCWSTR)lpCompareItemStruct->itemData2;

	int nResult = StrCmpW(pStr1, pStr2);

	if (nResult < 0) {
		nResult = -1;
	}
	else if (nResult > 0) {
		nResult = 1;
	}

	return nResult;
}


BOOL CMyComboBox::IsCaretInWindow() const
{
	CRect rect;
	GetWindowRect(&rect);

	CPoint  pt;
	GetCursorPos(&pt);

	TRACE("Window: (%d,%d,%d,%d)\n", RECT_PARAM(rect));
	TRACE("Cursor: (%d,%d)\n", POINT_PARAM(pt));

	return (rect.PtInRect(pt));
}

afx_msg LRESULT CMyComboBox::OnUmsgListboxMousePosition(WPARAM wParam, LPARAM lParam)
{
	if (m_bMouseHoverOnDelBtn && (wParam == -1))//如果是单击消息,并且鼠标当前停留在下拉按钮里
	{
		this->DeleteString(GetCurSel());
		this->SelectString(-1, m_strLastSelected);
		return 1;
	}
	CPoint point((int)wParam, (int)lParam);
	int result = m_rcDelButton.PtInRect(point);
	if (result && !m_bMouseHoverOnDelBtn)//如果鼠标在组合框内,并且是初次鼠标进入
	{
		m_bMouseHoverOnDelBtn = TRUE;
		HWND listWnd;
		s_mapComboWnd.Lookup(this->m_hWnd, listWnd);
		::InvalidateRect(listWnd, m_rcDelButton, true);
	}
	else if ((result == 0) && m_bMouseHoverOnDelBtn)
	{
		m_bMouseHoverOnDelBtn = FALSE;
		HWND listWnd;
		s_mapComboWnd.Lookup(this->m_hWnd, listWnd);
		::InvalidateRect(listWnd, m_rcDelButton, true);
	}
	//TRACE("DelButtonState: %d\n", m_bMouseHoverOnDelBtn);
	//TRACE("DelRect: %d, %d, Point: %d\n", m_rcDelButton.left, m_rcDelButton.right, point.x);
	return 0;
}


void CMyComboBox::MeasureItem(LPMEASUREITEMSTRUCT /*lpMeasureItemStruct*/)
{

	// TODO:  Add your code to determine the size of specified item
}



void CMyComboBox::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default

	CRect rect;
	GetWindowRect(&rect);

	CPoint  pt;
	GetCursorPos(&pt);

	if (rect.PtInRect(pt))
	{
		ScreenToClient(&pt);
		if (!m_bMouseOverArrow && m_rcArrow.PtInRect(pt))
		{
			m_bMouseOverArrow = TRUE;
			InvalidateRect(&m_rcArrow);
		}

		if (!m_bMouseOverBox)
		{
			m_bMouseOverBox = TRUE;
			//InvalidateRect(&rect);
			Invalidate();
		}
	}
	else
	{

		if (!GetDroppedState())
		{
			m_bMouseOverArrow = FALSE;
			m_bMouseOverBox = FALSE;
			Invalidate();
		}
		if (!m_bMouseOverBox)
		{
			KillTimer(TIMER_REFRESH_BOX);
		}
	}
	TRACE("Timer: OverBox: %d, OverArrow: %d\n", m_bMouseOverBox, m_bMouseOverArrow);

	CComboBox::OnTimer(nIDEvent);
}


afx_msg LRESULT CMyComboBox::OnUmsgEditboxMouseAction(WPARAM wParam, LPARAM lParam)
{
	UINT msg = (UINT)wParam;

	if (WM_SETFOCUS == msg)
	{
		m_bIsEditFocused = TRUE;
	}
	else if (WM_KILLFOCUS == msg)
	{
		m_bIsEditFocused = FALSE;
	}
	else if (WM_MOUSEMOVE == msg)
	{
		if (!m_bMouseOverBox)
		{
			SetTimer(TIMER_REFRESH_BOX, 50, 0);
		}
	}
	//TRACE("EditBox Focus: %d\n", m_bIsEditFocused);
	return 0;
}

玉生香 2020-03-02
  • 打赏
  • 举报
回复


#include "stdafx.h"
#include "MyComboBox.h"
#include <vector>

IMPLEMENT_DYNAMIC(CMyComboBox, CComboBox)

BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
	//消息反射声明
	ON_CONTROL_REFLECT(CBN_DROPDOWN, &CMyComboBox::OnCbnDropdown)
	ON_CONTROL_REFLECT(CBN_SELCHANGE, &CMyComboBox::OnCbnSelchange)
	ON_CONTROL_REFLECT(CBN_KILLFOCUS, &CMyComboBox::OnCbnKillfocus)
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(UMSG_LISTBOX_MOUSE_POSITION, &CMyComboBox::OnUmsgListboxMousePosition)
	ON_WM_PAINT()
	ON_WM_TIMER()
	ON_MESSAGE(UMSG_EDITBOX_MOUSE_ACTION, &CMyComboBox::OnUmsgEditboxMouseAction)
END_MESSAGE_MAP()

WNDPROC CMyComboBox::s_oldListWndProc = NULL;
WNDPROC CMyComboBox::s_oldEditWndProc = NULL;
HWND CMyComboBox::s_hwndComboBox;
CMap<HWND, HWND, HWND, HWND> CMyComboBox::s_mapComboWnd;
// CMyComboBox 消息处理程序
void CMyComboBox::OnCbnDropdown()
{
	CClientDC dc(this);
	int nWitdh = 10;
	int nSaveDC = dc.SaveDC();

	//获取字体信息,
	dc.SelectObject(GetFont());

	//计算最大的显示长度
	for (int i = 0; i < GetCount(); i++)
	{
		CString strLable = _T("");
		GetLBText(i, strLable);

		nWitdh = max(nWitdh, dc.GetTextExtent(strLable).cx);
	}

	//多增加的冗余宽度
	nWitdh += DEL_RECT_WIDTH + 5;

	//设置下拉列表宽度
	SetDroppedWidth(nWitdh);
	//恢复实际dc
	dc.RestoreDC(nSaveDC);
}
int CMyComboBox::SetCurSel(int nSelect)
{
	int nRet = CComboBox::SetCurSel(nSelect);
	::PostMessage(GetParent()->GetSafeHwnd(), UMSG_COMBO_SEL_CHANGE, (WPARAM)GetDlgCtrlID(), 0);
	Invalidate();
	return nRet;
}

void CMyComboBox::OnCbnSelchange()
{
	// TODO: Add your control notification handler code here
	int nSel = GetCurSel();
	if (nSel == -1) {
		m_strLastSelected = TEXT("");
	}
	else {
		GetLBText(nSel, m_strLastSelected);
	}
	::PostMessage(GetParent()->GetSafeHwnd(), UMSG_COMBO_SEL_CHANGE, (WPARAM)GetDlgCtrlID(), 0);
}


void CMyComboBox::OnCbnKillfocus()
{
	// TODO: Add your control notification handler code here
	GetWindowText(m_strLastSelected);

	if (!m_strLastSelected.IsEmpty())
	{
		if (FindString(-1, m_strLastSelected) == CB_ERR)
		{
			AddString(m_strLastSelected);
		}
	}
}
LRESULT CALLBACK HookListboxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_MOUSEMOVE)//鼠标移动
	{
		WORD xPos, yPos;
		xPos = LOWORD(lParam);
		yPos = HIWORD(lParam);
		HWND relWnd;
		CMyComboBox::s_mapComboWnd.Lookup(hWnd, relWnd);
		::SendMessage(relWnd, UMSG_LISTBOX_MOUSE_POSITION, xPos, yPos);//发送鼠标位置给列表窗口
	}
	else if (message == WM_LBUTTONDOWN)
	{
		HWND relWnd;
		CMyComboBox::s_mapComboWnd.Lookup(hWnd, relWnd);
		//消息类型我是直接以数字发送,觉得看着不舒服的,可自行定义
		//如#define WM_MOUSEPOSITION WM_USER+100
		LRESULT result = ::SendMessage(relWnd, UMSG_LISTBOX_MOUSE_POSITION, (WPARAM)-1, 0);//第三参数-1表明鼠标左键按下
		if (result == 1)
			return 0;//返回0,不让默认消息处理函数处理WM_LBUTTONDOWN
	}
	//调用列表框之前的默认消息处理函数
	return ::CallWindowProc(CMyComboBox::s_oldListWndProc, hWnd, message, wParam, lParam);
}
LRESULT CALLBACK HookEditBoxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	//TRACE("HookEditBoxWndProc, Msg: %d\n", message);
	switch (message)
	{
	case WM_SETFOCUS:
	case WM_KILLFOCUS:
	case WM_MOUSEMOVE:
		HWND relWnd;
		CMyComboBox::s_mapComboWnd.Lookup(hWnd, relWnd);
		::PostMessage(relWnd, UMSG_EDITBOX_MOUSE_ACTION, (WPARAM)message, lParam);
		break;
	default:
		break;

	}

	return ::CallWindowProc(CMyComboBox::s_oldEditWndProc, hWnd, message, wParam, lParam);
}

void CMyComboBox::PreSubclassWindow()
{
	// TODO: Add your specialized code here and/or call the base class

	CComboBox::PreSubclassWindow();

	COMBOBOXINFO cbi;
	cbi.cbSize = sizeof(COMBOBOXINFO);
	::GetComboBoxInfo(this->m_hWnd, &cbi);  //获取组合框信息

											//替换列表框消息处理函数

	LONG_PTR style = GetWindowLongPtr(cbi.hwndCombo, GWL_STYLE);
	int nDropType = (style & CBS_DROPDOWNLIST);

	m_bIsDropList = FALSE;
	if (nDropType == CBS_SIMPLE)
	{
		//
	}
	else
	{
		s_oldListWndProc = (WNDPROC)::SetWindowLongPtr(cbi.hwndList, GWLP_WNDPROC, reinterpret_cast<LONG_PTR> (HookListboxWndProc));
		if (nDropType == CBS_DROPDOWNLIST)
		{
			m_bIsDropList = TRUE;
		}
		else // CBS_DROPDOWN
		{
			CEdit* pEdit = (CEdit*)GetWindow(GW_CHILD);
			if (pEdit)
			{
				s_oldEditWndProc = (WNDPROC)::SetWindowLongPtr(pEdit->GetSafeHwnd(), GWLP_WNDPROC, reinterpret_cast<LONG_PTR> (HookEditBoxWndProc));

				s_mapComboWnd.SetAt(pEdit->GetSafeHwnd(), this->m_hWnd);
				s_mapComboWnd.SetAt(this->m_hWnd, pEdit->GetSafeHwnd());
			}
		}
	}

	//相互关联,到时可以依据两个中的任一窗口句柄,查询到另一个
	//我想,对于CMap类一定会有解决此问题的方法,但我现在实在不想深入了解 
	//只能给它互相关联,不知道是不是“主流”方法。
	s_mapComboWnd.SetAt(cbi.hwndList, this->m_hWnd);
	s_mapComboWnd.SetAt(this->m_hWnd, cbi.hwndList);


	SendMessage(CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)BOX_HEIGHT);   //改变控件本身的高度

	m_fontText.CreateFont(
		m_nHeight,                 //字体高度(旋转后的字体宽度)=56   
		0,                 //字体宽度(旋转后的字体高度)=20 
		0,             //字体显示角度=270° 
		0,                                     //nOrientation=0 
		FW_NORMAL,                                   //字体磅数=10 
		FALSE,                             //非斜体 
		FALSE,                             //无下划线 
		FALSE,             //无删除线 
		DEFAULT_CHARSET,         //使用缺省字符集 
		OUT_DEFAULT_PRECIS,   //缺省输出精度 
		CLIP_DEFAULT_PRECIS,//缺省裁减精度   
		DEFAULT_QUALITY,         //nQuality=缺省值 
		DEFAULT_PITCH,             //nPitchAndFamily=缺省值 
		_T("宋体"));                   //字体名=@system 

									  //SetFont(&m_fontText);
	m_rcArrow = cbi.rcButton;
	m_rcItem = cbi.rcItem;
}



void CMyComboBox::SetMouseOver(BOOL bOn)
{
	static ULONGLONG timeOn = GetTickCount64();
	static ULONGLONG timLeave = GetTickCount64();
	static const UINT TIME_FILTER_MS = 300;

	if (m_bMouseOverBox == bOn)
	{
		return;
	}

	if (bOn)
	{

		ULONGLONG span;
		timeOn = GetTickCount64();
		span = timeOn - timLeave;
		TRACE("ON: TimeSpan(%d)\n", span);
		if (span > TIME_FILTER_MS)
		{
			m_bMouseOverBox = TRUE;
		}
	}
	else
	{
		timLeave = GetTickCount64();
		m_bMouseOverBox = FALSE;
	}
}

void CMyComboBox::OnMouseMove(UINT nFlags, CPoint point)
{

	if (!m_bMouseOverBox)
	{
		SetTimer(TIMER_REFRESH_BOX, 50, 0);
	}

	CComboBox::OnMouseMove(nFlags, point);
}

void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);//组合框DC
	CRect itemRect(lpDrawItemStruct->rcItem);//项区域
	int nState = lpDrawItemStruct->itemState;//项状态
	int nIndex = lpDrawItemStruct->itemID;//项索引
	int nAction = lpDrawItemStruct->itemAction;

	//TRACE("Index: %d(DelBtn:%d), state: %04X, Action: %04X\n", nIndex, m_bMouseHoverOnDelBtn, nState, nAction);

	if (nIndex != -1)
	{

		if (nState & ODS_SELECTED)//如果选中该项
		{
			CPen pen;

			//计算位置
			m_rcDelButton.left = itemRect.right - DEL_RECT_WIDTH;
			m_rcDelButton.top = itemRect.top;
			m_rcDelButton.right = itemRect.right;
			m_rcDelButton.bottom = itemRect.bottom;

			dc.FillSolidRect(&itemRect, ITEM_SELECT_BK_COLOR);
			if (m_bMouseHoverOnDelBtn) //鼠标停留 
			{
				// 填充红色背影
				dc.FillSolidRect(&m_rcDelButton, DEL_BUTTON_MOUSE_ON_COLOR);
				pen.CreatePen(1, 2, ITEM_SELECT_TEXT_COLOR);
				itemRect.right -= DEL_RECT_WIDTH;
				// 画白色X按钮
				CRect temDelRect = m_rcDelButton;
				temDelRect.top += 5;
				temDelRect.right -= 5;
				temDelRect.bottom -= 5;
				temDelRect.left += 5;
				//temDelRect.DeflateRect(2, 2, 2, 2);
				dc.SelectObject(&pen);

				//TRACE("temDelRect:(%d,%d,%d,%d)\n", RECT_PARAM(temDelRect));
				dc.MoveTo(temDelRect.left, temDelRect.top);
				dc.LineTo(temDelRect.right, temDelRect.bottom);
				dc.MoveTo(temDelRect.right, temDelRect.top);
				dc.LineTo(temDelRect.left, temDelRect.bottom);
			}

			dc.SetTextColor(ITEM_SELECT_TEXT_COLOR);
		}
		else
		{
			dc.SetTextColor(ITEM_UNSELECT_TEXT_COLOR);
			dc.FillSolidRect(itemRect, ITEM_UNSELECT_BK_COLOR);
		}
		dc.SetBkMode(TRANSPARENT);
		if (nState == (ES_WANTRETURN | EN_CHANGE)) // 0x1300
		{
		}
		CString str;
		GetLBText(nIndex, str);
		itemRect.DeflateRect(2, 0, 0, 0);

		dc.DrawText(str, itemRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);//显示文本
	}

	dc.Detach();
}


void  CMyComboBox::RectResetCoord(RECT & rect, int offsetX, int offsetY)
{
	rect.right = RECT_WIDTH(rect) + offsetX;
	rect.bottom = RECT_HEIGHT(rect) + offsetY;
	rect.top = offsetY;
	rect.left = offsetX;
}

#define USE_COMPATIBLE_DC   0
void CMyComboBox::OnPaint()
{
#if 0
	CComboBox::OnPaint();
#else

#if USE_COMPATIBLE_DC
	CPaintDC parentDc(this); // device context for painting
							 // TODO: Add your message handler code here
							 // Do not call CComboBox::OnPaint() for painting messages

	CDC dc;
	CBitmap bmp;
	dc.CreateCompatibleDC(&parentDc);//创建与目标DC相兼容的内存DC,
	bmp.CreateCompatibleBitmap(&parentDc, rect.Width(), rect.Height());//根据目标DC创建位图,为什么?看后面
	dc.SelectObject(&bmp);//把位图选入内存DC
#else
	CPaintDC dc(this);
#endif

	static BOOL bFirstTime = TRUE;
	COLORREF clrBkground(COMBO_NORMAL_BK_COLOR);
	COLORREF clrText(ITEM_UNSELECT_TEXT_COLOR);
	COLORREF clrFrame(COMBO_NORMAL_FRAME_COLOR);
	POINT ptArrowBeg, ptArrowMid, ptArrowEnd;
	CRect rect, comboRect;
	COMBOBOXINFO cbi;
	cbi.cbSize = sizeof(COMBOBOXINFO);

	GetClientRect(&comboRect);
	GetComboBoxInfo(&cbi);  //获取组合框信息


	rect = comboRect;
	RectResetCoord(rect);

	m_rcArrow = cbi.rcButton;


	int nArrowPaddingX = (m_rcArrow.Width() - ARROW_TRIANGLE_WIDTH) / 2 - 1;
	int nArrowPaddingY = (m_rcArrow.Height() - ARROW_TRIANGLE_HEIGHT) / 2 - 1;

	// arrow的坐标 6*4 倒三角形, 底部上下加距相等
	ptArrowBeg.x = m_rcArrow.left + nArrowPaddingX;
	ptArrowBeg.y = m_rcArrow.top + nArrowPaddingY;
	ptArrowMid.x = m_rcArrow.left + m_rcArrow.Width() / 2;
	ptArrowMid.y = ptArrowBeg.y + ARROW_TRIANGLE_HEIGHT;
	ptArrowEnd.x = m_rcArrow.right - nArrowPaddingX;
	ptArrowEnd.y = ptArrowBeg.y;

	BOOL bDrawArrowRect = FALSE;
	BOOL bListDropped = GetDroppedState();
	BOOL bCurseInCtrl = FALSE;

	TRACE("OnPaint: Cursor: %d, ListDropped: %d, BtnState: %d, Enable: %d, Over: %d, ArrowOver: %d, DropList: %d\n", IsCaretInWindow(), bListDropped, cbi.stateButton, IsWindowEnabled(), m_bMouseOverBox, m_bMouseOverArrow, m_bIsDropList);

	if (!IsWindowEnabled())
	{
		clrBkground = COMBO_DISABLED_BK_COLOR;
		clrText = COMBO_DISABLED_TEXT_COLOR;
		clrFrame = COMBO_DISABLE

15,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧