MFC界面美化第四篇----自绘list列表(重绘列表)

1.前言

最近发现读者对我的mfc美化的专栏比较感兴趣,因此在这里进行续写,这里我会计划写几个连续的篇章,包括对MFC按钮的美化,菜单栏的美化,标题栏的美化,list列表的美化,直到最后形成一个完整的成品效果。

2.最终效果展示

3.思路分析

1.编写mfc的list的派生类对 列表进行重绘

2.list和其他的空间有些区别,要分别对标题栏,和内容栏进行重绘。

4.实现的过程

1.在mfc界面,增加空间list

2.修改list的属性

边框:false
静态边缘:false
视图:Reporte
无滚动:true
 

3.声明list的变量

public:CListCtrlComboEx  m_list;

4.OnInitDialog 里面的核心代码

BOOL CCustomListDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){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);		// 设置小图标//LIST CRect rect;m_list.GetClientRect(&rect);DWORD dwStyle = m_list.GetExtendedStyle();//dwStyle = (dwStyle | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);dwStyle |= dwStyle | LVS_REPORT & ~LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_SHOWSELALWAYS | LVS_EX_HEADERDRAGDROP;m_list.SetExtendedStyle(dwStyle);//m_list.SetBom_list.SetItemHeight(25);m_list.SetFontSize(17);m_list.InsertColumn(0, _T("编号"), LVCFMT_CENTER, (rect.Width() / 3) + 30, 0);m_list.InsertColumn(1, _T("菜谱"), LVCFMT_CENTER, (rect.Width() - (rect.Width() / 3) - 30), 1);m_list.InsertColumn(2, _T(""), LVCFMT_CENTER, 1000, 2);m_list.InsertItem(0, _T("1"));m_list.InsertItem(1, _T("2"));m_list.InsertItem(2, _T("3"));m_list.InsertItem(3, _T("4"));m_list.InsertItem(4, _T("5"));m_list.InsertItem(5, _T("6"));m_list.InsertItem(6, _T("7"));m_list.InsertItem(7, _T("8"));m_list.InsertItem(8, _T("9"));m_list.InsertItem(9, _T(""));m_list.InsertItem(10, _T(""));m_list.InsertItem(11, _T(""));// TODO: 在此添加额外的初始化代码return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

5.list重写的对应封装代码

BitMark.h

#pragma once#define BITMARK_MAX			(2500)#define BITMARK_ROWS_DEF		(100)
#define BITMARK_COLS_DEF		(20)class BitMark
{
public:BitMark(void);virtual ~BitMark(void);virtual BOOL	Seek(DWORD uRows, DWORD uCols);virtual void	Set(DWORD uRow, DWORD uCol, BOOL bValid);virtual BOOL	IsValid(DWORD uRow, DWORD uCol);virtual void	Clear();
protected:DWORD	m_uRows, m_uCols;BYTE	m_aBit[BITMARK_MAX];
};

BitMark.cpp

#include "pch.h"
#include "BitMark.h"#ifdef _AFX
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static const char THIS_FILE[] = __FILE__;
#endif
#endifBitMark::BitMark(void)
{ZeroMemory(m_aBit, BITMARK_MAX);
}BitMark::~BitMark(void)
{
}BOOL BitMark::Seek(DWORD uRows, DWORD uCols)
{if((uRows*uCols) > BITMARK_MAX)return FALSE;m_uRows = uRows;m_uCols = uCols;return TRUE;
}void BitMark::Set(DWORD uRow, DWORD uCol, BOOL bValid)
{if((uRow*m_uCols + uCol) >= BITMARK_MAX)return;m_aBit[uRow*m_uCols+ uCol] = ( bValid ? 1 : 0 );
}BOOL BitMark::IsValid(DWORD uRow, DWORD uCol)
{BOOL bValid =FALSE;if((uRow*m_uCols + uCol) >= BITMARK_MAX)return FALSE;if(0 != m_aBit[uRow*m_uCols + uCol])bValid = TRUE;return bValid;
}void BitMark::Clear()
{ZeroMemory(m_aBit, BITMARK_MAX);
}

HeaderCtrlEx.h

#pragma once
#include <afxcmn.h>class HeaderCtrlEx :public CHeaderCtrl
{DECLARE_DYNAMIC(HeaderCtrlEx)protected:DECLARE_MESSAGE_MAP()void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);LRESULT OnLayout(WPARAM wParam, LPARAM lParam);afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};

HeaderCtrlEx.cpp

