📄 customgrid.cpp
字号:
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
m_nMouseMode = MOUSE_OVER_COL_DIVIDE;
}
}
else if(m_nMouseMode == MOUSE_OVER_COL_DIVIDE && !(nFlags & MK_LBUTTON) ){
if( (m_nSizingCol = MouseOverColumnResizeArea(point)) < 0){
::SetClassLong(GetSafeHwnd(), GCL_HCURSOR, (LONG)AfxGetApp()->LoadStandardCursor(IDC_ARROW));
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
m_nMouseMode = MOUSE_NOTHING;
}
}
else if(m_nMouseMode == MOUSE_SIZING_COL){//改变列宽度
CRect invertedRect(m_OldPoint.x - 1, client.top, m_OldPoint.x + 1, client.bottom);
CDC* pDC = GetDC();
if(client.right <= point.x + 1 && m_bCanScrollPage){
int hPage = client.Width() - GetFixedColumnWidth();
m_nHScrollMax += hPage;
SetScrollRange(SB_HORZ, 0, m_nHScrollMax + hPage, TRUE);
SendMessage(WM_HSCROLL, SB_PAGERIGHT, 0);
m_bCanScrollPage = false;
}
else if (pDC)
pDC->InvertRect(&invertedRect);
if (pDC){
invertedRect.left = point.x -1; invertedRect.right = point.x + 1;
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
m_OldPoint = point;
}
}
}
void CCustomGrid::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
ClipCursor(NULL);
CRect client;
GetClientRect(client);
if(m_nMouseMode == MOUSE_SIZING_COL){
::SetClassLong(GetSafeHwnd(), GCL_HCURSOR, (LONG)AfxGetApp()->LoadStandardCursor(IDC_ARROW));
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
m_nMouseMode = MOUSE_NOTHING;
CRect CellRect = GetScrolledCellRect(0, m_nSizingCol);
if(CellRect.left < point.x - 2 * DEFAULT_TEXTWRAP - 1){
CellRect.right = point.x - 2 * DEFAULT_TEXTWRAP - 1;
m_nColumsWidth.SetAt(m_nSizingCol, CellRect.Width());
}
ResetScrollBars();
}
}
void CCustomGrid::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CPoint Cell = GetScrolledCellFromPT(point);
if(Cell.x >=0 && Cell.y >=0)
SendMessageToParent(Cell.y, Cell.x, GVN_DBCLICK);
}
LRESULT CCustomGrid::OnGetFont(WPARAM, LPARAM)
{
return (LRESULT) (HFONT) m_Font;
}
void CCustomGrid::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (GetFocus()->GetSafeHwnd() != GetSafeHwnd())
SetFocus(); // Auto-destroy any InPlaceEdit's
// Get the scroll position ourselves to ensure we get a 32 bit value
int scrollPos = GetScrollPos32(SB_VERT);
CRect rect;
GetClientRect(rect);
switch (nSBCode)
{
case SB_LINEDOWN:
if (scrollPos < m_nVScrollMax)
{
int yScroll = DEFAULT_LINESCROLL;
yScroll = m_nVScrollMax - scrollPos > abs(yScroll) ? yScroll : m_nVScrollMax - scrollPos;
SetScrollPos32(SB_VERT, scrollPos + yScroll);
rect.top += GetFixedRowHeight() + yScroll + 1;
ScrollWindow( 0, -yScroll, rect);
rect.top = rect.bottom - yScroll;
InvalidateRect(rect, false);
}
break;
case SB_LINEUP:
if (scrollPos > 0)
{
int yScroll = -DEFAULT_LINESCROLL;
yScroll = scrollPos > abs(yScroll) ? yScroll : -scrollPos;
SetScrollPos32(SB_VERT, max(0, scrollPos + yScroll));
rect.top += GetFixedRowHeight() + 1;
ScrollWindow(0, -yScroll, rect);
rect.bottom = rect.top + yScroll;
InvalidateRect(rect, false);
}
break;
case SB_PAGEDOWN:
if (scrollPos < m_nVScrollMax)
{
rect.top = GetFixedRowHeight();
scrollPos = min(m_nVScrollMax, scrollPos + rect.Height());
SetScrollPos32(SB_VERT, scrollPos);
rect.top = GetFixedRowHeight();
InvalidateRect(rect, false);
}
break;
case SB_PAGEUP:
if (scrollPos > 0)
{
rect.top = GetFixedRowHeight();
int offset = -rect.Height();
int pos = max(0, scrollPos + offset);
SetScrollPos32(SB_VERT, pos);
rect.top = GetFixedRowHeight();
InvalidateRect(rect, false);
}
break;
case SB_THUMBPOSITION:
{
int Postion = GetScrollPos32(SB_VERT);
int dPostion = Postion - GetScrollPos32(SB_VERT, TRUE);
SetScrollPos32(SB_VERT, GetScrollPos32(SB_VERT));
rect.top += GetFixedRowHeight();
InvalidateRect(rect, false);
}
break;
case SB_THUMBTRACK:
{
int Postion = GetScrollPos32(SB_VERT);
int dPostion = Postion - GetScrollPos32(SB_VERT, TRUE);
SetScrollPos32(SB_VERT, Postion - dPostion);
rect.top += GetFixedRowHeight();
if(rect.Height() >= dPostion){
// 移动量大于可实际可视范围
}
else if(dPostion > 0){
rect.bottom -= dPostion;
ScrollWindow(0, dPostion, rect);
rect.bottom = rect.top + dPostion;
}
else if(dPostion < 0){
rect.top -= dPostion;
ScrollWindow(0, dPostion, rect);
rect.top = rect.bottom + dPostion;
}
InvalidateRect(rect, false);
}
break;
case SB_TOP:
if (scrollPos > 0)
{
SetScrollPos32(SB_VERT, 0);
Invalidate(false);
}
break;
case SB_BOTTOM:
if (scrollPos < m_nVScrollMax)
{
SetScrollPos32(SB_VERT, m_nVScrollMax);
Invalidate(false);
}
default:
break;
}
}
void CCustomGrid::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (GetFocus()->GetSafeHwnd() != GetSafeHwnd())
SetFocus(); // Auto-destroy any InPlaceEdit's
int scrollPos = GetScrollPos32(SB_HORZ);
CRect rect;
GetClientRect(rect);
switch (nSBCode)
{
case SB_LINERIGHT:
if (scrollPos < m_nHScrollMax)
{
int xScroll = DEFAULT_LINESCROLL;
xScroll = m_nHScrollMax - scrollPos > abs(xScroll) ? xScroll : m_nHScrollMax - scrollPos;
SetScrollPos32(SB_HORZ, scrollPos + xScroll);
rect.left = GetFixedColumnWidth() + xScroll + 1;
ScrollWindow(-xScroll, 0, rect);
rect.left = rect.right - xScroll;
InvalidateRect(rect, false);
}
break;
case SB_LINELEFT:
if (scrollPos > 0)
{
int xScroll = -DEFAULT_LINESCROLL;
xScroll = scrollPos > abs(xScroll) ? xScroll : -scrollPos;
SetScrollPos32(SB_HORZ, scrollPos + xScroll);
rect.left += GetFixedColumnWidth() + 1;
ScrollWindow(-xScroll, 0, rect);
rect.right = rect.left - xScroll;
InvalidateRect(rect, false);
}
break;
case SB_PAGERIGHT:
if (scrollPos < m_nHScrollMax)
{
rect.left += GetFixedColumnWidth();
int offset = rect.Width();
int pos = min(m_nHScrollMax, scrollPos + offset);
SetScrollPos32(SB_HORZ, pos);
rect.left = GetFixedColumnWidth();
InvalidateRect(rect, false);
}
break;
case SB_PAGELEFT:
if (scrollPos > 0)
{
rect.left += GetFixedColumnWidth();
int offset = -rect.Width();
int pos = max(0, scrollPos + offset);
SetScrollPos32(SB_HORZ, pos);
InvalidateRect(rect, false);
}
break;
case SB_THUMBPOSITION:
SetScrollPos32(SB_HORZ, GetScrollPos32(SB_HORZ));
rect.left += GetFixedColumnWidth();
InvalidateRect(rect, false);
break;
case SB_THUMBTRACK:
{
int dPostion = scrollPos - GetScrollPos32(SB_HORZ, TRUE);
SetScrollPos32(SB_HORZ, scrollPos - dPostion);
rect.left += GetFixedColumnWidth();
if(rect.Width() >= dPostion){
// 移动量大于可实际可视范围
}
else if(dPostion > 0){
rect.right -= dPostion;
ScrollWindow(dPostion, 0, rect);
rect.right = rect.left + dPostion;
}
else if(dPostion < 0){
rect.left -= dPostion;
ScrollWindow(dPostion, 0, rect);
rect.left = rect.right + dPostion;
}
InvalidateRect(rect, false);
}
break;
case SB_LEFT:
if (scrollPos > 0)
{
SetScrollPos32(SB_HORZ, 0);
Invalidate(false);
}
break;
case SB_RIGHT:
if (scrollPos < m_nHScrollMax)
{
SetScrollPos32(SB_HORZ, m_nHScrollMax);
Invalidate(false);
}
break;
default:
break;
}
}
void CCustomGrid::OnPaint()
{
CPaintDC dc1(this); // device context for painting
CMemDC dc(&dc1);
CRect rect, clientrect;
GetClientRect(&clientrect);
dc.GetClipBox(&rect);
int nLeftPos, nRightPos;
int nLeftColum, nRightColum;
//计算滚动后更新区域中包含列的最小值(最左边的列)
nLeftPos = -GetScrollPos32(SB_HORZ);
for(nLeftColum = 0; nLeftColum < m_nColums; nLeftColum++){
if(nLeftPos <= rect.right && nLeftPos + m_nColumsWidth[nLeftColum] + 2 * DEFAULT_TEXTWRAP + 1 >= rect.left)
break;
nLeftPos += m_nColumsWidth[nLeftColum] + 2 * DEFAULT_TEXTWRAP + 1;
}
//计算滚动后更新区域中包含列的最大值(最右边的列)
nRightPos = nLeftPos;
nLeftPos += DEFAULT_TEXTWRAP + 1;
for(nRightColum = nLeftColum; nRightColum < m_nColums; nRightColum++){
if(nRightPos + m_nColumsWidth[nRightColum] + 2 * DEFAULT_TEXTWRAP + 1 >= rect.right)
break;
nRightPos += m_nColumsWidth[nRightColum] + 2 * DEFAULT_TEXTWRAP + 1;
}
nRightPos += DEFAULT_TEXTWRAP + 1;
if(nRightColum == m_nColums){
nRightColum = m_nColums - 1;
}
int nTopPos, nBottomPos;
int nTopRow, nBottomRow;
//计算滚动后更新区域中包含的最小行
nTopPos = -GetScrollPos32(SB_VERT);
for(nTopRow = 0; nTopRow < m_nRows; nTopRow++){
if(nTopPos < rect.bottom && nTopPos * m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1 >= rect.top)
break;
nTopPos += m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1;
}
//计算滚动后更新区域中包含的最大行
nBottomPos = nTopPos;
nTopPos += DEFAULT_TEXTWRAP + 1;
for(nBottomRow = nTopRow; nBottomRow < m_nRows; nBottomRow++){
if(nBottomPos + m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1 >= rect.bottom)
break;
nBottomPos += m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1;
}
nBottomPos += DEFAULT_TEXTWRAP + 1;
if(nBottomRow == m_nRows){
nBottomRow = m_nRows - 1;
}
//上述4部分计算获得更新区域中需要更新的表格范围
// 以下程序显示表格
int i, j;
CRect rect1;
// 显示表格可滚动部分
rect1.left = nLeftPos;
for(i = nLeftColum; i <= nRightColum; i++){
rect1.right = rect1.left + m_nColumsWidth[i];
rect1.top = nTopPos;
for(j = nTopRow; j <= nBottomRow; j++){
rect1.bottom = rect1.top + m_nFontHeight;
DrawCell(&dc, j, i, rect1);
rect1.top = rect1.bottom + 2 * DEFAULT_TEXTWRAP + 1;
}
rect1.left = rect1.right + 2 * DEFAULT_TEXTWRAP + 1;
}
//画可滚动部分表格线
rect1.left = nLeftPos - DEFAULT_TEXTWRAP - 1;
rect1.bottom = clientrect.Height() < GetVirtualHeight() ? clientrect.Height() : GetVirtualHeight()+1;
dc.MoveTo(rect1.left, clientrect.top);//竖线
dc.LineTo(rect1.left, rect1.bottom);
for(i = nLeftColum; i <= nRightColum ; i++){
rect1.left += m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1;
dc.MoveTo(rect1.left, clientrect.top);//竖线
dc.LineTo(rect1.left, rect1.bottom);
}
rect1.top = nTopPos - DEFAULT_TEXTWRAP - 1;
rect1.right = clientrect.Width() < GetVirtualWidth() ? clientrect.Width() : GetVirtualWidth();
dc.MoveTo(clientrect.left, rect1.top);//横线
dc.LineTo(rect1.right, rect1.top);
for(j = nTopRow; j <= nBottomRow; j++){
rect1.top += m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1;
dc.MoveTo(clientrect.left, rect1.top);//横线
dc.LineTo(rect1.right, rect1.top);
}
// 显示表格固定列
if(GetFixedColumnWidth() > rect.left && m_nFixedColums <= m_nColums){
rect1.left = DEFAULT_TEXTWRAP + 1;
for(i = 0; i < m_nFixedColums; i++){
rect1.right = rect1.left + m_nColumsWidth[i];
rect1.top = nTopPos;
for(j = nTopRow; j <= nBottomRow; j++){
rect1.bottom = rect1.top + m_nFontHeight;
DrawFixedCell(&dc, j, i, rect1);
rect1.top = rect1.bottom + 2 * DEFAULT_TEXTWRAP + 1;
}
rect1.left = rect1.right + 2 * DEFAULT_TEXTWRAP + 1;
}
}
// 显示表格固定行
if(GetFixedRowHeight() > rect.top && m_nFixedRows <= m_nRows){
rect1.left = nLeftPos;
for(i = nLeftColum; i <= nRightColum; i++){
rect1.top = DEFAULT_TEXTWRAP+1;
rect1.right = rect1.left + m_nColumsWidth.GetAt(i);
for(j = 0; j < m_nFixedRows; j++){
rect1.bottom = rect1.top + m_nFontHeight;
DrawFixedCell(&dc, j, i, rect1);
rect1.top = rect1.bottom + 2 * DEFAULT_TEXTWRAP + 1;
}
rect1.left = rect1.right + 2 * DEFAULT_TEXTWRAP + 1;
}
}
// 显示表格左上角(行、列均固定的单元)
if(GetFixedRowHeight() > rect.top && GetFixedColumnWidth() > rect.left){
for( i = 0; i < m_nFixedRows; i++ ){
rect1.left = DEFAULT_TEXTWRAP + 1;
rect1.top = i * (m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1) + DEFAULT_TEXTWRAP+1;
rect1.bottom = rect1.top + m_nFontHeight;
for(j = 0; j < m_nFixedColums; j++){
rect1.right = rect1.left + m_nColumsWidth[j];
DrawFixedCell(&dc, i, j, rect1);
rect1.left = rect1.right + 2 * DEFAULT_TEXTWRAP + 1;
}
}
}
//画表格固定行中的横线
if(GetFixedRowHeight() > rect.top){
rect1.top = - DEFAULT_TEXTWRAP - 1;
for(i = 1; i< m_nFixedRows; i++){
dc.MoveTo(clientrect.left, rect1.top);//横线
dc.LineTo(clientrect.right, rect1.top);
rect1.top += m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1;
}
}
//画表格固定列中的竖线
if(GetFixedColumnWidth() > rect.left){
rect1.left = - DEFAULT_TEXTWRAP - 1;
for(i = 1; i < m_nFixedColums; i++){
dc.MoveTo(rect1.left, clientrect.top);//竖线
dc.LineTo(rect1.left, clientrect.bottom);
rect1.left += m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1;
}
}
rect1.right = clientrect.Width() < GetVirtualWidth() ? clientrect.Width() : GetVirtualWidth();
rect1.bottom = clientrect.Height() < GetVirtualHeight() ? clientrect.Height() : GetVirtualHeight();
//画可滚动部分与固定部分的分割线
dc.MoveTo(clientrect.left, GetFixedRowHeight());//横线
dc.LineTo(rect1.right, GetFixedRowHeight());
dc.MoveTo(GetFixedColumnWidth(), clientrect.top);//竖线
dc.LineTo(GetFixedColumnWidth(), rect1.bottom);
//画表格边框
dc.MoveTo(clientrect.left, rect1.bottom);
dc.LineTo(clientrect.left, clientrect.top);
dc.LineTo(rect1.right, clientrect.top);
}
void CCustomGrid::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
ResetScrollBars();
}
void CCustomGrid::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
SetItemFont();
CWnd::PreSubclassWindow();
}
void CCustomGrid::OnModifyEditCell(NMHDR* pNMHDR, LRESULT* pResult)
{
NMHDR32* pNmhdr32 = (NMHDR32*)pNMHDR;
SetItemString(pNmhdr32->nRow, pNmhdr32->nCol, pNmhdr32->strText);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -