#include "stdafx.h"
#include "MemDC.h"
#include "GridCtrl.h"
#include <afxadv.h> // For CSharedFile
#include <afxconv.h> // For LPTSTR -> LPSTR macros
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static
char
THIS_FILE[] = __FILE__;
#endif
#ifdef GRIDCONTROL_NO_TITLETIPS
#pragma message(" -- CGridCtrl: No titletips for cells with large data")
#endif
#ifdef GRIDCONTROL_NO_DRAGDROP
#pragma message(" -- CGridCtrl: No OLE drag and drop")
#endif
#ifdef GRIDCONTROL_NO_CLIPBOARD
#pragma message(" -- CGridCtrl: No clipboard support")
#endif
#ifdef GRIDCONTROL_NO_PRINTING
#pragma message(" -- CGridCtrl: No printing support")
#endif
IMPLEMENT_DYNCREATE(CGridCtrl, CWnd)
UINT
GetMouseScrollLines()
{
int
nScrollLines = 3;
#ifndef _WIN32_WCE
OSVERSIONINFO VersionInfo;
VersionInfo.dwOSVersionInfoSize =
sizeof
(OSVERSIONINFO);
if
(!GetVersionEx(&VersionInfo) ||
(VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && VersionInfo.dwMinorVersion == 0))
{
HKEY
hKey;
if
(RegOpenKeyEx(HKEY_CURRENT_USER, _T(
"Control Panel\\Desktop"
),
0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
TCHAR
szData[128];
DWORD
dwKeyDataType;
DWORD
dwDataBufSize =
sizeof
(szData);
if
(RegQueryValueEx(hKey, _T(
"WheelScrollLines"
), NULL, &dwKeyDataType,
(
LPBYTE
) &szData, &dwDataBufSize) == ERROR_SUCCESS)
{
nScrollLines = _tcstoul(szData, NULL, 10);
}
RegCloseKey(hKey);
}
}
else
SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
#endif
return
nScrollLines;
}
CGridCtrl::CGridCtrl(
int
nRows,
int
nCols,
int
nFixedRows,
int
nFixedCols)
{
RegisterWindowClass();
#if !defined(GRIDCONTROL_NO_DRAGDROP) || !defined(GRIDCONTROL_NO_CLIPBOARD)
_AFX_THREAD_STATE* pState = AfxGetThreadState();
if
(!pState->m_bNeedTerm && !AfxOleInit())
AfxMessageBox(_T(
"OLE initialization failed. Make sure that the OLE libraries are the correct version"
));
#endif
m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
m_crGridLineColour = RGB(192,192,192);
m_nRows = 0;
m_nCols = 0;
m_nFixedRows = 0;
m_nFixedCols = 0;
m_bVirtualMode = FALSE;
m_pfnCallback = NULL;
m_nVScrollMax = 0;
m_nHScrollMax = 0;
m_nRowsPerWheelNotch = GetMouseScrollLines();
m_nBarState = GVL_NONE;
m_MouseMode = MOUSE_NOTHING;
m_nGridLines = GVL_BOTH;
m_bEditable = TRUE;
m_bListMode = FALSE;
m_bSingleRowSelection = FALSE;
m_bSingleColSelection = FALSE;
m_bLMouseButtonDown = FALSE;
m_bRMouseButtonDown = FALSE;
m_bAllowDraw = TRUE;
m_bEnableSelection = TRUE;
m_bFixedColumnSelection = TRUE;
m_bFixedRowSelection = TRUE;
m_bAllowRowResize = TRUE;
m_bAllowColumnResize = TRUE;
m_bSortOnClick = FALSE;
m_bHandleTabKey = TRUE;
#ifdef _WIN32_WCE
m_bDoubleBuffer = FALSE;
#else
m_bDoubleBuffer = TRUE;
#endif
m_bTitleTips = TRUE;
m_bWysiwygPrinting = FALSE;
m_bHiddenColUnhide = TRUE;
m_bHiddenRowUnhide = TRUE;
m_bAllowColHide = TRUE;
m_bAllowRowHide = TRUE;
m_bAscending = TRUE;
m_nSortColumn = -1;
m_pfnCompare = NULL;
m_nAutoSizeColumnStyle = GVS_BOTH;
m_nTimerID = 0;
m_nTimerInterval = 25;
m_nResizeCaptureRange = 3;
m_pImageList = NULL;
m_bAllowDragAndDrop = FALSE;
m_bTrackFocusCell = TRUE;
m_bFrameFocus = TRUE;
m_pRtcDefault = RUNTIME_CLASS(CGridCell);
SetupDefaultCells();
SetGridBkColor(m_crShadow);
SetRowCount(nRows);
SetColumnCount(nCols);
SetFixedRowCount(nFixedRows);
SetFixedColumnCount(nFixedCols);
SetTitleTipTextClr(CLR_DEFAULT);
SetTitleTipBackClr(CLR_DEFAULT);
m_SelectedCellMap.RemoveAll();
m_PrevSelectedCellMap.RemoveAll();
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
m_bShadedPrintOut = TRUE;
SetPrintMarginInfo(2, 2, 4, 4, 1, 1, 1);
#endif
}
CGridCtrl::~CGridCtrl()
{
DeleteAllItems();
#ifndef GRIDCONTROL_NO_TITLETIPS
if
(m_bTitleTips && ::IsWindow(m_TitleTip.GetSafeHwnd()))
m_TitleTip.DestroyWindow();
#endif
DestroyWindow();
#if !defined(GRIDCONTROL_NO_DRAGDROP) || !defined(GRIDCONTROL_NO_CLIPBOARD)
COleDataSource *pSource = COleDataSource::GetClipboardOwner();
if
(pSource)
COleDataSource::FlushClipboard();
#endif
}
BOOL
CGridCtrl::RegisterWindowClass()
{
WNDCLASS wndcls;
HINSTANCE
hInst = AfxGetResourceHandle();
if
(!(::GetClassInfo(hInst, GRIDCTRL_CLASSNAME, &wndcls)))
{
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
#ifndef _WIN32_WCE_NO_CURSOR
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
#else
wndcls.hCursor = 0;
#endif
wndcls.hbrBackground = (
HBRUSH
) (COLOR_3DFACE + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = GRIDCTRL_CLASSNAME;
if
(!AfxRegisterClass(&wndcls))
{
AfxThrowResourceException();
return
FALSE;
}
}
return
TRUE;
}
BOOL
CGridCtrl::Initialise()
{
static
BOOL
bInProcedure = FALSE;
if
(bInProcedure)
return
FALSE;
bInProcedure = TRUE;
#ifndef GRIDCONTROL_NO_TITLETIPS
m_TitleTip.SetParentWnd(
this
);
#endif
if
(::IsWindow(m_hWnd))
ModifyStyleEx(0, WS_EX_CLIENTEDGE);
CRect rect;
GetWindowRect(rect);
CWnd* pParent = GetParent();
if
(pParent != NULL)
pParent->ScreenToClient(rect);
rect.InflateRect(1,1); MoveWindow(rect);
rect.DeflateRect(1,1); MoveWindow(rect);
bInProcedure = FALSE;
return
TRUE;
}
BOOL
CGridCtrl::Create(
const
RECT& rect, CWnd* pParentWnd,
UINT
nID,
DWORD
dwStyle)
{
ASSERT(pParentWnd->GetSafeHwnd());
if
(!CWnd::Create(GRIDCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID))
return
FALSE;
TRY
{
m_arRowHeights.SetSize(m_nRows);
m_arColWidths.SetSize(m_nCols);
}
CATCH (CMemoryException, e)
{
e->ReportError();
return
FALSE;
}
END_CATCH
int
i;
for
(i = 0; i < m_nRows; i++)
m_arRowHeights[i] = m_cellDefault.GetHeight();
for
(i = 0; i < m_nCols; i++)
m_arColWidths[i] = m_cellDefault.GetWidth();
return
TRUE;
}
void
CGridCtrl::SetupDefaultCells()
{
m_cellDefault.SetGrid(
this
);
m_cellFixedColDef.SetGrid(
this
);
m_cellFixedRowDef.SetGrid(
this
);
m_cellFixedRowColDef.SetGrid(
this
);
m_cellDefault.SetTextClr(m_crWindowText);
m_cellDefault.SetBackClr(m_crWindowColour);
m_cellFixedColDef.SetTextClr(m_crWindowText);
m_cellFixedColDef.SetBackClr(m_cr3DFace);
m_cellFixedRowDef.SetTextClr(m_crWindowText);
m_cellFixedRowDef.SetBackClr(m_cr3DFace);
m_cellFixedRowColDef.SetTextClr(m_crWindowText);
m_cellFixedRowColDef.SetBackClr(m_cr3DFace);
}
void
CGridCtrl::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
Initialise();
}
LRESULT
CGridCtrl::SendMessageToParent(
int
nRow,
int
nCol,
int
nMessage)
const
{
if
(!IsWindow(m_hWnd))
return
0;
NM_GRIDVIEW nmgv;
nmgv.iRow = nRow;
nmgv.iColumn = nCol;
nmgv.hdr.hwndFrom = m_hWnd;
nmgv.hdr.idFrom = GetDlgCtrlID();
nmgv.hdr.code = nMessage;
CWnd *pOwner = GetOwner();
if
(pOwner && IsWindow(pOwner->m_hWnd))
return
pOwner->SendMessage(WM_NOTIFY, nmgv.hdr.idFrom, (
LPARAM
)&nmgv);
else
return
0;
}
LRESULT
CGridCtrl::SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo)
const
{
if
(!IsWindow(m_hWnd))
return
0;
pDisplayInfo->hdr.hwndFrom = m_hWnd;
pDisplayInfo->hdr.idFrom = GetDlgCtrlID();
pDisplayInfo->hdr.code = GVN_GETDISPINFO;
CWnd *pOwner = GetOwner();
if
(pOwner && IsWindow(pOwner->m_hWnd))
return
pOwner->SendMessage(WM_NOTIFY, pDisplayInfo->hdr.idFrom, (
LPARAM
)pDisplayInfo);
else
return
0;
}
LRESULT
CGridCtrl::SendCacheHintToParent(
const
CCellRange& range)
const
{
if
(!IsWindow(m_hWnd))
return
0;
GV_CACHEHINT CacheHint;
CacheHint.hdr.hwndFrom = m_hWnd;
CacheHint.hdr.idFrom = GetDlgCtrlID();
CacheHint.hdr.code = GVN_ODCACHEHINT;
CacheHint.range = range;
CWnd *pOwner = GetOwner();
if
(pOwner && IsWindow(pOwner->m_hWnd))
return
pOwner->SendMessage(WM_NOTIFY, CacheHint.hdr.idFrom, (
LPARAM
)&CacheHint);
else
return
0;
}
BEGIN_MESSAGE_MAP(CGridCtrl, CWnd)
ON_WM_PAINT()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_SIZE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_GETDLGCODE()
ON_WM_KEYDOWN()
ON_WM_CHAR()
ON_WM_LBUTTONDBLCLK()
ON_WM_ERASEBKGND()
ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_WM_SYSKEYDOWN()
#ifndef _WIN32_WCE_NO_CURSOR
ON_WM_SETCURSOR()
#endif
#ifndef _WIN32_WCE
ON_WM_RBUTTONUP()
ON_WM_SYSCOLORCHANGE()
ON_WM_CAPTURECHANGED()
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
#endif
#if (_WIN32_WCE >= 210)
ON_WM_SETTINGCHANGE()
#endif
#if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
ON_WM_MOUSEWHEEL()
#endif
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_MESSAGE(WM_GETFONT, OnGetFont)
ON_MESSAGE(WM_IME_CHAR, OnImeChar)
ON_NOTIFY(GVN_ENDLABELEDIT, IDC_INPLACE_CONTROL, OnEndInPlaceEdit)
ON_MESSAGE(WM_PRINTCLIENT, OnCustomPrint)
END_MESSAGE_MAP()
LRESULT
CGridCtrl::OnCustomPrint(
WPARAM
wParam,
LPARAM
)
{
OnDraw(CDC::FromHandle((
HDC
) wParam));
return
0;
}
void
CGridCtrl::OnPaint()
{
CPaintDC dc(
this
);
if
(m_bDoubleBuffer)
{
CMemDC MemDC(&dc);
OnDraw(&MemDC);
}
else
OnDraw(&dc);
}
BOOL
CGridCtrl::OnEraseBkgnd(CDC*
)
{
return
TRUE;
}
void
CGridCtrl::EraseBkgnd(CDC* pDC)
{
CRect VisRect, ClipRect, rect;
CBrush FixedRowColBack(GetDefaultCell(TRUE, TRUE)->GetBackClr()),
FixedRowBack(GetDefaultCell(TRUE, FALSE)->GetBackClr()),
FixedColBack(GetDefaultCell(FALSE, TRUE)->GetBackClr()),
TextBack(GetDefaultCell(FALSE, FALSE)->GetBackClr());
CBrush Back(GetGridBkColor());
if
(pDC->GetClipBox(ClipRect) == ERROR)
return
;
GetVisibleNonFixedCellRange(VisRect);
int
nFixedColumnWidth = GetFixedColumnWidth();
int
nFixedRowHeight = GetFixedRowHeight();
if
(ClipRect.left < nFixedColumnWidth && ClipRect.top < nFixedRowHeight)
pDC->FillRect(CRect(ClipRect.left, ClipRect.top,
nFixedColumnWidth, nFixedRowHeight),
&FixedRowColBack);
if
(ClipRect.left < nFixedColumnWidth && ClipRect.top < VisRect.bottom)
pDC->FillRect(CRect(ClipRect.left, ClipRect.top,
nFixedColumnWidth, VisRect.bottom),
&FixedColBack);
if
(ClipRect.top < nFixedRowHeight &&
ClipRect.right > nFixedColumnWidth && ClipRect.left < VisRect.right)
pDC->FillRect(CRect(nFixedColumnWidth-1, ClipRect.top,
VisRect.right, nFixedRowHeight),
&FixedRowBack);
if
(rect.IntersectRect(VisRect, ClipRect))
{
CRect CellRect(max(nFixedColumnWidth, rect.left),
max(nFixedRowHeight, rect.top),
rect.right, rect.bottom);
pDC->FillRect(CellRect, &TextBack);
}
if
(VisRect.right < ClipRect.right)
pDC->FillRect(CRect(VisRect.right, ClipRect.top,
ClipRect.right, ClipRect.bottom),
&Back);
if
(VisRect.bottom < ClipRect.bottom && ClipRect.left < VisRect.right)
pDC->FillRect(CRect(ClipRect.left, VisRect.bottom,
VisRect.right, ClipRect.bottom),
&Back);
}
void
CGridCtrl::OnSize(
UINT
nType,
int
cx,
int
cy)
{
static
BOOL
bAlreadyInsideThisProcedure = FALSE;
if
(bAlreadyInsideThisProcedure)
return
;
if
(!::IsWindow(m_hWnd))
return
;
#ifndef GRIDCONTROL_NO_DRAGDROP
m_DropTarget.Register(
this
);
#endif
bAlreadyInsideThisProcedure = TRUE;
EndEditing();
CWnd::OnSize(nType, cx, cy);
ResetScrollBars();
bAlreadyInsideThisProcedure = FALSE;
}
UINT
CGridCtrl::OnGetDlgCode()
{
UINT
nCode = DLGC_WANTARROWS | DLGC_WANTCHARS;
if
(m_bHandleTabKey && !IsCTRLpressed())
nCode |= DLGC_WANTTAB;
return
nCode;
}
#ifndef _WIN32_WCE
void
CGridCtrl::OnSysColorChange()
{
CWnd::OnSysColorChange();
if
(GetDefaultCell(FALSE, FALSE)->GetTextClr() == m_crWindowText)
GetDefaultCell(FALSE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(FALSE, FALSE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(FALSE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(TRUE, FALSE)->GetTextClr() == m_crWindowText)
GetDefaultCell(TRUE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(TRUE, FALSE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(TRUE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(FALSE, TRUE)->GetTextClr() == m_crWindowText)
GetDefaultCell(FALSE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(FALSE, TRUE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(FALSE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(TRUE, TRUE)->GetTextClr() == m_crWindowText)
GetDefaultCell(TRUE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(TRUE, TRUE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(TRUE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetGridBkColor() == m_crShadow)
SetGridBkColor(::GetSysColor(COLOR_3DSHADOW));
m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
}
#endif
#ifndef _WIN32_WCE_NO_CURSOR
void
CGridCtrl::OnCaptureChanged(CWnd *pWnd)
{
if
(pWnd->GetSafeHwnd() == GetSafeHwnd())
return
;
if
(m_nTimerID != 0)
{
KillTimer(m_nTimerID);
m_nTimerID = 0;
}
#ifndef GRIDCONTROL_NO_DRAGDROP
if
(m_MouseMode == MOUSE_DRAGGING)
m_MouseMode = MOUSE_NOTHING;
#endif
}
#endif
#if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210)
void
CGridCtrl::OnSettingChange(
UINT
uFlags,
LPCTSTR
lpszSection)
{
CWnd::OnSettingChange(uFlags, lpszSection);
if
(GetDefaultCell(FALSE, FALSE)->GetTextClr() == m_crWindowText)
GetDefaultCell(FALSE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(FALSE, FALSE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(FALSE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(TRUE, FALSE)->GetTextClr() == m_crWindowText)
GetDefaultCell(TRUE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(TRUE, FALSE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(TRUE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(FALSE, TRUE)->GetTextClr() == m_crWindowText)
GetDefaultCell(FALSE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(FALSE, TRUE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(FALSE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetDefaultCell(TRUE, TRUE)->GetTextClr() == m_crWindowText)
GetDefaultCell(TRUE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT));
if
(GetDefaultCell(TRUE, TRUE)->GetBackClr() == m_crWindowColour)
GetDefaultCell(TRUE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
if
(GetGridBkColor() == m_crShadow)
SetGridBkColor(::GetSysColor(COLOR_3DSHADOW));
m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
m_nRowsPerWheelNotch = GetMouseScrollLines();
}
#endif
void
CGridCtrl::OnTimer(
UINT
nIDEvent)
{
ASSERT(nIDEvent == WM_LBUTTONDOWN);
if
(nIDEvent != WM_LBUTTONDOWN)
return
;
CPoint pt, origPt;
#ifdef _WIN32_WCE
if
(m_MouseMode == MOUSE_NOTHING)
return
;
origPt = GetMessagePos();
#else
if
(!GetCursorPos(&origPt))
return
;
#endif
ScreenToClient(&origPt);
CRect rect;
GetClientRect(rect);
int
nFixedRowHeight = GetFixedRowHeight();
int
nFixedColWidth = GetFixedColumnWidth();
pt = origPt;
if
(pt.y > rect.bottom)
{
SendMessage(WM_KEYDOWN, VK_DOWN, 0);
if
(pt.x < rect.left)
pt.x = rect.left;
if
(pt.x > rect.right)
pt.x = rect.right;
pt.y = rect.bottom;
OnSelecting(GetCellFromPt(pt));
}
else
if
(pt.y < nFixedRowHeight)
{
SendMessage(WM_KEYDOWN, VK_UP, 0);
if
(pt.x < rect.left)
pt.x = rect.left;
if
(pt.x > rect.right)
pt.x = rect.right;
pt.y = nFixedRowHeight + 1;
OnSelecting(GetCellFromPt(pt));
}
pt = origPt;
if
(pt.x > rect.right)
{
SendMessage(WM_KEYDOWN, VK_RIGHT, 0);
if
(pt.y < rect.top)
pt.y = rect.top;
if
(pt.y > rect.bottom)
pt.y = rect.bottom;
pt.x = rect.right;
OnSelecting(GetCellFromPt(pt));
}
else
if
(pt.x < nFixedColWidth)
{
SendMessage(WM_KEYDOWN, VK_LEFT, 0);
if
(pt.y < rect.top)
pt.y = rect.top;
if
(pt.y > rect.bottom)
pt.y = rect.bottom;
pt.x = nFixedColWidth + 1;
OnSelecting(GetCellFromPt(pt));
}
}
void
CGridCtrl::OnKeyDown(
UINT
nChar,
UINT
nRepCnt,
UINT
nFlags)
{
if
(!IsValid(m_idCurrentCell))
{
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
return
;
}
CCellID next = m_idCurrentCell;
BOOL
bChangeLine = FALSE;
BOOL
bHorzScrollAction = FALSE;
BOOL
bVertScrollAction = FALSE;
if
(IsCTRLpressed())
{
switch
(nChar)
{
case
'A'
:
OnEditSelectAll();
break
;
#ifndef GRIDCONTROL_NO_CLIPBOARD
case
'X'
:
OnEditCut();
break
;
case
VK_INSERT:
case
'C'
:
OnEditCopy();
break
;
case
'V'
:
OnEditPaste();
break
;
#endif
}
}
#ifndef GRIDCONTROL_NO_CLIPBOARD
if
(IsSHIFTpressed() &&(nChar == VK_INSERT))
OnEditPaste();
#endif
BOOL
bFoundVisible;
int
iOrig;
if
(nChar == VK_DELETE)
{
CutSelectedText();
}
else
if
(nChar == VK_DOWN)
{
bFoundVisible = FALSE;
iOrig = next.row;
next.row++;
while
( next.row < GetRowCount())
{
if
( GetRowHeight( next.row) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.row++;
}
if
( !bFoundVisible)
next.row = iOrig;
}
else
if
(nChar == VK_UP)
{
bFoundVisible = FALSE;
iOrig = next.row;
next.row--;
while
( next.row >= m_nFixedRows)
{
if
( GetRowHeight( next.row) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.row--;
}
if
( !bFoundVisible)
next.row = iOrig;
}
else
if
(nChar == VK_RIGHT || (nChar == VK_TAB && !IsSHIFTpressed()) )
{
bFoundVisible = FALSE;
iOrig = next.col;
next.col++;
if
(nChar == VK_TAB)
{
if
(next.col == (GetColumnCount()) && next.row < (GetRowCount() - 1))
{
next.row++;
while
( next.row < GetRowCount())
{
if
( GetRowHeight(next.row) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.row++;
}
next.col = m_nFixedCols;
bChangeLine = TRUE;
}
else
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
while
( next.col < GetColumnCount())
{
if
( GetColumnWidth( next.col) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.col++;
}
if
( !bFoundVisible)
next.col = iOrig;
}
else
if
(nChar == VK_LEFT || (nChar == VK_TAB && IsSHIFTpressed()) )
{
bFoundVisible = FALSE;
iOrig = next.col;
next.col--;
if
(nChar == VK_TAB)
{
if
(next.col == (GetFixedColumnCount()-1) && next.row > GetFixedRowCount())
{
next.row--;
while
( next.row > GetFixedRowCount())
{
if
( GetRowHeight(next.row) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.row--;
}
next.col = GetColumnCount() - 1;
bChangeLine = TRUE;
}
else
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
while
( next.col >= m_nFixedCols)
{
if
( GetColumnWidth( next.col) > 0)
{
bFoundVisible = TRUE;
break
;
}
next.col--;
}
if
( !bFoundVisible)
next.col = iOrig;
}
else
if
(nChar == VK_NEXT)
{
CCellID idOldTopLeft = GetTopleftNonFixedCell();
SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
bVertScrollAction = TRUE;
CCellID 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;
}
else
if
(nChar == VK_PRIOR)
{
CCellID idOldTopLeft = GetTopleftNonFixedCell();
SendMessage(WM_VSCROLL, SB_PAGEUP, 0);
bVertScrollAction = TRUE;
CCellID 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;
}
else
if
(nChar == VK_HOME)
{
if
(IsCTRLpressed())
{
SendMessage(WM_VSCROLL, SB_TOP, 0);
SendMessage(WM_HSCROLL, SB_LEFT, 0);
bVertScrollAction = TRUE;
bHorzScrollAction = TRUE;
next.row = m_nFixedRows;
next.col = m_nFixedCols;
}
else
{
SendMessage(WM_HSCROLL, SB_LEFT, 0);
bHorzScrollAction = TRUE;
next.col = m_nFixedCols;
}
while
( next.col < GetColumnCount() - 1)
{
if
( GetColumnWidth( next.col) > 0)
break
;
next.col++;
}
while
( next.row < GetRowCount() - 1)
{
if
( GetRowHeight( next.row) > 0)
break
;
next.row++;
}
}
else
if
(nChar == VK_END)
{
if
(IsCTRLpressed())
{
SendMessage(WM_VSCROLL, SB_BOTTOM, 0);
SendMessage(WM_HSCROLL, SB_RIGHT, 0);
bHorzScrollAction = TRUE;
bVertScrollAction = TRUE;
next.row = GetRowCount() - 1;
next.col = GetColumnCount() - 1;
}
else
{
SendMessage(WM_HSCROLL, SB_RIGHT, 0);
bHorzScrollAction = TRUE;
next.col = GetColumnCount() - 1;
}
while
( next.col > m_nFixedCols + 1)
{
if
( GetColumnWidth( next.col) > 0)
break
;
next.col--;
}
while
( next.row > m_nFixedRows + 1)
{
if
( GetRowHeight( next.row) > 0)
break
;
next.row--;
}
}
else
if
(nChar == VK_F2)
{
OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint( -1, -1), VK_LBUTTON);
}
else
{
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
return
;
}
if
(next != m_idCurrentCell)
{
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;
SendMessageToParent(next.row, next.col, GVN_SELCHANGING);
OnSelecting(next);
SendMessageToParent(next.row, next.col, GVN_SELCHANGED);
m_MouseMode = MOUSE_NOTHING;
}
SetFocusCell(next);
if
(!IsCellVisible(next))
{
switch
(nChar)
{
case
VK_RIGHT:
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
bHorzScrollAction = TRUE;
break
;
case
VK_LEFT:
SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
bHorzScrollAction = TRUE;
break
;
case
VK_DOWN:
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
bVertScrollAction = TRUE;
break
;
case
VK_UP:
SendMessage(WM_VSCROLL, SB_LINEUP, 0);
bVertScrollAction = TRUE;
break
;
case
VK_TAB:
if
(IsSHIFTpressed())
{
if
(bChangeLine)
{
SendMessage(WM_VSCROLL, SB_LINEUP, 0);
bVertScrollAction = TRUE;
SetScrollPos32(SB_HORZ, m_nHScrollMax);
break
;
}
else
{
SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
bHorzScrollAction = TRUE;
}
}
else
{
if
(bChangeLine)
{
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
bVertScrollAction = TRUE;
SetScrollPos32(SB_HORZ, 0);
break
;
}
else
{
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
bHorzScrollAction = TRUE;
}
}
break
;
}
EnsureVisible(next);
Invalidate();
}
EnsureVisible(next);
if
(bHorzScrollAction)
SendMessage(WM_HSCROLL, SB_ENDSCROLL, 0);
if
(bVertScrollAction)
SendMessage(WM_VSCROLL, SB_ENDSCROLL, 0);
}
}
void
CGridCtrl::OnKeyUp(
UINT
nChar,
UINT
nRepCnt,
UINT
nFlags)
{
CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
}
void
CGridCtrl::OnSysKeyDown(
UINT
nChar,
UINT
nRepCnt,
UINT
nFlags)
{
#ifdef GRIDCONTROL_USE_TITLETIPS
m_TitleTip.Hide();
#endif
CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
}
void
CGridCtrl::OnChar(
UINT
nChar,
UINT
nRepCnt,
UINT
nFlags)
{
if
(!IsCTRLpressed() && m_MouseMode == MOUSE_NOTHING && nChar != VK_ESCAPE)
{
if
(!m_bHandleTabKey || (m_bHandleTabKey && nChar != VK_TAB))
OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint( -1, -1), nChar);
}
CWnd::OnChar(nChar, nRepCnt, nFlags);
}
LRESULT
CGridCtrl::OnImeChar(
WPARAM
wCharCode,
LPARAM
)
{
if
(!IsCTRLpressed() && m_MouseMode == MOUSE_NOTHING && wCharCode != VK_ESCAPE)
OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint( -1, -1), wCharCode);
return
0;
}
void
CGridCtrl::OnEndInPlaceEdit(NMHDR* pNMHDR,
LRESULT
* pResult)
{
GV_DISPINFO *pgvDispInfo = (GV_DISPINFO *)pNMHDR;
GV_ITEM *pgvItem = &pgvDispInfo->item;
if
(!IsWindow(GetSafeHwnd()))
return
;
OnEndEditCell(pgvItem->row, pgvItem->col, pgvItem->strText);
switch
(pgvItem->lParam)
{
case
VK_TAB:
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(pgvItem->lParam, 0, 0);
OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint( -1, -1), pgvItem->lParam);
}
*pResult = 0;
}
void
CGridCtrl::OnHScroll(
UINT
nSBCode,
UINT
, CScrollBar*
)
{
EndEditing();
#ifndef GRIDCONTROL_NO_TITLETIPS
m_TitleTip.Hide();
#endif
int
scrollPos = GetScrollPos32(SB_HORZ);
CCellID idTopLeft = GetTopleftNonFixedCell();
CRect rect;
GetClientRect(rect);
switch
(nSBCode)
{
case
SB_LINERIGHT:
if
(scrollPos < m_nHScrollMax)
{
while
(idTopLeft.col < (GetColumnCount()-1)
&& GetColumnWidth( idTopLeft.col) < 1 )
{
idTopLeft.col++;
}
int
xScroll = GetColumnWidth(idTopLeft.col);
SetScrollPos32(SB_HORZ, scrollPos + xScroll);
if
(GetScrollPos32(SB_HORZ) == scrollPos)
break
;
rect.left = GetFixedColumnWidth();
InvalidateRect(rect);
}
break
;
case
SB_LINELEFT:
if
(scrollPos > 0 && idTopLeft.col > GetFixedColumnCount())
{
int
iColToUse = idTopLeft.col-1;
while
( iColToUse > GetFixedColumnCount()
&& GetColumnWidth( iColToUse) < 1 )
{
iColToUse--;
}
int
xScroll = GetColumnWidth(iColToUse);
SetScrollPos32(SB_HORZ, max(0, scrollPos - xScroll));
rect.left = GetFixedColumnWidth();
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));
m_idTopLeftCell.row = -1;
CCellID idNewTopLeft = GetTopleftNonFixedCell();
if
(idNewTopLeft != idTopLeft)
{
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
;
default
:
break
;
}
}
void
CGridCtrl::OnVScroll(
UINT
nSBCode,
UINT
, CScrollBar*
)
{
EndEditing();
#ifndef GRIDCONTROL_NO_TITLETIPS
m_TitleTip.Hide();
#endif
int
scrollPos = GetScrollPos32(SB_VERT);
CCellID idTopLeft = GetTopleftNonFixedCell();
CRect rect;
GetClientRect(rect);
switch
(nSBCode)
{
case
SB_LINEDOWN:
if
(scrollPos < m_nVScrollMax)
{
while
( idTopLeft.row < (GetRowCount()-1)
&& GetRowHeight( idTopLeft.row) < 1 )
{
idTopLeft.row++;
}
int
yScroll = GetRowHeight(idTopLeft.row);
SetScrollPos32(SB_VERT, scrollPos + yScroll);
if
(GetScrollPos32(SB_VERT) == scrollPos)
break
;
rect.top = GetFixedRowHeight();
InvalidateRect(rect);
}
break
;
case
SB_LINEUP:
if
(scrollPos > 0 && idTopLeft.row > GetFixedRowCount())
{
int
iRowToUse = idTopLeft.row-1;
while
( iRowToUse > GetFixedRowCount()
&& GetRowHeight( iRowToUse) < 1 )
{
iRowToUse--;
}
int
yScroll = GetRowHeight( iRowToUse);
SetScrollPos32(SB_VERT, max(0, scrollPos - yScroll));
rect.top = GetFixedRowHeight();
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));
m_idTopLeftCell.row = -1;
CCellID idNewTopLeft = GetTopleftNonFixedCell();
if
(idNewTopLeft != idTopLeft)
{
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();
}
default
:
break
;
}
}
void
CGridCtrl::OnDraw(CDC* pDC)
{
if
(!m_bAllowDraw)
return
;
CRect clipRect;
if
(pDC->GetClipBox(&clipRect) == ERROR)
return
;
EraseBkgnd(pDC);
#ifdef _DEBUG
LARGE_INTEGER iStartCount;
QueryPerformanceCounter(&iStartCount);
#endif
CRect rect;
int
row, col;
CGridCellBase* pCell;
int
nFixedRowHeight = GetFixedRowHeight();
int
nFixedColWidth = GetFixedColumnWidth();
CCellID idTopLeft = GetTopleftNonFixedCell();
int
minVisibleRow = idTopLeft.row,
minVisibleCol = idTopLeft.col;
CRect VisRect;
CCellRange VisCellRange = GetVisibleNonFixedCellRange(VisRect);
int
maxVisibleRow = VisCellRange.GetMaxRow(),
maxVisibleCol = VisCellRange.GetMaxCol();
if
(GetVirtualMode())
SendCacheHintToParent(VisCellRange);
rect.bottom = -1;
for
(row = 0; row < m_nFixedRows; row++)
{
if
(GetRowHeight(row) <= 0)
continue
;
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
rect.right = -1;
for
(col = 0; col < m_nFixedCols; col++)
{
if
(GetColumnWidth(col) <= 0)
continue
;
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
pCell = GetCell(row, col);
if
(pCell)
{
pCell->SetCoords(row,col);
pCell->Draw(pDC, row, col, rect, FALSE);
}
}
}
rect.bottom = nFixedRowHeight-1;
for
(row = minVisibleRow; row <= maxVisibleRow; row++)
{
if
(GetRowHeight(row) <= 0)
continue
;
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
if
(rect.top > clipRect.bottom)
break
;
if
(rect.bottom < clipRect.top)
continue
;
rect.right = -1;
for
(col = 0; col < m_nFixedCols; col++)
{
if
(GetColumnWidth(col) <= 0)
continue
;
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
if
(rect.left > clipRect.right)
break
;
if
(rect.right < clipRect.left)
continue
;
pCell = GetCell(row, col);
if
(pCell)
{
pCell->SetCoords(row,col);
pCell->Draw(pDC, row, col, rect, FALSE);
}
}
}
rect.bottom = -1;
for
(row = 0; row < m_nFixedRows; row++)
{
if
(GetRowHeight(row) <= 0)
continue
;
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
if
(rect.top > clipRect.bottom)
break
;
if
(rect.bottom < clipRect.top)
continue
;
rect.right = nFixedColWidth-1;
for
(col = minVisibleCol; col <= maxVisibleCol; col++)
{
if
(GetColumnWidth(col) <= 0)
continue
;
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
if
(rect.left > clipRect.right)
break
;
if
(rect.right < clipRect.left)
continue
;
pCell = GetCell(row, col);
if
(pCell)
{
pCell->SetCoords(row,col);
pCell->Draw(pDC, row, col, rect, FALSE);
}
}
}
rect.bottom = nFixedRowHeight-1;
for
(row = minVisibleRow; row <= maxVisibleRow; row++)
{
if
(GetRowHeight(row) <= 0)
continue
;
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row)-1;
if
(rect.top > clipRect.bottom)
break
;
if
(rect.bottom < clipRect.top)
continue
;
rect.right = nFixedColWidth-1;
for
(col = minVisibleCol; col <= maxVisibleCol; col++)
{
if
(GetColumnWidth(col) <= 0)
continue
;
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth(col)-1;
if
(rect.left > clipRect.right)
break
;
if
(rect.right < clipRect.left)
continue
;
pCell = GetCell(row, col);
if
(pCell)
{
pCell->SetCoords(row,col);
pCell->Draw(pDC, row, col, rect, FALSE);
}
}
}
CPen pen;
pen.CreatePen(PS_SOLID, 0, m_crGridLineColour);
pDC->SelectObject(&pen);
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
int
x = nFixedColWidth;
for
(col = minVisibleCol; col <= maxVisibleCol; col++)
{
if
(GetColumnWidth(col) <= 0)
continue
;
x += GetColumnWidth(col);
pDC->MoveTo(x-1, nFixedRowHeight);
pDC->LineTo(x-1, VisRect.bottom);
}
}
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
int
y = nFixedRowHeight;
for
(row = minVisibleRow; row <= maxVisibleRow; row++)
{
if
(GetRowHeight(row) <= 0)
continue
;
y += GetRowHeight(row);
pDC->MoveTo(nFixedColWidth, y-1);
pDC->LineTo(VisRect.right, y-1);
}
}
pDC->SelectStockObject(NULL_PEN);
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(-1,-1,-1,-1));
#ifdef _DEBUG
LARGE_INTEGER iEndCount;
QueryPerformanceCounter(&iEndCount);
TRACE1(
"Draw counter ticks: %d\n"
, iEndCount.LowPart-iStartCount.LowPart);
#endif
}
BOOL
CGridCtrl::IsValid(
int
nRow,
int
nCol)
const
{
return
(nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols);
}
BOOL
CGridCtrl::IsValid(
const
CCellID& cell)
const
{
return
IsValid(cell.row, cell.col);
}
BOOL
CGridCtrl::IsValid(
const
CCellRange& range)
const
{
return
(range.GetMinRow() >= 0 && range.GetMinCol() >= 0 &&
range.GetMaxRow() >= 0 && range.GetMaxCol() >= 0 &&
range.GetMaxRow() < m_nRows && range.GetMaxCol() < m_nCols &&
range.GetMinRow() <= range.GetMaxRow() && range.GetMinCol() <= range.GetMaxCol());
}
void
CGridCtrl::SetRedraw(
BOOL
bAllowDraw,
BOOL
bResetScrollBars
)
{
if
(bAllowDraw && !m_bAllowDraw)
{
m_bAllowDraw = TRUE;
Refresh();
}
m_bAllowDraw = bAllowDraw;
if
(bResetScrollBars)
ResetScrollBars();
}
BOOL
CGridCtrl::RedrawCell(
const
CCellID& cell, CDC* pDC
)
{
return
RedrawCell(cell.row, cell.col, pDC);
}
BOOL
CGridCtrl::RedrawCell(
int
nRow,
int
nCol, CDC* pDC
)
{
BOOL
bResult = TRUE;
BOOL
bMustReleaseDC = FALSE;
if
(!m_bAllowDraw || !IsCellVisible(nRow, nCol))
return
FALSE;
CRect rect;
if
(!GetCellRect(nRow, nCol, rect))
return
FALSE;
if
(!pDC)
{
pDC = GetDC();
if
(pDC)
bMustReleaseDC = TRUE;
}
if
(pDC)
{
if
(nRow < m_nFixedRows || nCol < m_nFixedCols)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
bResult = pCell->Draw(pDC, nRow, nCol, rect, TRUE);
}
else
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
bResult = pCell->Draw(pDC, nRow, nCol, rect, TRUE);
CPen pen;
pen.CreatePen(PS_SOLID, 0, m_crGridLineColour);
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);
if
(bMustReleaseDC)
ReleaseDC(pDC);
return
bResult;
}
BOOL
CGridCtrl::RedrawRow(
int
row)
{
BOOL
bResult = TRUE;
CDC* pDC = GetDC();
for
(
int
col = 0; col < GetColumnCount(); col++)
bResult = RedrawCell(row, col, pDC) && bResult;
if
(pDC)
ReleaseDC(pDC);
return
bResult;
}
BOOL
CGridCtrl::RedrawColumn(
int
col)
{
BOOL
bResult = TRUE;
CDC* pDC = GetDC();
for
(
int
row = 0; row < GetRowCount(); row++)
bResult = RedrawCell(row, col, pDC) && bResult;
if
(pDC)
ReleaseDC(pDC);
return
bResult;
}
CCellID CGridCtrl::SetFocusCell(
int
nRow,
int
nCol)
{
return
SetFocusCell(CCellID(nRow, nCol));
}
CCellID CGridCtrl::SetFocusCell(CCellID cell)
{
if
(cell == m_idCurrentCell)
return
m_idCurrentCell;
CCellID idPrev = m_idCurrentCell;
if
(cell.row != -1 && cell.row < GetFixedRowCount())
cell.row = GetFixedRowCount();
if
(cell.col != -1 && cell.col < GetFixedColumnCount())
cell.col = GetFixedColumnCount();
m_idCurrentCell = cell;
if
(IsValid(idPrev))
{
SetItemState(idPrev.row, idPrev.col,
GetItemState(idPrev.row, idPrev.col) & ~GVIS_FOCUSED);
RedrawCell(idPrev);
if
(GetTrackFocusCell() && idPrev.col != m_idCurrentCell.col)
for
(
int
row = 0; row < m_nFixedRows; row++)
RedrawCell(row, idPrev.col);
if
(GetTrackFocusCell() && idPrev.row != m_idCurrentCell.row)
for
(
int
col = 0; col < m_nFixedCols; col++)
RedrawCell(idPrev.row, col);
}
if
(IsValid(m_idCurrentCell))
{
SetItemState(m_idCurrentCell.row, m_idCurrentCell.col,
GetItemState(m_idCurrentCell.row, m_idCurrentCell.col) | GVIS_FOCUSED);
RedrawCell(m_idCurrentCell);
if
(GetTrackFocusCell() && idPrev.col != m_idCurrentCell.col)
for
(
int
row = 0; row < m_nFixedRows; row++)
RedrawCell(row, m_idCurrentCell.col);
if
(GetTrackFocusCell() && idPrev.row != m_idCurrentCell.row)
for
(
int
col = 0; col < m_nFixedCols; col++)
RedrawCell(m_idCurrentCell.row, col);
}
return
idPrev;
}
void
CGridCtrl::SetSelectedRange(
const
CCellRange& Range,
BOOL
bForceRepaint
,
BOOL
bSelectCells
)
{
SetSelectedRange(Range.GetMinRow(), Range.GetMinCol(),
Range.GetMaxRow(), Range.GetMaxCol(),
bForceRepaint, bSelectCells);
}
void
CGridCtrl::SetSelectedRange(
int
nMinRow,
int
nMinCol,
int
nMaxRow,
int
nMaxCol,
BOOL
bForceRepaint
,
BOOL
bSelectCells
)
{
if
(!m_bEnableSelection)
return
;
CWaitCursor wait;
CDC* pDC = NULL;
if
(bForceRepaint)
pDC = GetDC();
CCellRange VisCellRange;
if
(IsWindow(GetSafeHwnd()))
VisCellRange = GetVisibleNonFixedCellRange();
if
(nMinRow >= 0 && nMinRow < GetFixedRowCount())
nMinRow = GetFixedRowCount();
if
(nMaxRow >= 0 && nMaxRow < GetFixedRowCount())
nMaxRow = GetFixedRowCount();
if
(nMinCol >= 0 && nMinCol < GetFixedColumnCount())
nMinCol = GetFixedColumnCount();
if
(nMaxCol >= 0 && nMaxCol < GetFixedColumnCount())
nMaxCol = GetFixedColumnCount();
if
(bSelectCells)
{
POSITION pos;
for
(pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD
key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
if
(IsValid(cell))
{
SetItemState(cell.row, cell.col,
GetItemState(cell.row, cell.col) & ~GVIS_SELECTED);
if
(nMinRow <= cell.row && cell.row <= nMaxRow &&
nMinCol <= cell.col && cell.col <= nMaxCol)
continue
;
if
( VisCellRange.IsValid() && VisCellRange.InRange( cell ) )
{
if
(bForceRepaint && pDC)
RedrawCell(cell.row, cell.col, pDC);
else
InvalidateCellRect(cell);
}
}
else
{
m_SelectedCellMap.RemoveKey( key);
}
}
if
( !(GetSingleRowSelection()||GetSingleColSelection()) &&
nMinRow >= 0 && nMinCol >= 0 && nMaxRow >= 0 && nMaxCol >= 0)
{
for
(pos = m_PrevSelectedCellMap.GetStartPosition(); pos != NULL;
)
{
DWORD
key;
CCellID cell;
m_PrevSelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
if
(!IsValid(cell))
continue
;
int
nState = GetItemState(cell.row, cell.col);
SetItemState(cell.row, cell.col, nState | GVIS_SELECTED);
if
( VisCellRange.IsValid() && VisCellRange.InRange( cell ) )
{
if
(bForceRepaint && pDC)
RedrawCell(cell.row, cell.col, pDC);
else
InvalidateCellRect(cell);
}
}
}
}
if
(nMinRow >= 0 && nMinCol >= 0 && nMaxRow >= 0 && nMaxCol >= 0 &&
nMaxRow < m_nRows && nMaxCol < m_nCols &&
nMinRow <= nMaxRow && nMinCol <= nMaxCol)
{
for
(
int
row = nMinRow; row <= nMaxRow; row++)
for
(
int
col = nMinCol; col <= nMaxCol; col++)
{
BOOL
bCellSelected = IsCellSelected(row, col);
if
(bSelectCells == bCellSelected)
continue
;
if
(bSelectCells)
SetItemState(row, col, GetItemState(row, col) | GVIS_SELECTED);
else
SetItemState(row, col, GetItemState(row, col) & ~GVIS_SELECTED);
if
( VisCellRange.IsValid() && VisCellRange.InRange(row, col) )
{
if
(bForceRepaint && pDC)
RedrawCell(row, col, pDC);
else
InvalidateCellRect(row, col);
}
}
}
if
(pDC != NULL)
ReleaseDC(pDC);
}
void
CGridCtrl::SelectAllCells()
{
if
(!m_bEnableSelection)
return
;
SetSelectedRange(m_nFixedRows, m_nFixedCols, GetRowCount()-1, GetColumnCount()-1);
}
void
CGridCtrl::SelectColumns(CCellID currentCell,
BOOL
bForceRedraw
,
BOOL
bSelectCells
)
{
if
(!m_bEnableSelection)
return
;
if
(currentCell.col < m_nFixedCols)
return
;
if
(!IsValid(currentCell))
return
;
if
(GetSingleColSelection())
SetSelectedRange(GetFixedRowCount(), currentCell.col,
GetRowCount()-1, currentCell.col,
bForceRedraw, bSelectCells);
else
SetSelectedRange(GetFixedRowCount(),
min(m_SelectionStartCell.col, currentCell.col),
GetRowCount()-1,
max(m_SelectionStartCell.col, currentCell.col),
bForceRedraw, bSelectCells);
}
void
CGridCtrl::SelectRows(CCellID currentCell,
BOOL
bForceRedraw
,
BOOL
bSelectCells
)
{
if
(!m_bEnableSelection)
return
;
if
(currentCell.row < m_nFixedRows)
return
;
if
(!IsValid(currentCell))
return
;
if
(GetSingleRowSelection())
SetSelectedRange(currentCell.row, GetFixedColumnCount(),
currentCell.row, GetColumnCount()-1,
bForceRedraw, bSelectCells);
else
SetSelectedRange(min(m_SelectionStartCell.row, currentCell.row),
GetFixedColumnCount(),
max(m_SelectionStartCell.row, currentCell.row),
GetColumnCount()-1,
bForceRedraw, bSelectCells);
}
void
CGridCtrl::SelectCells(CCellID currentCell,
BOOL
bForceRedraw
,
BOOL
bSelectCells
)
{
if
(!m_bEnableSelection)
return
;
int
row = currentCell.row;
int
col = currentCell.col;
if
(row < m_nFixedRows || col < m_nFixedCols)
return
;
if
(!IsValid(currentCell))
return
;
SetSelectedRange(min(m_SelectionStartCell.row, row),
min(m_SelectionStartCell.col, col),
max(m_SelectionStartCell.row, row),
max(m_SelectionStartCell.col, col),
bForceRedraw, bSelectCells);
}
void
CGridCtrl::OnSelecting(
const
CCellID& currentCell)
{
if
(!m_bEnableSelection)
return
;
switch
(m_MouseMode)
{
case
MOUSE_SELECT_ALL:
SelectAllCells();
break
;
case
MOUSE_SELECT_COL:
SelectColumns(currentCell, FALSE);
break
;
case
MOUSE_SELECT_ROW:
SelectRows(currentCell, FALSE);
break
;
case
MOUSE_SELECT_CELLS:
SelectCells(currentCell, FALSE);
break
;
}
}
void
CGridCtrl::ValidateAndModifyCellContents(
int
nRow,
int
nCol,
LPCTSTR
strText)
{
if
(!IsCellEditable(nRow, nCol))
return
;
if
(SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT) >= 0)
{
CString strCurrentText = GetItemText(nRow, nCol);
if
(strCurrentText != strText)
{
SetItemText(nRow, nCol, strText);
if
(ValidateEdit(nRow, nCol, strText) &&
SendMessageToParent(nRow, nCol, GVN_ENDLABELEDIT) >= 0)
{
SetModified(TRUE, nRow, nCol);
RedrawCell(nRow, nCol);
}
else
{
SetItemText(nRow, nCol, strCurrentText);
}
}
}
}
void
CGridCtrl::ClearCells(CCellRange Selection)
{
for
(
int
row = Selection.GetMinRow(); row <= Selection.GetMaxRow(); row++)
{
for
(
int
col = Selection.GetMinCol(); col <= Selection.GetMaxCol(); col++)
{
if
( m_arRowHeights[row] > 0 && m_arColWidths[col] > 0 )
{
ValidateAndModifyCellContents(row, col, _T(
""
));
}
}
}
Refresh();
}
#ifndef GRIDCONTROL_NO_CLIPBOARD
void
CGridCtrl::CutSelectedText()
{
if
(!IsEditable())
return
;
for
(POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD
key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
ValidateAndModifyCellContents(cell.row, cell.col, _T(
""
));
}
}
COleDataSource* CGridCtrl::CopyTextFromGrid()
{
USES_CONVERSION;
CCellRange Selection = GetSelectedCellRange();
if
(!IsValid(Selection))
return
NULL;
if
(GetVirtualMode())
SendCacheHintToParent(Selection);
CSharedFile sf(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
CString str;
CGridCellBase *pCell;
for
(
int
row = Selection.GetMinRow(); row <= Selection.GetMaxRow(); row++)
{
if
( m_arRowHeights[row] <= 0 )
continue
;
str.Empty();
for
(
int
col = Selection.GetMinCol(); col <= Selection.GetMaxCol(); col++)
{
if
( m_arColWidths[col] <= 0 )
continue
;
pCell = GetCell(row, col);
if
(pCell &&(pCell->GetState() & GVIS_SELECTED))
{
str += pCell->GetText();
}
if
(col != Selection.GetMaxCol())
str += _T(
"\t"
);
}
if
(row != Selection.GetMaxRow())
str += _T(
"\r\n"
);
sf.Write(T2A(str.GetBuffer(1)), str.GetLength());
str.ReleaseBuffer();
}
char
c =
'\0'
;
sf.Write(&c, 1);
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(-1,-1,-1,-1));
DWORD
dwLen = (
DWORD
) sf.GetLength();
HGLOBAL
hMem = sf.Detach();
if
(!hMem)
return
NULL;
hMem = ::GlobalReAlloc(hMem, dwLen, GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
if
(!hMem)
return
NULL;
COleDataSource* pSource =
new
COleDataSource();
pSource->CacheGlobalData(CF_TEXT, hMem);
return
pSource;
}
BOOL
CGridCtrl::PasteTextToGrid(CCellID cell, COleDataObject* pDataObject,
BOOL
bSelectPastedCells
)
{
if
(!IsValid(cell) || !IsCellEditable(cell) || !pDataObject->IsDataAvailable(CF_TEXT))
return
FALSE;
HGLOBAL
hmem = pDataObject->GetGlobalData(CF_TEXT);
CMemFile sf((
BYTE
*) ::GlobalLock(hmem), ::GlobalSize(hmem));
LPTSTR
szBuffer =
new
TCHAR
[::GlobalSize(hmem)];
if
(!szBuffer)
return
FALSE;
sf.Read(szBuffer, ::GlobalSize(hmem));
::GlobalUnlock(hmem);
CString strText = szBuffer;
delete
szBuffer;
strText.LockBuffer();
CString strLine = strText;
int
nLine = 0;
CCellRange PasteRange(cell.row, cell.col,-1,-1);
int
nIndex;
do
{
int
nColumn = 0;
nIndex = strLine.Find(_T(
"\n"
));
CString strNext = (nIndex < 0)? _T(
""
) : strLine.Mid(nIndex + 1);
if
(nIndex >= 0)
strLine = strLine.Left(nIndex);
int
nLineIndex = strLine.FindOneOf(_T(
"\t,"
));
CString strCellText = (nLineIndex >= 0)? strLine.Left(nLineIndex) : strLine;
int
iRowVis = cell.row + nLine;
while
( iRowVis < GetRowCount())
{
if
( GetRowHeight( iRowVis) > 0)
break
;
nLine++;
iRowVis++;
}
while
(!strLine.IsEmpty())
{
int
iColVis = cell.col + nColumn;
while
( iColVis < GetColumnCount())
{
if
( GetColumnWidth( iColVis) > 0)
break
;
nColumn++;
iColVis++;
}
CCellID TargetCell(iRowVis, iColVis);
if
(IsValid(TargetCell))
{
strCellText.TrimLeft();
strCellText.TrimRight();
ValidateAndModifyCellContents(TargetCell.row, TargetCell.col, strCellText);
SetItemState(TargetCell.row, TargetCell.col,
GetItemState(TargetCell.row, TargetCell.col) & ~GVIS_SELECTED);
if
(iRowVis > PasteRange.GetMaxRow()) PasteRange.SetMaxRow(iRowVis);
if
(iColVis > PasteRange.GetMaxCol()) PasteRange.SetMaxCol(iColVis);
}
strLine = (nLineIndex >= 0)? strLine.Mid(nLineIndex + 1) : _T(
""
);
nLineIndex = strLine.FindOneOf(_T(
"\t,"
));
strCellText = (nLineIndex >= 0)? strLine.Left(nLineIndex) : strLine;
nColumn++;
}
strLine = strNext;
nLine++;
}
while
(nIndex >= 0);
strText.UnlockBuffer();
if
(bSelectPastedCells)
SetSelectedRange(PasteRange, TRUE);
else
{
ResetSelectedRange();
Refresh();
}
return
TRUE;
}
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
void
CGridCtrl::OnBeginDrag()
{
if
(!m_bAllowDragAndDrop)
return
;
COleDataSource* pSource = CopyTextFromGrid();
if
(pSource)
{
SendMessageToParent(GetSelectedCellRange().GetTopLeft().row,
GetSelectedCellRange().GetTopLeft().col,
GVN_BEGINDRAG);
m_MouseMode = MOUSE_DRAGGING;
m_bLMouseButtonDown = FALSE;
DROPEFFECT dropEffect = pSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE);
if
(dropEffect & DROPEFFECT_MOVE)
CutSelectedText();
if
(pSource)
delete
pSource;
}
}
DROPEFFECT CGridCtrl::OnDragOver(COleDataObject* pDataObject,
DWORD
dwKeyState,
CPoint point)
{
if
(!m_bAllowDragAndDrop || !IsEditable() || !pDataObject->IsDataAvailable(CF_TEXT))
return
DROPEFFECT_NONE;
CCellID cell = GetCellFromPt(point, FALSE);
if
(!IsValid(cell))
{
OnDragLeave();
m_LastDragOverCell = CCellID(-1,-1);
return
DROPEFFECT_NONE;
}
if
(!IsCellEditable(cell))
return
DROPEFFECT_NONE;
if
(cell != m_LastDragOverCell)
{
if
(IsValid(m_LastDragOverCell))
{
UINT
nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState & ~GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
m_LastDragOverCell = cell;
if
(IsValid(m_LastDragOverCell))
{
UINT
nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState | GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
}
if
(dwKeyState & MK_CONTROL)
return
DROPEFFECT_COPY;
else
return
DROPEFFECT_MOVE;
}
DROPEFFECT CGridCtrl::OnDragEnter(COleDataObject* pDataObject,
DWORD
dwKeyState,
CPoint point)
{
if
(!m_bAllowDragAndDrop || !pDataObject->IsDataAvailable(CF_TEXT))
return
DROPEFFECT_NONE;
m_LastDragOverCell = GetCellFromPt(point, FALSE);
if
(!IsValid(m_LastDragOverCell))
return
DROPEFFECT_NONE;
if
(!IsCellEditable(m_LastDragOverCell))
return
DROPEFFECT_NONE;
if
(IsValid(m_LastDragOverCell))
{
UINT
nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState | GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
if
(dwKeyState & MK_CONTROL)
return
DROPEFFECT_COPY;
else
return
DROPEFFECT_MOVE;
}
void
CGridCtrl::OnDragLeave()
{
if
(IsValid(m_LastDragOverCell))
{
UINT
nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState & ~GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
}
BOOL
CGridCtrl::OnDrop(COleDataObject* pDataObject, DROPEFFECT
,
CPoint
)
{
m_MouseMode = MOUSE_NOTHING;
if
(!m_bAllowDragAndDrop || !IsCellEditable(m_LastDragOverCell))
return
FALSE;
OnDragLeave();
return
PasteTextToGrid(m_LastDragOverCell, pDataObject, FALSE);
}
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
void
CGridCtrl::OnEditCut()
{
if
(!IsEditable())
return
;
COleDataSource* pSource = CopyTextFromGrid();
if
(!pSource)
return
;
pSource->SetClipboard();
CutSelectedText();
}
void
CGridCtrl::OnEditCopy()
{
COleDataSource* pSource = CopyTextFromGrid();
if
(!pSource)
return
;
pSource->SetClipboard();
}
void
CGridCtrl::OnEditPaste()
{
if
(!IsEditable())
return
;
CCellRange cellRange = GetSelectedCellRange();
CCellID cell;
if
(cellRange.IsValid())
{
cell.row = cellRange.GetMinRow();
cell.col = cellRange.GetMinCol();
}
else
{
cell = GetFocusCell();
if
(!IsValid(cell))
cell = GetTopleftNonFixedCell();
if
(!IsValid(cell))
return
;
}
if
( IsItemEditing(cell.row, cell.col) )
{
CGridCellBase* pCell = GetCell(cell.row, cell.col);
ASSERT(pCell);
if
(!pCell)
return
;
CWnd* pEditWnd = pCell->GetEditWnd();
if
( pEditWnd && pEditWnd->IsKindOf(RUNTIME_CLASS(CEdit)) )
{
((CEdit*)pEditWnd)->Paste();
return
;
}
}
COleDataObject obj;
if
(obj.AttachClipboard())
PasteTextToGrid(cell, &obj);
}
#endif
void
CGridCtrl::OnEditSelectAll()
{
SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
SelectAllCells();
SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
}
#ifndef GRIDCONTROL_NO_CLIPBOARD
void
CGridCtrl::OnUpdateEditCopy(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetSelectedCount() > 0);
}
void
CGridCtrl::OnUpdateEditCut(CCmdUI* pCmdUI)
{
pCmdUI->Enable(IsEditable() && GetSelectedCount() > 0);
}
void
CGridCtrl::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
CCellID cell = GetFocusCell();
BOOL
bCanPaste = IsValid(cell) && IsCellEditable(cell) &&
::IsClipboardFormatAvailable(CF_TEXT);
pCmdUI->Enable(bCanPaste);
}
#endif
void
CGridCtrl::OnUpdateEditSelectAll(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bEnableSelection);
}
BOOL
CGridCtrl::MouseOverRowResizeArea(CPoint& point)
{
if
(point.x >= GetFixedColumnWidth())
return
FALSE;
CCellID idCurrentCell = GetCellFromPt(point);
CPoint start;
if
(!GetCellOrigin(idCurrentCell, &start))
return
FALSE;
int
endy = start.y + GetRowHeight(idCurrentCell.row);
if
((point.y - start.y < m_nResizeCaptureRange && idCurrentCell.row != 0) ||
endy - point.y < m_nResizeCaptureRange)
{
return
TRUE;
}
else
return
FALSE;
}
BOOL
CGridCtrl::MouseOverColumnResizeArea(CPoint& point)
{
if
(point.y >= GetFixedRowHeight())
return
FALSE;
CCellID idCurrentCell = GetCellFromPt(point);
CPoint start;
if
(!GetCellOrigin(idCurrentCell, &start))
return
FALSE;
int
endx = start.x + GetColumnWidth(idCurrentCell.col);
if
((point.x - start.x < m_nResizeCaptureRange && idCurrentCell.col != 0) ||
endx - point.x < m_nResizeCaptureRange)
{
return
TRUE;
}
else
return
FALSE;
}
CCellID CGridCtrl::GetCellFromPt(CPoint point,
BOOL
bAllowFixedCellCheck
)
{
CCellID cellID;
CCellID idTopLeft = GetTopleftNonFixedCell();
if
(!bAllowFixedCellCheck && !IsValid(idTopLeft))
return
cellID;
int
fixedColWidth = GetFixedColumnWidth();
if
(point.x < 0 || (!bAllowFixedCellCheck && point.x < fixedColWidth))
cellID.col = -1;
else
if
(point.x < fixedColWidth)
{
int
xpos = 0;
int
col = 0;
while
(col < m_nFixedCols)
{
xpos += GetColumnWidth(col);
if
(xpos > point.x)
break
;
col++;
}
cellID.col = col;
}
else
{
int
xpos = fixedColWidth;
int
col = idTopLeft.col;
while
( col < GetColumnCount())
{
xpos += GetColumnWidth(col);
if
(xpos > point.x)
break
;
col++;
}
if
(col >= GetColumnCount())
cellID.col = -1;
else
cellID.col = col;
}
int
fixedRowHeight = GetFixedRowHeight();
if
(point.y < 0 || (!bAllowFixedCellCheck && point.y < fixedRowHeight))
cellID.row = -1;
else
if
(point.y < fixedRowHeight)
{
int
ypos = 0;
int
row = 0;
while
(row < m_nFixedRows)
{
ypos += GetRowHeight(row);
if
(ypos > point.y)
break
;
row++;
}
cellID.row = row;
}
else
{
int
ypos = fixedRowHeight;
int
row = idTopLeft.row;
while
( row < GetRowCount() )
{
ypos += GetRowHeight(row);
if
(ypos > point.y)
break
;
row++;
}
if
(row >= GetRowCount())
cellID.row = -1;
else
cellID.row = row;
}
return
cellID;
}
CCellID CGridCtrl::GetTopleftNonFixedCell(
BOOL
bForceRecalculation
)
{
if
(m_idTopLeftCell.IsValid() && !bForceRecalculation)
return
m_idTopLeftCell;
int
nVertScroll = GetScrollPos(SB_VERT),
nHorzScroll = GetScrollPos(SB_HORZ);
m_idTopLeftCell.col = m_nFixedCols;
int
nRight = 0;
while
(nRight < nHorzScroll && m_idTopLeftCell.col < (GetColumnCount()-1))
nRight += GetColumnWidth(m_idTopLeftCell.col++);
m_idTopLeftCell.row = m_nFixedRows;
int
nTop = 0;
while
(nTop < nVertScroll && m_idTopLeftCell.row < (GetRowCount()-1))
nTop += GetRowHeight(m_idTopLeftCell.row++);
return
m_idTopLeftCell;
}
CCellRange CGridCtrl::GetVisibleNonFixedCellRange(LPRECT pRect
,
BOOL
bForceRecalculation
)
{
CRect rect;
GetClientRect(rect);
CCellID idTopLeft = GetTopleftNonFixedCell(bForceRecalculation);
int
bottom = GetFixedRowHeight();
for
(
int
i = idTopLeft.row; i < GetRowCount(); i++)
{
bottom += GetRowHeight(i);
if
(bottom >= rect.bottom)
{
bottom = rect.bottom;
break
;
}
}
int
maxVisibleRow = min(i, GetRowCount() - 1);
int
right = GetFixedColumnWidth();
for
(i = idTopLeft.col; i < GetColumnCount(); i++)
{
right += GetColumnWidth(i);
if
(right >= rect.right)
{
right = rect.right;
break
;
}
}
int
maxVisibleCol = min(i, GetColumnCount() - 1);
if
(pRect)
{
pRect->left = pRect->top = 0;
pRect->right = right;
pRect->bottom = bottom;
}
return
CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
}
CCellRange CGridCtrl::GetUnobstructedNonFixedCellRange(
BOOL
bForceRecalculation
)
{
CRect rect;
GetClientRect(rect);
CCellID idTopLeft = GetTopleftNonFixedCell(bForceRecalculation);
int
bottom = GetFixedRowHeight();
for
(
int
i = idTopLeft.row; i < GetRowCount(); i++)
{
bottom += GetRowHeight(i);
if
(bottom >= rect.bottom)
break
;
}
int
maxVisibleRow = min(i, GetRowCount() - 1);
if
(maxVisibleRow > 0 && bottom > rect.bottom)
maxVisibleRow--;
int
right = GetFixedColumnWidth();
for
(i = idTopLeft.col; i < GetColumnCount(); i++)
{
right += GetColumnWidth(i);
if
(right >= rect.right)
break
;
}
int
maxVisibleCol = min(i, GetColumnCount() - 1);
if
(maxVisibleCol > 0 && right > rect.right)
maxVisibleCol--;
return
CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
}
CCellRange CGridCtrl::GetSelectedCellRange()
const
{
CCellRange Selection(GetRowCount(), GetColumnCount(), -1,-1);
for
(POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD
key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
Selection.SetMinRow( min(Selection.GetMinRow(), cell.row) );
Selection.SetMinCol( min(Selection.GetMinCol(), cell.col) );
Selection.SetMaxRow( max(Selection.GetMaxRow(), cell.row) );
Selection.SetMaxCol( max(Selection.GetMaxCol(), cell.col) );
}
return
Selection;
}
CCellRange CGridCtrl::GetCellRange()
const
{
return
CCellRange(0, 0, GetRowCount() - 1, GetColumnCount() - 1);
}
void
CGridCtrl::ResetSelectedRange()
{
m_PrevSelectedCellMap.RemoveAll();
SetSelectedRange(-1,-1,-1,-1);
SetFocusCell(-1,-1);
}
int
CGridCtrl::GetScrollPos32(
int
nBar,
BOOL
bGetTrackPos
)
{
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
CGridCtrl::SetScrollPos32(
int
nBar,
int
nPos,
BOOL
bRedraw
)
{
m_idTopLeftCell.row = -1;
SCROLLINFO si;
si.cbSize =
sizeof
(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = nPos;
return
SetScrollInfo(nBar, &si, bRedraw);
}
void
CGridCtrl::EnableScrollBars(
int
nBar,
BOOL
bEnable
)
{
if
(bEnable)
{
if
(!IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
{
m_nBarState |= GVL_HORZ;
CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
}
if
(!IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
{
m_nBarState |= GVL_VERT;
CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
}
}
else
{
if
( IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
{
m_nBarState &= ~GVL_HORZ;
CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
}
if
( IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
{
m_nBarState &= ~GVL_VERT;
CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
}
}
}
void
CGridCtrl::ResetScrollBars()
{
m_idTopLeftCell.row = -1;
if
(!m_bAllowDraw || !::IsWindow(GetSafeHwnd()))
return
;
CRect rect;
GetClientRect(rect);
if
(rect.left == rect.right || rect.top == rect.bottom)
return
;
if
(IsVisibleVScroll())
rect.right += GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXBORDER);
if
(IsVisibleHScroll())
rect.bottom += GetSystemMetrics(SM_CYHSCROLL) + GetSystemMetrics(SM_CYBORDER);
rect.left += GetFixedColumnWidth();
rect.top += GetFixedRowHeight();
if
(rect.left >= rect.right || rect.top >= rect.bottom)
{
EnableScrollBarCtrl(SB_BOTH, FALSE);
return
;
}
CRect VisibleRect(GetFixedColumnWidth(), GetFixedRowHeight(),
rect.right, rect.bottom);
CRect VirtualRect(GetFixedColumnWidth(), GetFixedRowHeight(),
GetVirtualWidth(), GetVirtualHeight());
if
(VisibleRect.Height() < VirtualRect.Height())
VisibleRect.right -= ::GetSystemMetrics(SM_CXVSCROLL);
if
(VisibleRect.Width() < VirtualRect.Width())
VisibleRect.bottom -= ::GetSystemMetrics(SM_CYHSCROLL);
if
(VisibleRect.Height() < VirtualRect.Height())
{
EnableScrollBars(SB_VERT, TRUE);
m_nVScrollMax = VirtualRect.Height() - 1;
}
else
{
EnableScrollBars(SB_VERT, FALSE);
m_nVScrollMax = 0;
}
if
(VisibleRect.Width() < VirtualRect.Width())
{
EnableScrollBars(SB_HORZ, TRUE);
m_nHScrollMax = VirtualRect.Width() - 1;
}
else
{
EnableScrollBars(SB_HORZ, FALSE);
m_nHScrollMax = 0;
}
ASSERT(m_nVScrollMax < INT_MAX && m_nHScrollMax < INT_MAX);
SCROLLINFO si;
si.cbSize =
sizeof
(SCROLLINFO);
si.fMask = SIF_PAGE | SIF_RANGE;
si.nPage = (m_nHScrollMax>0)? VisibleRect.Width() : 0;
si.nMin = 0;
si.nMax = m_nHScrollMax;
SetScrollInfo(SB_HORZ, &si, TRUE);
si.fMask |= SIF_DISABLENOSCROLL;
si.nPage = (m_nVScrollMax>0)? VisibleRect.Height() : 0;
si.nMin = 0;
si.nMax = m_nVScrollMax;
SetScrollInfo(SB_VERT, &si, TRUE);
}
BOOL
CGridCtrl::GetCellOrigin(
int
nRow,
int
nCol, LPPOINT p)
{
int
i;
if
(!IsValid(nRow, nCol))
return
FALSE;
CCellID 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)
for
(i = 0; i < nCol; i++)
p->x += GetColumnWidth(i);
else
{
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)
for
(i = 0; i < nRow; i++)
p->y += GetRowHeight(i);
else
{
for
(i = 0; i < m_nFixedRows; i++)
p->y += GetRowHeight(i);
for
(i = idTopLeft.row; i < nRow; i++)
p->y += GetRowHeight(i);
}
return
TRUE;
}
BOOL
CGridCtrl::GetCellOrigin(
const
CCellID& cell, LPPOINT p)
{
return
GetCellOrigin(cell.row, cell.col, p);
}
BOOL
CGridCtrl::GetCellRect(
const
CCellID& cell, LPRECT pRect)
{
return
GetCellRect(cell.row, cell.col, pRect);
}
BOOL
CGridCtrl::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
CGridCtrl::GetTextRect(
const
CCellID& cell, LPRECT pRect)
{
return
GetTextRect(cell.row, cell.col, pRect);
}
BOOL
CGridCtrl::GetTextRect(
int
nRow,
int
nCol, LPRECT pRect)
{
CGridCellBase* pCell = GetCell( nRow, nCol);
if
( pCell == NULL)
return
FALSE;
if
( !GetCellRect( nRow, nCol, pRect) )
return
FALSE;
return
pCell->GetTextRect( pRect);
}
BOOL
CGridCtrl::GetCellRangeRect(
const
CCellRange& cellRange, LPRECT lpRect)
{
CPoint MinOrigin,MaxOrigin;
if
(!GetCellOrigin(cellRange.GetMinRow(), cellRange.GetMinCol(), &MinOrigin))
return
FALSE;
if
(!GetCellOrigin(cellRange.GetMaxRow(), cellRange.GetMaxCol(), &MaxOrigin))
return
FALSE;
lpRect->left = MinOrigin.x;
lpRect->top = MinOrigin.y;
lpRect->right = MaxOrigin.x + GetColumnWidth(cellRange.GetMaxCol()) - 1;
lpRect->bottom = MaxOrigin.y + GetRowHeight(cellRange.GetMaxRow()) - 1;
return
TRUE;
}
LRESULT
CGridCtrl::OnSetFont(
WPARAM
hFont,
LPARAM
)
{
LRESULT
result = Default();
LOGFONT lf;
if
(!GetObject((
HFONT
) hFont,
sizeof
(LOGFONT), &lf))
return
result;
m_cellDefault.SetFont(&lf);
m_cellFixedColDef.SetFont(&lf);
m_cellFixedRowDef.SetFont(&lf);
m_cellFixedRowColDef.SetFont(&lf);
Refresh();
return
result;
}
LRESULT
CGridCtrl::OnGetFont(
WPARAM
,
LPARAM
)
{
return
(
LRESULT
) m_cellDefault.GetFontObject()->GetSafeHandle();
}
#ifndef _WIN32_WCE_NO_CURSOR
BOOL
CGridCtrl::OnSetCursor(CWnd* pWnd,
UINT
nHitTest,
UINT
message)
{
if
(nHitTest == HTCLIENT)
{
switch
(m_MouseMode)
{
case
MOUSE_OVER_COL_DIVIDE:
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
break
;
case
MOUSE_OVER_ROW_DIVIDE:
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
break
;
#ifndef GRIDCONTROL_NO_DRAGDROP
case
MOUSE_DRAGGING:
break
;
#endif
default
:
if
(!GetVirtualMode())
{
CPoint pt(GetMessagePos());
ScreenToClient(&pt);
CCellID cell = GetCellFromPt(pt);
if
(IsValid(cell))
{
CGridCellBase* pCell = GetCell(cell.row, cell.col);
if
(pCell)
return
pCell->OnSetCursor();
}
}
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
}
return
TRUE;
}
return
CWnd::OnSetCursor(pWnd, nHitTest, message);
}
#endif
BOOL
CGridCtrl::SetFixedRowCount(
int
nFixedRows)
{
if
(m_nFixedRows == nFixedRows)
return
TRUE;
ASSERT(nFixedRows >= 0);
ResetSelectedRange();
m_idTopLeftCell.col = -1;
if
(nFixedRows > GetRowCount())
if
(!SetRowCount(nFixedRows))
return
FALSE;
if
(m_idCurrentCell.row < nFixedRows)
SetFocusCell(-1, - 1);
if
(!GetVirtualMode())
{
if
(nFixedRows > m_nFixedRows)
{
for
(
int
i = m_nFixedRows; i < nFixedRows; i++)
for
(
int
j = 0; j < GetColumnCount(); j++)
{
SetItemState(i, j, GetItemState(i, j) | GVIS_FIXED | GVIS_FIXEDROW);
SetItemBkColour(i, j, CLR_DEFAULT );
SetItemFgColour(i, j, CLR_DEFAULT );
}
}
else
{
for
(
int
i = nFixedRows; i < m_nFixedRows; i++)
{
int
j;
for
(j = 0; j < GetFixedColumnCount(); j++)
SetItemState(i, j, GetItemState(i, j) & ~GVIS_FIXEDROW );
for
(j = GetFixedColumnCount(); j < GetColumnCount(); j++)
{
SetItemState(i, j, GetItemState(i, j) & ~(GVIS_FIXED | GVIS_FIXEDROW) );
SetItemBkColour(i, j, CLR_DEFAULT );
SetItemFgColour(i, j, CLR_DEFAULT );
}
}
}
}
m_nFixedRows = nFixedRows;
Refresh();
return
TRUE;
}
BOOL
CGridCtrl::SetFixedColumnCount(
int
nFixedCols)
{
if
(m_nFixedCols == nFixedCols)
return
TRUE;
ASSERT(nFixedCols >= 0);
if
(nFixedCols > GetColumnCount())
if
(!SetColumnCount(nFixedCols))
return
FALSE;
if
(m_idCurrentCell.col < nFixedCols)
SetFocusCell(-1, - 1);
ResetSelectedRange();
m_idTopLeftCell.col = -1;
if
(!GetVirtualMode())
{
if
(nFixedCols > m_nFixedCols)
{
for
(
int
i = 0; i < GetRowCount(); i++)
for
(
int
j = m_nFixedCols; j < nFixedCols; j++)
{
SetItemState(i, j, GetItemState(i, j) | GVIS_FIXED | GVIS_FIXEDCOL);
SetItemBkColour(i, j, CLR_DEFAULT );
SetItemFgColour(i, j, CLR_DEFAULT );
}
}
else
{
{
for
(
int
i = 0; i < GetFixedRowCount(); i++)
for
(
int
j = nFixedCols; j < m_nFixedCols; j++)
SetItemState(i, j, GetItemState(i, j) & ~GVIS_FIXEDCOL );
}
{
for
(
int
i = GetFixedRowCount(); i < GetRowCount(); i++)
for
(
int
j = nFixedCols; j < m_nFixedCols; j++)
{
SetItemState(i, j, GetItemState(i, j) & ~(GVIS_FIXED | GVIS_FIXEDCOL) );
SetItemBkColour(i, j, CLR_DEFAULT );
SetItemFgColour(i, j, CLR_DEFAULT );
}
}
}
}
m_nFixedCols = nFixedCols;
Refresh();
return
TRUE;
}
BOOL
CGridCtrl::SetRowCount(
int
nRows)
{
BOOL
bResult = TRUE;
ASSERT(nRows >= 0);
if
(nRows == GetRowCount())
return
bResult;
m_idTopLeftCell.col = -1;
if
(nRows < m_nFixedRows)
m_nFixedRows = nRows;
if
(m_idCurrentCell.row >= nRows)
SetFocusCell(-1, - 1);
int
addedRows = nRows - GetRowCount();
if
(addedRows < 0)
{
if
(!GetVirtualMode())
{
for
(
int
row = nRows; row < m_nRows; row++)
{
for
(
int
col = 0; col < m_nCols; col++)
DestroyCell(row, col);
GRID_ROW* pRow = m_RowData[row];
if
(pRow)
delete
pRow;
}
}
m_nRows = nRows;
}
TRY
{
m_arRowHeights.SetSize(nRows);
if
(GetVirtualMode())
{
m_nRows = nRows;
if
(addedRows > 0)
{
int
startRow = nRows - addedRows;
for
(
int
row = startRow; row < nRows; row++)
m_arRowHeights[row] = m_cellDefault.GetHeight();
}
}
else
{
m_RowData.SetSize(nRows);
if
(addedRows > 0)
{
int
startRow = nRows - addedRows;
for
(
int
row = startRow; row < nRows; row++)
{
m_arRowHeights[row] = m_cellDefault.GetHeight();
m_RowData[row] =
new
GRID_ROW;
m_RowData[row]->SetSize(m_nCols);
for
(
int
col = 0; col < m_nCols; col++)
{
GRID_ROW* pRow = m_RowData[row];
if
(pRow && !GetVirtualMode())
pRow->SetAt(col, CreateCell(row, col));
}
m_nRows++;
}
}
}
}
CATCH (CMemoryException, e)
{
e->ReportError();
bResult = FALSE;
}
END_CATCH
SetModified();
ResetScrollBars();
Refresh();
return
bResult;
}
BOOL
CGridCtrl::SetColumnCount(
int
nCols)
{
BOOL
bResult = TRUE;
ASSERT(nCols >= 0);
if
(nCols == GetColumnCount())
return
bResult;
m_idTopLeftCell.col = -1;
if
(nCols < m_nFixedCols)
m_nFixedCols = nCols;
if
(m_idCurrentCell.col >= nCols)
SetFocusCell(-1, - 1);
int
addedCols = nCols - GetColumnCount();
if
(addedCols < 0 && !GetVirtualMode())
{
for
(
int
row = 0; row < m_nRows; row++)
for
(
int
col = nCols; col < GetColumnCount(); col++)
DestroyCell(row, col);
}
TRY
{
m_arColWidths.SetSize(nCols);
if
(!GetVirtualMode())
for
(
int
i = 0; i < m_nRows; i++)
if
(m_RowData[i])
m_RowData[i]->SetSize(nCols);
if
(addedCols > 0)
{
int
startCol = nCols - addedCols;
for
(
int
col = startCol; col < nCols; col++)
m_arColWidths[col] = m_cellFixedColDef.GetWidth();
if
(!GetVirtualMode())
{
for
(
int
row = 0; row < m_nRows; row++)
for
(col = startCol; col < nCols; col++)
{
GRID_ROW* pRow = m_RowData[row];
if
(pRow)
pRow->SetAt(col, CreateCell(row, col));
}
}
}
}
CATCH (CMemoryException, e)
{
e->ReportError();
bResult = FALSE;
}
END_CATCH
m_nCols = nCols;
SetModified();
ResetScrollBars();
Refresh();
return
bResult;
}
int
CGridCtrl::InsertColumn(
LPCTSTR
strHeading,
UINT
nFormat
,
int
nColumn
)
{
if
(nColumn >= 0 && nColumn < m_nFixedCols)
{
ASSERT(FALSE);
return
-1;
}
if
(nColumn >= 0 && nColumn > GetColumnCount())
return
-1;
m_idTopLeftCell.col = -1;
ResetSelectedRange();
if
(m_nRows < 1)
SetRowCount(1);
if
(nColumn == GetColumnCount())
nColumn = -1;
TRY
{
if
(nColumn < 0)
{
nColumn = m_nCols;
m_arColWidths.Add(0);
if
(!GetVirtualMode())
{
for
(
int
row = 0; row < m_nRows; row++)
{
GRID_ROW* pRow = m_RowData[row];
if
(!pRow)
return
-1;
pRow->Add(CreateCell(row, nColumn));
}
}
}
else
{
m_arColWidths.InsertAt(nColumn, (
UINT
)0);
if
(!GetVirtualMode())
{
for
(
int
row = 0; row < m_nRows; row++)
{
GRID_ROW* pRow = m_RowData[row];
if
(!pRow)
return
-1;
pRow->InsertAt(nColumn, CreateCell(row, nColumn));
}
}
}
}
CATCH (CMemoryException, e)
{
e->ReportError();
return
-1;
}
END_CATCH
m_nCols++;
SetItemText(0, nColumn, strHeading);
for
(
int
row = 0; row < m_nRows; row++)
SetItemFormat(row, nColumn, nFormat);
m_arColWidths[nColumn] = GetTextExtent(0, nColumn, strHeading).cx;
if
(m_idCurrentCell.col != -1 && nColumn < m_idCurrentCell.col)
m_idCurrentCell.col++;
ResetScrollBars();
SetModified();
return
nColumn;
}
int
CGridCtrl::InsertRow(
LPCTSTR
strHeading,
int
nRow
)
{
if
(nRow >= 0 && nRow < m_nFixedRows)
{
ASSERT(FALSE);
return
-1;
}
if
(nRow >= 0 && nRow >= GetRowCount())
return
-1;
m_idTopLeftCell.col = -1;
ResetSelectedRange();
if
(m_nCols < 1)
SetColumnCount(1);
TRY
{
if
(nRow < 0)
{
nRow = m_nRows;
m_arRowHeights.Add(0);
if
(!GetVirtualMode())
m_RowData.Add(
new
GRID_ROW);
}
else
{
m_arRowHeights.InsertAt(nRow, (
UINT
)0);
if
(!GetVirtualMode())
m_RowData.InsertAt(nRow,
new
GRID_ROW);
}
if
(!GetVirtualMode())
m_RowData[nRow]->SetSize(m_nCols);
}
CATCH (CMemoryException, e)
{
e->ReportError();
return
-1;
}
END_CATCH
m_nRows++;
if
(!GetVirtualMode())
{
for
(
int
col = 0; col < m_nCols; col++)
{
GRID_ROW* pRow = m_RowData[nRow];
if
(!pRow)
return
-1;
pRow->SetAt(col, CreateCell(nRow, col));
}
}
SetItemText(nRow, 0, strHeading);
if
(strHeading && strHeading[0])
m_arRowHeights[nRow] = GetTextExtent(nRow, 0, strHeading).cy;
else
m_arRowHeights[nRow] = m_cellFixedRowDef.GetHeight();
if
(m_idCurrentCell.row != -1 && nRow < m_idCurrentCell.row)
m_idCurrentCell.row++;
ResetScrollBars();
SetModified();
return
nRow;
}
BOOL
CGridCtrl::SetCellType(
int
nRow,
int
nCol, CRuntimeClass* pRuntimeClass)
{
if
(GetVirtualMode())
return
FALSE;
ASSERT(IsValid(nRow, nCol));
if
(!IsValid(nRow, nCol))
return
FALSE;
if
(!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
{
ASSERT( FALSE);
return
FALSE;
}
CGridCellBase* pNewCell = (CGridCellBase*) pRuntimeClass->CreateObject();
CGridCellBase* pCurrCell = GetCell(nRow, nCol);
if
(pCurrCell)
*pNewCell = *pCurrCell;
SetCell(nRow, nCol, pNewCell);
delete
pCurrCell;
return
TRUE;
}
BOOL
CGridCtrl::SetDefaultCellType( CRuntimeClass* pRuntimeClass)
{
ASSERT( pRuntimeClass != NULL );
if
(!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
{
ASSERT( FALSE);
return
FALSE;
}
m_pRtcDefault = pRuntimeClass;
return
TRUE;
}
CGridCellBase* CGridCtrl::CreateCell(
int
nRow,
int
nCol)
{
ASSERT(!GetVirtualMode());
if
(!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
{
ASSERT( FALSE);
return
NULL;
}
CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject();
if
(!pCell)
return
NULL;
pCell->SetGrid(
this
);
pCell->SetCoords(nRow, nCol);
if
(nCol < m_nFixedCols)
pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);
if
(nRow < m_nFixedRows)
pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);
pCell->SetFormat(pCell->GetDefaultCell()->GetFormat());
return
pCell;
}
void
CGridCtrl::DestroyCell(
int
nRow,
int
nCol)
{
ASSERT(!GetVirtualMode());
SetItemState(nRow, nCol, 0);
delete
GetCell(nRow, nCol);
}
BOOL
CGridCtrl::DeleteColumn(
int
nColumn)
{
if
(nColumn < 0 || nColumn >= GetColumnCount())
return
FALSE;
ResetSelectedRange();
if
(!GetVirtualMode())
{
for
(
int
row = 0; row < GetRowCount(); row++)
{
GRID_ROW* pRow = m_RowData[row];
if
(!pRow)
return
FALSE;
DestroyCell(row, nColumn);
pRow->RemoveAt(nColumn);
}
}
m_arColWidths.RemoveAt(nColumn);
m_nCols--;
if
(nColumn < m_nFixedCols)
m_nFixedCols--;
if
(nColumn == m_idCurrentCell.col)
m_idCurrentCell.row = m_idCurrentCell.col = -1;
else
if
(nColumn < m_idCurrentCell.col)
m_idCurrentCell.col--;
ResetScrollBars();
SetModified();
return
TRUE;
}
BOOL
CGridCtrl::DeleteRow(
int
nRow)
{
if
(nRow < 0 || nRow >= GetRowCount())
return
FALSE;
ResetSelectedRange();
if
(!GetVirtualMode())
{
GRID_ROW* pRow = m_RowData[nRow];
if
(!pRow)
return
FALSE;
for
(
int
col = 0; col < GetColumnCount(); col++)
DestroyCell(nRow, col);
delete
pRow;
m_RowData.RemoveAt(nRow);
}
m_arRowHeights.RemoveAt(nRow);
m_nRows--;
if
(nRow < m_nFixedRows)
m_nFixedRows--;
if
(nRow == m_idCurrentCell.row)
m_idCurrentCell.row = m_idCurrentCell.col = -1;
else
if
(nRow < m_idCurrentCell.row)
m_idCurrentCell.row--;
ResetScrollBars();
SetModified();
return
TRUE;
}
BOOL
CGridCtrl::DeleteNonFixedRows()
{
ResetSelectedRange();
int
nFixed = GetFixedRowCount();
int
nCount = GetRowCount();
for
(
int
nRow = nCount; nRow >= nFixed; nRow--)
DeleteRow(nRow);
return
TRUE;
}
BOOL
CGridCtrl::DeleteAllItems()
{
ResetSelectedRange();
m_arColWidths.RemoveAll();
m_arRowHeights.RemoveAll();
if
(!GetVirtualMode())
{
for
(
int
row = 0; row < m_nRows; row++)
{
for
(
int
col = 0; col < m_nCols; col++)
DestroyCell(row, col);
GRID_ROW* pRow = m_RowData[row];
delete
pRow;
}
m_RowData.RemoveAll();
}
m_idCurrentCell.row = m_idCurrentCell.col = -1;
m_nRows = m_nFixedRows = m_nCols = m_nFixedCols = 0;
ResetScrollBars();
SetModified();
return
TRUE;
}
void
CGridCtrl::AutoFill()
{
if
(!::IsWindow(m_hWnd))
return
;
CRect rect;
GetClientRect(rect);
SetColumnCount(rect.Width() / m_cellDefault.GetWidth() + 1);
SetRowCount(rect.Height() / m_cellDefault.GetHeight() + 1);
SetFixedRowCount(1);
SetFixedColumnCount(1);
ExpandToFit();
}
CCellID CGridCtrl::GetNextItem(CCellID& cell,
int
nFlags)
const
{
if
((nFlags & GVNI_ALL) == GVNI_ALL)
{
int
row = cell.row , col = cell.col + 1;
if
(row <= 0)
row = GetFixedRowCount();
for
(; row < GetRowCount(); row++)
{
if
(col <= 0)
col = GetFixedColumnCount();
for
(; col < GetColumnCount(); col++)
{
int
nState = GetItemState(row, col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(row, col);
}
col = GetFixedColumnCount();
}
}
else
if
((nFlags & GVNI_BELOW) == GVNI_BELOW &&
(nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
{
int
row = cell.row;
if
(row <= 0)
row = GetFixedRowCount();
for
(; row < GetRowCount(); row++)
{
int
col = cell.col + 1;
if
(col <= 0)
col = GetFixedColumnCount();
for
(; col < GetColumnCount(); col++)
{
int
nState = GetItemState(row, col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(row, col);
}
}
}
else
if
((nFlags & GVNI_ABOVE) == GVNI_ABOVE)
{
for
(
int
row = cell.row - 1; row >= GetFixedRowCount(); row--)
{
int
nState = GetItemState(row, cell.col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(row, cell.col);
}
}
else
if
((nFlags & GVNI_BELOW) == GVNI_BELOW)
{
for
(
int
row = cell.row + 1; row < GetRowCount(); row++)
{
int
nState = GetItemState(row, cell.col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(row, cell.col);
}
}
else
if
((nFlags & GVNI_TOLEFT) == GVNI_TOLEFT)
{
for
(
int
col = cell.col - 1; col >= GetFixedColumnCount(); col--)
{
int
nState = GetItemState(cell.row, col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(cell.row, col);
}
}
else
if
((nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
{
for
(
int
col = cell.col + 1; col < GetColumnCount(); col++)
{
int
nState = GetItemState(cell.row, col);
if
((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
(nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
(nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
(nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
(nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
(nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
return
CCellID(cell.row, col);
}
}
return
CCellID(-1, -1);
}
BOOL
CGridCtrl::SortTextItems(
int
nCol,
BOOL
bAscending,
LPARAM
data
)
{
return
CGridCtrl::SortItems(pfnCellTextCompare, nCol, bAscending, data);
}
void
CGridCtrl::SetCompareFunction(PFNLVCOMPARE pfnCompare)
{
m_pfnCompare = pfnCompare;
}
BOOL
CGridCtrl::SortItems(
int
nCol,
BOOL
bAscending,
LPARAM
data
)
{
SetSortColumn(nCol);
SetSortAscending(bAscending);
ResetSelectedRange();
SetFocusCell(-1, - 1);
if
(m_pfnCompare == NULL)
return
CGridCtrl::SortItems(pfnCellTextCompare, nCol, bAscending, data);
else
return
CGridCtrl::SortItems(m_pfnCompare, nCol, bAscending, data);
}
BOOL
CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare,
int
nCol,
BOOL
bAscending,
LPARAM
data
)
{
SetSortColumn(nCol);
SetSortAscending(bAscending);
ResetSelectedRange();
SetFocusCell(-1, -1);
return
SortItems(pfnCompare, nCol, bAscending, data, GetFixedRowCount(), -1);
}
int
CALLBACK CGridCtrl::pfnCellTextCompare(
LPARAM
lParam1,
LPARAM
lParam2,
LPARAM
lParamSort)
{
UNUSED_ALWAYS(lParamSort);
CGridCellBase* pCell1 = (CGridCellBase*) lParam1;
CGridCellBase* pCell2 = (CGridCellBase*) lParam2;
if
(!pCell1 || !pCell2)
return
0;
return
_tcscmp(pCell1->GetText(), pCell2->GetText());
}
int
CALLBACK CGridCtrl::pfnCellNumericCompare(
LPARAM
lParam1,
LPARAM
lParam2,
LPARAM
lParamSort)
{
UNUSED_ALWAYS(lParamSort);
CGridCellBase* pCell1 = (CGridCellBase*) lParam1;
CGridCellBase* pCell2 = (CGridCellBase*) lParam2;
if
(!pCell1 || !pCell2)
return
0;
int
nValue1 = _ttol(pCell1->GetText());
int
nValue2 = _ttol(pCell2->GetText());
if
(nValue1 < nValue2)
return
-1;
else
if
(nValue1 == nValue2)
return
0;
else
return
1;
}
BOOL
CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare,
int
nCol,
BOOL
bAscending,
LPARAM
data,
int
low,
int
high)
{
if
(nCol >= GetColumnCount())
return
FALSE;
if
(high == -1)
high = GetRowCount() - 1;
int
lo = low;
int
hi = high;
if
(hi <= lo)
return
FALSE;
LPARAM
pMidCell = (
LPARAM
) GetCell((lo + hi)/2, nCol);
while
(lo <= hi)
{
if
(bAscending)
while
(lo < high && pfnCompare( (
LPARAM
)GetCell(lo, nCol), (
LPARAM
) pMidCell, data) < 0)
++lo;
else
while
(lo < high && pfnCompare((
LPARAM
)GetCell(lo, nCol), pMidCell, data) > 0)
++lo;
if
(bAscending)
while
(hi > low && pfnCompare((
LPARAM
)GetCell(hi, nCol), pMidCell, data) > 0)
--hi;
else
while
(hi > low && pfnCompare((
LPARAM
)GetCell(hi, nCol), pMidCell, data) < 0)
--hi;
if
(lo <= hi)
{
if
(pfnCompare((
LPARAM
)GetCell(lo, nCol), (
LPARAM
)GetCell(hi, nCol), data) != 0)
{
for
(
int
col = 0; col < GetColumnCount(); col++)
{
CGridCellBase *pCell = GetCell(lo, col);
SetCell(lo, col, GetCell(hi, col));
SetCell(hi, col, pCell);
}
UINT
nRowHeight = m_arRowHeights[lo];
m_arRowHeights[lo] = m_arRowHeights[hi];
m_arRowHeights[hi] = nRowHeight;
}
++lo;
--hi;
}
}
if
(low < hi)
SortItems(pfnCompare, nCol, bAscending, data, low, hi);
if
(lo < high)
SortItems(pfnCompare, nCol, bAscending, data, lo, high);
return
TRUE;
}
BOOL
CGridCtrl::SetItem(
const
GV_ITEM* pItem)
{
if
(!pItem || GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
if
(!pCell)
return
FALSE;
SetModified(TRUE, pItem->row, pItem->col);
if
(pItem->mask & GVIF_TEXT)
pCell->SetText(pItem->strText);
if
(pItem->mask & GVIF_PARAM)
pCell->SetData(pItem->lParam);
if
(pItem->mask & GVIF_IMAGE)
pCell->SetImage(pItem->iImage);
if
(pItem->mask & GVIF_STATE)
SetItemState(pItem->row, pItem->col, pItem->nState);
if
(pItem->mask & GVIF_FORMAT)
pCell->SetFormat(pItem->nFormat);
if
(pItem->mask & GVIF_BKCLR)
pCell->SetBackClr(pItem->crBkClr);
if
(pItem->mask & GVIF_FGCLR)
pCell->SetTextClr(pItem->crFgClr);
if
(pItem->mask & GVIF_FONT)
pCell->SetFont(&(pItem->lfFont));
if
( pItem->mask & GVIF_MARGIN)
pCell->SetMargin( pItem->nMargin);
return
TRUE;
}
BOOL
CGridCtrl::GetItem(GV_ITEM* pItem)
{
if
(!pItem)
return
FALSE;
CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
if
(!pCell)
return
FALSE;
if
(pItem->mask & GVIF_TEXT)
pItem->strText = GetItemText(pItem->row, pItem->col);
if
(pItem->mask & GVIF_PARAM)
pItem->lParam = pCell->GetData();;
if
(pItem->mask & GVIF_IMAGE)
pItem->iImage = pCell->GetImage();
if
(pItem->mask & GVIF_STATE)
pItem->nState = pCell->GetState();
if
(pItem->mask & GVIF_FORMAT)
pItem->nFormat = pCell->GetFormat();
if
(pItem->mask & GVIF_BKCLR)
pItem->crBkClr = pCell->GetBackClr();
if
(pItem->mask & GVIF_FGCLR)
pItem->crFgClr = pCell->GetTextClr();
if
(pItem->mask & GVIF_FONT)
memcpy
(&(pItem->lfFont), pCell->GetFont(),
sizeof
(LOGFONT));
if
( pItem->mask & GVIF_MARGIN)
pItem->nMargin = pCell->GetMargin();
return
TRUE;
}
BOOL
CGridCtrl::SetItemText(
int
nRow,
int
nCol,
LPCTSTR
str)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
FALSE;
pCell->SetText(str);
SetModified(TRUE, nRow, nCol);
return
TRUE;
}
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210)
BOOL
CGridCtrl::SetItemTextFmt(
int
nRow,
int
nCol,
LPCTSTR
szFmt, ...)
{
if
(GetVirtualMode())
return
FALSE;
CString strText;
va_list
argptr;
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
FALSE;
va_start
(argptr, szFmt);
strText.FormatV(szFmt, argptr);
va_end
(argptr);
pCell->SetText(strText);
SetModified(TRUE, nRow, nCol);
return
TRUE;
}
BOOL
CGridCtrl::SetItemTextFmtID(
int
nRow,
int
nCol,
UINT
nID, ...)
{
if
(GetVirtualMode())
return
FALSE;
CString strFmt, strText;
va_list
argptr;
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
FALSE;
va_start
(argptr, nID);
VERIFY(strFmt.LoadString(nID));
strText.FormatV(strFmt, argptr);
va_end
(argptr);
pCell->SetText(strText);
SetModified(TRUE, nRow, nCol);
return
TRUE;
}
#endif
BOOL
CGridCtrl::SetItemData(
int
nRow,
int
nCol,
LPARAM
lParam)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
FALSE;
pCell->SetData(lParam);
SetModified(TRUE, nRow, nCol);
return
TRUE;
}
LPARAM
CGridCtrl::GetItemData(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
(
LPARAM
) 0;
return
pCell->GetData();
}
BOOL
CGridCtrl::SetItemImage(
int
nRow,
int
nCol,
int
iImage)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
FALSE;
pCell->SetImage(iImage);
SetModified(TRUE, nRow, nCol);
return
TRUE;
}
int
CGridCtrl::GetItemImage(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
-1;
return
pCell->GetImage();
}
BOOL
CGridCtrl::SetItemState(
int
nRow,
int
nCol,
UINT
state)
{
BOOL
bSelected = IsCellSelected(nRow, nCol);
if
(bSelected && !(state & GVIS_SELECTED))
{
CCellID cell;
DWORD
key = MAKELONG(nRow, nCol);
if
(m_SelectedCellMap.Lookup(key, (CCellID&)cell))
m_SelectedCellMap.RemoveKey(key);
}
else
if
(!bSelected && (state & GVIS_SELECTED))
{
CCellID cell(nRow, nCol);
m_SelectedCellMap.SetAt(MAKELONG(nRow, nCol), cell);
}
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
pCell->SetState(state);
return
TRUE;
}
UINT
CGridCtrl::GetItemState(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
0;
return
pCell->GetState();
}
BOOL
CGridCtrl::SetItemFormat(
int
nRow,
int
nCol,
UINT
nFormat)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
pCell->SetFormat(nFormat);
return
TRUE;
}
UINT
CGridCtrl::GetItemFormat(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
0;
return
pCell->GetFormat();
}
BOOL
CGridCtrl::SetItemBkColour(
int
nRow,
int
nCol,
COLORREF
cr
)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
pCell->SetBackClr(cr);
return
TRUE;
}
COLORREF
CGridCtrl::GetItemBkColour(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
0;
return
pCell->GetBackClr();
}
BOOL
CGridCtrl::SetItemFgColour(
int
nRow,
int
nCol,
COLORREF
cr
)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
pCell->SetTextClr(cr);
return
TRUE;
}
COLORREF
CGridCtrl::GetItemFgColour(
int
nRow,
int
nCol)
const
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
0;
return
pCell->GetTextClr();
}
BOOL
CGridCtrl::SetItemFont(
int
nRow,
int
nCol,
const
LOGFONT* plf)
{
if
(GetVirtualMode())
return
FALSE;
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
pCell->SetFont(plf);
return
TRUE;
}
const
LOGFONT* CGridCtrl::GetItemFont(
int
nRow,
int
nCol)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
GetDefaultCell(nRow < GetFixedRowCount(), nCol < GetFixedColumnCount())->GetFont();
return
pCell->GetFont();
}
BOOL
CGridCtrl::IsItemEditing(
int
nRow,
int
nCol)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
FALSE;
return
pCell->IsEditing();
}
long
CGridCtrl::GetVirtualWidth()
const
{
long
lVirtualWidth = 0;
int
iColCount = GetColumnCount();
for
(
int
i = 0; i < iColCount; i++)
lVirtualWidth += m_arColWidths[i];
return
lVirtualWidth;
}
long
CGridCtrl::GetVirtualHeight()
const
{
long
lVirtualHeight = 0;
int
iRowCount = GetRowCount();
for
(
int
i = 0; i < iRowCount; i++)
lVirtualHeight += m_arRowHeights[i];
return
lVirtualHeight;
}
int
CGridCtrl::GetRowHeight(
int
nRow)
const
{
ASSERT(nRow >= 0 && nRow < m_nRows);
if
(nRow < 0 || nRow >= m_nRows)
return
-1;
return
m_arRowHeights[nRow];
}
int
CGridCtrl::GetColumnWidth(
int
nCol)
const
{
ASSERT(nCol >= 0 && nCol < m_nCols);
if
(nCol < 0 || nCol >= m_nCols)
return
-1;
return
m_arColWidths[nCol];
}
BOOL
CGridCtrl::SetRowHeight(
int
nRow,
int
height)
{
ASSERT(nRow >= 0 && nRow < m_nRows && height >= 0);
if
(nRow < 0 || nRow >= m_nRows || height < 0)
return
FALSE;
m_arRowHeights[nRow] = height;
ResetScrollBars();
return
TRUE;
}
BOOL
CGridCtrl::SetColumnWidth(
int
nCol,
int
width)
{
ASSERT(nCol >= 0 && nCol < m_nCols && width >= 0);
if
(nCol < 0 || nCol >= m_nCols || width < 0)
return
FALSE;
m_arColWidths[nCol] = width;
ResetScrollBars();
return
TRUE;
}
int
CGridCtrl::GetFixedRowHeight()
const
{
int
nHeight = 0;
for
(
int
i = 0; i < m_nFixedRows; i++)
nHeight += GetRowHeight(i);
return
nHeight;
}
int
CGridCtrl::GetFixedColumnWidth()
const
{
int
nWidth = 0;
for
(
int
i = 0; i < m_nFixedCols; i++)
nWidth += GetColumnWidth(i);
return
nWidth;
}
BOOL
CGridCtrl::AutoSizeColumn(
int
nCol,
UINT
nAutoSizeStyle
,
BOOL
bResetScroll
)
{
ASSERT(nCol >= 0 && nCol < m_nCols);
if
(nCol < 0 || nCol >= m_nCols)
return
FALSE;
if
( GetColumnWidth( nCol) <=0 )
return
FALSE;
CSize size;
CDC* pDC = GetDC();
if
(!pDC)
return
FALSE;
int
nWidth = 0;
ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
if
(nAutoSizeStyle == GVS_DEFAULT)
nAutoSizeStyle = GetAutoSizeStyle();
int
nStartRow = (nAutoSizeStyle & GVS_HEADER)? 0 : GetFixedRowCount();
int
nEndRow = (nAutoSizeStyle & GVS_DATA)? GetRowCount()-1 : GetFixedRowCount()-1;
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(nStartRow, nCol, nEndRow, nCol));
for
(
int
nRow = nStartRow; nRow <= nEndRow; nRow++)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
size = pCell->GetCellExtent(pDC);
if
(size.cx > nWidth)
nWidth = size.cx;
}
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(-1,-1,-1,-1));
m_arColWidths[nCol] = nWidth;
ReleaseDC(pDC);
if
(bResetScroll)
ResetScrollBars();
return
TRUE;
}
BOOL
CGridCtrl::AutoSizeRow(
int
nRow,
BOOL
bResetScroll
)
{
ASSERT(nRow >= 0 && nRow < m_nRows);
if
(nRow < 0 || nRow >= m_nRows)
return
FALSE;
if
( GetRowHeight( nRow) <=0 )
return
FALSE;
CSize size;
CDC* pDC = GetDC();
if
(!pDC)
return
FALSE;
int
nHeight = 0;
int
nNumColumns = GetColumnCount();
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(nRow, 0, nRow, nNumColumns));
for
(
int
nCol = 0; nCol < nNumColumns; nCol++)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
size = pCell->GetCellExtent(pDC);
if
(size.cy > nHeight)
nHeight = size.cy;
}
m_arRowHeights[nRow] = nHeight;
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(-1,-1,-1,-1));
ReleaseDC(pDC);
if
(bResetScroll)
ResetScrollBars();
return
TRUE;
}
void
CGridCtrl::AutoSizeColumns(
UINT
nAutoSizeStyle
)
{
int
nNumColumns = GetColumnCount();
for
(
int
nCol = 0; nCol < nNumColumns; nCol++)
{
if
( GetColumnWidth( nCol) > 0 )
AutoSizeColumn(nCol, nAutoSizeStyle, FALSE);
}
ResetScrollBars();
}
void
CGridCtrl::AutoSizeRows()
{
int
nNumRows = GetRowCount();
for
(
int
nRow = 0; nRow < nNumRows; nRow++)
{
if
( GetRowHeight( nRow) > 0 )
AutoSizeRow(nRow, FALSE);
}
ResetScrollBars();
}
void
CGridCtrl::AutoSize(
UINT
nAutoSizeStyle
)
{
CDC* pDC = GetDC();
if
(!pDC)
return
;
int
nNumColumns = GetColumnCount();
int
nCol, nRow;
ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
if
(nAutoSizeStyle == GVS_DEFAULT)
nAutoSizeStyle = GetAutoSizeStyle();
int
nStartRow = (nAutoSizeStyle & GVS_HEADER)? 0 : GetFixedRowCount();
int
nEndRow = (nAutoSizeStyle & GVS_DATA)? GetRowCount()-1 : GetFixedRowCount()-1;
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(nStartRow, 0, nEndRow, nNumColumns));
for
(nRow = nStartRow; nRow <= nEndRow; nRow++)
{
if
( GetRowHeight( nRow) > 0 )
m_arRowHeights[nRow] = 1;
}
CSize size;
for
(nCol = 0; nCol < nNumColumns; nCol++)
{
if
( GetColumnWidth( nCol) > 0 )
{
m_arColWidths[nCol] = 0;
for
(nRow = nStartRow; nRow <= nEndRow; nRow++)
{
if
( GetRowHeight( nRow) > 0 )
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
size = pCell->GetCellExtent(pDC);
if
(size.cx >(
int
) m_arColWidths[nCol])
m_arColWidths[nCol] = size.cx;
if
(size.cy >(
int
) m_arRowHeights[nRow])
m_arRowHeights[nRow] = size.cy;
}
}
}
}
if
(GetVirtualMode())
SendCacheHintToParent(CCellRange(-1,-1,-1,-1));
ReleaseDC(pDC);
ResetScrollBars();
Refresh();
}
void
CGridCtrl::ExpandColumnsToFit(
BOOL
bExpandFixed
)
{
if
(bExpandFixed)
{
if
(GetColumnCount() <= 0)
return
;
}
else
{
if
(GetColumnCount() <= GetFixedColumnCount())
return
;
}
EnableScrollBars(SB_HORZ, FALSE);
CRect rect;
GetClientRect(rect);
int
nFirstColumn = (bExpandFixed)? 0 : GetFixedColumnCount();
int
nNumColumnsAffected = 0;
for
(
int
col = nFirstColumn; col < GetColumnCount(); col++)
{
if
(m_arColWidths[col] > 0)
nNumColumnsAffected++;
}
if
(nNumColumnsAffected <= 0)
return
;
long
virtualWidth = GetVirtualWidth();
int
nDifference = rect.Width() -(
int
) virtualWidth;
int
nColumnAdjustment = nDifference / nNumColumnsAffected;
for
(col = nFirstColumn; col < GetColumnCount(); col++)
{
if
(m_arColWidths[col] > 0)
m_arColWidths[col] += nColumnAdjustment;
}
if
(nDifference > 0)
{
int
leftOver = nDifference % nNumColumnsAffected;
for
(
int
nCount = 0, col = nFirstColumn;
(col < GetColumnCount()) && (nCount < leftOver); col++, nCount++)
{
if
(m_arColWidths[col] > 0)
m_arColWidths[col] += 1;
}
}
else
{
int
leftOver = (-nDifference) % nNumColumnsAffected;
for
(
int
nCount = 0, col = nFirstColumn;
(col < GetColumnCount()) && (nCount < leftOver); col++, nCount++)
{
if
(m_arColWidths[col] > 0)
m_arColWidths[col] -= 1;
}
}
Refresh();
ResetScrollBars();
}
void
CGridCtrl::ExpandLastColumn()
{
if
(GetColumnCount() <= 0)
return
;
int
nLastColumn = GetColumnCount()-1;
while
(m_arColWidths[nLastColumn] <= 0)
nLastColumn--;
if
(nLastColumn <= 0)
return
;
EnableScrollBars(SB_HORZ, FALSE);
CRect rect;
GetClientRect(rect);
long
virtualWidth = GetVirtualWidth();
int
nDifference = rect.Width() -(
int
) virtualWidth;
if
(nDifference > 0)
{
m_arColWidths[ nLastColumn ] += nDifference;
Refresh();
}
ResetScrollBars();
}
void
CGridCtrl::ExpandRowsToFit(
BOOL
bExpandFixed
)
{
if
(bExpandFixed)
{
if
(GetRowCount() <= 0)
return
;
}
else
{
if
(GetRowCount() <= GetFixedRowCount())
return
;
}
EnableScrollBars(SB_VERT, FALSE);
CRect rect;
GetClientRect(rect);
int
nFirstRow = (bExpandFixed)? 0 : GetFixedRowCount();
int
nNumRowsAffected = 0;
for
(
int
row = nFirstRow; row < GetRowCount(); row++)
{
if
(m_arRowHeights[row] > 0)
nNumRowsAffected++;
}
if
(nNumRowsAffected <= 0)
return
;
long
virtualHeight = GetVirtualHeight();
int
nDifference = rect.Height() -(
int
) virtualHeight;
int
nRowAdjustment = nDifference / nNumRowsAffected;
for
(row = nFirstRow; row < GetRowCount(); row++)
{
if
(m_arRowHeights[row] > 0)
m_arRowHeights[row] += nRowAdjustment;
}
if
(nDifference > 0)
{
int
leftOver = nDifference % nNumRowsAffected;
for
(
int
nCount = 0, row = nFirstRow;
(row < GetRowCount()) && (nCount < leftOver); row++, nCount++)
{
if
(m_arRowHeights[row] > 0)
m_arRowHeights[row] += 1;
}
}
else
{
int
leftOver = (-nDifference) % nNumRowsAffected;
for
(
int
nCount = 0, row = nFirstRow;
(row < GetRowCount()) && (nCount < leftOver); row++, nCount++)
{
if
(m_arRowHeights[row] > 0)
m_arRowHeights[row] -= 1;
}
}
Refresh();
ResetScrollBars();
}
void
CGridCtrl::ExpandToFit(
BOOL
bExpandFixed
)
{
ExpandColumnsToFit(bExpandFixed);
ExpandRowsToFit(bExpandFixed);
ExpandColumnsToFit(bExpandFixed);
Refresh();
}
void
CGridCtrl::SetVirtualMode(
BOOL
bVirtual)
{
DeleteAllItems();
m_bVirtualMode = bVirtual;
if
(m_bVirtualMode)
{
SetEditable(FALSE);
SetHeaderSort(FALSE);
SetAutoSizeStyle(GVS_HEADER);
SetFixedColumnSelection(FALSE);
SetFixedRowSelection(FALSE);
}
}
void
CGridCtrl::SetGridLines(
int
nWhichLines
)
{
m_nGridLines = nWhichLines;
Refresh();
}
void
CGridCtrl::SetListMode(
BOOL
bEnableListMode
)
{
ResetSelectedRange();
SetSortColumn(-1);
m_bListMode = bEnableListMode;
SetFixedRowSelection(FALSE);
Refresh();
}
void
CGridCtrl::SetSortColumn(
int
nCol)
{
if
(m_nSortColumn >= 0)
InvalidateCellRect(0, m_nSortColumn);
m_nSortColumn = nCol;
if
(nCol >= 0)
InvalidateCellRect(0, nCol);
}
BOOL
CGridCtrl::IsCellFixed(
int
nRow,
int
nCol)
{
return
(nRow < GetFixedRowCount() || nCol < GetFixedColumnCount());
}
void
CGridCtrl::SetModified(
BOOL
bModified
,
int
nRow
,
int
nCol
)
{
if
(nCol < 0 || nCol == GetSortColumn())
SetSortColumn(-1);
if
(nRow >= 0 && nCol >= 0)
{
if
(bModified)
{
SetItemState(nRow, nCol, GetItemState(nRow, nCol) | GVIS_MODIFIED);
m_bModified = TRUE;
}
else
SetItemState(nRow, nCol, GetItemState(nRow, nCol) & ~GVIS_MODIFIED);
}
else
m_bModified = bModified;
if
(!m_bModified)
{
for
(
int
row = 0; row < GetRowCount(); row++)
for
(
int
col = 0; col < GetColumnCount(); col++)
SetItemState(row, col, GetItemState(row, col) & ~GVIS_MODIFIED);
}
}
BOOL
CGridCtrl::GetModified(
int
nRow
,
int
nCol
)
{
if
(nRow >= 0 && nCol >= 0)
return
( (GetItemState(nRow, nCol) & GVIS_MODIFIED) == GVIS_MODIFIED );
else
return
m_bModified;
}
void
CGridCtrl::Refresh()
{
if
(GetSafeHwnd() && m_bAllowDraw)
Invalidate();
}
void
CGridCtrl::EnsureVisible(
int
nRow,
int
nCol)
{
if
(!m_bAllowDraw)
return
;
CRect rectWindow;
CWnd* pFocusWnd = GetFocus();
CCellRange VisibleCells = GetVisibleNonFixedCellRange();
int
right = nCol - VisibleCells.GetMaxCol();
int
left = VisibleCells.GetMinCol() - nCol;
int
down = nRow - VisibleCells.GetMaxRow();
int
up = VisibleCells.GetMinRow() - nRow;
int
iColumnStart;
int
iRowStart;
iColumnStart = VisibleCells.GetMaxCol() + 1;
while
( right > 0 )
{
if
( GetColumnWidth( iColumnStart ) > 0 )
SendMessage( WM_HSCROLL, SB_LINERIGHT, 0 );
right--;
iColumnStart++;
}
iColumnStart = VisibleCells.GetMinCol() - 1;
while
( left > 0 )
{
if
( GetColumnWidth( iColumnStart ) > 0 )
SendMessage( WM_HSCROLL, SB_LINELEFT, 0 );
left--;
iColumnStart--;
}
iRowStart = VisibleCells.GetMaxRow() + 1;
while
( down > 0 )
{
if
( GetRowHeight( iRowStart ) > 0 )
SendMessage( WM_VSCROLL, SB_LINEDOWN, 0 );
down--;
iRowStart++;
}
iRowStart = VisibleCells.GetMinRow() - 1;
while
( up > 0 )
{
if
( GetRowHeight( iRowStart ) > 0 )
SendMessage( WM_VSCROLL, SB_LINEUP, 0 );
up--;
iRowStart--;
}
CRect rectCell;
if
(!GetCellRect(nRow, nCol, rectCell))
{
if
(pFocusWnd && ::IsWindow(pFocusWnd->GetSafeHwnd()))
pFocusWnd->SetFocus();
return
;
}
GetClientRect(rectWindow);
while
(rectCell.right > rectWindow.right
&& rectCell.left > GetFixedColumnWidth()
&& IsVisibleHScroll()
)
{
SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
if
(!GetCellRect(nRow, nCol, rectCell))
{
pFocusWnd->SetFocus();
return
;
}
}
while
(rectCell.bottom > rectWindow.bottom
&& rectCell.top > GetFixedRowHeight()
&& IsVisibleVScroll()
)
{
SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
if
(!GetCellRect(nRow, nCol, rectCell))
{
pFocusWnd->SetFocus();
return
;
}
}
pFocusWnd->SetFocus();
}
BOOL
CGridCtrl::IsCellEditable(CCellID &cell)
const
{
return
IsCellEditable(cell.row, cell.col);
}
BOOL
CGridCtrl::IsCellEditable(
int
nRow,
int
nCol)
const
{
return
IsEditable() && ((GetItemState(nRow, nCol) & GVIS_READONLY) != GVIS_READONLY);
}
BOOL
CGridCtrl::IsCellSelected(CCellID &cell)
const
{
return
IsCellSelected(cell.row, cell.col);
}
BOOL
CGridCtrl::IsCellSelected(
int
nRow,
int
nCol)
const
{
if
(GetVirtualMode())
{
if
(!IsSelectable())
return
FALSE;
CCellID cell;
DWORD
key = MAKELONG(nRow, nCol);
return
(m_SelectedCellMap.Lookup(key, (CCellID&)cell));
}
else
return
IsSelectable() && ((GetItemState(nRow, nCol) & GVIS_SELECTED) == GVIS_SELECTED);
}
BOOL
CGridCtrl::IsCellVisible(CCellID cell)
{
return
IsCellVisible(cell.row, cell.col);
}
BOOL
CGridCtrl::IsCellVisible(
int
nRow,
int
nCol)
{
if
(!IsWindow(m_hWnd))
return
FALSE;
int
x, y;
CCellID 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;
}
BOOL
CGridCtrl::InvalidateCellRect(
const
CCellID& cell)
{
return
InvalidateCellRect(cell.row, cell.col);
}
BOOL
CGridCtrl::InvalidateCellRect(
const
int
row,
const
int
col)
{
if
(!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
return
FALSE;
if
(!IsValid(row, col))
return
FALSE;
if
(!IsCellVisible(row, col))
return
FALSE;
CRect rect;
if
(!GetCellRect(row, col, rect))
return
FALSE;
rect.right++;
rect.bottom++;
InvalidateRect(rect, TRUE);
return
TRUE;
}
BOOL
CGridCtrl::InvalidateCellRect(
const
CCellRange& cellRange)
{
ASSERT(IsValid(cellRange));
if
(!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
return
FALSE;
CCellRange visibleCellRange = GetVisibleNonFixedCellRange().Intersect(cellRange);
CRect rect;
if
(!GetCellRangeRect(visibleCellRange, rect))
return
FALSE;
rect.right++;
rect.bottom++;
InvalidateRect(rect, TRUE);
return
TRUE;
}
#if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
BOOL
CGridCtrl::OnMouseWheel(
UINT
nFlags,
short
zDelta, CPoint pt)
{
if
(m_nRowsPerWheelNotch == -1)
{
int
nPagesScrolled = zDelta / 120;
if
(nPagesScrolled > 0)
{
for
(
int
i = 0; i < nPagesScrolled; i++)
{
PostMessage(WM_VSCROLL, SB_PAGEUP, 0);
}
}
else
{
for
(
int
i = 0; i > nPagesScrolled; i--)
{
PostMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
}
}
}
else
{
int
nRowsScrolled = m_nRowsPerWheelNotch * zDelta / 120;
if
(nRowsScrolled > 0)
{
for
(
int
i = 0; i < nRowsScrolled; i++)
{
PostMessage(WM_VSCROLL, SB_LINEUP, 0);
}
}
else
{
for
(
int
i = 0; i > nRowsScrolled; i--)
{
PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
}
}
}
return
CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
#endif // !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
void
CGridCtrl::OnMouseMove(
UINT
, CPoint point)
{
CRect rect;
GetClientRect(rect);
#ifndef GRIDCONTROL_NO_DRAGDROP
if
(m_MouseMode != MOUSE_DRAGGING && !rect.PtInRect(point))
return
;
#endif
if
(!m_bLMouseButtonDown ||
(m_bLMouseButtonDown && m_MouseMode == MOUSE_NOTHING))
{
if
(m_bAllowColumnResize && MouseOverColumnResizeArea(point))
{
if
(m_MouseMode != MOUSE_OVER_COL_DIVIDE)
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
#endif
m_MouseMode = MOUSE_OVER_COL_DIVIDE;
}
}
else
if
(m_bAllowRowResize && MouseOverRowResizeArea(point))
{
if
(m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
#endif
m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
}
}
else
if
(m_MouseMode != MOUSE_NOTHING)
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
#endif
m_MouseMode = MOUSE_NOTHING;
}
if
(m_MouseMode == MOUSE_NOTHING)
{
CGridCellBase* pCell = NULL;
CCellID idCurrentCell;
if
(!GetVirtualMode() || m_bTitleTips)
{
idCurrentCell = GetCellFromPt(point);
pCell = GetCell(idCurrentCell.row, idCurrentCell.col);
if
(pCell)
pCell->OnMouseOver();
}
#ifndef GRIDCONTROL_NO_TITLETIPS
if
(m_bTitleTips)
{
CRect TextRect, CellRect;
if
(pCell)
{
LPCTSTR
szTipText = pCell->GetTipText();
if
(!m_bRMouseButtonDown
&& szTipText && szTipText[0]
&& !pCell->IsEditing()
&& GetCellRect(idCurrentCell.row, idCurrentCell.col, &TextRect)
&& pCell->GetTipTextRect( &TextRect)
&& GetCellRect(idCurrentCell.row, idCurrentCell.col, CellRect) )
{
TRACE0(
"Showing TitleTip\n"
);
m_TitleTip.Show(TextRect, pCell->GetTipText(), 0, CellRect,
pCell->GetFont(), GetTitleTipTextClr(), GetTitleTipBackClr());
}
}
}
#endif
}
m_LastMousePoint = point;
return
;
}
if
(!IsValid(m_LeftClickDownCell))
{
m_LastMousePoint = point;
return
;
}
if
(m_bLMouseButtonDown)
{
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
;
if
(idCurrentCell != GetFocusCell())
{
OnSelecting(idCurrentCell);
if
((idCurrentCell.row >= m_nFixedRows &&
idCurrentCell.col >= m_nFixedCols) ||
m_MouseMode==MOUSE_SELECT_COL ||
m_MouseMode==MOUSE_SELECT_ROW)
{
SetFocusCell(idCurrentCell);
}
}
break
;
}
case
MOUSE_SIZING_COL:
{
CDC* pDC = GetDC();
if
(!pDC)
break
;
CRect oldInvertedRect(m_LastMousePoint.x, rect.top,
m_LastMousePoint.x + 2, rect.bottom);
pDC->InvertRect(&oldInvertedRect);
CRect newInvertedRect(point.x, rect.top,
point.x + 2, rect.bottom);
pDC->InvertRect(&newInvertedRect);
ReleaseDC(pDC);
}
break
;
case
MOUSE_SIZING_ROW:
{
CDC* pDC = GetDC();
if
(!pDC)
break
;
CRect oldInvertedRect(rect.left, m_LastMousePoint.y,
rect.right, m_LastMousePoint.y + 2);
pDC->InvertRect(&oldInvertedRect);
CRect newInvertedRect(rect.left, point.y,
rect.right, point.y + 2);
pDC->InvertRect(&newInvertedRect);
ReleaseDC(pDC);
}
break
;
#ifndef GRIDCONTROL_NO_DRAGDROP
case
MOUSE_PREPARE_EDIT:
case
MOUSE_PREPARE_DRAG:
m_MouseMode = MOUSE_PREPARE_DRAG;
OnBeginDrag();
break
;
#endif
}
}
m_LastMousePoint = point;
}
CPoint CGridCtrl::GetPointClicked(
int
nRow,
int
nCol,
const
CPoint& point)
{
CPoint PointCellOrigin;
if
( !GetCellOrigin( nRow, nCol, &PointCellOrigin) )
return
CPoint( 0, 0);
CPoint PointClickedCellRelative( point);
PointClickedCellRelative -= PointCellOrigin;
return
PointClickedCellRelative;
}
void
CGridCtrl::OnLButtonDblClk(
UINT
nFlags, CPoint point)
{
TRACE0(
"CGridCtrl::OnLButtonDblClk\n"
);
CCellID cell = GetCellFromPt(point);
if
( !IsValid( cell) )
{
return
;
}
#ifdef _WIN32_WCE
if
(MouseOverColumnResizeArea(point))
#else
if
(m_MouseMode == MOUSE_OVER_COL_DIVIDE)
#endif
{
CPoint start;
if
(!GetCellOrigin(0, cell.col, &start))
return
;
if
(point.x - start.x < m_nResizeCaptureRange)
cell.col--;
BOOL
bFoundVisible = FALSE;
while
( cell.col >= 0)
{
if
( GetColumnWidth( cell.col) > 0)
{
bFoundVisible = TRUE;
break
;
}
cell.col--;
}
if
( !bFoundVisible)
return
;
AutoSizeColumn(cell.col, GetAutoSizeStyle());
Invalidate();
}
#ifdef _WIN32_WCE
else
if
(MouseOverRowResizeArea(point))
#else
else
if
(m_MouseMode == MOUSE_OVER_ROW_DIVIDE)
#endif
{
CPoint start;
if
(!GetCellOrigin(0, cell.col, &start))
return
;
if
(point.y - start.y < m_nResizeCaptureRange)
cell.row--;
BOOL
bFoundVisible = FALSE;
while
( cell.row >= 0)
{
if
( GetRowHeight( cell.row) > 0)
{
bFoundVisible = TRUE;
break
;
}
cell.row--;
}
if
( !bFoundVisible)
return
;
AutoSizeRow(cell.row);
Invalidate();
}
else
if
(m_MouseMode == MOUSE_NOTHING)
{
CPoint pointClickedRel;
pointClickedRel = GetPointClicked( cell.row, cell.col, point);
CGridCellBase* pCell = NULL;
if
(IsValid(cell))
pCell = GetCell(cell.row, cell.col);
BOOL
bInTextArea = FALSE;
if
(pCell)
{
CRect rectCell;
if
(GetCellRect(cell.row, cell.col, rectCell) && pCell->GetTextRect(rectCell))
bInTextArea = rectCell.PtInRect(point);
}
if
(cell.row >= m_nFixedRows && IsValid(m_LeftClickDownCell) &&
cell.col >= m_nFixedCols && bInTextArea)
{
OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
}
else
if
(m_bListMode)
{
if
(!IsValid(cell))
return
;
if
(cell.row >= m_nFixedRows && cell.col >= m_nFixedCols && bInTextArea)
OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
}
if
(IsValid(cell))
{
CGridCellBase* pCell = GetCell(cell.row, cell.col);
if
(pCell)
pCell->OnDblClick(pointClickedRel);
SendMessageToParent(cell.row, cell.col, NM_DBLCLK);
}
}
CWnd::OnLButtonDblClk(nFlags, point);
}
void
CGridCtrl::OnLButtonDown(
UINT
nFlags, CPoint point)
{
#ifdef GRIDCONTROL_USE_TITLETIPS
m_TitleTip.Hide();
#endif
SetFocus();
m_bLMouseButtonDown = TRUE;
m_LeftClickDownPoint = point;
m_LeftClickDownCell = GetCellFromPt(point);
if
(!IsValid(m_LeftClickDownCell))
return
;
if
((nFlags & MK_SHIFT) != MK_SHIFT)
m_SelectionStartCell = m_LeftClickDownCell;
else
{
if
(!IsValid(m_SelectionStartCell))
m_SelectionStartCell = m_idCurrentCell;
}
EndEditing();
CGridCellBase* pCell = GetCell(m_LeftClickDownCell.row, m_LeftClickDownCell.col);
if
(pCell)
pCell->OnClickDown(GetPointClicked( m_LeftClickDownCell.row, m_LeftClickDownCell.col, point));
BOOL
bInTextArea = FALSE;
if
(pCell)
{
CRect rectCell;
if
(GetCellRect(m_LeftClickDownCell.row, m_LeftClickDownCell.col, rectCell) &&
pCell->GetTextRect(rectCell))
{
bInTextArea = rectCell.PtInRect(point);
}
}
if
(m_LeftClickDownCell == m_idCurrentCell &&
!(nFlags & MK_CONTROL) && bInTextArea &&
IsCellEditable(m_LeftClickDownCell))
{
m_MouseMode = MOUSE_PREPARE_EDIT;
return
;
}
else
if
(IsCellSelected(m_LeftClickDownCell))
{
SetFocusCell(m_LeftClickDownCell.row, m_LeftClickDownCell.col);
if
(nFlags & MK_CONTROL)
{
SetFocusCell(m_LeftClickDownCell);
if
(GetListMode())
SelectRows(m_LeftClickDownCell, TRUE, FALSE);
else
SelectCells(m_LeftClickDownCell, TRUE, FALSE);
return
;
}
#ifndef GRIDCONTROL_NO_DRAGDROP
else
if
(m_bAllowDragAndDrop)
m_MouseMode = MOUSE_PREPARE_DRAG;
#endif
}
else
if
(m_MouseMode != MOUSE_OVER_COL_DIVIDE &&
m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
{
if
(m_LeftClickDownCell.row >= GetFixedRowCount() &&
m_LeftClickDownCell.col >= GetFixedColumnCount())
{
SetFocusCell(m_LeftClickDownCell.row, m_LeftClickDownCell.col);
}
else
SetFocusCell(-1, -1);
}
SetCapture();
if
(m_MouseMode == MOUSE_NOTHING)
{
if
(m_bAllowColumnResize && MouseOverColumnResizeArea(point))
{
if
(m_MouseMode != MOUSE_OVER_COL_DIVIDE)
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
#endif
m_MouseMode = MOUSE_OVER_COL_DIVIDE;
}
}
else
if
(m_bAllowRowResize && MouseOverRowResizeArea(point))
{
if
(m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
#endif
m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
}
}
}
if
(m_MouseMode == MOUSE_OVER_COL_DIVIDE)
{
m_MouseMode = MOUSE_SIZING_COL;
if
(GetColumnWidth(GetColumnCount()-1) < m_nResizeCaptureRange)
{
CRect VisRect;
GetVisibleNonFixedCellRange(VisRect);
if
(
abs
(point.x - VisRect.right) < m_nResizeCaptureRange)
m_LeftClickDownCell.col = GetColumnCount()-1;
}
CPoint start;
if
(!GetCellOrigin(0, m_LeftClickDownCell.col, &start))
return
;
if
( !m_bHiddenColUnhide)
{
BOOL
bLookForVisible = TRUE;
BOOL
bIsCellRightBorder = point.x - start.x >= m_nResizeCaptureRange;
if
( bIsCellRightBorder
&& m_LeftClickDownCell.col + 1 >= GetColumnCount() )
{
if
( m_LeftClickDownCell.col >= 0)
bLookForVisible = FALSE;
}
if
( bLookForVisible)
{
BOOL
bFoundVisible = FALSE;
int
iOffset = 1;
if
( bIsCellRightBorder)
iOffset = 0;
while
( m_LeftClickDownCell.col - iOffset >= 0)
{
if
( GetColumnWidth( m_LeftClickDownCell.col - iOffset) > 0)
{
bFoundVisible = TRUE;
break
;
}
m_LeftClickDownCell.col--;
}
if
( !bFoundVisible)
return
;
}
}
CRect rect;
GetClientRect(rect);
CRect invertedRect(point.x, rect.top, point.x + 2, rect.bottom);
CDC* pDC = GetDC();
if
(pDC)
{
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
}
if
(point.x - start.x < m_nResizeCaptureRange)
{
if
(m_LeftClickDownCell.col < GetColumnCount()-1 ||
GetColumnWidth(GetColumnCount()-1) >= m_nResizeCaptureRange)
{
if
(!GetCellOrigin(0, --m_LeftClickDownCell.col, &start))
return
;
}
}
int
nMaxCellWidth = rect.Width()-GetFixedColumnWidth();
rect.left = start.x + 1;
rect.right = rect.left + nMaxCellWidth;
ClientToScreen(rect);
#ifndef _WIN32_WCE_NO_CURSOR
ClipCursor(rect);
#endif
}
else
if
(m_MouseMode == MOUSE_OVER_ROW_DIVIDE)
{
m_MouseMode = MOUSE_SIZING_ROW;
if
(GetRowHeight(GetRowCount()-1) < m_nResizeCaptureRange)
{
CRect VisRect;
GetVisibleNonFixedCellRange(VisRect);
if
(
abs
(point.y - VisRect.bottom) < m_nResizeCaptureRange)
m_LeftClickDownCell.row = GetRowCount()-1;
}
CPoint start;
if
(!GetCellOrigin(m_LeftClickDownCell, &start))
return
;
if
( !m_bHiddenRowUnhide)
{
BOOL
bLookForVisible = TRUE;
BOOL
bIsCellBottomBorder = point.y - start.y >= m_nResizeCaptureRange;
if
( bIsCellBottomBorder
&& m_LeftClickDownCell.row + 1 >= GetRowCount() )
{
if
( m_LeftClickDownCell.row >= 0)
bLookForVisible = FALSE;
}
if
( bLookForVisible)
{
BOOL
bFoundVisible = FALSE;
int
iOffset = 1;
if
( bIsCellBottomBorder)
iOffset = 0;
while
( m_LeftClickDownCell.row - iOffset >= 0)
{
if
( GetRowHeight( m_LeftClickDownCell.row - iOffset) > 0)
{
bFoundVisible = TRUE;
break
;
}
m_LeftClickDownCell.row--;
}
if
( !bFoundVisible)
return
;
}
}
CRect rect;
GetClientRect(rect);
CRect invertedRect(rect.left, point.y, rect.right, point.y + 2);
CDC* pDC = GetDC();
if
(pDC)
{
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
}
if
(point.y - start.y < m_nResizeCaptureRange)
{
if
(m_LeftClickDownCell.row < GetRowCount()-1 ||
GetRowHeight(GetRowCount()-1) >= m_nResizeCaptureRange)
{
if
(!GetCellOrigin(--m_LeftClickDownCell.row, 0, &start))
return
;
}
}
int
nMaxCellHeight = rect.Height()-GetFixedRowHeight();
rect.top = start.y + 1;
rect.bottom = rect.top + nMaxCellHeight;
ClientToScreen(rect);
#ifndef _WIN32_WCE_NO_CURSOR
ClipCursor(rect);
#endif
}
else
#ifndef GRIDCONTROL_NO_DRAGDROP
if
(m_MouseMode != MOUSE_PREPARE_DRAG)
#endif
{
SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
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
CGridCtrl::OnLButtonUp(
UINT
nFlags, CPoint point)
{
CWnd::OnLButtonUp(nFlags, point);
m_bLMouseButtonDown = FALSE;
#ifndef _WIN32_WCE_NO_CURSOR
ClipCursor(NULL);
#endif
if
(GetCapture()->GetSafeHwnd() == GetSafeHwnd())
{
ReleaseCapture();
KillTimer(m_nTimerID);
m_nTimerID = 0;
}
CPoint pointClickedRel;
pointClickedRel = GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point);
if
(m_MouseMode == MOUSE_PREPARE_EDIT)
{
OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, pointClickedRel, VK_LBUTTON);
}
#ifndef GRIDCONTROL_NO_DRAGDROP
else
if
(m_MouseMode == MOUSE_PREPARE_DRAG)
{
CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
if
(pCell)
pCell->OnClick( GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point) );
SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
ResetSelectedRange();
SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
}
#endif
else
if
(m_MouseMode == MOUSE_SIZING_COL)
{
CRect rect;
GetClientRect(rect);
CRect invertedRect(m_LastMousePoint.x, rect.top, m_LastMousePoint.x + 2, rect.bottom);
CDC* pDC = GetDC();
if
(pDC)
{
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
}
if
(m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0))
{
CPoint start;
if
(!GetCellOrigin(m_LeftClickDownCell, &start))
return
;
int
nColumnWidth = max(point.x - start.x, m_bAllowColHide? 0 : 1);
SetColumnWidth(m_LeftClickDownCell.col, nColumnWidth);
ResetScrollBars();
Invalidate();
}
}
else
if
(m_MouseMode == MOUSE_SIZING_ROW)
{
CRect rect;
GetClientRect(rect);
CRect invertedRect(rect.left, m_LastMousePoint.y, rect.right, m_LastMousePoint.y + 2);
CDC* pDC = GetDC();
if
(pDC)
{
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
}
if
(m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0))
{
CPoint start;
if
(!GetCellOrigin(m_LeftClickDownCell, &start))
return
;
int
nRowHeight = max(point.y - start.y, m_bAllowRowHide? 0 : 1);
SetRowHeight(m_LeftClickDownCell.row, nRowHeight);
ResetScrollBars();
Invalidate();
}
}
else
{
SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
if
(pCell)
pCell->OnClick( GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point) );
SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
}
m_MouseMode = MOUSE_NOTHING;
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
#endif
if
(!IsValid(m_LeftClickDownCell))
return
;
CWnd *pOwner = GetOwner();
if
(pOwner && IsWindow(pOwner->m_hWnd))
pOwner->PostMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), BN_CLICKED),
(
LPARAM
) GetSafeHwnd());
}
#ifndef _WIN32_WCE
void
CGridCtrl::OnRButtonDown(
UINT
nFlags, CPoint point)
{
CWnd::OnRButtonDown(nFlags, point);
m_bRMouseButtonDown = TRUE;
#ifdef GRIDCONTROL_USE_TITLETIPS
TRACE0(
"Hiding TitleTip\n"
);
m_TitleTip.Hide();
#endif
}
void
CGridCtrl::OnRButtonUp(
UINT
nFlags, CPoint point)
{
CWnd::OnRButtonUp(nFlags, point);
m_bRMouseButtonDown = FALSE;
CCellID FocusCell;
FocusCell = GetCellFromPt(point);
EndEditing();
if
(!IsValid(FocusCell))
SendMessageToParent(-1, -1, NM_RCLICK);
else
{
SetFocusCell(-1,-1);
SetFocusCell(max(FocusCell.row, m_nFixedRows),
max(FocusCell.col, m_nFixedCols));
CGridCellBase* pCell = GetCell(FocusCell.row, FocusCell.col);
if
(pCell)
pCell->OnRClick( GetPointClicked( FocusCell.row, FocusCell.col, point) );
SendMessageToParent(FocusCell.row, FocusCell.col, NM_RCLICK);
}
}
#endif
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
void
CGridCtrl::SetPrintMarginInfo(
int
nHeaderHeight,
int
nFooterHeight,
int
nLeftMargin,
int
nRightMargin,
int
nTopMargin,
int
nBottomMargin,
int
nGap)
{
if
(nHeaderHeight > -1)
m_nHeaderHeight = nHeaderHeight;
if
(nFooterHeight > -1)
m_nFooterHeight = nFooterHeight;
if
(nLeftMargin > -1)
m_nLeftMargin = nLeftMargin;
if
(nRightMargin > -1)
m_nRightMargin = nRightMargin;
if
(nTopMargin > -1)
m_nTopMargin = nTopMargin;
if
(nBottomMargin > -1)
m_nBottomMargin = nBottomMargin;
if
(nGap > -1)
m_nGap = nGap;
}
void
CGridCtrl::GetPrintMarginInfo(
int
&nHeaderHeight,
int
&nFooterHeight,
int
&nLeftMargin,
int
&nRightMargin,
int
&nTopMargin,
int
&nBottomMargin,
int
&nGap)
{
nHeaderHeight = m_nHeaderHeight;
nFooterHeight = m_nFooterHeight;
nLeftMargin = m_nLeftMargin;
nRightMargin = m_nRightMargin;
nTopMargin = m_nTopMargin;
nBottomMargin = m_nBottomMargin;
nGap = m_nGap;
}
void
CGridCtrl::Print(CPrintDialog* pPrntDialog
)
{
CDC dc;
if
(pPrntDialog == NULL)
{
CPrintDialog printDlg(FALSE);
if
(printDlg.DoModal() != IDOK)
return
;
dc.Attach(printDlg.GetPrinterDC());
}
else
dc.Attach(pPrntDialog->GetPrinterDC());
dc.m_bPrinting = TRUE;
CString strTitle;
strTitle.LoadString(AFX_IDS_APP_TITLE);
if
( strTitle.IsEmpty() )
{
CWnd *pParentWnd = GetParent();
while
(pParentWnd)
{
pParentWnd->GetWindowText(strTitle);
if
(strTitle.GetLength())
break
;
pParentWnd = pParentWnd->GetParent();
}
}
DOCINFO di;
memset
(&di, 0,
sizeof
(DOCINFO));
di.cbSize =
sizeof
(DOCINFO);
di.lpszDocName = strTitle;
BOOL
bPrintingOK = dc.StartDoc(&di);
CPrintInfo Info;
Info.m_rectDraw.SetRect(0,0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
OnBeginPrinting(&dc, &Info);
for
(
UINT
page = Info.GetMinPage(); page <= Info.GetMaxPage() && bPrintingOK; page++)
{
dc.StartPage();
Info.m_nCurPage = page;
OnPrint(&dc, &Info);
bPrintingOK = (dc.EndPage() > 0);
}
OnEndPrinting(&dc, &Info);
if
(bPrintingOK)
dc.EndDoc();
else
dc.AbortDoc();
dc.Detach();
}
void
CGridCtrl::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo)
{
ASSERT(pDC && pInfo);
if
(!pDC || !pInfo)
return
;
CDC *pCurrentDC = GetDC();
if
(!pCurrentDC)
return
;
CSize PaperPixelsPerInch(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
CSize ScreenPixelsPerInch(pCurrentDC->GetDeviceCaps(LOGPIXELSX), pCurrentDC->GetDeviceCaps(LOGPIXELSY));
int
nFontSize = -10;
CString strFontName = _T(
"Arial"
);
m_PrinterFont.CreateFont(nFontSize, 0,0,0, FW_NORMAL, 0,0,0, DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, strFontName);
CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
m_CharSize = pDC->GetTextExtent(_T(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSATUVWXYZ"
),52);
m_CharSize.cx /= 52;
int
nMargins = (m_nLeftMargin+m_nRightMargin)*m_CharSize.cx;
m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
if
( m_bWysiwygPrinting)
{
m_LogicalPageSize.cx = ScreenPixelsPerInch.cx * m_PaperSize.cx / PaperPixelsPerInch.cx * 3 / 4;
m_LogicalPageSize.cy = ScreenPixelsPerInch.cy * m_PaperSize.cy / PaperPixelsPerInch.cy * 3 / 4;
}
else
{
m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
m_LogicalPageSize.cx = GetVirtualWidth()+nMargins;
#ifdef _WIN32_WCE
m_LogicalPageSize.cy = (m_LogicalPageSize.cx * m_PaperSize.cy) / m_PaperSize.cx;
#else
m_LogicalPageSize.cy = MulDiv(m_LogicalPageSize.cx, m_PaperSize.cy, m_PaperSize.cx);
#endif
}
m_nPageHeight = m_LogicalPageSize.cy - GetFixedRowHeight()
- (m_nHeaderHeight+m_nFooterHeight + 2*m_nGap)*m_CharSize.cy;
int
nTotalRowHeight = 0;
m_nNumPages = 1;
for
(
int
row = GetFixedRowCount(); row < GetRowCount(); row++)
{
nTotalRowHeight += GetRowHeight(row);
if
(nTotalRowHeight > m_nPageHeight) {
m_nNumPages++;
nTotalRowHeight = GetRowHeight(row);
}
}
int
iColumnOffset = 0;
int
i1;
for
( i1=0; i1 < GetFixedColumnCount(); i1++)
{
iColumnOffset += GetColumnWidth( i1);
}
m_nPageWidth = m_LogicalPageSize.cx - iColumnOffset
- nMargins;
m_nPageMultiplier = 1;
if
( m_bWysiwygPrinting)
{
int
iTotalRowWidth = 0;
for
( i1 = GetFixedColumnCount(); i1 < GetColumnCount(); i1++)
{
iTotalRowWidth += GetColumnWidth( i1);
if
( iTotalRowWidth > m_nPageWidth)
{
m_nPageMultiplier++;
iTotalRowWidth = GetColumnWidth( i1);
}
}
m_nNumPages *= m_nPageMultiplier;
}
pInfo->SetMaxPage(m_nNumPages);
pInfo->m_nCurPage = 1;
ReleaseDC(pCurrentDC);
pDC->SelectObject(pOldFont);
}
void
CGridCtrl::OnPrint(CDC *pDC, CPrintInfo *pInfo)
{
if
(!pDC || !pInfo)
return
;
CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(m_LogicalPageSize);
pDC->SetViewportExt(m_PaperSize);
pDC->SetWindowOrg(-m_nLeftMargin * m_CharSize.cx, 0);
pInfo->m_rectDraw.top = 0;
pInfo->m_rectDraw.left = 0;
pInfo->m_rectDraw.right = m_LogicalPageSize.cx - (m_nLeftMargin + m_nRightMargin) * m_CharSize.cx;
pInfo->m_rectDraw.bottom = m_nHeaderHeight * m_CharSize.cy;
PrintHeader(pDC, pInfo);
pDC->OffsetWindowOrg(0, -m_nHeaderHeight * m_CharSize.cy);
pDC->OffsetWindowOrg(0, -m_nGap * m_CharSize.cy);
pDC->OffsetWindowOrg(0, -GetFixedRowHeight());
int
nTotalRowHeight = 0;
UINT
nNumPages = 1;
m_nCurrPrintRow = GetFixedRowCount();
int
iPageIfIgnoredWideCols = pInfo->m_nCurPage / m_nPageMultiplier;
int
iWideColPageOffset = pInfo->m_nCurPage - ( iPageIfIgnoredWideCols * m_nPageMultiplier);
if
( iWideColPageOffset > 0)
iPageIfIgnoredWideCols++;
if
( iWideColPageOffset == 0)
iWideColPageOffset = m_nPageMultiplier;
iWideColPageOffset--;
while
( m_nCurrPrintRow < GetRowCount()
&& (
int
)nNumPages < iPageIfIgnoredWideCols)
{
nTotalRowHeight += GetRowHeight(m_nCurrPrintRow);
if
(nTotalRowHeight > m_nPageHeight) {
nNumPages++;
if
((
int
)nNumPages == iPageIfIgnoredWideCols)
break
;
nTotalRowHeight = GetRowHeight(m_nCurrPrintRow);
}
m_nCurrPrintRow++;
}
m_nPrintColumn = GetFixedColumnCount();
int
iTotalRowWidth = 0;
int
i1, i2;
for
( i1 = 0; i1 < iWideColPageOffset; i1++)
{
for
( i2 = m_nPrintColumn; i2 < GetColumnCount(); i2++)
{
iTotalRowWidth += GetColumnWidth( i2);
if
( iTotalRowWidth > m_nPageWidth)
{
m_nPrintColumn = i2;
iTotalRowWidth = 0;
break
;
}
}
}
PrintRowButtons( pDC, pInfo);
int
iColumnOffset = 0;
for
( i1=0; i1 < GetFixedColumnCount(); i1++)
{
iColumnOffset += GetColumnWidth( i1);
}
pInfo->m_rectDraw.bottom = GetFixedRowHeight();
if
( m_nPrintColumn == GetFixedColumnCount())
{
pDC->OffsetWindowOrg( 0, +GetFixedRowHeight());
m_nPageWidth += iColumnOffset;
m_nPrintColumn = 0;
PrintColumnHeadings(pDC, pInfo);
m_nPageWidth -= iColumnOffset;
m_nPrintColumn = GetFixedColumnCount();
pDC->OffsetWindowOrg( -iColumnOffset, -GetFixedRowHeight());
}
else
{
pDC->OffsetWindowOrg( 0, +GetFixedRowHeight());
m_nPageWidth += iColumnOffset;
PrintColumnHeadings(pDC, pInfo);
m_nPageWidth -= iColumnOffset;
pDC->OffsetWindowOrg( -iColumnOffset, -GetFixedRowHeight());
}
if
(m_nCurrPrintRow >= GetRowCount())
return
;
BOOL
bFirstPrintedRow = TRUE;
CRect rect;
rect.bottom = -1;
while
(m_nCurrPrintRow < GetRowCount())
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(m_nCurrPrintRow) - 1;
if
(rect.bottom > m_nPageHeight)
break
;
rect.right = -1;
for
(
int
col = m_nPrintColumn; col < GetColumnCount(); col++)
{
rect.left = rect.right+1;
rect.right = rect.left
+ GetColumnWidth( col)
- 1;
if
( rect.right > m_nPageWidth)
break
;
CGridCellBase* pCell = GetCell(m_nCurrPrintRow, col);
if
(pCell)
pCell->PrintCell(pDC, m_nCurrPrintRow, col, rect);
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
int
Overlap = (col == 0)? 0:1;
pDC->MoveTo(rect.left-Overlap, rect.bottom);
pDC->LineTo(rect.right, rect.bottom);
if
(m_nCurrPrintRow == 0) {
pDC->MoveTo(rect.left-Overlap, rect.top);
pDC->LineTo(rect.right, rect.top);
}
}
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
int
Overlap = (bFirstPrintedRow)? 0:1;
pDC->MoveTo(rect.right, rect.top-Overlap);
pDC->LineTo(rect.right, rect.bottom);
if
(col == 0) {
pDC->MoveTo(rect.left, rect.top-Overlap);
pDC->LineTo(rect.left, rect.bottom);
}
}
}
m_nCurrPrintRow++;
bFirstPrintedRow = FALSE;
}
pInfo->m_rectDraw.bottom = m_nFooterHeight * m_CharSize.cy;
pDC->SetWindowOrg( -m_nLeftMargin * m_CharSize.cx,
-m_LogicalPageSize.cy + m_nFooterHeight * m_CharSize.cy);
PrintFooter(pDC, pInfo);
pDC->SetWindowOrg(0,0);
pDC->SelectObject(pOldFont);
}
void
CGridCtrl::PrintFixedRowCells(
int
nStartColumn,
int
nStopColumn,
int
& row, CRect& rect,
CDC *pDC,
BOOL
& bFirst)
{
for
(
int
col =nStartColumn; col < nStopColumn; col++)
{
rect.left = rect.right+1;
rect.right = rect.left + GetColumnWidth( col) - 1;
if
( rect.right > m_nPageWidth)
break
;
CGridCellBase* pCell = GetCell(row, col);
if
(pCell)
pCell->PrintCell(pDC, row, col, rect);
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
int
Overlap = (col == 0)? 0:1;
pDC->MoveTo(rect.left-Overlap, rect.bottom);
pDC->LineTo(rect.right, rect.bottom);
if
(row == 0)
{
pDC->MoveTo(rect.left-Overlap, rect.top);
pDC->LineTo(rect.right, rect.top);
}
}
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
int
Overlap = (row == 0)? 0:1;
pDC->MoveTo(rect.right, rect.top-Overlap);
pDC->LineTo(rect.right, rect.bottom);
if
( bFirst)
{
pDC->MoveTo(rect.left-1, rect.top-Overlap);
pDC->LineTo(rect.left-1, rect.bottom);
bFirst = FALSE;
}
}
}
}
void
CGridCtrl::PrintColumnHeadings(CDC *pDC, CPrintInfo*
)
{
CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
CRect rect;
rect.bottom = -1;
BOOL
bFirst = TRUE;
BOOL
bOriginal;
for
(
int
row = 0; row < GetFixedRowCount(); row++)
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight(row) - 1;
rect.right = -1;
if
(m_nPrintColumn>= GetFixedColumnCount())
{
bOriginal=bFirst;
PrintFixedRowCells(0,GetFixedColumnCount(), row, rect, pDC, bFirst);
bFirst=bOriginal;
}
PrintFixedRowCells(m_nPrintColumn, GetColumnCount(), row, rect, pDC, bFirst);
}
pDC->SelectObject(pOldFont);
}
void
CGridCtrl::PrintRowButtons(CDC *pDC, CPrintInfo*
)
{
CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
CRect rect;
rect.right = -1;
BOOL
bFirst = TRUE;
for
(
int
iCol = 0; iCol < GetFixedColumnCount(); iCol++)
{
rect.left = rect.right+1;
rect.right = rect.left
+ GetColumnWidth( iCol)
- 1;
rect.bottom = -1;
for
(
int
iRow = m_nCurrPrintRow; iRow < GetRowCount(); iRow++)
{
rect.top = rect.bottom+1;
rect.bottom = rect.top + GetRowHeight( iRow) - 1;
if
( rect.bottom > m_nPageHeight)
break
;
CGridCellBase* pCell = GetCell(iRow, iCol);
if
(pCell)
pCell->PrintCell(pDC, iRow, iCol, rect);
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
int
Overlap = (iCol == 0)? 0:1;
pDC->MoveTo(rect.left-Overlap, rect.bottom);
pDC->LineTo(rect.right, rect.bottom);
if
( bFirst) {
pDC->MoveTo(rect.left-Overlap, rect.top-1);
pDC->LineTo(rect.right, rect.top-1);
bFirst = FALSE;
}
}
if
(m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
int
Overlap = (iRow == 0)? 0:1;
pDC->MoveTo(rect.right, rect.top-Overlap);
pDC->LineTo(rect.right, rect.bottom);
if
(iCol == 0) {
pDC->MoveTo(rect.left, rect.top-Overlap);
pDC->LineTo(rect.left, rect.bottom);
}
}
}
}
pDC->SelectObject(pOldFont);
}
void
CGridCtrl::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
{
CString strRight;
strRight.LoadString(AFX_IDS_APP_TITLE);
CString strCenter;
CWnd *pParentWnd = GetParent();
while
(pParentWnd)
{
pParentWnd->GetWindowText(strCenter);
if
(strCenter.GetLength())
break
;
pParentWnd = pParentWnd->GetParent();
}
CFont BoldFont;
LOGFONT lf;
VERIFY(m_PrinterFont.GetLogFont(&lf));
lf.lfWeight = FW_BOLD;
VERIFY(BoldFont.CreateFontIndirect(&lf));
CFont *pNormalFont = pDC->SelectObject(&BoldFont);
int
nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
CRect rc(pInfo->m_rectDraw);
if
( !strCenter.IsEmpty() )
pDC->DrawText( strCenter, &rc, DT_CENTER | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
if
( !strRight.IsEmpty() )
pDC->DrawText( strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
pDC->SetBkMode(nPrevBkMode);
pDC->SelectObject(pNormalFont);
BoldFont.DeleteObject();
pDC->SelectStockObject(BLACK_PEN);
pDC->MoveTo(rc.left, rc.bottom);
pDC->LineTo(rc.right, rc.bottom);
}
void
CGridCtrl::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
{
CString strLeft;
strLeft.Format(_T(
"Page %d of %d"
), pInfo->m_nCurPage, pInfo->GetMaxPage() );
CString strRight;
COleDateTime t = COleDateTime::GetCurrentTime();
strRight = t.Format(_T(
"%c"
));
CRect rc(pInfo->m_rectDraw);
pDC->SelectStockObject(BLACK_PEN);
pDC->MoveTo(rc.left, rc.top);
pDC->LineTo(rc.right, rc.top);
CFont BoldFont;
LOGFONT lf;
m_PrinterFont.GetLogFont(&lf);
lf.lfWeight = FW_BOLD;
BoldFont.CreateFontIndirect(&lf);
CFont *pNormalFont = pDC->SelectObject(&BoldFont);
int
nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(0, 0, 0));
if
( !strLeft.IsEmpty() )
pDC->DrawText( strLeft, &rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
if
( !strRight.IsEmpty() )
pDC->DrawText( strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
pDC->SetBkMode(nPrevBkMode);
pDC->SelectObject(pNormalFont);
BoldFont.DeleteObject();
}
void
CGridCtrl::OnEndPrinting(CDC*
, CPrintInfo*
)
{
m_PrinterFont.DeleteObject();
}
#endif // !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
#ifndef _WIN32_WCE
BOOL
CGridCtrl::Save(
LPCTSTR
filename,
TCHAR
chSeparator
)
{
CStdioFile File;
CFileException ex;
CString strSeparator(chSeparator);
if
(!File.Open(filename, CFile::modeWrite | CFile::modeCreate| CFile::typeText, &ex))
{
ex.ReportError();
return
FALSE;
}
TRY
{
int
nNumColumns = GetColumnCount();
for
(
int
i = 0; i < GetRowCount(); i++)
{
for
(
int
j = 0; j < nNumColumns; j++)
{
File.WriteString(GetItemText(i,j));
File.WriteString((j==(nNumColumns-1))? _T(
"\n"
): strSeparator);
}
}
File.Close();
}
CATCH (CFileException, e)
{
AfxMessageBox(_T(
"Unable to save grid list"
));
return
FALSE;
}
END_CATCH
return
TRUE;
}
BOOL
CGridCtrl::Load(
LPCTSTR
filename,
TCHAR
chSeparator
)
{
if
(GetVirtualMode())
return
FALSE;
TCHAR
*token, *end;
TCHAR
buffer[1024];
CStdioFile File;
CFileException ex;
if
(!File.Open(filename, CFile::modeRead | CFile::typeText))
{
ex.ReportError();
return
FALSE;
}
DeleteAllItems();
TRY
{
File.ReadString(buffer, 1024);
for
(token=buffer, end=buffer;
*end && (*end != chSeparator) && (*end != _T(
'\n'
));
end++)
;
if
((*end == _T(
'\0'
)) && (token == end))
token = NULL;
*end = _T(
'\0'
);
while
(token)
{
InsertColumn(token);
for
(token=++end; *end && (*end != chSeparator) && (*end != _T(
'\n'
));
end++)
;
if
((*end == _T(
'\0'
)) && (token == end))
token = NULL;
*end = _T(
'\0'
);
}
int
nItem = 1;
while
(File.ReadString(buffer, 1024))
{
for
(token=buffer, end=buffer;
*end && (*end != chSeparator) && (*end != _T(
'\n'
)); end++)
;
if
((*end == _T(
'\0'
)) && (token == end))
token = NULL;
*end = _T(
'\0'
);
int
nSubItem = 0;
while
(token)
{
if
(!nSubItem)
InsertRow(token);
else
SetItemText(nItem, nSubItem, token);
for
(token=++end; *end && (*end != chSeparator) && (*end != _T(
'\n'
));
end++)
;
if
((*end == _T(
'\0'
)) && (token == end))
token = NULL;
*end = _T(
'\0'
);
nSubItem++;
}
nItem++;
}
AutoSizeColumns(GetAutoSizeStyle());
File.Close();
}
CATCH (CFileException, e)
{
AfxMessageBox(_T(
"Unable to load grid data"
));
return
FALSE;
}
END_CATCH
return
TRUE;
}
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
CImageList* CGridCtrl::CreateDragImage(CPoint *pHotSpot)
{
CDC* pDC = GetDC();
if
(!pDC)
return
NULL;
CRect rect;
CCellID cell = GetFocusCell();
if
(!GetCellRect(cell.row, cell.col, rect))
return
NULL;
rect.BottomRight() = CPoint(rect.Width(), rect.Height());
rect.TopLeft() = CPoint(0, 0);
*pHotSpot = rect.BottomRight();
CImageList* pList =
new
CImageList;
if
(!pList || !pList->Create(rect.Width(), rect.Height(), ILC_MASK, 1, 1))
{
if
(pList)
delete
pList;
return
NULL;
}
CDC MemDC;
CBitmap bm;
MemDC.CreateCompatibleDC(pDC);
bm.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* pOldBitmap = MemDC.SelectObject(&bm);
MemDC.SetWindowOrg(0, 0);
CGridCellBase* pCell = GetCell(cell.row, cell.col);
if
(pCell)
pCell->Draw(&MemDC, cell.row, cell.col, rect, FALSE);
MemDC.SelectObject(pOldBitmap);
ReleaseDC(pDC);
pList->Add(&bm, GetDefaultCell(FALSE, FALSE)->GetBackClr());
bm.DeleteObject();
return
pList;
}
#endif
void
CGridCtrl::OnFixedRowClick(CCellID& cell)
{
if
(!IsValid(cell))
return
;
if
(GetHeaderSort())
{
CWaitCursor waiter;
if
(cell.col == GetSortColumn())
SortItems(cell.col, !GetSortAscending());
else
SortItems(cell.col, TRUE);
Invalidate();
}
if
(GetFixedColumnSelection())
{
if
(cell.col < GetFixedColumnCount())
{
m_MouseMode = MOUSE_SELECT_ALL;
OnSelecting(cell);
}
else
{
m_MouseMode = MOUSE_SELECT_COL;
OnSelecting(cell);
}
}
}
void
CGridCtrl::OnFixedColumnClick(CCellID& cell)
{
if
(!IsValid(cell))
return
;
if
(GetFixedRowSelection())
{
if
(cell.row < GetFixedRowCount())
{
m_MouseMode = MOUSE_SELECT_ALL;
OnSelecting(cell);
}
else
{
m_MouseMode = MOUSE_SELECT_ROW;
OnSelecting(cell);
}
}
}
CSize CGridCtrl::GetTextExtent(
int
nRow,
int
nCol,
LPCTSTR
str)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(!pCell)
return
CSize(0, 0);
else
return
pCell->GetTextExtent(str);
}
void
CGridCtrl::OnEditCell(
int
nRow,
int
nCol, CPoint point,
UINT
nChar)
{
#ifndef GRIDCONTROL_NO_TITLETIPS
m_TitleTip.Hide();
#endif
CCellID cell(nRow, nCol);
if
(!IsValid(cell) || !IsCellEditable(nRow, nCol))
return
;
EnsureVisible(nRow, nCol);
if
(!IsCellVisible(nRow, nCol))
return
;
CRect rect;
if
(!GetCellRect(cell, rect))
return
;
if
(SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT) >= 0)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
pCell->Edit(nRow, nCol, rect, point, IDC_INPLACE_CONTROL, nChar);
}
}
void
CGridCtrl::EndEditing()
{
CCellID cell = GetFocusCell();
if
(!IsValid(cell))
return
;
CGridCellBase *pCell = GetCell(cell.row, cell.col);
if
(pCell)
pCell->EndEdit();
}
void
CGridCtrl::OnEndEditCell(
int
nRow,
int
nCol, CString str)
{
CString strCurrentText = GetItemText(nRow, nCol);
if
(strCurrentText != str)
{
SetItemText(nRow, nCol, str);
if
(ValidateEdit(nRow, nCol, str) &&
SendMessageToParent(nRow, nCol, GVN_ENDLABELEDIT) >= 0)
{
SetModified(TRUE, nRow, nCol);
RedrawCell(nRow, nCol);
}
else
{
SetItemText(nRow, nCol, strCurrentText);
}
}
CGridCellBase* pCell = GetCell(nRow, nCol);
if
(pCell)
pCell->OnEndEdit();
}
BOOL
CGridCtrl::ValidateEdit(
int
nRow,
int
nCol,
LPCTSTR
str)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
TRUE;
return
pCell->ValidateEdit(str);
}
CString CGridCtrl::GetItemText(
int
nRow,
int
nCol)
const
{
if
(nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
return
_T(
""
);
CGridCellBase* pCell = GetCell(nRow, nCol);
ASSERT(pCell);
if
(!pCell)
return
_T(
""
);
return
pCell->GetText();
}