leocad/win/terrctrl.cpp

1850 lines
43 KiB
C++

#include "lc_global.h"
#include "LeoCAD.h"
#include "TerrCtrl.h"
#include "IPEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define IDC_INPLACE_EDIT 8 // ID of inplace edit control
#define GRIDSIZE 28
#define ControlPoint(row, col) m_pControl[row-1][(col-1)*3+2]
#define GetFixedRowHeight() GRIDSIZE
#define GetFixedColumnWidth() GRIDSIZE
#define m_nFixedRows 1
#define m_nFixedCols 1
#define GetRowHeight(a) GRIDSIZE
#define GetColumnWidth(a) GRIDSIZE
#define GetVirtualWidth() m_nCols*GRIDSIZE
#define GetVirtualHeight() m_nRows*GRIDSIZE
#define m_nMargin 1
#define GetFixedRowCount() 1
#define GetFixedColumnCount() 1
#define GetColumnCount() m_nCols
#define GetRowCount() m_nRows
/////////////////////////////////////////////////////////////////////////////
// CTerrainCtrl
CTerrainCtrl::CTerrainCtrl()
{
RegisterWindowClass();
m_nRows = 0;
m_nCols = 0;
m_nVScrollMax = 0; // Scroll position
m_nHScrollMax = 0;
m_MouseMode = MOUSE_NOTHING;
m_pControl = NULL;
/*
m_nMargin = 0; // cell padding
m_nRowsPerWheelNotch = GetMouseScrollLines(); // Get the number of lines
// per mouse wheel notch to scroll
m_bHandleTabKey = TRUE;
m_bTitleTips = TRUE; // show cell title tips
m_nTimerID = 0; // For drag-selection
m_nTimerInterval = 25; // (in milliseconds)
m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
m_crGridColour = RGB(0,0,0);
SetTextColor(m_crWindowText);
SetBkColor(m_crShadow);
SetTextBkColor(RGB(0xFF, 0xFF, 0xE0));
*/
// Set the colours
m_crFixedBkColour = GetSysColor(COLOR_3DFACE);
m_crFixedTextColour = GetSysColor(COLOR_WINDOWTEXT);
m_crTextBkColour = GetSysColor(COLOR_WINDOW);
// Initially use the system message font for the GridCtrl font
NONCLIENTMETRICS ncm;
LOGFONT lf;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
memcpy(&lf, &(ncm.lfMessageFont), sizeof(LOGFONT));
// lf.lfWeight = SELECTED_CELL_FONT_WEIGHT;
m_Font.CreateFontIndirect(&lf);
// Set up the initial grid size
SetRowCount(5);
SetColumnCount(5);
/*
// set initial selection range (ie. none)
m_SelectedCellMap.RemoveAll();
m_PrevSelectedCellMap.RemoveAll();
*/
}
CTerrainCtrl::~CTerrainCtrl()
{
/*
DeleteAllItems();
*/
DestroyWindow();
m_Font.DeleteObject();
}
// Register the window class if it has not already been registered.
BOOL CTerrainCtrl::RegisterWindowClass()
{
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetResourceHandle();
if (!(::GetClassInfo(hInst, TERRAINCTRL_CLASSNAME, &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = TERRAINCTRL_CLASSNAME;
if (!AfxRegisterClass(&wndcls)) {
AfxThrowResourceException();
return FALSE;
}
}
return TRUE;
}
BEGIN_MESSAGE_MAP(CTerrainCtrl, CWnd)
//{{AFX_MSG_MAP(CTerrainCtrl)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_GETDLGCODE()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_KEYDOWN()
ON_WM_CHAR()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_GETFONT, OnGetFont)
ON_MESSAGE(WM_LC_EDIT_CLOSED, OnEditClosed)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTerrainCtrl message handlers
BOOL CTerrainCtrl::Create(const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwStyle)
{
ASSERT(pParentWnd->GetSafeHwnd());
if (!CWnd::Create(TERRAINCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID))
return FALSE;
// Create titletips
#ifdef GRIDCONTROL_USE_TITLETIPS
if (m_bTitleTips)
m_TitleTip.Create(this);
#endif
ResetScrollBars();
return TRUE;
}
void CTerrainCtrl::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
/*
HFONT hFont = ::CreateFontIndirect(&m_Logfont);
OnSetFont((LPARAM)hFont, 0);
DeleteObject(hFont);
*/
ResetScrollBars();
}
BOOL CTerrainCtrl::SubclassWindow(HWND hWnd)
{
if (!CWnd::SubclassWindow(hWnd))
return FALSE;
#ifdef GRIDCONTROL_USE_TITLETIPS
if (m_bTitleTips && !IsWindow(m_TitleTip.m_hWnd))
m_TitleTip.Create(this);
#endif
return TRUE;
}
LRESULT CTerrainCtrl::OnGetFont(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
return (LRESULT) (HFONT) m_Font;
}
void CTerrainCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CDC MemDC;
CRect rect;
CBitmap bitmap, *pOldBitmap;
dc.GetClipBox(&rect);
MemDC.CreateCompatibleDC(&dc);
bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
pOldBitmap = MemDC.SelectObject(&bitmap);
MemDC.SetWindowOrg(rect.left, rect.top);
OnDraw(&MemDC);
dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &MemDC, rect.left, rect.top, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
}
BOOL CTerrainCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE; // Don't erase the background.
}
// Custom background erasure. This gets called from within the OnDraw function,
// since we will (most likely) be using a memory DC to stop flicker. If we just
// erase the background normally through OnEraseBkgnd, and didn't fill the memDC's
// selected bitmap with colour, then all sorts of vis problems would occur
void CTerrainCtrl::EraseBkgnd(CDC* pDC)
{
CRect VisRect, ClipRect, rect;
CBrush FixedBack(m_crFixedBkColour), TextBack(m_crTextBkColour);
if (pDC->GetClipBox(ClipRect) == ERROR)
return;
int nFixedColumnWidth = GetFixedColumnWidth();
int nFixedRowHeight = GetFixedRowHeight();
GetClientRect(VisRect);
VisRect.top = nFixedRowHeight;
VisRect.left = nFixedColumnWidth;
// Draw Fixed columns background
if (ClipRect.left < nFixedColumnWidth && ClipRect.top < VisRect.bottom)
pDC->FillRect(CRect(ClipRect.left, ClipRect.top, nFixedColumnWidth, VisRect.bottom),
&FixedBack);
// Draw Fixed rows background
if (ClipRect.top < nFixedRowHeight &&
ClipRect.right > nFixedColumnWidth && ClipRect.left < VisRect.right)
pDC->FillRect(CRect(nFixedColumnWidth-1, ClipRect.top, VisRect.right, nFixedRowHeight),
&FixedBack);
// Draw non-fixed cell background
if (rect.IntersectRect(VisRect, ClipRect))
{
CRect CellRect(max(nFixedColumnWidth, rect.left), max(nFixedRowHeight, rect.top),
rect.right, rect.bottom);
pDC->FillRect(CellRect, &TextBack);
}
}
void CTerrainCtrl::OnSize(UINT nType, int cx, int cy)
{
if (::IsWindow(GetSafeHwnd()) && GetFocus()->GetSafeHwnd() != GetSafeHwnd())
SetFocus(); // Auto-destroy any InPlaceEdit's
CWnd::OnSize(nType, cx, cy);
ResetScrollBars();
}
UINT CTerrainCtrl::OnGetDlgCode()
{
UINT nCode = DLGC_WANTARROWS | DLGC_WANTCHARS;
/*
if (m_bHandleTabKey && !IsCTRLpressed())
nCode |= DLGC_WANTTAB;
*/
return nCode;
}
// wParam = key pressed, lParam = modified
LRESULT CTerrainCtrl::OnEditClosed(WPARAM wParam, LPARAM lParam)
{
// In case OnEndInPlaceEdit called as window is being destroyed
if (!IsWindow(GetSafeHwnd()))
return TRUE;
// Only set as modified if it actually was, and ESC was not hit.
if ((wParam != VK_ESCAPE) && (lParam == TRUE))
{
CWnd* pParent = GetOwner();
if (pParent)
pParent->SendMessage(WM_LC_EDIT_CLOSED);
// SetModified(TRUE);
}
switch (wParam)
{
case VK_DOWN:
case VK_UP:
case VK_RIGHT:
case VK_LEFT:
case VK_NEXT:
case VK_PRIOR:
case VK_HOME:
case VK_END:
OnKeyDown(wParam, 0, 0);
EditCell(m_idCurrentCell.row, m_idCurrentCell.col, wParam);
}
return TRUE;
}
// Handle horz scrollbar notifications
void CTerrainCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (GetFocus()->GetSafeHwnd() != GetSafeHwnd())
SetFocus(); // Auto-destroy any InPlaceEdit's
#ifdef GRIDCONTROL_USE_TITLETIPS
m_TitleTip.Hide(); // hide any titletips
#endif
int scrollPos = GetScrollPos32(SB_HORZ);
CELLID idTopLeft = GetTopleftNonFixedCell();
CRect rect;
GetClientRect(rect);
switch (nSBCode)
{
case SB_LINERIGHT:
if (scrollPos < m_nHScrollMax)
{
int xScroll = GetColumnWidth(nTopLeftCol);
SetScrollPos32(SB_HORZ, scrollPos + xScroll);
if (GetScrollPos32(SB_HORZ) == scrollPos)
break; // didn't work
rect.left = GetFixedColumnWidth() + xScroll;
ScrollWindow(-xScroll, 0, rect);
rect.left = rect.right - xScroll;
InvalidateRect(rect);
} break;
case SB_LINELEFT:
if (scrollPos > 0 && idTopLeft.col > GetFixedColumnCount())
{
int xScroll = GetColumnWidth(nTopLeftCol-1);
SetScrollPos32(SB_HORZ, max(0,scrollPos - xScroll));
rect.left = GetFixedColumnWidth();
ScrollWindow(xScroll, 0, rect);
rect.right = rect.left + xScroll;
InvalidateRect(rect);
} 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);
} break;
case SB_PAGELEFT:
if (scrollPos > 0)
{
rect.left = GetFixedColumnWidth();
int offset = -rect.Width();
int pos = max(0, scrollPos + offset);
SetScrollPos32(SB_HORZ, pos);
rect.left = GetFixedColumnWidth();
InvalidateRect(rect);
} break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
SetScrollPos32(SB_HORZ, GetScrollPos32(SB_HORZ, TRUE));
rect.left = GetFixedColumnWidth();
InvalidateRect(rect);
} break;
case SB_LEFT:
if (scrollPos > 0)
{
SetScrollPos32(SB_HORZ, 0);
Invalidate();
} break;
case SB_RIGHT:
if (scrollPos < m_nHScrollMax)
{
SetScrollPos32(SB_HORZ, m_nHScrollMax);
Invalidate();
} break;
}
}
// Handle vert scrollbar notifications
void CTerrainCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (GetFocus()->GetSafeHwnd() != GetSafeHwnd())
SetFocus(); // Auto-destroy any InPlaceEdit's
#ifdef GRIDCONTROL_USE_TITLETIPS
m_TitleTip.Hide(); // hide any titletips
#endif
// Get the scroll position ourselves to ensure we get a 32 bit value
int scrollPos = GetScrollPos32(SB_VERT);
CELLID idTopLeft = GetTopleftNonFixedCell();
CRect rect;
GetClientRect(rect);
switch (nSBCode)
{
case SB_LINEDOWN:
if (scrollPos < m_nVScrollMax)
{
int yScroll = GetRowHeight(nTopLeftRow);
SetScrollPos32(SB_VERT, scrollPos + yScroll);
if (GetScrollPos32(SB_VERT) == scrollPos)
break; // didn't work
rect.top = GetFixedRowHeight() + yScroll;
ScrollWindow( 0, -yScroll, rect);
rect.top = rect.bottom - yScroll;
InvalidateRect(rect);
} break;
case SB_LINEUP:
if (scrollPos > 0 && idTopLeft.row > GetFixedRowCount())
{
int yScroll = GetRowHeight(nTopLeftRow-1);
SetScrollPos32(SB_VERT, max(0, scrollPos - yScroll));
rect.top = GetFixedRowHeight();
ScrollWindow(0, yScroll, rect);
rect.bottom = rect.top + yScroll;
InvalidateRect(rect);
} 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);
} 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);
} break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
SetScrollPos32(SB_VERT, GetScrollPos32(SB_VERT, TRUE));
rect.top = GetFixedRowHeight();
InvalidateRect(rect);
} break;
case SB_TOP:
if (scrollPos > 0)
{
SetScrollPos32(SB_VERT, 0);
Invalidate();
} break;
case SB_BOTTOM:
if (scrollPos < m_nVScrollMax)
{
SetScrollPos32(SB_VERT, m_nVScrollMax);
Invalidate();
}
}
}
void CTerrainCtrl::OnDraw(CDC* pDC)
{
int row,col;
CRect clientRect;
GetClientRect(clientRect);
CRect clipRect;
if (pDC->GetClipBox(&clipRect) == ERROR)
return;
// OnEraseBkgnd does nothing, so erase bkgnd here.
// This necessary since we may be using a Memory DC.
EraseBkgnd(pDC);
int nFixedRowHeight = GetFixedRowHeight();
int nFixedColWidth = GetFixedColumnWidth();
CELLID idTopLeft = GetTopleftNonFixedCell();
/*
CRect VisRect;
CCellRange VisCellRange = GetVisibleNonFixedCellRange(VisRect);
int maxVisibleRow = VisCellRange.GetMaxRow(),
maxVisibleCol = VisCellRange.GetMaxCol();
*/
// calc bottom
int i, bottom = GetFixedRowHeight();
for (i = idTopLeft.row; i < m_nRows; i++)
{
bottom += GetRowHeight(i);
if (bottom >= clientRect.bottom)
{
bottom = clientRect.bottom;
break;
}
}
int maxVisibleRow = min(i, m_nRows - 1);
// calc right
int right = GetFixedColumnWidth();
for (i = idTopLeft.col; i < m_nCols; i++)
{
right += GetColumnWidth(i);
if (right >= clientRect.right)
{
right = clientRect.right;
break;
}
}
int maxVisibleCol = min(i, m_nCols - 1);
// draw top-left cell
CRect rect;
rect.top = 0;
rect.bottom = GetRowHeight(0)-1;
rect.left = 0;
rect.right = GetColumnWidth(0)-1;
DrawFixedCell(pDC, 0, 0, rect);
// draw fixed column cells
rect.bottom = nFixedRowHeight-1;
for (row = idTopLeft.row; row <= maxVisibleRow; row++)
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
// rect.bottom = bottom pixel of previous row
if (rect.top > clipRect.bottom) break; // Gone past cliprect
if (rect.bottom < clipRect.top) continue; // Reached cliprect yet?
rect.left = 0;
rect.right = GetColumnWidth(0)-1;
if (rect.left > clipRect.right) break; // gone past cliprect
if (rect.right < clipRect.left) continue; // Reached cliprect yet?
DrawFixedCell(pDC, row, 0, rect);
}
// draw end of column
if (rect.bottom < clientRect.bottom)
{
rect.top = rect.bottom+1;
rect.bottom = clientRect.bottom-1;
if (rect.top < clipRect.bottom)
if (rect.bottom > clipRect.top)
if (rect.left < clipRect.right)
if (rect.right > clipRect.left)
DrawFixedCell(pDC, 0, 0, rect);
}
// draw fixed row cells 0..m_nFixedRows, m_nFixedCols..n
rect.top = 0;
rect.bottom = GetRowHeight(0)-1;
// rect.bottom = bottom pixel of previous row
if (rect.top < clipRect.bottom) // Gone past cliprect
if (rect.bottom > clipRect.top) // Reached cliprect yet?
{
rect.right = nFixedColWidth-1;
for (col = idTopLeft.col; col <= maxVisibleCol; col++)
{
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
if (rect.left > clipRect.right) break; // gone past cliprect
if (rect.right < clipRect.left) continue; // Reached cliprect yet?
DrawFixedCell(pDC, 0, col, rect);
}
}
// draw end of row
if (rect.right < clientRect.right)
{
rect.left = rect.right+1;
rect.right = clientRect.right - 1;
if (rect.top < clipRect.bottom)
if (rect.bottom > clipRect.top)
if (rect.left < clipRect.right)
if (rect.right > clipRect.left)
DrawFixedCell(pDC, 0, 0, rect);
}
// draw rest of non-fixed cells
rect.bottom = nFixedRowHeight-1;
for (row = idTopLeft.row; row <= maxVisibleRow; row++)
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
// rect.bottom = bottom pixel of previous row
if (rect.top > clipRect.bottom) break; // Gone past cliprect
if (rect.bottom < clipRect.top) continue; // Reached cliprect yet?
rect.right = nFixedColWidth-1;
for (col = idTopLeft.col; col <= maxVisibleCol; col++)
{
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
if (rect.left > clipRect.right) break; // gone past cliprect
if (rect.right < clipRect.left) continue; // Reached cliprect yet?
DrawCell(pDC, row, col, rect);
}
}
}
// Get/Set scroll position using 32 bit functions
int CTerrainCtrl::GetScrollPos32(int nBar, BOOL bGetTrackPos /* = FALSE */)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
if (bGetTrackPos)
{
if (GetScrollInfo(nBar, &si, SIF_TRACKPOS))
return si.nTrackPos;
}
else
{
if (GetScrollInfo(nBar, &si, SIF_POS))
return si.nPos;
}
return 0;
}
BOOL CTerrainCtrl::SetScrollPos32(int nBar, int nPos, BOOL bRedraw /* = TRUE */)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = nPos;
return SetScrollInfo(nBar, &si, bRedraw);
}
void CTerrainCtrl::ResetScrollBars()
{
if (!::IsWindow(GetSafeHwnd()))
return;
CRect rect;
GetClientRect(rect);
rect.left += GetFixedColumnWidth();
rect.top += GetFixedRowHeight();
if (rect.left >= rect.right || rect.top >= rect.bottom)
return;
CRect VisibleRect(GetFixedColumnWidth(), GetFixedRowHeight(), rect.right, rect.bottom);
CRect VirtualRect(GetFixedColumnWidth(), GetFixedRowHeight(), GetVirtualWidth(), GetVirtualHeight());
/*
CCellRange visibleCells = GetUnobstructedNonFixedCellRange();
if (!IsValid(visibleCells)) return;
*/
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE;
si.nPage = VisibleRect.Width();
SetScrollInfo(SB_HORZ, &si, FALSE);
si.nPage = VisibleRect.Height();
SetScrollInfo(SB_VERT, &si, FALSE);
if (VisibleRect.Height() < VirtualRect.Height())
m_nVScrollMax = VirtualRect.Height()-1;//-VisibleRect.Height();//+GetRowHeight(0);
else
m_nVScrollMax = 0;
if (VisibleRect.Width() < VirtualRect.Width())
m_nHScrollMax = VirtualRect.Width()-1;//-VisibleRect.Width();//+GetColumnWidth(0);
else
m_nHScrollMax = 0;
ASSERT(m_nVScrollMax < INT_MAX && m_nHScrollMax < INT_MAX); // This should be fine :)
SetScrollRange(SB_VERT, 0, m_nVScrollMax, TRUE);
SetScrollRange(SB_HORZ, 0, m_nHScrollMax, TRUE);
}
BOOL CTerrainCtrl::DrawFixedCell(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBk)
{
if (bEraseBk)
{
CBrush brush(m_crFixedBkColour);
pDC->FillRect(rect, &brush);
}
pDC->SetTextColor(m_crFixedTextColour);
int nSavedDC = pDC->SaveDC();
/*
// Create the appropriate font and select into DC
LOGFONT lf, *pLF = GetItemFont(nRow, nCol);
if (pLF)
memcpy(&lf, pLF, sizeof(LOGFONT));
else
memcpy(&lf, &m_Logfont, sizeof(LOGFONT));
CCellID FocusCell = GetFocusCell();
if (FocusCell.row == nRow || FocusCell.col == nCol)
lf.lfWeight = SELECTED_CELL_FONT_WEIGHT;
CFont Font;
Font.CreateFontIndirect(&lf);
pDC->SelectObject(&Font);
if (IsValid(FocusCell) && (FocusCell.row == nRow || FocusCell.col == nCol))
{
rect.right++; rect.bottom++;
pDC->DrawEdge(rect, EDGE_RAISED, BF_RECT);
rect.DeflateRect(1,1);
}
else
*/ {
CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)),
darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)),
*pOldPen = pDC->GetCurrentPen();
pDC->SelectObject(&lightpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.left, rect.top);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(&darkpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(pOldPen);
rect.DeflateRect(1,1);
}
pDC->SetBkMode(TRANSPARENT);
rect.DeflateRect(m_nMargin, 0);
if ((nRow != 0 || nCol != 0) && nRow < m_nRows && nCol < m_nCols)
{
char szText[10];
sprintf(szText, "%d", nRow == 0 ? nCol : nRow);
DrawText(pDC->m_hDC, szText, -1, rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
pDC->RestoreDC(nSavedDC);
return TRUE;
}
BOOL CTerrainCtrl::DrawCell(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBk)
{
COLORREF TextClr = m_crFixedTextColour;
int nSavedDC = pDC->SaveDC();
pDC->SetBkMode(TRANSPARENT);
if (m_RowData[nRow][nCol].state & GS_FOCUSED)
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
if (bEraseBk)
{
CBrush brush(m_crTextBkColour);
pDC->FillRect(rect, &brush);
}
rect.right--; rect.bottom--;
pDC->SelectStockObject(BLACK_PEN);
pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(rect);
pDC->SetTextColor(TextClr);
rect.DeflateRect(1,1);
}
else if (m_RowData[nRow][nCol].state & GS_SELECTED)
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
rect.right--; rect.bottom--;
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
if (bEraseBk)
{
CBrush brush(m_crTextBkColour);
pDC->FillRect(rect, &brush);
}
rect.right--; rect.bottom--;
pDC->SetTextColor(TextClr);
}
/*
if (Item.state & GVIS_DROPHILITED)
{
pDC->SelectStockObject(BLACK_PEN);
pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(rect);
}
*/
CPen lightpen(PS_SOLID, 1, RGB(0xE0, 0xE0, 0xE0)),
darkpen(PS_SOLID, 1, RGB(0,0,0)),
*pOldPen = pDC->GetCurrentPen();
int left = nCol == 1 ? GRIDSIZE/2-1 : 0;
int top = nRow == 1 ? GRIDSIZE/2-1 : 0;
int right = nCol == m_nCols-1 ? GRIDSIZE/2-1 : -1;
int bottom = nRow == m_nRows-1 ? GRIDSIZE/2-1 : -1;
if ((nRow-1) % 3)
{
pDC->SelectObject(&lightpen);
pDC->MoveTo(rect.left + left, (rect.top + rect.bottom)/2);
pDC->LineTo(rect.right - right, (rect.top + rect.bottom)/2);
}
if ((nCol-1) % 3)
{
pDC->SelectObject(&lightpen);
pDC->MoveTo((rect.left + rect.right)/2, rect.top + top);
pDC->LineTo((rect.left + rect.right)/2, rect.bottom - bottom);
}
if ((nRow-1) % 3 == 0)
{
pDC->SelectObject(&darkpen);
pDC->MoveTo(rect.left + left, (rect.top + rect.bottom)/2);
pDC->LineTo(rect.right - right, (rect.top + rect.bottom)/2);
}
if ((nCol-1) % 3 == 0)
{
pDC->SelectObject(&darkpen);
pDC->MoveTo((rect.left + rect.right)/2, rect.top + top);
pDC->LineTo((rect.left + rect.right)/2, rect.bottom - bottom);
}
pDC->SelectObject(pOldPen);
/* // Create the appropriate font and select into DC
CFont Font;
LOGFONT *pLF = GetItemFont(nRow, nCol);
if (pLF)
Font.CreateFontIndirect(pLF);
else
Font.CreateFontIndirect(&m_Logfont);
*/
CFont *pOldFont = pDC->SelectObject(&m_Font);
rect.DeflateRect(m_nMargin, 0);
rect.OffsetRect(GRIDSIZE/2, GRIDSIZE/4+2);
char szText[10];
sprintf(szText, "%.0f", ControlPoint(nRow, nCol));
DrawText(pDC->m_hDC, szText, -1, rect, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
pDC->SelectObject(pOldFont);
pDC->RestoreDC(nSavedDC);
return TRUE;
}
BOOL CTerrainCtrl::SetRowCount(int nRows)
{
ASSERT(nRows > 0);
if (nRows == m_nRows)
return TRUE;
if (m_idCurrentCell.row >= nRows)
SetFocusCell(-1,-1);
int addedRows = nRows - m_nRows;
// Change the number of rows.
m_nRows = nRows;
m_RowData.SetSize(m_nRows);
// If we have just added rows, we need to construct new elements for each cell
// and set the default row height
if (addedRows > 0)
{
// initialize row heights and data
int startRow = nRows - addedRows;
for (int row = startRow; row < m_nRows; row++)
{
m_RowData[row].SetSize(m_nCols);
for (int col = 0; col < m_nCols; col++)
m_RowData[row][col].state = 0;
}
}
if (GetSafeHwnd())
{
ResetScrollBars();
Invalidate();
}
return TRUE;
}
BOOL CTerrainCtrl::SetColumnCount(int nCols)
{
ASSERT(nCols > 0);
if (nCols == m_nCols)
return TRUE;
if (m_idCurrentCell.col >= nCols)
SetFocusCell(-1,-1);
int addedCols = nCols - m_nCols;
// Change the number of columns.
m_nCols = nCols;
// Change the number of columns in each row.
for (int i = 0; i < m_nRows; i++)
m_RowData[i].SetSize(nCols);
// If we have just added columns, we need to construct new elements for each cell
// and set the default column width
if (addedCols > 0)
{
int startCol = nCols - addedCols;
for (int row = 0; row < m_nRows; row++)
for (int col = startCol; col < m_nCols; col++)
m_RowData[row][col].state = 0;
}
if (GetSafeHwnd())
{
ResetScrollBars();
Invalidate();
}
return TRUE;
}
CELLID CTerrainCtrl::GetTopleftNonFixedCell()
{
CELLID cell;
int nVertScroll = GetScrollPos(SB_VERT), nHorzScroll = GetScrollPos(SB_HORZ);
int nColumn = m_nFixedCols, nRight = 0;
while (nRight < nHorzScroll && nColumn < (m_nCols-1))
{
nColumn++;
nRight += GetColumnWidth(nColumn);
}
int nRow = m_nFixedRows, nTop = 0;
while (nTop < nVertScroll && nRow < (m_nRows-1))
{
nRow++;
nTop += GetRowHeight(nRow);
}
cell.row = nRow;
cell.col = nColumn;
return cell;
}
void CTerrainCtrl::SetControlPoints(int uCount, int vCount, float** pControl)
{
SetRowCount(uCount+1);
SetColumnCount(vCount+1);
m_pControl = pControl;
InvalidateRect(NULL, FALSE);
}
void CTerrainCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
/*
HWND hOldFocusWnd = ::GetFocus();
*/
m_LeftClickDownPoint = point;
m_LeftClickDownCell = GetCellFromPt(point);
if (!IsValid(m_LeftClickDownCell))
return;
/*
m_SelectionStartCell = (nFlags & MK_SHIFT)? m_idCurrentCell : m_LeftClickDownCell;
*/
SetFocus(); // Auto-destroy any InPlaceEdit's
// If the user clicks on the current cell, then prepare to edit it.
// (If the user moves the mouse, then dragging occurs)
if (m_LeftClickDownCell == m_idCurrentCell)
{
m_MouseMode = MOUSE_PREPARE_EDIT;
return;
}
else
{
SetFocusCell(-1,-1);
SetFocusCell(max(m_LeftClickDownCell.row, 1),
max(m_LeftClickDownCell.col, 1));
}
/*
// If the user clicks on a selected cell, then prepare to drag it.
// (If the user moves the mouse, then dragging occurs)
if (m_bAllowDragAndDrop && hOldFocusWnd == GetSafeHwnd() &&
GetItemState(m_LeftClickDownCell.row, m_LeftClickDownCell.col) & GVNI_SELECTED)
{
m_MouseMode = MOUSE_PREPARE_DRAG;
return;
}
*/
SetCapture();
// If Ctrl pressed, save the current cell selection. This will get added
/* // to the new cell selection at the end of the cell selection process
m_PrevSelectedCellMap.RemoveAll();
if (nFlags & MK_CONTROL)
{
for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
m_PrevSelectedCellMap.SetAt(key, cell);
}
}
if (m_LeftClickDownCell.row < GetFixedRowCount())
OnFixedRowClick(m_LeftClickDownCell);
else if (m_LeftClickDownCell.col < GetFixedColumnCount())
OnFixedColumnClick(m_LeftClickDownCell);
else
{
m_MouseMode = m_bListMode? MOUSE_SELECT_ROW : MOUSE_SELECT_CELLS;
OnSelecting(m_LeftClickDownCell);
}
m_nTimerID = SetTimer(WM_LBUTTONDOWN, m_nTimerInterval, 0);
m_LastMousePoint = point;
*/
}
void CTerrainCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
CWnd::OnLButtonUp(nFlags, point);
ClipCursor(NULL);
if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
{
ReleaseCapture();
/* KillTimer(m_nTimerID);
m_nTimerID = 0;
*/ }
// m_MouseMode == MOUSE_PREPARE_EDIT only if user clicked down on current cell
// and then didn't move mouse before clicking up (releasing button)
if (m_MouseMode == MOUSE_PREPARE_EDIT)
{
EditCell(m_idCurrentCell.row, m_idCurrentCell.col, VK_LBUTTON);
}
// m_MouseMode == MOUSE_PREPARE_DRAG only if user clicked down on a selected cell
/* // and then didn't move mouse before clicking up (releasing button)
else if (m_MouseMode == MOUSE_PREPARE_DRAG)
{
ResetSelectedRange();
}
*/
m_MouseMode = MOUSE_NOTHING;
SetCursor(::LoadCursor(NULL, IDC_ARROW));
if (!IsValid(m_LeftClickDownCell))
return;
/*
CWnd *pOwner = GetOwner();
if (pOwner && IsWindow(pOwner->m_hWnd))
pOwner->PostMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), BN_CLICKED),
(LPARAM) GetSafeHwnd());
*/
}
void CTerrainCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
CRect rect;
GetClientRect(rect);
/*
// If outside client area, return (unless we are drag n dropping)
if (m_MouseMode != MOUSE_DRAGGING && !rect.PtInRect(point))
return;
// If the left mouse button is up, then test to see if row/column sizing is imminent
if (!(nFlags & MK_LBUTTON))
{
if (point.y < GetFixedRowHeight() && m_bAllowColumnResize)
{
CCellID idCurrentCell = GetCellFromPt(point);
CPoint start;
if (!GetCellOrigin(idCurrentCell, &start)) return;
int endx = start.x + GetColumnWidth(idCurrentCell.col);
if ((point.x - start.x <= m_nResizeCaptureRange && idCurrentCell.col != 0) ||
endx - point.x <= m_nResizeCaptureRange)
{
if (m_MouseMode != MOUSE_OVER_COL_DIVIDE)
SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
m_MouseMode = MOUSE_OVER_COL_DIVIDE;
}
else
{
if (m_MouseMode != MOUSE_NOTHING)
SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_MouseMode = MOUSE_NOTHING;
}
}
else if (point.x < GetFixedColumnWidth() && m_bAllowRowResize)
{
CCellID idCurrentCell = GetCellFromPt(point);
CPoint start;
if (!GetCellOrigin(idCurrentCell, &start)) return;
int endy = start.y + GetRowHeight(idCurrentCell.row);
if ((point.y - start.y <= m_nResizeCaptureRange && idCurrentCell.row != 0) ||
endy - point.y <= m_nResizeCaptureRange)
{
if (m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
SetCursor(::LoadCursor(NULL, IDC_SIZENS));
m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
}
else
{
if (m_MouseMode != MOUSE_NOTHING)
SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_MouseMode = MOUSE_NOTHING;
}
}
else
{
if (m_MouseMode != MOUSE_NOTHING)
SetCursor(::LoadCursor(NULL, IDC_ARROW));
m_MouseMode = MOUSE_NOTHING;
}
#ifdef GRIDCONTROL_USE_TITLETIPS
if (m_MouseMode == MOUSE_NOTHING && m_bTitleTips)
{
CCellID idCurrentCell = GetCellFromPt(point);
CRect rect;
if (GetCellRect(idCurrentCell.row, idCurrentCell.col, rect))
m_TitleTip.Show( rect, GetItemText(idCurrentCell.row, idCurrentCell.col), 0);
}
#endif
m_LastMousePoint = point;
return;
}
if (!IsValid(m_LeftClickDownCell))
{
m_LastMousePoint = point;
return;
}
// If the left mouse button is down, the process appropriately
if (nFlags & MK_LBUTTON)
{
switch(m_MouseMode)
{
case MOUSE_SELECT_ALL:
break;
case MOUSE_SELECT_COL:
case MOUSE_SELECT_ROW:
case MOUSE_SELECT_CELLS:
{
CCellID idCurrentCell = GetCellFromPt(point);
if (!IsValid(idCurrentCell))
return;
OnSelecting(idCurrentCell);
// SetFocusCell(max(idCurrentCell.row, m_nFixedRows),
// max(idCurrentCell.col, m_nFixedCols));
if (idCurrentCell.row >= m_nFixedRows &&
idCurrentCell.col >= m_nFixedCols)
SetFocusCell(idCurrentCell);
break;
}
case MOUSE_PREPARE_DRAG:
OnBeginDrag();
break;
}
}
m_LastMousePoint = point;
*/
}
// Sets the currently selected cell
void CTerrainCtrl::SetFocusCell(CELLID cell)
{
SetFocusCell(cell.row, cell.col);
}
void CTerrainCtrl::SetFocusCell(int nRow, int nCol)
{
CELLID cell(nRow, nCol);
if (cell == m_idCurrentCell)
return;
CELLID idPrev = m_idCurrentCell;
m_idCurrentCell = cell;
if (IsValid(idPrev))
{
/* SendMessageToParent(idPrev.row, idPrev.col, GVN_SELCHANGING);
*/
m_RowData[idPrev.row][idPrev.col].state &= ~GS_FOCUSED;
RedrawCell(idPrev);
/*
if (idPrev.col != m_idCurrentCell.col)
for (int row = 0; row < m_nFixedRows; row++)
RedrawCell(row, idPrev.col);
if (idPrev.row != m_idCurrentCell.row)
for (int col = 0; col < m_nFixedCols; col++)
RedrawCell(idPrev.row, col);
*/ }
if (IsValid(m_idCurrentCell))
{
m_RowData[nRow][nCol].state |= GS_FOCUSED;
RedrawCell(m_idCurrentCell);
/*
if (idPrev.col != m_idCurrentCell.col)
for (int row = 0; row < m_nFixedRows; row++)
RedrawCell(row, m_idCurrentCell.col);
if (idPrev.row != m_idCurrentCell.row)
for (int col = 0; col < m_nFixedCols; col++)
RedrawCell(m_idCurrentCell.row, col);
SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
*/ }
}
BOOL CTerrainCtrl::IsValid(int nRow, int nCol)
{
return (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols);
}
BOOL CTerrainCtrl::IsValid(CELLID cell)
{
return IsValid(cell.row, cell.col);
}
// Get cell from point
CELLID CTerrainCtrl::GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck)
{
CELLID idTopLeft = GetTopleftNonFixedCell();
CELLID cellID; // return value
// calculate column index
int fixedColWidth = GetFixedColumnWidth();
if (point.x < 0 || (!bAllowFixedCellCheck && point.x < fixedColWidth)) // not in window
cellID.col = -1;
else if (point.x < fixedColWidth) // in fixed col
{
int col, xpos = 0;
for (col = 0; col < m_nFixedCols; col++)
{
xpos += GetColumnWidth(col);
if (xpos > point.x) break;
}
cellID.col = col;
}
else // in non-fixed col
{
int col, xpos = fixedColWidth;
for (col = idTopLeft.col; col < m_nCols; col++)
{
xpos += GetColumnWidth(col);
if (xpos > point.x) break;
}
if (col >= GetColumnCount())
cellID.col = -1;
else
cellID.col = col;
}
// calculate row index
int fixedRowHeight = GetFixedRowHeight();
if (point.y < 0 || (!bAllowFixedCellCheck && point.y < fixedRowHeight)) // not in window
cellID.row = -1;
else if (point.y < fixedRowHeight) // in fixed col
{
int row, ypos = 0;
for (row = 0; row < m_nFixedRows; row++)
{
ypos += GetRowHeight(row);
if (ypos > point.y) break;
}
cellID.row = row;
}
else
{
int row, ypos = fixedRowHeight;
for (row = idTopLeft.row; row < GetRowCount(); row++)
{
ypos += GetRowHeight(row);
if (ypos > point.y) break;
}
if (row >= GetRowCount())
cellID.row = -1;
else
cellID.row = row;
}
return cellID;
}
// Forces a redraw of a cell immediately using a direct
// DC construction, or the supplied DC
BOOL CTerrainCtrl::RedrawCell(CELLID cell, CDC* pDC)
{
return RedrawCell(cell.row, cell.col, pDC);
}
BOOL CTerrainCtrl::RedrawCell(int nRow, int nCol, CDC* pDC)
{
BOOL bResult = TRUE;
BOOL bMustReleaseDC = FALSE;
if (!IsCellVisible(nRow, nCol))
return FALSE;
CRect rect;
if (!GetCellRect(nRow, nCol, rect))
return FALSE;
if (!pDC)
{
pDC = GetDC();
if (pDC)
bMustReleaseDC = TRUE;
}
if (pDC)
{
// Redraw cells directly
if (nRow < m_nFixedRows || nCol < m_nFixedCols)
bResult = DrawFixedCell(pDC, nRow, nCol, rect, TRUE);
else
bResult = DrawCell(pDC, nRow, nCol, rect, TRUE);
/*
// Since we have erased the background, we will need to redraw the gridlines
CPen pen;
try {
pen.CreatePen(PS_SOLID, 0, m_crGridColour);
} catch (...) {}
CPen* pOldPen = (CPen*) pDC->SelectObject(&pen);
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
pDC->MoveTo(rect.left, rect.bottom);
pDC->LineTo(rect.right+1, rect.bottom);
}
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom+1);
}
pDC->SelectObject(pOldPen);
*/
} else
InvalidateRect(rect, TRUE); // Could not get a DC - invalidate it anyway
// and hope that OnPaint manages to get one
if (bMustReleaseDC)
ReleaseDC(pDC);
return bResult;
}
// returns the top left point of the cell. Returns FALSE if cell not visible.
BOOL CTerrainCtrl::GetCellOrigin(CELLID cell, LPPOINT p)
{
return GetCellOrigin(cell.row, cell.col, p);
}
BOOL CTerrainCtrl::GetCellOrigin(int nRow, int nCol, LPPOINT p)
{
int i;
if (!IsValid(nRow, nCol))
return FALSE;
CELLID idTopLeft;
if (nCol >= m_nFixedCols || nRow >= m_nFixedRows)
idTopLeft = GetTopleftNonFixedCell();
if ((nRow >= m_nFixedRows && nRow < idTopLeft.row) ||
(nCol>= m_nFixedCols && nCol < idTopLeft.col))
return FALSE;
p->x = 0;
if (nCol < m_nFixedCols) // is a fixed column
for (i = 0; i < nCol; i++)
p->x += GetColumnWidth(i);
else // is a scrollable data column
{
for (i = 0; i < m_nFixedCols; i++)
p->x += GetColumnWidth(i);
for (i = idTopLeft.col; i < nCol; i++)
p->x += GetColumnWidth(i);
}
p->y = 0;
if (nRow < m_nFixedRows) // is a fixed row
for (i = 0; i < nRow; i++)
p->y += GetRowHeight(i);
else // is a scrollable data row
{
for (i = 0; i < m_nFixedRows; i++)
p->y += GetRowHeight(i);
for (i = idTopLeft.row; i < nRow; i++)
p->y += GetRowHeight(i);
}
return TRUE;
}
// Returns the bounding box of the cell
BOOL CTerrainCtrl::GetCellRect(CELLID cell, LPRECT pRect)
{
return GetCellRect(cell.row, cell.col, pRect);
}
BOOL CTerrainCtrl::GetCellRect(int nRow, int nCol, LPRECT pRect)
{
CPoint CellOrigin;
if (!GetCellOrigin(nRow, nCol, &CellOrigin))
return FALSE;
pRect->left = CellOrigin.x;
pRect->top = CellOrigin.y;
pRect->right = CellOrigin.x + GetColumnWidth(nCol)-1;
pRect->bottom = CellOrigin.y + GetRowHeight(nRow)-1;
return TRUE;
}
BOOL CTerrainCtrl::IsCellVisible(CELLID cell)
{
return IsCellVisible(cell.row, cell.col);
}
BOOL CTerrainCtrl::IsCellVisible(int nRow, int nCol)
{
if (!IsWindow(m_hWnd))
return FALSE;
int x,y;
CELLID TopLeft;
if (nCol >= GetFixedColumnCount() || nRow >= GetFixedRowCount())
{
TopLeft = GetTopleftNonFixedCell();
if (nCol >= GetFixedColumnCount() && nCol < TopLeft.col) return FALSE;
if (nRow >= GetFixedRowCount() && nRow < TopLeft.row) return FALSE;
}
CRect rect;
GetClientRect(rect);
if (nCol < GetFixedColumnCount())
{
x = 0;
for (int i = 0; i <= nCol; i++)
{
if (x >= rect.right) return FALSE;
x += GetColumnWidth(i);
}
}
else
{
x = GetFixedColumnWidth();
for (int i = TopLeft.col; i <= nCol; i++)
{
if (x >= rect.right) return FALSE;
x += GetColumnWidth(i);
}
}
if (nRow < GetFixedRowCount())
{
y = 0;
for (int i = 0; i <= nRow; i++)
{
if (y >= rect.bottom) return FALSE;
y += GetRowHeight(i);
}
}
else
{
if (nRow < TopLeft.row) return FALSE;
y = GetFixedRowHeight();
for (int i = TopLeft.row; i <= nRow; i++)
{
if (y >= rect.bottom) return FALSE;
y += GetRowHeight(i);
}
}
return TRUE;
}
// move about with keyboard
void CTerrainCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!IsValid(m_idCurrentCell))
{
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
return;
}
CELLID next = m_idCurrentCell;
BOOL bChangeLine = FALSE;
/*
if (IsCTRLpressed())
{
switch (nChar)
{
case 'A': OnEditSelectAll(); break;
}
}
*/
switch (nChar)
{
/*
case VK_DELETE:
if (IsCellEditable(m_idCurrentCell.row, m_idCurrentCell.col))
{
SetItemText(m_idCurrentCell.row, m_idCurrentCell.col, _T(""));
RedrawCell(m_idCurrentCell);
SetModified(TRUE);
}
break;
case VK_TAB:
if (IsSHIFTpressed())
{
if (next.col > m_nFixedCols)
next.col--;
else if (next.col == m_nFixedCols && next.row > m_nFixedRows)
{
next.row--;
next.col = GetColumnCount() - 1;
bChangeLine = TRUE;
}
else
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
else
{
if (next.col < (GetColumnCount() - 1))
next.col++;
else if (next.col == (GetColumnCount() - 1) &&
next.row < (GetRowCount() - 1) )
{
next.row++;
next.col = m_nFixedCols;
bChangeLine = TRUE;
}
else
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
break;
*/
case VK_DOWN:
if (next.row < (GetRowCount() - 1))
next.row++;
break;
case VK_UP:
if (next.row > 1)
next.row--;
break;
case VK_RIGHT:
if (next.col < (GetColumnCount() - 1))
next.col++;
break;
case VK_LEFT:
if (next.col > 1)
next.col--;
break;
case VK_NEXT:
{
CELLID idOldTopLeft = GetTopleftNonFixedCell();
SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
CELLID idNewTopLeft = GetTopleftNonFixedCell();
int increment = idNewTopLeft.row - idOldTopLeft.row;
if (increment)
{
next.row += increment;
if (next.row > (GetRowCount() - 1))
next.row = GetRowCount() - 1;
}
else
next.row = GetRowCount() - 1;
break;
}
case VK_PRIOR:
{
CELLID idOldTopLeft = GetTopleftNonFixedCell();
SendMessage(WM_VSCROLL, SB_PAGEUP, 0);
CELLID idNewTopLeft = GetTopleftNonFixedCell();
int increment = idNewTopLeft.row - idOldTopLeft.row;
if (increment)
{
next.row += increment;
if (next.row < m_nFixedRows)
next.row = m_nFixedRows;
}
else
next.row = m_nFixedRows;
break;
}
case VK_HOME:
SendMessage(WM_VSCROLL, SB_TOP, 0);
next.row = m_nFixedRows;
break;
case VK_END:
SendMessage(WM_VSCROLL, SB_BOTTOM, 0);
next.row = GetRowCount() - 1;
break;
default:
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
if (next != m_idCurrentCell)
{
// While moving with the Cursorkeys the current ROW/CELL will get selected
// OR Selection will get expanded when SHIFT is pressed
// Cut n paste from OnLButtonDown - Franco Bez
/* // Added check for NULL mouse mode - Chris Maunder.
if (m_MouseMode == MOUSE_NOTHING)
{
m_PrevSelectedCellMap.RemoveAll();
m_MouseMode = m_bListMode? MOUSE_SELECT_ROW : MOUSE_SELECT_CELLS;
if (!IsSHIFTpressed() || nChar == VK_TAB)
m_SelectionStartCell = next;
OnSelecting(next);
m_MouseMode = MOUSE_NOTHING;
}
*/
SetFocusCell(next);
if (!IsCellVisible(next))
{
EnsureVisible(next); // Make sure cell is visible
switch (nChar)
{
case VK_RIGHT:
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
break;
case VK_LEFT:
SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
break;
case VK_DOWN:
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
break;
case VK_UP:
SendMessage(WM_VSCROLL, SB_LINEUP, 0);
break;
/*
case VK_TAB:
if (IsSHIFTpressed())
{
if (bChangeLine)
{
SendMessage(WM_VSCROLL, SB_LINEUP, 0);
SetScrollPos32(SB_HORZ, m_nHScrollMax);
break;
}
else
SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
}
else
{
if (bChangeLine)
{
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
SetScrollPos32(SB_HORZ, 0);
break;
}
else
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
}
break;
*/
}
Invalidate();
}
}
}
void CTerrainCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (
/* !IsCTRLpressed() &&
*/
m_MouseMode == MOUSE_NOTHING)
{
/* if (!m_bHandleTabKey || (m_bHandleTabKey && nChar != VK_TAB))
*/ EditCell(m_idCurrentCell.row, m_idCurrentCell.col, nChar);
}
CWnd::OnChar(nChar, nRepCnt, nFlags);
}
// Instant editing of cells when keys are pressed
void CTerrainCtrl::EditCell(int nRow, int nCol, UINT nChar)
{
EnsureVisible(nRow, nCol);
if (!IsValid(nRow, nCol) || !IsCellVisible(nRow, nCol))
return;
CRect rect;
if (!GetCellRect(nRow, nCol, rect))
return;
/*
SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT);
*/
char szText[20];
sprintf(szText, "%.2f", ControlPoint(nRow, nCol));
new CInPlaceEdit(this, rect, ES_LEFT, IDC_INPLACE_EDIT, &ControlPoint(nRow, nCol), szText, nChar);
}
void CTerrainCtrl::EnsureVisible(CELLID cell)
{
EnsureVisible(cell.row, cell.col);
}
void CTerrainCtrl::EnsureVisible(int nRow, int nCol)
{
// CCellRange VisibleCells = GetVisibleNonFixedCellRange();
CRect rect;
GetClientRect(rect);
CELLID idTopLeft = GetTopleftNonFixedCell();
// calc bottom
int i, bottom = GetFixedRowHeight();
for (i = idTopLeft.row; i < m_nRows; i++)
{
bottom += GetRowHeight(i);
if (bottom >= rect.bottom)
{
bottom = rect.bottom;
break;
}
}
int maxVisibleRow = min(i, m_nRows - 1);
// calc right
int right = GetFixedColumnWidth();
for (i = idTopLeft.col; i < m_nCols; i++)
{
right += GetColumnWidth(i);
if (right >= rect.right)
{
right = rect.right;
break;
}
}
int maxVisibleCol = min(i, m_nCols - 1);
right = nCol - maxVisibleCol;
int left = idTopLeft.col - nCol;
int down = nRow - maxVisibleRow;
int up = idTopLeft.row - nRow;
while (right > 0)
{
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
right--;
}
while (left > 0)
{
SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
left--;
}
while (down > 0)
{
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
down--;
}
while (up > 0)
{
SendMessage(WM_VSCROLL, SB_LINEUP, 0);
up--;
}
// Move one more if we only see a small bit of the cell
CRect rectCell, rectWindow;
GetCellRect(nRow, nCol, rectCell);
GetClientRect(rectWindow);
if (rectCell.right > rectWindow.right)
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
if (rectCell.bottom > rectWindow.bottom)
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
}