#include "pch.h"
#include "HeaderCtrlEx.h"IMPLEMENT_DYNAMIC(HeaderCtrlEx, CHeaderCtrl)BEGIN_MESSAGE_MAP(HeaderCtrlEx, CHeaderCtrl)ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &HeaderCtrlEx::OnNMCustomdraw)ON_MESSAGE(HDM_LAYOUT, &HeaderCtrlEx::OnLayout)ON_WM_ERASEBKGND()
END_MESSAGE_MAP()void HeaderCtrlEx::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
{// ref: https://stackoverflow.com/questions/28766659/changing-mfc-list-control-header-colorLPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);// TODO: Add your control notification handler code here*pResult = CDRF_DODEFAULT;if (pNMCD->dwDrawStage == CDDS_PREPAINT){CDC* pDC = CDC::FromHandle(pNMCD->hdc);CRect rect(0, 0, 0, 0);GetClientRect(&rect);//pDC->FillSolidRect(&rect, RGB(215, 235, 226));pDC->FillSolidRect(&rect, RGB(30, 34, 39));*pResult = CDRF_NOTIFYITEMDRAW;}else if (pNMCD->dwDrawStage == CDDS_ITEMPREPAINT){HDITEM hditem;TCHAR buffer[MAX_PATH] = { 0 };SecureZeroMemory(&hditem, sizeof(HDITEM));hditem.mask = HDI_TEXT;hditem.pszText = buffer;hditem.cchTextMax = MAX_PATH;GetItem(pNMCD->dwItemSpec, &hditem);CDC* pDC = CDC::FromHandle(pNMCD->hdc);//pDC->SetTextColor(RGB(0, 0, 0));pDC->SetTextColor(RGB(255, 255, 255));//pDC->SetBkColor(RGB(215, 235, 226));pDC->SetBkColor(RGB(30, 34, 39));//CFont m_pFont;//m_pFont.CreateFont(ConvertWithDPIRatio(31),//    0, 0, 0, FW_MEDIUM,//    FALSE, FALSE,//    0,//    ANSI_CHARSET,              // nCharSet//    OUT_DEFAULT_PRECIS,        // nOutPrecision//    CLIP_DEFAULT_PRECIS,       // nClipPrecision//    DEFAULT_QUALITY,           // nQuality//    DEFAULT_PITCH | FF_SWISS, _T("Arial"));//pDC->SelectObject(m_pFont);CString str(buffer);CRect rect = pNMCD->rc;rect.OffsetRect(6, 0);pDC->DrawText(str, CRect(rect), DT_SINGLELINE | DT_VCENTER);*pResult = CDRF_SKIPDEFAULT;}
}/*
*   Describe: Change the height of table header
*   Author  : Canliang Wu
*   Date    : 2021/12/15
*/
LRESULT HeaderCtrlEx::OnLayout(WPARAM wParam, LPARAM lParam)
{LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam;RECT* prc = hdl.prc;            // The table list rectangleWINDOWPOS* pwpos = hdl.pwpos;   // The table header rectangleint nHeight = (int)(pwpos->cy * 1.3);pwpos->cy = nHeight;            // New table header height//pwpos->x += 3;prc->top = nHeight;             // Decreases the table list height on the table header heightreturn lResult;
}BOOL HeaderCtrlEx::OnEraseBkgnd(CDC* pDC)
{// TODO: Add your message handler code here and/or call default//return CListCtrl::OnEraseBkgnd(pDC);return FALSE;
}

ListControlDefine.h

#pragma once#define ListCtrlMask_Rows			(500)
#define ListCtrlMask_Cols			(20)
#define ListCtrlMask_Max			(ListCtrlMask_Rows * ListCtrlMask_Cols)
typedef struct ListCtrlMask {BYTE	Bit[ListCtrlMask_Max];
} ListCtrlMask;

ListControlDefine.cpp

#include "pch.h"
#include "ListControlDefine.h"

ListCtrlComboEx.h

#if !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_)
#define AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ListCtrlComboEx.h : header file#include "ListControlDefine.h"
#include "BitMark.h"
#include "HeaderCtrlEx.h"
#include <afxcmn.h>
#define cgCComboBox CComboBox  //you can use yourself defined combobox
/
// CListCtrlComboEx window
#include <vector>
using namespace std;
struct stEditAble
{int nRow;int nCol;
};struct stComboAble
{int nRow;int nCol;cgCComboBox *pCombo;
};#define IDCB_ONLISTCONTROL			9001#define CListCtrlComboEx_ColumnMax		(200)
class CListCtrlComboEx : public CListCtrl
{
// Construction
public:CListCtrlComboEx();public:UINT	m_nMsgComboSelChange;BitMark	m_oBm;int		m_nRowDblClk;int		m_nColDblClk;int InsertColumn(int nCol, LPCTSTR lpszColumnHeading,int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);void SetItemWarning(int nItem, int nSubItem, BOOL bValid);int m_anFormat[CListCtrlComboEx_ColumnMax];void	CreateComboBox(UINT nMsgComboSelChange);void	CreateEditBox();CComboBox*	GetCombo();
protected:CComboBox*	m_pcbListCtrl;HeaderCtrlEx m_HeaderCtrl;
protected:vector<stEditAble> m_EditAbleArray;vector<stComboAble> m_ComboAbleArray;int m_iRow;int m_iCol;CEdit *m_pEdit;int m_iHeight;CFont m_oFont;// Attributes
public:void SetEditAble(int nRow,int nCol);void SetComboAble(int nRow,int nCol,cgCComboBox *pCombo);void SetItemHeight(int nHeight);COLORREF GetTableItemColor(int nRow, int nCol, COLORREF clrDef);void ClearAllAbles();BOOL GetCellRect(int nRow, int nCol, CRect& rect);void SetFontSize(int cHeight = 18);BOOL m_bFontSeted;
// Operations
public:virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CListCtrlComboEx)//}}AFX_VIRTUAL// Implementation
public:virtual ~CListCtrlComboEx();// Generated message map functions
protected:BOOL IsEditAble(int nRow,int nCol);BOOL IsComboAble(int nRow,int nCol);virtual void PreSubclassWindow();LPCTSTR MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset);protected://{{AFX_MSG(CListCtrlComboEx)// NOTE - the ClassWizard will add and remove member functions here.virtual afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point);virtual afx_msg BOOL OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult);afx_msg void OnCbnKillfocusCombo();afx_msg void OnCbnSelchangeCombo();afx_msg BOOL OnEraseBkgnd(CDC* pDC);//}}AFX_MSGDECLARE_DYNAMIC(CListCtrlComboEx)DECLARE_MESSAGE_MAP()
public:afx_msg void OnPaint();
public:afx_msg BOOL OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
};///{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_)

