Skip to content

Instantly share code, notes, and snippets.

@zhenghao1
Created February 27, 2014 19:15
Show Gist options
  • Save zhenghao1/9257043 to your computer and use it in GitHub Desktop.
Save zhenghao1/9257043 to your computer and use it in GitHub Desktop.
MFC Multi-line CComboBox
// BoxDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Box.h"
#include "BoxDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CBoxDlg dialog
CBoxDlg::CBoxDlg(CWnd* pParent /*=NULL*/)
: CDialog(CBoxDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CBoxDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO1, m_combo);
}
BEGIN_MESSAGE_MAP(CBoxDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CBoxDlg message handlers
BOOL CBoxDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_combo.Init();
m_combo.AddItem("Introducing uppercuts crisps!");
m_combo.AddItem("Today is a good day to go to Orchard Road for shopping");
m_combo.AddItem("Finely sliced potato chips, delicately seasoned with the most authentic.");
m_combo.AddItem("192.0.2.123/16 is online. Please disconnect the device");
m_combo.SetCurSel(0);
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CBoxDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the
// cursor to display while the user drags
// the minimized window.
HCURSOR CBoxDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
#pragma once
#include "mybox.h"
#include "afxwin.h"
// CBoxDlg dialog
class CBoxDlg : public CDialog
{
// Construction
public:
CBoxDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_BOX_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
// Implementation
protected:
HICON m_hIcon;
CMyBox m_combo;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
};
// ODrawCombo.cpp : implementation file
//
#include "stdafx.h"
#include "mybox.h"
// CMyBox
IMPLEMENT_DYNAMIC(CMyBox, CComboBox)
CMyBox::CMyBox()
{
}
CMyBox::~CMyBox()
{
}
BEGIN_MESSAGE_MAP(CMyBox, CComboBox)
END_MESSAGE_MAP()
// CMyBox message handlers
void CMyBox::Init()
{
}
void CMyBox::AddItem(CString nItem)
{
this->AddString(nItem);
}
void CMyBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct->CtlType == ODT_COMBOBOX);
if(lpDrawItemStruct->itemID != 0xffffffff)
{
// 1 - Get combobox item ID
UINT id = (UINT) (WORD) lpDrawItemStruct->itemID;
// Consistency checks
ASSERT(id == lpDrawItemStruct->itemID);
// 2 - Get device context & item rectangle
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);
CRect rcItem = lpDrawItemStruct->rcItem;
int nCurrentX = rcItem.left;
// 3 - Select background and foreground
// colors depending on item selected state
COLORREF crBack, crFore;
if(lpDrawItemStruct->itemState & ODS_SELECTED)
{
crBack = ::GetSysColor(COLOR_HIGHLIGHT);
crFore = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
}
else
{
crBack = ::GetSysColor(COLOR_WINDOW);
crFore = ::GetSysColor(COLOR_WINDOWTEXT);
}
// 4 - Fill item background
CRect rcBack(nCurrentX, rcItem.top, rcItem.right, rcItem.bottom);
CBrush brFill(crBack);
dc.FillRect(&rcBack, &brFill);
// 5 - Draw item color rectangle
CBrush brColor(::GetSysColor(COLOR_WINDOWTEXT));
CBrush* pOldBrush = dc.SelectObject(&brColor);
CRect rcColor(nCurrentX, rcItem.top, nCurrentX, rcItem.bottom);
dc.Rectangle(rcColor);
dc.SelectObject(pOldBrush);
// 6 - Draw item text
COLORREF crOldTextColor = dc.SetTextColor(crFore);
int nOldBkMode = dc.SetBkMode(TRANSPARENT);
CString str;
this->GetLBText(id, str);
dc.DrawText(str, -1, rcItem, DT_LEFT|DT_WORDBREAK);
dc.SetTextColor(crOldTextColor);
dc.SetBkMode(nOldBkMode);
dc.Detach();
}
}
void CMyBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
/*DWORD dwStyle = ::GetWindowLong( m_hWnd, GWL_STYLE );*/
/*ASSERT( dwStyle & CBS_DROPDOWNLIST );*/
CFont* pFont = GetFont();
CFont* pOldFont = 0;
CString str;
CDC* pDC = GetDC();
pOldFont = pDC->SelectObject(pFont);
// Get text from combo box
this->GetLBText(lpMeasureItemStruct->itemID, str);
// Obtain rectangle that text is originally in
CRect rc;
GetClientRect(&rc);
//GetWindowRect(&rc);
rc.left = 0;
rc.top = 0;
rc.bottom = 0;
// With the inclusion of DT_CALCRECT
// this DrawText does not draw the text
// it just measures the rectangle
pDC->DrawText(str, str.GetLength(), &rc, DT_CALCRECT|DT_LEFT|DT_WORDBREAK);
lpMeasureItemStruct->itemHeight = rc.bottom;
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
}
#pragma once
// CMyBox
class CMyBox : public CComboBox
{
DECLARE_DYNAMIC(CMyBox)
public:
CMyBox();
virtual ~CMyBox();
void Init();
void AddItem(CString nItem);
virtual void DrawItem(LPDRAWITEMSTRUCT);
virtual void MeasureItem(LPMEASUREITEMSTRUCT);
protected:
DECLARE_MESSAGE_MAP()
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment