当前位置:首页 > 带复选框的下拉列表
MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd); } #endif break; }
// Make the combobox always return -1 as the current selection. This // causes the lpDrawItemStruct->itemID in DrawItem() to be -1 // when the always-visible-portion of the combo is drawn case LB_GETCURSEL: { return -1; }
case WM_CHAR: {
if (wParam == VK_SPACE) { // Get the current selection INT nIndex = CallWindowProcA(m_pWndProc, hWnd, LB_GETCURSEL, wParam, lParam); CRect rcItem;
SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem); InvalidateRect(hWnd, rcItem, FALSE);
// Invert the check mark
m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex)); // Notify that selection has changed
m_pComboBox->GetParent()->SendMessage(WM_COMMAND,
MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd); return 0; } break; }
case WM_LBUTTONDOWN: {
CRect rcClient;
GetClientRect(hWnd, rcClient);
CPoint pt;
pt.x = LOWORD(lParam); pt.y = HIWORD(lParam);
if (PtInRect(rcClient, pt)) {
INT nItemHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0); INT nTopIndex = SendMessage(hWnd, LB_GETTOPINDEX, 0, 0); // Compute which index to check/uncheck
INT nIndex = nTopIndex + pt.y / nItemHeight;
CRect rcItem;
SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem); if (PtInRect(rcItem, pt)) { // Invalidate this window
InvalidateRect(hWnd, rcItem, FALSE);
m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex)); // Notify that selection has changed
m_pComboBox->GetParent()->SendMessage(WM_COMMAND,
MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd);
} }
// Do the default handling now (such as close the popup // window when clicked outside) break; }
case WM_LBUTTONUP: {
// Don't do anything here. This causes the combobox popup // windows to remain open after a selection has been made return 0; } }
return CallWindowProc(m_pWndProc, hWnd, nMsg, wParam, lParam); }
CCheckComboBox::CCheckComboBox() {
m_hListBox = 0; m_bTextUpdated = FALSE; m_bItemHeightSet = FALSE; }
CCheckComboBox::~CCheckComboBox() { }
BOOL CCheckComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) {
// 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 CComboBox::Create(dwStyle, rect, pParentWnd, nID); }
LRESULT CCheckComboBox::OnCtlColorListBox(WPARAM wParam, LPARAM lParam) {
// 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);
} }
return DefWindowProc(WM_CTLCOLORLISTBOX, wParam, lParam); }
void CCheckComboBox::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 INT nCheck = 0;
// 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;
// Don't draw any boxes on this item nCheck = 0; }
// Otherwise it is one of the items else {
GetLBText(lpDrawItemStruct->itemID, strText);
nCheck = 1 + (GetItemData(lpDrawItemStruct->itemID) != 0); TEXTMETRIC metrics;
GetTextMetrics(dc, &metrics);
rcBitmap.left = 0;
rcBitmap.right = rcBitmap.left + metrics.tmHeight + metrics.tmExternalLeading + 6; rcBitmap.top += 1; rcBitmap.bottom -= 1;
共分享92篇相关文档