ListCtrlComboEx.cpp

// ListCtrlComboEx.cpp : implementation file
//#include "pch.h"
//#include "cgListComboTest.h"
#include "ListCtrlComboEx.h"
//#include "resource.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/
// CListCtrlComboExCListCtrlComboEx::CListCtrlComboEx()
{m_pcbListCtrl = NULL;m_nRowDblClk = 0;m_nColDblClk = 0;m_bFontSeted = FALSE;m_EditAbleArray.clear();m_ComboAbleArray.clear();m_iRow = -1;m_iCol = -1;m_iHeight = 0;m_pEdit = NULL;m_nMsgComboSelChange = 0;ZeroMemory(&m_anFormat, sizeof(m_anFormat));//m_pListCtrlMask = NULL;
}CListCtrlComboEx::~CListCtrlComboEx()
{if(m_pcbListCtrl) {m_pcbListCtrl->DestroyWindow();delete m_pcbListCtrl;m_pcbListCtrl = NULL;}
}int CListCtrlComboEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading,int nFormat /*= LVCFMT_LEFT*/, int nWidth /*= -1*/, int nSubItem /*= -1*/)
{if(nCol>=0)m_anFormat[nCol] = nFormat;return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem);
}void CListCtrlComboEx::SetItemWarning(int nItem, int nSubItem, BOOL bValid)
{//return;m_oBm.Set(nItem, nSubItem, bValid);
}void CListCtrlComboEx::CreateComboBox(UINT nMsgComboSelChange)
{m_nMsgComboSelChange = nMsgComboSelChange;CFont* cf = GetFont();CComboBox *pCombo;pCombo = new CComboBox();CRect rect;GetCellRect(0,1,rect);pCombo->Create(WS_CHILD/*|WS_VISIBLE*/|CBS_AUTOHSCROLL|CBS_DROPDOWNLIST,rect,(CWnd*)this, IDCB_ONLISTCONTROL);pCombo->SetFont(cf);m_pcbListCtrl = pCombo;
}CComboBox* CListCtrlComboEx::GetCombo()
{return m_pcbListCtrl;
}COLORREF CListCtrlComboEx::GetTableItemColor(int nRow, int nCol, COLORREF clrDef)
{COLORREF clr;clr = clrDef; //RGB(0, 0, 0);//if((nRow*nCol) >= ListCtrlMask_Max)//	return clr;//if(!m_pListCtrlMask)//	return clr;//if(m_pListCtrlMask->Bit[nRow*ListCtrlMask_Cols + nCol])//	clr = RGB(255, 0, 0);if(m_oBm.IsValid(nRow, nCol))clr = RGB(255, 0, 0);//if(myutil::GetBit(m_oWarningBitMark.bit[nRow], nCol))//{//	clr = RGB(255, 0, 0);//}//if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].upper_warning_bit, nCol))//{//	clr = RGB(255, 0, 0);//}//if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].lower_warning_bit, nCol))//{//	clr = RGB(255, 0, 0);//}//if(m_oVoltTbl.v_row[nRow].v[nCol] > m_nUpper)//{//	clr = RGB(255, 0, 0);//}//if(m_oVoltTbl.v_row[nRow].v[nCol] < m_nLower)//{//	clr = RGB(255, 0, 0);//}//if(theApp.m_pYmVoltTblRow[nRow].V.volt[nCol] < theApp.m_pYmVoltTblRow[nRow].Lower)//{//	clr = RGB(255, 0, 0);//}return clr;
}void CListCtrlComboEx::ClearAllAbles()
{m_EditAbleArray.clear();m_ComboAbleArray.clear();m_iRow = -1;m_iCol = -1;m_pEdit = NULL;
}IMPLEMENT_DYNAMIC(CListCtrlComboEx, CListCtrl)BEGIN_MESSAGE_MAP(CListCtrlComboEx, CListCtrl)//{{AFX_MSG_MAP(CListCtrlComboEx)// NOTE - the ClassWizard will add and remove mapping macros here.ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)ON_NOTIFY_EX(HDN_ENDTRACKA, 0, OnHeaderEndResize)ON_NOTIFY_EX(HDN_ENDTRACKW, 0, OnHeaderEndResize)ON_WM_MEASUREITEM_REFLECT()ON_WM_LBUTTONDOWN()ON_WM_ERASEBKGND()ON_CBN_KILLFOCUS(IDCB_ONLISTCONTROL, &CListCtrlComboEx::OnCbnKillfocusCombo)ON_CBN_SELCHANGE(IDCB_ONLISTCONTROL, &CListCtrlComboEx::OnCbnSelchangeCombo)//}}AFX_MSG_MAPON_WM_PAINT()ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CListCtrlComboEx::OnNMDblclk)
END_MESSAGE_MAP()/
// CListCtrlComboEx message handlersvoid CListCtrlComboEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);int nRow = (int)pLVCD->nmcd.dwItemSpec;pResult = CDRF_DODEFAULT;/*	// Allow column-traits to perform their custom drawingif (pLVCD->nmcd.dwDrawStage & CDDS_SUBITEM){CComboBox* pCombo = GetCellColumnTrait(nRow, pLVCD->iSubItem);if (pCombo != NULL)return;	// Everything is handled by the column-trait}// Always perform drawing of cell-focus rectangleswitch (pLVCD->nmcd.dwDrawStage){case CDDS_PREPAINT:*pResult |= CDRF_NOTIFYITEMDRAW;break;// Before painting a rowcase CDDS_ITEMPREPAINT:{*pResult |= CDRF_NOTIFYPOSTPAINT;	// Ensure row-traits gets called*pResult |= CDRF_NOTIFYSUBITEMDRAW;	// Ensure column-traits gets called} break;// After painting the entire rowcase CDDS_ITEMPOSTPAINT:{;} break;}*/}BOOL CListCtrlComboEx::OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{int size = m_ComboAbleArray.size();int i;for(i=0;i<size;i++){int nRow = m_ComboAbleArray[i].nRow;int nCol = m_ComboAbleArray[i].nCol;cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;CRect rect;GetCellRect(nRow,nCol,rect);rect.bottom -=  2*::GetSystemMetrics(SM_CXEDGE);pCombo->MoveWindow(rect);pCombo->SetWindowPos(NULL,		// not relative to any other windows0, 0,		// TopLeft corner doesn't changerect.Width(), (pCombo->GetCount()+1)*rect.Height(),   // existing width, new heightSWP_NOMOVE | SWP_NOZORDER	// don't move box or change z-ordering.);pCombo->ShowWindow(TRUE);}Invalidate(FALSE);return FALSE;
}void CListCtrlComboEx::OnCbnKillfocusCombo()
{int size = m_ComboAbleArray.size();int i;for(i=0;i<size;i++){int nRow = m_ComboAbleArray[i].nRow;int nCol = m_ComboAbleArray[i].nCol;cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;pCombo->ShowWindow(FALSE);}Invalidate(FALSE);
}void CListCtrlComboEx::OnCbnSelchangeCombo()
{CWnd* P = this->GetParent();if(m_nMsgComboSelChange)P->PostMessage(m_nMsgComboSelChange);int size = m_ComboAbleArray.size();int i;for(i=0;i<size;i++){int nRow = m_ComboAbleArray[i].nRow;int nCol = m_ComboAbleArray[i].nCol;cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;pCombo->ShowWindow(FALSE);}Invalidate(FALSE);
}void CListCtrlComboEx::SetItemHeight(int nHeight)
{m_iHeight = nHeight;CRect rcWin;GetWindowRect(&rcWin);WINDOWPOS wp;wp.hwnd = m_hWnd;wp.cx = rcWin.Width();wp.cy = rcWin.Height();wp.flags = SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER;SendMessage(WM_WINDOWPOSCHANGED,0,(LPARAM)&wp);
}BOOL CListCtrlComboEx::GetCellRect(int nRow, int nCol,CRect& rect)
{if (GetSubItemRect(nRow, nCol, LVIR_BOUNDS, rect)==FALSE)return FALSE;CRect colRect;if (GetHeaderCtrl()->GetItemRect(nCol, colRect)==FALSE)return FALSE;if (nCol==0){// Fix bug where LVIR_BOUNDS gives the entire row for nCol==0CRect labelRect;if (GetSubItemRect(nRow, nCol, LVIR_LABEL, labelRect)==FALSE)return FALSE;rect.right = labelRect.right; rect.left  = labelRect.right - colRect.Width();}else{// Fix bug when width is smaller than subitem image widthrect.right = rect.left + colRect.Width();}return TRUE;
}void CListCtrlComboEx::SetFontSize(int cHeight)
{if(m_bFontSeted)return;m_bFontSeted = TRUE;m_oFont.CreateFont(cHeight,                        // nHeight0,                         // nWidth0,                         // nEscapement0,                         // nOrientationFW_NORMAL,                 // nWeightFALSE,                     // bItalicFALSE,                     // bUnderline0,                         // cStrikeOutANSI_CHARSET,              // nCharSetOUT_DEFAULT_PRECIS,        // nOutPrecisionCLIP_DEFAULT_PRECIS,       // nClipPrecisionDEFAULT_QUALITY,           // nQualityDEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily_T("Arial"));                 // lpszFacenameSetFont(&m_oFont, TRUE);}BOOL CListCtrlComboEx::IsEditAble(int nRow,int nCol)
{int i;int size = m_EditAbleArray.size();if(size > 0){for(i=0;i<size;i++){if(m_EditAbleArray[i].nRow == nRow && m_EditAbleArray[i].nCol == nCol)return TRUE;}}return FALSE;
}BOOL CListCtrlComboEx::IsComboAble(int nRow,int nCol)
{int i;int size = m_ComboAbleArray.size();if(size > 0){for(i=0;i<size;i++){if(m_ComboAbleArray[i].nRow == nRow && m_ComboAbleArray[i].nCol == nCol)return TRUE;}}return FALSE;
}void CListCtrlComboEx::SetEditAble(int nRow,int nCol)
{stEditAble sam;sam.nRow = nRow;sam.nCol = nCol;m_EditAbleArray.push_back(sam);
}void CListCtrlComboEx::SetComboAble(int nRow,int nCol,cgCComboBox *pCombo)
{stComboAble sam;sam.nRow = nRow;sam.nCol = nCol;sam.pCombo = pCombo;m_ComboAbleArray.push_back(sam);CRect rect;GetCellRect(nRow,nCol,rect);rect.bottom -=  2*::GetSystemMetrics(SM_CXEDGE);pCombo->SetWindowPos(NULL,		// not relative to any other windows0, 0,		// TopLeft corner doesn't changerect.Width(), (pCombo->GetCount()+1)*rect.Height(),   // existing width, new heightSWP_NOMOVE | SWP_NOZORDER	// don't move box or change z-ordering.);pCombo->ShowWindow(TRUE);pCombo->SetFocus();
}void CListCtrlComboEx::OnLButtonDown(UINT nFlags, CPoint point)
{int nRow, nCol;if(m_pEdit != NULL){CString str;m_pEdit->GetWindowText(str);SetItemText(m_iRow,m_iCol,str);m_iRow = -1;m_iCol = -1;delete m_pEdit;//	m_pEdit->PostMessage(WM_CLOSE);m_pEdit = NULL;}LVHITTESTINFO lvhti = {0};lvhti.pt = point;nRow = ListView_SubItemHitTest(m_hWnd, &lvhti);	// SubItemHitTest is non-constnCol = lvhti.iSubItem;if (!(lvhti.flags & LVHT_ONITEM))nRow = -1;if(nRow == -1 || nCol == -1){CListCtrl::OnLButtonDown(nFlags, point);return;}if(IsEditAble(nRow,nCol)){m_iRow = nRow;m_iCol = nCol;CRect rect;GetCellRect(nRow,nCol,rect);m_pEdit = new CEdit();m_pEdit->Create(WS_CHILD|ES_LEFT|ES_AUTOHSCROLL,rect,this,0);CString str;str = GetItemText(nRow,nCol);m_pEdit->SetWindowText(str);m_pEdit->ShowWindow(SW_SHOW);m_pEdit->SetFocus();return;}CListCtrl::OnLButtonDown(nFlags,point);}void CListCtrlComboEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{if(m_iHeight>0){lpMeasureItemStruct->itemHeight = m_iHeight;}}void CListCtrlComboEx::PreSubclassWindow()
{ModifyStyle(0,LVS_OWNERDRAWFIXED);//CListCtrl::PreSubclassWindow();CHeaderCtrl* pHeader = GetHeaderCtrl();if (pHeader != NULL) { VERIFY(m_HeaderCtrl.SubclassWindow(pHeader->m_hWnd)); }CListCtrl::PreSubclassWindow();}void CListCtrlComboEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{int nItem = lpDrawItemStruct->itemID;if(nItem == -1)return;CRect rcCol = lpDrawItemStruct->rcItem;CString sText;CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);int nOldDCMode = pDC->SaveDC();LVITEM item;item.iItem = nItem;item.iSubItem = 0;item.mask = LVIF_IMAGE|LVIF_STATE;item.stateMask = 0xFFFF;GetItem(&item);BOOL bSelected = item.state & LVIS_SELECTED;COLORREF color = RGB(30, 34, 39);if(bSelected){pDC->SetBkColor(RGB(30, 34, 39));pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_HIGHLIGHTTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/);color = RGB(30, 34, 39);}else{pDC->SetBkColor(RGB(30, 34, 39));pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_WINDOWTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/);}LV_COLUMN lvc;lvc.mask = LVCF_FMT|LVCF_WIDTH;rcCol.right = rcCol.left;for(int nCol=0;GetColumn(nCol,&lvc);nCol++){rcCol.left = rcCol.right;rcCol.right = rcCol.left + GetColumnWidth(nCol);HPEN hOldPen = (HPEN)::SelectObject(lpDrawItemStruct->hDC,::CreatePen(PS_SOLID,1,color));HBRUSH hOldBrush = (HBRUSH)::SelectObject(lpDrawItemStruct->hDC,::CreateSolidBrush(color));::Rectangle(lpDrawItemStruct->hDC,rcCol.left-1,rcCol.top-1,rcCol.right,rcCol.bottom);::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldBrush));::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldPen));sText = MakeShortString(pDC,GetItemText(nItem,nCol),rcCol.Width(),3);if(bSelected){pDC->SetBkColor(RGB(30, 34, 39));//pDC->SetTextColor(GetTableItemColor(nItem, nCol, ::GetSysColor(COLOR_HIGHLIGHTTEXT)));pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255)));color = RGB(30, 34, 39);}else{pDC->SetBkColor(RGB(30, 34, 39));pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255)));}//在这里进行测试//在这里进行测试UINT format = DT_CENTER;switch(/*lvc.fmt*/m_anFormat[nCol] & (LVCFMT_LEFT | LVCFMT_CENTER | LVCFMT_RIGHT)){case LVCFMT_LEFT:format = DT_LEFT;break;case LVCFMT_CENTER:format = DT_CENTER;break;case LVCFMT_RIGHT:format = DT_RIGHT;break;default:break;}pDC->DrawText(sText,CRect::CRect(rcCol.left+3,rcCol.top,rcCol.right,rcCol.bottom), format/*DT_CENTER*//*format*//*DT_LEFT*/|DT_VCENTER|DT_SINGLELINE );}pDC->RestoreDC(nOldDCMode);}LPCTSTR CListCtrlComboEx::MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset)
{static const _TCHAR szThreeDots[] = _T("...");int nStringLen = lstrlen(lpszLong);if(nStringLen == 0 ||(pDC->GetTextExtent(lpszLong,nStringLen).cx+nOffset) <= nColumnLen){return(lpszLong);}static _TCHAR szShort[MAX_PATH];lstrcpy(szShort,lpszLong);int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;for(int i=nStringLen-1; i>0; i--){szShort[i] = 0;if((pDC->GetTextExtent(szShort,i).cx+nAddLen+nOffset) <= nColumnLen){break;}}lstrcat(szShort,szThreeDots);return(szShort);
}
void CListCtrlComboEx::OnPaint()
{//CPaintDC dc(this); // device context for paintingTODO: 在此处添加消息处理程序代码不为绘图消息调用 CListCtrl::OnPaint()////CPaintDC dc(this); // device context for painting//const MSG *msg = GetCurrentMessage();//DefWindowProc( msg->message, msg->wParam, msg->lParam ); //这两句不能省,否则程序会因消息循环出现异常Draw the lines only for LVS_REPORT mode//if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )//{//	// Get the number of columns//	CClientDC dc(this );//	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);//	int nColumnCount = pHeader->GetItemCount();//	// The bottom of the header corresponds to the top of the line//	RECT rect;//	pHeader->GetClientRect( &rect );//	int top = rect.bottom;//	// Now get the client rect so we know the line length and//	// when to stop//	GetClientRect( &rect );//	// The border of the column is offset by the horz scroll//	int borderx = 0 - GetScrollPos( SB_HORZ ); //	CPen listSepPen(PS_SOLID, 1, RGB(201, 213, 240)); //定制你的分割线的颜色//	//CPen listSepPen(PS_SOLID, 1, RGB(30, 34, 39));//	CPen *pOldPen = dc.SelectObject(&listSepPen);//	for( int i = 0; i < nColumnCount; i++ )//	{//		// Get the next border//		borderx += GetColumnWidth( i );//		// if next border is outside client area, break out//		if( borderx >= rect.right ) break;//		// Draw the line.//		dc.MoveTo( borderx, top);//		dc.LineTo( borderx, rect.bottom );//	}//	// Draw the horizontal grid lines//	// First get the height//	if( !GetItemRect( 0, &rect, LVIR_BOUNDS ))//		return;//	int height = rect.bottom - rect.top;//	GetClientRect( &rect );//	int width = rect.right;//	for(int i = 1; i <= GetCountPerPage(); i++ )//	{//		dc.MoveTo( 0, top + height*i);//		dc.LineTo( width, top + height*i );//	}//	dc.SelectObject(pOldPen);//	//} //-------------------------------替换const MSG* msg = GetCurrentMessage();DefWindowProc(msg->message, msg->wParam, msg->lParam);CClientDC dc(this);CRect rect;GetClientRect(&rect);CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);int nColumnCount = pHeader->GetItemCount();CRect rectHead;pHeader->GetClientRect(&rectHead);// 画边框//CPen penBorder(PS_SOLID, 1, RGB(0, 66, 66));//CPen* pOldPen = dc->SelectObject(&penBorder);//dc.MoveTo(rect.left, rect.top );//dc.LineTo(rect.left, rect.bottom);//dc.MoveTo(rect.right - 1, rect.top );//dc.LineTo(rect.right - 1, rect.bottom)if ((GetStyle() & LVS_TYPEMASK) == LVS_REPORT){CPen penGrid;//penGrid.CreatePen(PS_SOLID, 1, RGB(0, 66, 66));//颜色penGrid.CreatePen(PS_SOLID, 1, RGB(48, 48, 48));//颜色CPen* oldPen = dc.SelectObject(&penGrid);int borderx = 0 - GetScrollPos(SB_HORZ);//画边框//dc.MoveTo(rect.right, rect.top);//dc.LineTo(rect.left, rect.top);//dc.MoveTo(rect.right, rect.bottom);//dc.LineTo(rect.left, rect.bottom);//dc.MoveTo(rect.left, rect.top);//dc.LineTo(rect.left, rect.bottom);//dc.MoveTo(rect.right, rect.top);//dc.LineTo(rect.right, rect.bottom);//取客户区域CRect item;int nHightPerLine = 18;if (GetItemRect(0, &item, LVIR_BOUNDS)){nHightPerLine = item.bottom - item.top;}//画纵向线for (int i = 0; i < nColumnCount; i++){borderx += GetColumnWidth(i);if (borderx > rect.right){break;}dc.MoveTo(borderx, rectHead.bottom);dc.LineTo(borderx, rect.bottom);}//画横向线for (int i = 0; i <= GetCountPerPage(); i++){dc.MoveTo(rect.left, rectHead.bottom + nHightPerLine * i + 1);dc.LineTo(borderx, rectHead.bottom + nHightPerLine * i + 1);}dc.SelectObject(penGrid);penGrid.DeleteObject();}}BOOL CListCtrlComboEx::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{// TODO: 在此添加控件通知处理程序代码*pResult = 0;NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR;m_nRowDblClk=pNMListView->iItem;//m_row为被选中行的行序号(int类型成员变量)m_nColDblClk=pNMListView->iSubItem;//m_column为被选中行的列序号(int类型成员变量)return FALSE;
}BOOL CListCtrlComboEx::OnEraseBkgnd(CDC* pDC)
{// TODO: Add your message handler code here and/or call default//return CListCtrl::OnEraseBkgnd(pDC);return FALSE;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757797.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 935 (Div. 3)(A,B,C,D,E,F)

比赛链接 阳间场&#xff0c;阴间题&#xff0c;最考阅读理解的一场。题目本身的难度不大。 A. Setting up Camp 题意&#xff1a; 组委会计划在奥运会结束后带领参赛者进行一次徒步旅行。目前&#xff0c;需要携带的帐篷数量正在计算中。据了解&#xff0c;每个帐篷最多可容…

什么是硬件加速?

硬件加速是指通过使用专门设计的硬件来提高计算机系统的性能和效率。传统的软件运行在通用的中央处理器&#xff08;CPU&#xff09;上&#xff0c;而硬件加速则利用专用的硬件组件来加速特定的计算任务。这些硬件组件可以是图形处理器&#xff08;GPU&#xff09;、数字信号处…

前端vue3-手动设置滚动条位置/自动定位

从B页面进行xx操作后需要跳转到A页面&#xff0c;并定位到AA职位&#xff0c;上图为A页面。 A页面的左侧是div&#xff0c;内层包裹List组件 给div定义refleftRef,在代码中写如下&#xff1a; function scrollTop() {if (leftRef.value) {console.log(99, leftRef.value);next…

每天学习一个Linux命令之vim

每天学习一个Linux命令之vim Vim是一款功能强大的文本编辑器&#xff0c;在Linux系统中广泛使用。本篇博客将介绍一些常用的Vim命令及其选项&#xff0c;帮助您更好地使用Vim进行文本编辑。 命令及选项 以下是Vim的常用命令及其可用选项&#xff1a; 1. 打开文件 $ vim fi…

0基础 三个月掌握C语言(13)

数据在内存中的存储 整数在内存中的存储 在讲解操作符时 我们就已经学习了该部分的内容 这里我们回顾一下 整数的二进制表示方法有三种&#xff1a;原码 反码 补码 有符号的整数&#xff08;unsigned&#xff09; 三种表达方式均有符号位和数值位两部分 最高位的一位被当…

文件包含漏洞之包含SESSION(CTF题目)

这次使用的环境是ubuntunginxphpmysql 首先四个文件源码在以下链接中&#xff1a; 一道CTF题&#xff1a;PHP文件包含 | Chybeta 我们注册一个用户名111密码111&#xff0c;然后登录查看cookie和linux的session&#xff0c;因为我们的de服务器 是手动搭建的&#xff0c;所以…

Java IO模型

NIO Java IO 模型1. 什么是IO计算机结构角度应用程序角度 2. 常见的内存模型3. Java中常见的IO模型3.1 BIO&#xff08;Blocking I/O&#xff09;3.2 NIO&#xff08;Non-blocking/New I/O&#xff09;同步非阻塞 IO 模型I/O 多路复用模型 3.3 AIO&#xff08;Asynchronous I/O…

Python从入门到精通秘籍八

一、Python中函数的多返回值 在Python中&#xff0c;函数可以返回多个值。这种特性可以通过将多个变量包装在一个元组或列表中来实现。下面是一个示例代码&#xff1a; def multiple_returns():a 1b 2c 3return a, b, cresult multiple_returns() print(result) # 输出&…

Spring6.1新特性,四种方式调用REST接口(RestClient、WebClient、RestTemplate、HTTP Interface)

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 官网 REST Clients :: Spring Framework The Spring Framework provides the following choices for…

电子元器件批发采购中的供应链透明度与可追溯性

电子元器件批发采购中的供应链透明度与可追溯性是非常重要的&#xff0c;特别是考虑到供应链的复杂性和全球化。以下是一些关于如何增强供应链透明度和可追溯性的建议&#xff1a; 供应商审核与选择&#xff1a;对潜在的供应商进行全面的审核和评估&#xff0c;了解其供应链结构…

Leetcode-06-Z字形变换

将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你的输出需要从左往右…

【Leetcode】1793. 好子数组的最大分数

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个整数数组 n u m s nums nums &#xff08;下标从 0 0 0 开始&#xff09;和一个整数 k k k 。 一个子数组 ( i , j ) (i, j) (i,j) 的 分数 定义为 m i n ( n u m s …

ROS2从入门到精通0-3:VSCode 搭建 ROS2 工程环境

目录 0 专栏介绍1 Ubuntu下安装VSCode1.1 基本安装1.2 将VSCode添加到侧边栏 2 VSCode集成相关插件3 VSCode运行ROS2环境步骤3.1 安装编译依赖项3.2 创建工作空间和源码空间3.3 启动VSCode与配置 4 测试工程环境4.1 C版本4.2 Python版本 0 专栏介绍 本专栏旨在通过对ROS2的系统…

一、初识 web3

瑾以此系列文章&#xff0c;献给那些出于好奇并且想要学习这方面知识的开发者们 在多数时间里&#xff0c;我们对 web3 的理解是非常模糊的 就好比提及什么是 web1 以及 web2&#xff0c;相关概念的解释是&#xff1a; 1. 从 Web3 的开始 Web3&#xff0c;也被称为Web3.0&…

idea error java:compilation failed:internal java compiler error

idea中编译运行maven项目报错如下 idea error java:compilation failed:internal java compiler error 尝试如下操作 注意&#xff1a;jdk8 需要设置4个地方 1.首先打开File->Project Structure中的Project&#xff0c;将SDK和language level都设置一致&#xff0c;如下…

大语言模型无代码构建知识图谱+视频链接

之前通过系列文章介绍了如何利用HugggingFists系统无代码构建知识图谱&#xff0c;这次给出视频&#xff0c;方便大家更直观的了解如何操作。视频链接如下&#xff1a; 《玩转数据之利用LLM构建知识图谱》 文章链接&#xff1a; 《大语言模型无代码构建知识图谱(1)--提示工程准…

基于Java的考研专业课程管理系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…

2024届 C++ 刷题 笔试强训 Day 03

选择题 01 以下程序的输出结果是&#xff08;&#xff09; #include <stdio.h> void main() {char a[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, *p;int i;i 8;p a i;printf("%s\n", p - 3); }A 6 B 6789 C ‘6’ D 789 题目解析&#xff1a; 题目中定义了一个…

js改变页面上输入框的值

方案一&#xff08;大众方案包含vue和原生js的输入框&#xff09; // 填写输入框内容&#xff0c;并且赋值给输入框 function fillInput(input, value) {input.value value;input.dispatchEvent(new Event(input, {bubbles: true,cancelable: true,composed: true}));// 所以…

文件操作:文本文件(写/读)

文件操作可以将数据永久化&#xff0c;C中对文件操作需要包含头文件 < fstream > 文件类型分为两种&#xff1a; 1. 文本文件&#xff1a;文件以文本的ASCII码形式存储在计算机中 2. 二进制文件&#xff1a;文件以文本的二进制形式存储在计算机中&#xff0c;…