home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- // Grid.c
- //---------------------------------------------------------------------------
- // Grid Button Control
- //---------------------------------------------------------------------------
-
- #define NOCOMM
-
- #include <windows.h>
-
- #include "vbapi.h"
- #include "grid.h"
-
- typedef union tagPARAMS // event procedure parameter profiles
- {
- struct {
- LPVOID Index; // reserve space for index parameter to array ctl
- } Void; // NO PARAMS: Click, GotFocus, LostFocus events
- // KeyPress event is handled inside VB
- }
- PARAMS;
-
- VOID FAR * _cdecl _fmemset(VOID FAR *, USHORT, USHORT);
-
- ERR NEAR ClearGridSel(HCTL hctl, HWND hwnd);
- VOID NEAR GetCellRect(PGRID pgrid, SHORT Row, SHORT Col, LPRECT lprect);
- BHSTR NEAR GetCellText(PGRID pgrid, SHORT Row, SHORT Col);
- HSZ NEAR GetClipText(PGRID pgrid);
- BOOL NEAR GridCellSelected(PGRID pgrid, SHORT Row, SHORT Col);
- VOID NEAR GridKeyDown(HCTL hctl, HWND hwnd, USHORT VKKey);
- VOID NEAR GridKeyUp(HCTL hctl, HWND hwnd, USHORT VKKey);
- VOID NEAR GridMouseDblClick(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
- VOID NEAR GridMouseDown(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
- VOID NEAR GridMouseMove(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
- VOID NEAR GridMouseUp(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
- VOID NEAR GridScrollToView(PGRID pgrid, HWND hwnd, SHORT Row, SHORT Col);
- BOOL NEAR InitGrid(HCTL hctl);
- VOID NEAR InvalidateCell(PGRID pgrid, HWND hwnd, SHORT Row, SHORT Col);
- VOID NEAR InvalidateCol(PGRID pgrid, HWND hwnd, SHORT Col);
- VOID NEAR InvalidateRow(PGRID pgrid, HWND hwnd, SHORT Row);
- BHVOID NEAR MemAlloc(USHORT cb);
- VOID NEAR MemFree(BHVOID bhTemp);
- BHVOID NEAR MemReAlloc(BHVOID bhTemp, USHORT cb);
- WORD NEAR MemSize(BHVOID bhTemp);
- VOID NEAR NewFont(PGRID pgrid, HWND hwnd);
- VOID NEAR PaintGrid(PGRID pgrid, HWND hwnd, HDC hdc);
- SHORT NEAR XToCol(PGRID pgrid, SHORT X, BOOL fFixed);
- SHORT NEAR YToRow(PGRID pgrid, SHORT Y, BOOL fFixed);
- VOID NEAR ScrollGridHorz(PGRID pgrid, HWND hwnd, USHORT Code, USHORT Val);
- VOID NEAR ScrollGridVert(PGRID pgrid, HWND hwnd, USHORT Code, USHORT Val);
- ERR NEAR SetCellText(HCTL hctl, HWND hwnd, SHORT Row, SHORT Col, LPSTR pszText);
- ERR NEAR SetClipText(HCTL hctl, HWND hwnd, LPSTR pszText);
- ERR NEAR SetGridCols(HCTL hctl, SHORT Cols);
- ERR NEAR SetGridRowCol(HCTL hctl, PGRID pgrid, HWND hwnd, SHORT Row, SHORT Col);
- ERR NEAR SetGridRows(HCTL hctl, SHORT Rows);
- VOID NEAR SetGridScroll(PGRID pgrid, HWND hwnd);
- ERR NEAR SetGridSel(HCTL hctl, HWND hwnd, BOOL fSwap,
- SHORT StartRow, SHORT StartCol, SHORT EndRow, SHORT EndCol);
- VOID NEAR SizeGrid(PGRID pgrid, HWND hwnd);
-
- #define ROW(Row) (*(*pgrid->bhRowArray)->bhRowData[Row])
- #define ROWHEIGHT(Row) ROW(Row)->Height
- #define COL(Col) (*pgrid->bhColArray)->ColData[Col]
- #define COLWIDTH(Col) COL(Col).Width
- #define COLALIGN(Col) COL(Col).Alignment
-
- #define limit(a,b,c) (min(max(a, b), c))
-
- //---------------------------------------------------------------------------
- // Grid control function
- //---------------------------------------------------------------------------
- LONG _export GridCtlProc
- (
- HCTL hctl,
- HWND hwnd,
- USHORT msg,
- USHORT wp,
- LONG lp
- )
- {
- LONG lResult;
- PGRID pgrid;
-
- segGrid = (_segment)hctl;
- if (hctl) {
- pgrid = GRIDDEREF(hctl);
- segData = pgrid->segData;
- }
-
- // Message pre-processing
- switch( msg )
- {
- case WM_NCCREATE:
- NewFont(pgrid, hwnd);
- if (!InitGrid(hctl))
- return FALSE;
- break;
-
- case WM_NCDESTROY:
- GlobalFree(LOWORD(GlobalHandle(pgrid->segData)));
- if (pgrid->segClip)
- GlobalFree(LOWORD(GlobalHandle(pgrid->segClip)));
- break;
-
- case WM_SETFONT:
- pgrid->hFont = (HFONT)wp;
- NewFont(pgrid, hwnd);
- break;
-
- case WM_GETFONT:
- return pgrid->hFont;
-
- case WM_ERASEBKGND:
- return TRUE;
-
- case WM_SIZE:
- SizeGrid(pgrid, hwnd);
- break;
-
- case WM_PAINT:
- if (wp)
- PaintGrid(pgrid, hwnd, (HDC)wp);
- else {
- PAINTSTRUCT ps;
-
- BeginPaint(hwnd, &ps);
- PaintGrid(pgrid, hwnd, ps.hdc);
- EndPaint(hwnd, &ps);
- }
- break;
-
- case WM_KILLFOCUS:
- pgrid->fFocus = FALSE;
- InvalidateCell(pgrid, hwnd, pgrid->Row, pgrid->Col);
- break;
-
- case WM_SETFOCUS:
- pgrid->fFocus = TRUE;
- InvalidateCell(pgrid, hwnd, pgrid->Row, pgrid->Col);
- break;
-
- case WM_HSCROLL:
- ScrollGridHorz(pgrid, hwnd, wp, LOWORD(lp));
- break;
-
- case WM_VSCROLL:
- ScrollGridVert(pgrid, hwnd, wp, LOWORD(lp));
- break;
-
- case WM_LBUTTONDOWN:
- GridMouseDown(hctl, hwnd, (SHORT)LOWORD(lp), (SHORT)HIWORD(lp));
- return 0;
-
- case WM_MOUSEMOVE:
- GridMouseMove(hctl, hwnd, (SHORT)LOWORD(lp), (SHORT)HIWORD(lp));
- return 0;
-
- case WM_LBUTTONUP:
- GridMouseUp(hctl, hwnd, (SHORT)LOWORD(lp), (SHORT)HIWORD(lp));
- return 0;
-
- case WM_LBUTTONDBLCLK:
- GridMouseDblClick(hctl, hwnd, (SHORT)LOWORD(lp), (SHORT)HIWORD(lp));
- return 0;
-
- case VBM_GETPROPERTY:
- switch ( wp ) {
- case IPROP_GRID_TEXT:
- {
- BHSTR bhStr;
- BHSTR bhStr2;
-
- bhStr = GetCellText(pgrid, pgrid->Row, pgrid->Col);
- bhStr2 = MemAlloc((bhStr ? lstrlen(*bhStr) : 0) + 1);
- if (!bhStr2)
- return 1; // UNDONE
- if (bhStr)
- lstrcpy(*bhStr2, *bhStr);
- *((HSZ FAR *)lp) = (HSZ)MAKELONG(bhStr2, segData);
- return 0;
- }
-
- case IPROP_GRID_CLIP:
- {
- HSZ hszClip;
-
- hszClip = GetClipText(pgrid);
- if (!hszClip)
- return 1; // UNDONE
- *((HSZ FAR *)lp) = hszClip;
- return 0;
- }
-
- case IPROP_GRID_ROWHEIGHT:
- *(LONG FAR *)lp = VBYPixelsToTwips(ROWHEIGHT(pgrid->Row));
- return 0;
-
- case IPROP_GRID_COLWIDTH:
- *(LONG FAR *)lp = VBXPixelsToTwips(COLWIDTH(pgrid->Col));
- return 0;
-
- case IPROP_GRID_COLALIGN:
- *(SHORT FAR *)lp = COLALIGN(pgrid->Col);
- return 0;
-
- case IPROP_GRID_SCROLLBARS:
- *(USHORT FAR *)lp = (pgrid->fScrollHorz | (pgrid->fScrollVert << 1));
- return 0;
-
- case IPROP_GRID_CELLSEL:
- *(USHORT FAR *)lp = GridCellSelected(pgrid, pgrid->Row, pgrid->Col);
- return 0;
- }
- break;
-
- case VBM_SETPROPERTY:
- switch ( wp ) {
- case IPROP_GRID_ROW:
- if ((SHORT)lp < 0L || (SHORT)lp >= (SHORT)pgrid->Rows)
- return 1; // UNDONE
-
- SetGridRowCol(hctl, pgrid, hwnd, (SHORT)lp, pgrid->Col);
- return 0;
-
- case IPROP_GRID_COL:
- if ((SHORT)lp < 0L || (SHORT)lp >= (SHORT)pgrid->Cols)
- return 1; // UNDONE
-
- SetGridRowCol(hctl, pgrid, hwnd, pgrid->Row, (SHORT)lp);
- return 0;
-
- case IPROP_GRID_SELSTARTROW:
- if ((SHORT)lp < pgrid->FixedRows
- || (SHORT)lp >= (SHORT)pgrid->Rows)
- return 1; // UNDONE
- SetGridSel(hctl, hwnd, FALSE,
- (SHORT)lp, pgrid->SelLeftCol,
- pgrid->SelBottomRow, pgrid->SelRightCol);
- return 0;
-
- case IPROP_GRID_SELENDROW:
- if ((SHORT)lp < pgrid->FixedRows
- || (SHORT)lp >= (SHORT)pgrid->Rows)
- return 1; // UNDONE
- SetGridSel(hctl, hwnd, FALSE,
- pgrid->SelTopRow, pgrid->SelLeftCol,
- (SHORT)lp, pgrid->SelRightCol);
- return 0;
-
- case IPROP_GRID_SELSTARTCOL:
- if ((SHORT)lp < pgrid->FixedCols
- || (SHORT)lp >= (SHORT)pgrid->Cols)
- return 1; // UNDONE
- SetGridSel(hctl, hwnd, FALSE,
- pgrid->SelTopRow, (SHORT)lp,
- pgrid->SelBottomRow, pgrid->SelRightCol);
- return 0;
-
- case IPROP_GRID_SELENDCOL:
- if ((SHORT)lp < pgrid->FixedCols
- || (SHORT)lp >= (SHORT)pgrid->Cols)
- return 1; // UNDONE
- SetGridSel(hctl, hwnd, FALSE,
- pgrid->SelTopRow, pgrid->SelLeftCol,
- pgrid->SelBottomRow, (SHORT)lp);
- return 0;
-
- case IPROP_GRID_TEXT:
- return SetCellText(hctl, hwnd, pgrid->Row,
- pgrid->Col, (LPSTR)lp);
-
- case IPROP_GRID_CLIP:
- return SetClipText(hctl, hwnd, (LPSTR)lp);
-
- case IPROP_GRID_ROWS:
- case IPROP_GRID_COLS:
- {
- ERR err;
-
- if ((SHORT)lp <= 0)
- return 1; // UNDONE
- if (wp == IPROP_GRID_ROWS) {
- if (pgrid->Rows == (SHORT)lp)
- return 0;
- err = SetGridRows(hctl, (SHORT)lp);
- }
- else {
- if (pgrid->Cols == (SHORT)lp)
- return 0;
- err = SetGridCols(hctl, (SHORT)lp);
- }
- SizeGrid(GRIDDEREF(hctl), hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- return err;
- }
-
- case IPROP_GRID_FIXEDROWS:
- if ((SHORT)lp < 0 || (SHORT)lp >= (SHORT)pgrid->Rows)
- return 1; // UNDONE
- if (pgrid->FixedRows == (SHORT)lp)
- return 0;
- pgrid->TopRow -= pgrid->FixedRows - (SHORT)lp;
- pgrid->FixedRows = (SHORT)lp;
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- return 0;
-
- case IPROP_GRID_FIXEDCOLS:
- if ((SHORT)lp < 0 || (SHORT)lp >= (SHORT)pgrid->Cols)
- return 1; // UNDONE
- if (pgrid->FixedCols == (SHORT)lp)
- return 0;
- pgrid->LeftCol -= pgrid->FixedCols - (SHORT)lp;
- pgrid->FixedCols = (SHORT)lp;
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- return 0;
-
- case IPROP_GRID_ROWHEIGHT:
- {
- SHORT Height;
-
- // UNDONE: limit overall height
- Height = VBYTwipsToPixels((LONG)lp);
- if (ROWHEIGHT(pgrid->Row) == Height)
- return 0;
- ROWHEIGHT(pgrid->Row) = Height;
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- return 0;
- }
-
- case IPROP_GRID_COLWIDTH:
- {
- SHORT Width;
-
- // UNDONE: limit overall width
- Width = VBXTwipsToPixels((LONG)lp);
- if (COLWIDTH(pgrid->Col) == Width)
- return 0;
- COLWIDTH(pgrid->Col) = Width;
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- return 0;
- }
-
- case IPROP_GRID_COLALIGN:
- if ((SHORT)lp > 2)
- return 1; // UNDONE
- if (COLALIGN(pgrid->Col) == (SHORT)lp)
- return 0;
- COLALIGN(pgrid->Col) = (SHORT)lp;
- InvalidateCol(pgrid, hwnd, pgrid->Col);
- return 0;
-
- case IPROP_GRID_SCROLLBARS:
- {
- if ((USHORT)lp == (pgrid->fScrollHorz | (pgrid->fScrollVert << 1)))
- return 0;
- pgrid->fScrollHorz = ((USHORT)lp & 1) != 0;
- pgrid->fScrollVert = ((USHORT)lp & 2) != 0;
- SetGridScroll(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, TRUE);
- return 0;
- }
- }
- break;
- }
-
- // Default processing:
- lResult = VBDefControlProc( hctl, hwnd, msg, wp, lp );
-
- // Message post-processing:
- switch( msg )
- {
- case WM_KEYDOWN:
- // make sure the control is still valid after events
- if (!IsWindow(hwnd))
- break;
- GridKeyDown(hctl, hwnd, wp);
- return 0;
-
- case WM_KEYUP:
- // make sure the control is still valid after events
- if (!IsWindow(hwnd))
- break;
- GridKeyUp(hctl, hwnd, wp);
- return 0;
- }
-
- return lResult;
- }
-
-
- //---------------------------------------------------------------------------
- // SetGridRowCol
- //---------------------------------------------------------------------------
- ERR NEAR SetGridRowCol
- (
- HCTL hctl,
- PGRID pgrid,
- HWND hwnd,
- SHORT Row,
- SHORT Col
- )
- {
- if (pgrid->Row == Row && pgrid->Col == Col)
- return 0;
- if (pgrid->fFocus && hwnd)
- InvalidateCell(pgrid, hwnd, pgrid->Row, pgrid->Col);
- pgrid->Row = Row;
- pgrid->Col = Col;
- if (pgrid->fFocus && hwnd)
- InvalidateCell(pgrid, hwnd, Row, Col);
- return VBFireEvent(hctl, EVENT_GRID_CLICK, NULL);
- }
-
-
- //---------------------------------------------------------------------------
- // SetGridCols
- //---------------------------------------------------------------------------
- ERR NEAR SetGridCols
- (
- HCTL hctl,
- SHORT Cols
- )
- {
- BHVOID bhTemp;
- SHORT Row;
- SHORT Col;
- SHORT cb;
- ERR err;
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (Cols == pgrid->Cols)
- return 0;
-
- cb = sizeof(COLARRAY) + sizeof(COLDATA) * (Cols-1);
- if (Cols == 0) {
- bhTemp = NULL;
- MemFree((BHVOID)pgrid->bhColArray);
- }
- else {
- err = SetGridRowCol(hctl, pgrid, NULL, pgrid->Row, min(pgrid->Col,Cols-1));
- if (err)
- return err;
- pgrid = GRIDDEREF(hctl);
- err = SetGridSel(hctl, NULL, FALSE,
- pgrid->SelTopRow, min(pgrid->SelLeftCol,Cols-1),
- pgrid->SelBottomRow, min(pgrid->SelRightCol,Cols-1));
- if (err)
- return err;
- pgrid = GRIDDEREF(hctl);
- if (pgrid->FixedCols >= Cols)
- pgrid->FixedCols = Cols - 1;
- pgrid->LeftCol = pgrid->KeySelCol = pgrid->FixedCols;
- if (pgrid->Cols)
- bhTemp = MemReAlloc(pgrid->bhColArray, cb);
- else
- bhTemp = MemAlloc(cb);
- if (!bhTemp)
- return 1; // UNDONE
- pgrid = GRIDDEREF(hctl);
- }
- pgrid->bhColArray = (COLARRAY DBH)bhTemp;
- if (Cols > pgrid->Cols)
- // set default widths for all new columns
- for (Col = pgrid->Cols; Col < Cols; Col++) {
- COLWIDTH(Col) = pgrid->DefWidth;
- COL(Col).fDefWidth = TRUE;
- COLALIGN(Col) = DT_CENTER;
- }
- else
- // shorten row data to remove old columns
- for (Row = 0; Row < pgrid->Rows; Row++)
- if (Cols < ROW(Row)->Cols) {
- for (Col = Cols; Col < ROW(Row)->Cols; Col++) {
- bhTemp = ROW(Row)->bhStr[Col];
- if (bhTemp)
- MemFree(bhTemp);
- }
- // reduce row size
- bhTemp = MemReAlloc((*pgrid->bhRowArray)->bhRowData[Row],
- sizeof(ROWDATA) + sizeof(BHSTR)*(Cols-1));
- pgrid = GRIDDEREF(hctl);
- (*pgrid->bhRowArray)->bhRowData[Row] = (ROWDATA DBH)bhTemp;
- ROW(Row)->Cols = Cols;
- }
- pgrid->Cols = Cols;
- return 0;
- }
-
-
- //---------------------------------------------------------------------------
- // SetGridRows
- //---------------------------------------------------------------------------
- ERR NEAR SetGridRows
- (
- HCTL hctl,
- SHORT Rows
- )
- {
- BHVOID bhTemp;
- SHORT Row;
- SHORT Col;
- SHORT cb;
- ERR err;
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (Rows == pgrid->Rows)
- return 0;
-
- if (Rows < pgrid->Rows)
- // remove old rows
- for (Row = Rows; Row < pgrid->Rows; Row++) {
- for (Col = 0; Col < ROW(Row)->Cols; Col++) {
- bhTemp = ROW(Row)->bhStr[Col];
- if (bhTemp)
- MemFree(bhTemp);
- }
- MemFree((BHVOID)(*pgrid->bhRowArray)->bhRowData[Row]);
- }
- if (Rows == 0) {
- bhTemp = NULL;
- MemFree((BHVOID)pgrid->bhRowArray);
- }
- else {
- err = SetGridRowCol(hctl, pgrid, NULL, min(pgrid->Row,Rows-1), pgrid->Col);
- if (err)
- return err;
- pgrid = GRIDDEREF(hctl);
- err = SetGridSel(hctl, NULL, FALSE,
- min(pgrid->SelTopRow,Rows-1), pgrid->SelLeftCol,
- min(pgrid->SelBottomRow,Rows-1), pgrid->SelRightCol);
- if (err)
- return err;
- pgrid = GRIDDEREF(hctl);
- if (pgrid->FixedRows >= Rows)
- pgrid->FixedRows = Rows - 1;
- pgrid->TopRow = pgrid->KeySelRow = pgrid->FixedRows;
- cb = sizeof(ROWARRAY) + sizeof(ROWDATA DBH) * (Rows-1);
- if (pgrid->Rows)
- bhTemp = MemReAlloc(pgrid->bhRowArray, cb);
- else
- bhTemp = MemAlloc(cb);
- if (!bhTemp)
- return 1; // UNDONE
- pgrid = GRIDDEREF(hctl);
- }
- pgrid->bhRowArray = (ROWARRAY DBH)bhTemp;
-
- if (Rows > pgrid->Rows)
- // setup all new rows
- for (Row = pgrid->Rows; Row < Rows; Row++) {
- bhTemp = MemAlloc(sizeof(ROWDATA));
- pgrid = GRIDDEREF(hctl);
- if (!bhTemp) {
- while (--Row >= pgrid->Rows)
- MemFree((BHVOID)(*pgrid->bhRowArray)->bhRowData[Row]);
- if (!pgrid->Rows)
- MemFree((BHVOID)pgrid->bhRowArray);
- return 1; // UNDONE
- }
- (*pgrid->bhRowArray)->bhRowData[Row] = (ROWDATA DBH)bhTemp;
- ROWHEIGHT(Row) = pgrid->DefHeight;
- ROW(Row)->fDefHeight = TRUE;
- }
- pgrid->Rows = Rows;
- return 0;
- }
-
- //---------------------------------------------------------------------------
- // InitGrid
- //---------------------------------------------------------------------------
- BOOL NEAR InitGrid
- (
- HCTL hctl
- )
- {
- HANDLE hseg;
-
- PGRID pgrid = GRIDDEREF(hctl);
-
- pgrid->Row = 1;
- pgrid->Col = 1;
- pgrid->Rows = 0;
- pgrid->Cols = 0;
- pgrid->FixedRows = 1;
- pgrid->FixedCols = 1;
- pgrid->TopRow = 1;
- pgrid->LeftCol = 1;
- pgrid->KeySelRow = pgrid->FixedRows;
- pgrid->KeySelCol = pgrid->FixedCols;
- pgrid->fSelection = FALSE;
- pgrid->hFont = NULL;
- pgrid->fScrollVert = TRUE;
- pgrid->fScrollHorz = TRUE;
-
- hseg = GlobalAlloc(GHND, 1000);
- if (!hseg)
- return FALSE;
- pgrid->segData = segData = (_segment)GlobalLock(hseg);
- LocalInit(segData, 16, (USHORT)GlobalSize(hseg));
-
- if (SetGridCols(hctl, 2))
- return FALSE;
-
- if (SetGridRows(hctl, 2)) {
- GlobalFree(hseg);
- return FALSE;
- }
-
- return TRUE;
- }
-
-
- //---------------------------------------------------------------------------
- // SizeGrid
- //---------------------------------------------------------------------------
- VOID NEAR SizeGrid
- (
- PGRID pgrid,
- HWND hwnd
- )
- {
- RECT rect;
- SHORT Row;
- SHORT Col;
- SHORT coord;
-
- GetClientRect(hwnd, &rect);
-
- coord = 0;
- for (Row = 0; Row < pgrid->Rows; Row++) {
- if (Row == pgrid->FixedRows) {
- pgrid->OrgY = coord;
- Row = pgrid->TopRow;
- }
- coord += ROWHEIGHT(Row) + 1;
- pgrid->BottomRow = Row;
- if (Row >= pgrid->TopRow && coord >= rect.bottom)
- break;
- }
- pgrid->Height = min(coord, rect.bottom);
- pgrid->WholeBottomRow = pgrid->BottomRow;
- if (coord > rect.bottom && pgrid->WholeBottomRow > pgrid->TopRow)
- pgrid->WholeBottomRow--;
-
- coord = rect.bottom;
- Row = pgrid->Rows;
- do {
- coord -= ROWHEIGHT(Row-1) + 1;
- } while (coord >= pgrid->OrgY && --Row > pgrid->FixedRows);
- pgrid->TopRowMax = min(Row, pgrid->Rows-1);
-
- coord = 0;
- for (Col = 0; Col < pgrid->Cols; Col++) {
- if (Col == pgrid->FixedCols) {
- pgrid->OrgX = coord;
- Col = pgrid->LeftCol;
- }
- coord += COLWIDTH(Col) + 1;
- pgrid->RightCol = Col;
- if (Col >= pgrid->LeftCol && coord >= rect.right)
- break;
- }
- pgrid->Width = min(coord, rect.right);
- pgrid->WholeRightCol = pgrid->RightCol;
- if (coord > rect.right && pgrid->WholeRightCol > pgrid->LeftCol)
- pgrid->WholeRightCol--;
-
- coord = rect.right;
- Col = pgrid->Cols;
- do {
- coord -= COLWIDTH(Col-1) + 1;
- } while (coord >= pgrid->OrgX && --Col > pgrid->FixedCols);
- pgrid->LeftColMax = min(Col, pgrid->Cols-1);
-
- SetGridScroll(pgrid, hwnd);
- }
-
- //---------------------------------------------------------------------------
- // SetGridScroll
- //---------------------------------------------------------------------------
- VOID NEAR SetGridScroll
- (
- PGRID pgrid,
- HWND hwnd
- )
- {
- RECT rcHome, rcEnd;
-
- GetCellRect(pgrid, pgrid->FixedRows, pgrid->FixedCols, &rcHome);
- GetCellRect(pgrid, pgrid->TopRowMax, pgrid->LeftColMax, &rcEnd);
- if (pgrid->fScrollHorz) {
- SetScrollRange(hwnd, SB_HORZ, rcHome.left, rcEnd.left, FALSE);
- SetScrollPos(hwnd, SB_HORZ, pgrid->OrgX, TRUE);
- }
- else {
- SetScrollRange(hwnd, SB_HORZ, 0, 0, FALSE);
- SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
- }
- if (pgrid->fScrollVert) {
- SetScrollRange(hwnd, SB_VERT, rcHome.top, rcEnd.top, FALSE);
- SetScrollPos(hwnd, SB_VERT, pgrid->OrgY, TRUE);
- }
- else {
- SetScrollRange(hwnd, SB_VERT, 0, 0, FALSE);
- SetScrollPos(hwnd, SB_VERT, 0, TRUE);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // GridCellSelected
- //---------------------------------------------------------------------------
- BOOL NEAR GridCellSelected
- (
- PGRID pgrid,
- SHORT Row,
- SHORT Col
- )
- {
- if (pgrid->fSelection
- && Row >= pgrid->SelTopRow && Row <= pgrid->SelBottomRow
- && Col >= pgrid->SelLeftCol && Col <= pgrid->SelRightCol)
- return TRUE;
- return FALSE;
- }
-
-
- //---------------------------------------------------------------------------
- // PaintGrid
- //---------------------------------------------------------------------------
- VOID NEAR PaintGrid
- (
- PGRID pgrid,
- HWND hwnd,
- HDC hdc
- )
- {
- RECT rcCell;
- SHORT Row;
- SHORT Col;
- RECT rcClient;
- LPSTR pszText;
- BHSTR bhStr;
- BOOL fFocus;
- HBRUSH hbrGray;
- HBRUSH hbrBlack;
- DWORD colorUse;
- DWORD colorHilite;
- DWORD colorText;
- HBRUSH hbr;
- HBRUSH hbrUse;
- HBRUSH hbrHilite = NULL;
-
- GetClientRect(hwnd, &rcClient);
- hbr = (HBRUSH)SendMessage(GetParent(hwnd), WM_CTLCOLOR, hdc, MAKELONG(hwnd, 0));
- colorText = GetTextColor(hdc);
- if (pgrid->fSelection) {
- colorHilite = GetSysColor(COLOR_HIGHLIGHTTEXT);
- hbrHilite = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
- }
- // Use the gizmo's font, if any
- if (pgrid->hFont)
- SelectObject(hdc, pgrid->hFont);
- hbrGray = GetStockObject(LTGRAY_BRUSH); // UNDONE
- hbrBlack = GetStockObject(BLACK_BRUSH); // UNDONE
- rcCell.top = 0;
- for (Row = 0; Row <= pgrid->BottomRow; Row++) {
- if (Row == pgrid->FixedRows)
- Row = pgrid->TopRow;
- rcCell.bottom = rcCell.top + ROWHEIGHT(Row);
- if (Row != pgrid->BottomRow) {
- SelectObject(hdc, hbrBlack);
- PatBlt(hdc, 0, rcCell.bottom, pgrid->OrgX, 1, PATCOPY);
- if (Row >= pgrid->FixedRows)
- SelectObject(hdc, hbrGray);
- PatBlt(hdc, pgrid->OrgX, rcCell.bottom,
- pgrid->Width - pgrid->OrgX, 1, PATCOPY);
- }
- rcCell.left = 0;
- for (Col = 0; Col <= pgrid->RightCol; Col++) {
- if (Col == pgrid->FixedCols)
- Col = pgrid->LeftCol;
- rcCell.right = rcCell.left + COLWIDTH(Col);
- if (rcCell.top == 0 && Col != pgrid->RightCol) {
- SelectObject(hdc, hbrBlack);
- PatBlt(hdc, rcCell.right, 0, 1, pgrid->OrgY, PATCOPY);
- if (Col >= pgrid->FixedCols)
- SelectObject(hdc, hbrGray);
- PatBlt(hdc, rcCell.right, pgrid->OrgY,
- 1, pgrid->Height - pgrid->OrgY, PATCOPY);
- }
- if (RectVisible(hdc, &rcCell)) {
- colorUse = colorText;
- fFocus = FALSE;
- if (Row < pgrid->FixedRows || Col < pgrid->FixedCols)
- hbrUse = hbrGray;
- else if (pgrid->fFocus && Row == pgrid->Row && Col == pgrid->Col) {
- fFocus = TRUE;
- hbrUse = hbr;
- }
- else if (GridCellSelected(pgrid, Row, Col)) {
- hbrUse = hbrHilite;
- colorUse = colorHilite;
- }
- else
- hbrUse = hbr;
- bhStr = GetCellText(pgrid, Row, Col);
- FillRect(hdc, &rcCell, hbrUse);
- if (bhStr) {
- pszText = (LPSTR)*bhStr;
- rcCell.left++;
- InflateRect(&rcCell, -1, -1);
- SetTextColor(hdc, colorUse);
- SetBkMode(hdc, TRANSPARENT);
- DrawText(hdc, pszText, -1, &rcCell,
- DT_WORDBREAK | COLALIGN(Col));
- InflateRect(&rcCell, 1, 1);
- rcCell.left--;
- }
- if (fFocus)
- DrawFocusRect(hdc, &rcCell);
- }
- rcCell.left = rcCell.right + 1;
- }
- rcCell.top = rcCell.bottom + 1;
- }
- SelectObject(hdc, hbrBlack);
- PatBlt(hdc, 0, rcCell.bottom, rcCell.right, 1, PATCOPY);
- PatBlt(hdc, rcCell.right, 0, 1, rcCell.bottom, PATCOPY);
- // fill area behind grid
- rcCell = rcClient;
- rcCell.top = pgrid->Height;
- FillRect(hdc, &rcCell, hbrGray);
- rcCell.top = 0;
- rcCell.left = pgrid->Width;
- rcCell.bottom = pgrid->Height;
- FillRect(hdc, &rcCell, hbrGray);
- SelectObject(hdc, hbr);
- if (hbrHilite)
- DeleteObject(hbrHilite);
- }
-
-
- //---------------------------------------------------------------------------
- // MemAlloc
- //---------------------------------------------------------------------------
-
- BHVOID NEAR MemAlloc
- (
- USHORT cb
- )
- {
- HANDLE hTemp;
-
- _asm
- {
- push ds
- mov ds,segData
- }
-
- hTemp = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, cb);
-
- _asm
- {
- pop ds
- }
-
- return (BHVOID)hTemp;
- }
-
-
- //---------------------------------------------------------------------------
- // MemReAlloc
- //---------------------------------------------------------------------------
-
- BHVOID NEAR MemReAlloc
- (
- BHVOID bhTemp,
- USHORT cb
- )
- {
- HANDLE hTemp;
- WORD size1;
- WORD size2;
-
- size1 = MemSize(bhTemp);
- if (size1 >= cb)
- return bhTemp;
-
- _asm
- {
- push ds
- mov ds,segData
- }
-
- hTemp = LocalReAlloc((HANDLE)bhTemp, cb, LMEM_MOVEABLE | LMEM_ZEROINIT);
-
- _asm
- {
- pop ds
- }
-
- if (hTemp) {
- size2 = MemSize((BHVOID)hTemp);
- _fmemset((*(BHSTR)hTemp)+size1, 0, size2-size1);
- }
-
- return (BHVOID)hTemp;
- }
-
-
- //---------------------------------------------------------------------------
- // MemFree
- //---------------------------------------------------------------------------
-
- VOID NEAR MemFree
- (
- BHVOID bhTemp
- )
- {
- _asm
- {
- push ds
- mov ds,segData
- }
-
- LocalFree((HANDLE)bhTemp);
-
- _asm
- {
- pop ds
- }
-
- return bhTemp;
- }
-
-
- //---------------------------------------------------------------------------
- // MemSize
- //---------------------------------------------------------------------------
-
- WORD NEAR MemSize
- (
- BHVOID bhTemp
- )
- {
- WORD size;
-
- _asm
- {
- push ds
- mov ds,segData
- }
-
- size = LocalSize((HANDLE)bhTemp);
-
- _asm
- {
- pop ds
- }
-
- return size;
- }
-
-
- //---------------------------------------------------------------------------
- // GetCellText
- //---------------------------------------------------------------------------
- BHSTR NEAR GetCellText
- (
- PGRID pgrid,
- SHORT Row,
- SHORT Col
- )
- {
- if (Col >= ROW(Row)->Cols)
- return NULL;
- return ROW(Row)->bhStr[Col];
- }
-
-
- //---------------------------------------------------------------------------
- // SetCellText
- //---------------------------------------------------------------------------
- ERR NEAR SetCellText
- (
- HCTL hctl,
- HWND hwnd,
- SHORT Row,
- SHORT Col,
- LPSTR pszText
- )
- {
- BHVOID bhTemp;
- SHORT cbLen;
- PGRID pgrid = GRIDDEREF(hctl);
-
- cbLen = pszText ? lstrlen(pszText) : 0;
- if (Col >= ROW(Row)->Cols) {
- if (cbLen == 0)
- return 0;
- // grow data for this row to include this column
- bhTemp = MemReAlloc((*pgrid->bhRowArray)->bhRowData[Row],
- sizeof(ROWDATA) + sizeof(BHSTR)*Col);
- if (!bhTemp)
- return 1; // UNDONE: idaNoMem
- pgrid = GRIDDEREF(hctl);
- (*pgrid->bhRowArray)->bhRowData[Row] = (ROWDATA DBH)bhTemp;
- // clear new cols
- _fmemset(&ROW(Row)->bhStr[ROW(Row)->Cols], 0,
- (Col+1-ROW(Row)->Cols)*sizeof(BHSTR));
- ROW(Row)->Cols = Col+1;
- if (ROW(Row)->bhStr[Col]) // UNDONE: remove
- return 5;
- }
- bhTemp = ROW(Row)->bhStr[Col];
- if (cbLen == 0) {
- // removing the item
- if (bhTemp == NULL)
- // already gone
- return 0;
- // free it
- MemFree(bhTemp);
- bhTemp = NULL;
- }
- else {
- if (bhTemp)
- // RE-allocate existing string for this entry
- bhTemp = MemReAlloc(bhTemp, cbLen+1);
- else
- // allocate new string for this entry
- bhTemp = MemAlloc(cbLen+1);
- if (!bhTemp)
- return 1; // UNDONE: idaNoMem
- lstrcpy((LPSTR)*(BHSTR)bhTemp, pszText);
- pgrid = GRIDDEREF(hctl);
- }
- ROW(Row)->bhStr[Col] = (BHSTR)bhTemp;
- InvalidateCell(pgrid, hwnd, Row, Col);
- return 0;
- }
-
-
- //---------------------------------------------------------------------------
- // CellIsUnobstructed
- //---------------------------------------------------------------------------
- BOOL NEAR CellIsUnobstructed
- (
- PGRID pgrid,
- SHORT Row,
- SHORT Col
- )
- {
- BOOL a,b,c,d;
-
- a = (Row >= pgrid->TopRow && Row <= pgrid->WholeBottomRow);
- b = (Col >= pgrid->LeftCol && Col <= pgrid->WholeRightCol);
- c = (Row < pgrid->FixedRows);
- d = (Col < pgrid->FixedCols);
-
- return (a && (b || d) || b && (a || c) || c && d);
- }
-
-
- //---------------------------------------------------------------------------
- // CellIsVisible
- //---------------------------------------------------------------------------
- BOOL NEAR CellIsVisible
- (
- PGRID pgrid,
- SHORT Row,
- SHORT Col
- )
- {
- BOOL a,b,c,d;
-
- a = (Row >= pgrid->TopRow && Row <= pgrid->BottomRow);
- b = (Col >= pgrid->LeftCol && Col <= pgrid->RightCol);
- c = (Row < pgrid->FixedRows);
- d = (Col < pgrid->FixedCols);
-
- return (a && (b || d) || b && (a || c) || c && d);
- }
-
-
- //---------------------------------------------------------------------------
- // XToCol
- //---------------------------------------------------------------------------
- SHORT NEAR XToCol
- (
- PGRID pgrid,
- SHORT X,
- BOOL fFixed
- )
- {
- SHORT c;
- SHORT lim;
- SHORT coord;
-
- coord = pgrid->OrgX;
- if (X >= pgrid->OrgX) {
- for (c = pgrid->LeftCol; c < pgrid->Cols; c++) {
- coord += COLWIDTH(c) + 1;
- if (X <= coord)
- return c;
- }
- return pgrid->Cols-1;
- }
- else {
- if (fFixed) {
- lim = 0;
- c = pgrid->FixedCols-1;
- }
- else {
- lim = pgrid->FixedCols;
- c = pgrid->LeftCol-1;
- }
- for (; c > lim; c--) {
- coord -= COLWIDTH(c) + 1;
- if (X > coord)
- return c;
- }
- return lim;
- }
- }
-
-
- //---------------------------------------------------------------------------
- // YToRow
- //---------------------------------------------------------------------------
- SHORT NEAR YToRow
- (
- PGRID pgrid,
- SHORT Y,
- BOOL fFixed
- )
- {
- SHORT r;
- SHORT lim;
- SHORT coord;
-
- coord = pgrid->OrgY;
- if (Y >= pgrid->OrgY) {
- for (r = pgrid->TopRow; r < pgrid->Rows; r++) {
- coord += ROWHEIGHT(r) + 1;
- if (Y <= coord)
- return r;
- }
- return pgrid->Rows-1;
- }
- else {
- if (fFixed) {
- lim = 0;
- r = pgrid->FixedRows-1;
- }
- else {
- lim = pgrid->FixedRows;
- r = pgrid->TopRow-1;
- }
- for (; r > lim; r--) {
- coord -= ROWHEIGHT(r) + 1;
- if (Y > coord)
- return r;
- }
- return lim;
- }
- }
-
-
- //---------------------------------------------------------------------------
- // GetCellRect
- //---------------------------------------------------------------------------
- VOID NEAR GetCellRect
- (
- PGRID pgrid,
- SHORT Row,
- SHORT Col,
- LPRECT lprect
- )
- {
- SHORT i;
- SHORT coord;
-
- coord = pgrid->OrgY;
- if (Row >= pgrid->TopRow)
- for (i = pgrid->TopRow; i < Row; i++)
- coord += ROWHEIGHT(i) + 1;
- else if (Row >= pgrid->FixedRows)
- for (i = 0; i < pgrid->TopRow; i++)
- coord -= ROWHEIGHT(i) + 1;
- else {
- coord = 0;
- for (i = 0; i < Row; i++)
- coord += ROWHEIGHT(i) + 1;
- }
- lprect->top = coord;
- lprect->bottom = coord + ROWHEIGHT(Row) + 1;
-
- coord = pgrid->OrgX;
- if (Col >= pgrid->LeftCol) {
- for (i = pgrid->LeftCol; i < Col; i++)
- coord += COLWIDTH(i) + 1;
- }
- else if (Col >= pgrid->FixedCols)
- for (i = 0; i < pgrid->LeftCol; i++)
- coord -= COLWIDTH(i) + 1;
- else {
- coord = 0;
- for (i = 0; i < Col; i++)
- coord += COLWIDTH(i) + 1;
- }
- lprect->left = coord;
- lprect->right = coord + COLWIDTH(Col) + 1;
- }
-
-
- //---------------------------------------------------------------------------
- // InvalidateCell
- //---------------------------------------------------------------------------
- VOID NEAR InvalidateCell
- (
- PGRID pgrid,
- HWND hwnd,
- SHORT Row,
- SHORT Col
- )
- {
- RECT rect;
-
- if (CellIsVisible(pgrid, Row, Col)) {
- GetCellRect(pgrid, Row, Col, &rect);
- InvalidateRect(hwnd, &rect, FALSE);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // InvalidateCol
- //---------------------------------------------------------------------------
- VOID NEAR InvalidateCol
- (
- PGRID pgrid,
- HWND hwnd,
- SHORT Col
- )
- {
- RECT rect;
-
- if (CellIsVisible(pgrid, pgrid->TopRow, Col)) {
- GetCellRect(pgrid, pgrid->TopRow, Col, &rect);
- rect.top = 0;
- rect.bottom = pgrid->Height;
- InvalidateRect(hwnd, &rect, FALSE);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // InvalidateRow
- //---------------------------------------------------------------------------
- VOID NEAR InvalidateRow
- (
- PGRID pgrid,
- HWND hwnd,
- SHORT Row
- )
- {
- RECT rect;
-
- if (CellIsVisible(pgrid, Row, pgrid->LeftCol)) {
- GetCellRect(pgrid, Row, pgrid->LeftCol, &rect);
- rect.left = 0;
- rect.right = pgrid->Width;
- InvalidateRect(hwnd, &rect, FALSE);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // ScrollGridVert
- //---------------------------------------------------------------------------
- VOID NEAR ScrollGridVert
- (
- PGRID pgrid,
- HWND hwnd,
- USHORT Code,
- USHORT Val
- )
- {
- SHORT Row;
- RECT rect;
-
- switch (Code) {
- case SB_TOP:
- Row = pgrid->FixedRows;
- break;
-
- case SB_BOTTOM:
- Row = pgrid->TopRowMax;
- break;
-
- case SB_LINEUP:
- Row = pgrid->TopRow - 1;
- break;
-
- case SB_LINEDOWN:
- Row = pgrid->TopRow + 1;
- break;
-
- case SB_PAGEUP:
- Row = YToRow(pgrid, pgrid->OrgY - (pgrid->Height - pgrid->OrgY),
- FALSE);
- if (Row == pgrid->TopRow)
- Row--;
- break;
-
- case SB_PAGEDOWN:
- Row = YToRow(pgrid, pgrid->OrgY + (pgrid->Height - pgrid->OrgY),
- FALSE);
- if (Row == pgrid->TopRow)
- Row++;
- break;
-
- case SB_THUMBPOSITION:
- Row = YToRow(pgrid, Val, FALSE);
- break;
-
- case SB_ENDSCROLL:
- case SB_THUMBTRACK:
- default:
- return;
- }
-
- Row = limit(Row, pgrid->FixedRows, pgrid->TopRowMax);
- if (Row == pgrid->TopRow)
- return;
- pgrid->TopRow = Row;
- SizeGrid(pgrid, hwnd);
- GetClientRect(hwnd, &rect);
- rect.top = pgrid->OrgY;
- InvalidateRect(hwnd, &rect, FALSE);
- }
-
-
- //---------------------------------------------------------------------------
- // ScrollGridHorz
- //---------------------------------------------------------------------------
- VOID NEAR ScrollGridHorz
- (
- PGRID pgrid,
- HWND hwnd,
- USHORT Code,
- USHORT Val
- )
- {
- SHORT Col;
- RECT rect;
-
- switch (Code) {
- case SB_TOP:
- Col = pgrid->FixedCols;
- break;
-
- case SB_BOTTOM:
- Col = pgrid->LeftColMax;
- break;
-
- case SB_LINEUP:
- Col = pgrid->LeftCol - 1;
- break;
-
- case SB_LINEDOWN:
- Col = pgrid->LeftCol + 1;
- break;
-
- case SB_PAGEUP:
- Col = XToCol(pgrid, pgrid->OrgX - (pgrid->Width - pgrid->OrgX),
- FALSE);
- if (Col == pgrid->LeftCol)
- Col--;
- break;
-
- case SB_PAGEDOWN:
- Col = XToCol(pgrid, pgrid->OrgX + (pgrid->Width - pgrid->OrgX),
- FALSE);
- if (Col == pgrid->LeftCol)
- Col++;
- break;
-
- case SB_THUMBPOSITION:
- Col = XToCol(pgrid, Val, FALSE);
- break;
-
- case SB_ENDSCROLL:
- case SB_THUMBTRACK:
- default:
- return;
- }
-
- Col = limit(Col, pgrid->FixedCols, pgrid->LeftColMax);
- if (Col == pgrid->LeftCol)
- return;
- pgrid->LeftCol = Col;
- SizeGrid(pgrid, hwnd);
- GetClientRect(hwnd, &rect);
- rect.left = pgrid->OrgX;
- InvalidateRect(hwnd, &rect, FALSE);
- }
-
-
- //---------------------------------------------------------------------------
- // GridScrollToView
- //---------------------------------------------------------------------------
- VOID NEAR GridScrollToView
- (
- PGRID pgrid,
- HWND hwnd,
- SHORT Row,
- SHORT Col
- )
- {
- RECT rect;
- RECT rcCell;
-
- if (CellIsUnobstructed(pgrid, Row, Col))
- return;
- GetClientRect(hwnd, &rect);
- rect.top = pgrid->OrgY;
- rect.left = pgrid->OrgX;
- GetCellRect(pgrid, Row, Col, &rcCell);
- if (Row < pgrid->TopRow) {
- pgrid->TopRow = Row;
- rect.left = 0;
- }
- else if (Row > pgrid->WholeBottomRow) {
- do {
- pgrid->Height += ROWHEIGHT(pgrid->TopRow++);
- } while (pgrid->Height < rcCell.bottom
- && Row > pgrid->TopRow);
- rect.left = 0;
- }
- if (Col < pgrid->LeftCol) {
- pgrid->LeftCol = Col;
- rect.top = 0;
- }
- else if (Col > pgrid->WholeRightCol) {
- do {
- pgrid->Width += COLWIDTH(pgrid->LeftCol++);
- } while (pgrid->Width < rcCell.right
- && Col > pgrid->LeftCol);
- rect.top = 0;
- }
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, &rect, FALSE);
- }
-
-
- //---------------------------------------------------------------------------
- // InvalidateSelection
- //---------------------------------------------------------------------------
- VOID NEAR InvalidateSelection
- (
- PGRID pgrid,
- HWND hwnd
- )
- {
- RECT rcSel;
- RECT rcCell;
-
- if (!pgrid->fSelection)
- return;
-
- GetCellRect(pgrid, pgrid->SelTopRow, pgrid->SelLeftCol, &rcSel);
- if (pgrid->SelBottomRow > pgrid->SelTopRow
- || pgrid->SelRightCol > pgrid->SelLeftCol) {
- GetCellRect(pgrid, pgrid->SelBottomRow, pgrid->SelRightCol, &rcCell);
- UnionRect(&rcSel, &rcSel, &rcCell);
- }
- InvalidateRect(hwnd, &rcSel, FALSE);
- }
-
-
- //---------------------------------------------------------------------------
- // ClearGridSel
- //---------------------------------------------------------------------------
- ERR NEAR ClearGridSel
- (
- HCTL hctl,
- HWND hwnd
- )
- {
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (!pgrid->fSelection)
- return 0;
- if (hwnd)
- InvalidateSelection(pgrid, hwnd);
- pgrid->SelTopRow = 0;
- pgrid->SelBottomRow = 0;
- pgrid->SelLeftCol = 0;
- pgrid->SelRightCol = 0;
- pgrid->fSelection = FALSE;
- return VBFireEvent(hctl, EVENT_GRID_SELCHANGE, NULL);
- }
-
-
- //---------------------------------------------------------------------------
- // SetGridSel
- //---------------------------------------------------------------------------
- ERR NEAR SetGridSel
- (
- HCTL hctl,
- HWND hwnd,
- BOOL fSwap,
- SHORT StartRow,
- SHORT StartCol,
- SHORT EndRow,
- SHORT EndCol
- )
- {
- PGRID pgrid = GRIDDEREF(hctl);
- SHORT Swap;
- BOOL fSel = TRUE;
-
- if (StartRow > EndRow) {
- if (fSwap) {
- Swap = StartRow;
- StartRow = EndRow;
- EndRow = Swap;
- }
- else
- fSel = FALSE;
- }
- if (StartCol > EndCol) {
- if (fSwap) {
- Swap = StartCol;
- StartCol = EndCol;
- EndCol = Swap;
- }
- else
- fSel = FALSE;
- }
-
- if ((BOOL)pgrid->fSelection == fSel
- && pgrid->SelTopRow == StartRow
- && pgrid->SelBottomRow == EndRow
- && pgrid->SelLeftCol == StartCol
- && pgrid->SelRightCol == EndCol)
- return 0;
-
- if (hwnd)
- InvalidateSelection(pgrid, hwnd);
- pgrid->SelTopRow = StartRow;
- pgrid->SelBottomRow = EndRow;
- pgrid->SelLeftCol = StartCol;
- pgrid->SelRightCol = EndCol;
- pgrid->fSelection = fSel;
- if (hwnd)
- InvalidateSelection(pgrid, hwnd);
- return VBFireEvent(hctl, EVENT_GRID_SELCHANGE, NULL);
- }
-
- #define HIT_NONE 0
- #define HIT_VERT 1
- #define HIT_HORZ 2
-
- //---------------------------------------------------------------------------
- // GridMouseHit
- //---------------------------------------------------------------------------
- LONG NEAR GridMouseHit
- (
- PGRID pgrid,
- SHORT x,
- SHORT y
- )
- {
- SHORT coord;
- SHORT i;
-
- if (x >= pgrid->OrgX && y >= pgrid->OrgY)
- return HIT_NONE;
-
- if (y < pgrid->OrgY) {
- coord = 0;
- for (i = 0; i < pgrid->Cols; i++) {
- if (i == pgrid->FixedCols)
- i = pgrid->LeftCol;
- coord += COLWIDTH(i) + 1;
- if (coord > pgrid->Width)
- break;
- if (x >= coord-3 && x <= coord+1)
- return MAKELONG(HIT_VERT, i);
- if (coord > x)
- break;
- }
- }
-
- if (x < pgrid->OrgX) {
- coord = 0;
- for (i = 0; i < pgrid->Rows; i++) {
- if (i == pgrid->FixedRows)
- i = pgrid->TopRow;
- coord += ROWHEIGHT(i) + 1;
- if (coord > pgrid->Height)
- break;
- if (y >= coord-3 && y <= coord+1) {
- return MAKELONG(HIT_HORZ, i);
- }
- if (coord > y)
- break;
- }
- }
- return HIT_NONE;
- }
-
-
- #define SEL_RNG 0
- #define SEL_ROWS 1
- #define SEL_COLS 2
-
- USHORT OldCaretRate;
-
- LONG Hit;
- SHORT HitCoord;
-
- //---------------------------------------------------------------------------
- // GridMouseDown
- //---------------------------------------------------------------------------
- VOID NEAR GridMouseDown
- (
- HCTL hctl,
- HWND hwnd,
- SHORT x,
- SHORT y
- )
- {
- SHORT Row;
- SHORT Col;
- SHORT StartRow;
- SHORT EndRow;
- SHORT StartCol;
- SHORT EndCol;
- BOOL fShift;
- PGRID pgrid = GRIDDEREF(hctl);
-
- SetFocus(hwnd);
- if (y > pgrid->Height || x > pgrid->Width)
- return;
- SetCapture(hwnd);
- pgrid->fMouseCapture = TRUE;
-
- Hit = GridMouseHit(pgrid, x, y);
- if (Hit) {
- RECT rcCell;
- RECT rcClip;
-
- GetClientRect(hwnd, &rcClip);
- if (LOWORD(Hit) == HIT_VERT) {
- GetCellRect(pgrid, 0, HIWORD(Hit), &rcCell);
- CreateCaret(hwnd, NULL, 2, pgrid->Height);
- SetCaretPos(x, 0);
- rcClip.left = HitCoord = rcCell.left;
- }
- else {
- GetCellRect(pgrid, HIWORD(Hit), 0, &rcCell);
- CreateCaret(hwnd, NULL, pgrid->Width, 2);
- SetCaretPos(0, y);
- rcClip.top = HitCoord = rcCell.top;
- }
- OldCaretRate = GetCaretBlinkTime();
- SetCaretBlinkTime(0xFFFF);
- ShowCaret(hwnd);
- ClientToScreen(hwnd, (LPPOINT)&rcClip.left);
- ClientToScreen(hwnd, (LPPOINT)&rcClip.right);
- ClipCursor(&rcClip);
- return;
- }
-
- fShift = GetAsyncKeyState(VK_SHIFT);
-
- Row = YToRow(pgrid, y, TRUE);
- Col = XToCol(pgrid, x, TRUE);
- StartRow = fShift ? pgrid->Row : Row;
- EndRow = Row;
- StartCol = fShift ? pgrid->Col : Col;
- EndCol = Col;
- pgrid->SelType = SEL_RNG;
- if (Row < pgrid->FixedRows) {
- pgrid->SelType |= SEL_COLS;
- Row = pgrid->TopRow;
- StartRow = pgrid->FixedRows;
- EndRow = pgrid->Rows - 1;
- }
- if (Col < pgrid->FixedCols) {
- pgrid->SelType |= SEL_ROWS;
- Col = pgrid->LeftCol;
- StartCol = pgrid->FixedCols;
- EndCol = pgrid->Cols - 1;
- }
- pgrid->KeySelRow = Row;
- pgrid->KeySelCol = Col;
- if (!fShift)
- if (SetGridRowCol(hctl, pgrid, hwnd, Row, Col))
- return;
- SetGridSel(hctl, hwnd, TRUE, StartRow, StartCol, EndRow, EndCol);
- }
-
-
- //---------------------------------------------------------------------------
- // GridMouseDblClick
- //---------------------------------------------------------------------------
- VOID NEAR GridMouseDblClick
- (
- HCTL hctl,
- HWND hwnd,
- SHORT x,
- SHORT y
- )
- {
- PGRID pgrid = GRIDDEREF(hctl);
-
- hwnd = hwnd;
- if (y > pgrid->Height || x > pgrid->Width)
- return;
- VBFireEvent(hctl, EVENT_GRID_DBLCLICK, NULL);
- }
-
-
- //---------------------------------------------------------------------------
- // GridMouseMove
- //---------------------------------------------------------------------------
- VOID NEAR GridMouseMove
- (
- HCTL hctl,
- HWND hwnd,
- SHORT x,
- SHORT y
- )
- {
- SHORT StartRow;
- SHORT EndRow;
- SHORT StartCol;
- SHORT EndCol;
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (!pgrid->fMouseCapture) {
- LONG Hit;
-
- Hit = GridMouseHit(pgrid, x, y);
- if (!Hit) {
- SetCursor(hcurArrow);
- return;
- }
- if (LOWORD(Hit) == HIT_VERT)
- SetCursor(hcurVSep);
- else
- SetCursor(hcurHSep);
- return;
- }
-
- if (LOWORD(Hit) == HIT_VERT) {
- SetCursor(hcurVSep);
- SetCaretPos(x, 0);
- return;
- }
- if (LOWORD(Hit) == HIT_HORZ) {
- SetCursor(hcurHSep);
- SetCaretPos(0, y);
- return;
- }
-
- StartRow = pgrid->Row;
- EndRow = YToRow(pgrid, y, FALSE);
- StartCol = pgrid->Col;
- EndCol = XToCol(pgrid, x, FALSE);
- GridScrollToView(pgrid, hwnd, EndRow, EndCol);
- pgrid->KeySelRow = EndRow;
- pgrid->KeySelCol = EndCol;
-
- if (pgrid->SelType & SEL_ROWS) {
- StartCol = pgrid->FixedCols;
- EndCol = pgrid->Cols-1;
- }
- if (pgrid->SelType & SEL_COLS) {
- StartRow = pgrid->FixedRows;
- EndRow = pgrid->Rows-1;
- }
- SetGridSel(hctl, hwnd, TRUE, StartRow, StartCol, EndRow, EndCol);
- }
-
-
- //---------------------------------------------------------------------------
- // GridMouseUp
- //---------------------------------------------------------------------------
- VOID NEAR GridMouseUp
- (
- HCTL hctl,
- HWND hwnd,
- SHORT x,
- SHORT y
- )
- {
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (!pgrid->fMouseCapture)
- return;
-
- pgrid->fMouseCapture = FALSE;
- ReleaseCapture();
-
- if (Hit) {
- BOOL fChange;
-
- ClipCursor(NULL);
- SetCaretBlinkTime(OldCaretRate);
- HideCaret(hwnd);
- if (LOWORD(Hit) == HIT_VERT) {
- fChange = COLWIDTH(HIWORD(Hit)) != x - HitCoord;
- COLWIDTH(HIWORD(Hit)) = x - HitCoord;
- }
- else {
- fChange = ROWHEIGHT(HIWORD(Hit)) != y - HitCoord;
- ROWHEIGHT(HIWORD(Hit)) = y - HitCoord;
- }
- Hit = 0L;
- if (fChange) {
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- }
- }
- }
-
-
- //---------------------------------------------------------------------------
- // GridKeyDown
- //---------------------------------------------------------------------------
- VOID NEAR GridKeyDown
- (
- HCTL hctl,
- HWND hwnd,
- USHORT VKKey
- )
- {
- RECT rect;
- SHORT Temp;
- SHORT Row;
- SHORT Col;
- BOOL fShift;
- BOOL fCtrl;
- PGRID pgrid = GRIDDEREF(hctl);
-
- if (pgrid->fMouseCapture)
- return;
-
- pgrid = GRIDDEREF(hctl);
-
-
- fShift = GetAsyncKeyState(VK_SHIFT);
- fCtrl = GetAsyncKeyState(VK_CONTROL);
-
- if (fShift && pgrid->fSelection && VKKey != VK_RETURN) {
- Row = pgrid->KeySelRow;
- Col = pgrid->KeySelCol;
- }
- else {
- pgrid->SelType = SEL_RNG;
- Row = pgrid->Row;
- Col = pgrid->Col;
- }
-
- switch (VKKey) {
- case VK_RETURN:
- if (!pgrid->fSelection)
- return;
- do {
- if (fShift) {
- if (Col-- < pgrid->FixedCols) {
- Col = pgrid->Cols-1;
- Row--;
- if (Row < pgrid->FixedRows)
- Row = pgrid->Rows-1;
- }
- }
- else {
- if (Col++ >= pgrid->Cols) {
- Col = pgrid->FixedCols;
- Row++;
- if (Row >= pgrid->Rows)
- Row = pgrid->FixedRows;
- }
- }
- } while (!GridCellSelected(pgrid, Row, Col));
- GridScrollToView(pgrid, hwnd, Row, Col);
- SetGridRowCol(hctl, pgrid, hwnd, Row, Col);
- return;
-
- case VK_PRIOR:
- GetCellRect(pgrid, Row, Col, &rect);
- if (fCtrl) {
- Temp = XToCol(pgrid, rect.left - (pgrid->Width - pgrid->OrgX),
- FALSE);
- if (Temp == Col)
- Col--;
- else
- Col = Temp;
- }
- else {
- Temp = YToRow(pgrid, rect.top - (pgrid->Height - pgrid->OrgY),
- FALSE);
- if (Temp == Row)
- Row--;
- else
- Row = Temp;
- }
- break;
-
- case VK_NEXT:
- GetCellRect(pgrid, Row, Col, &rect);
- if (fCtrl) {
- Temp = XToCol(pgrid, rect.left + (pgrid->Width - pgrid->OrgX),
- FALSE);
- if (Temp == Col)
- Col++;
- else
- Col = Temp;
- }
- else {
- Temp = YToRow(pgrid, rect.top + (pgrid->Height - pgrid->OrgY),
- FALSE);
- if (Temp == Row)
- Row++;
- else
- Row = Temp;
- }
- break;
-
- case VK_END:
- if (fCtrl)
- Row = pgrid->Rows-1;
- Col = pgrid->Cols-1;
- break;
-
- case VK_HOME:
- if (fCtrl)
- Row = pgrid->FixedRows;
- Col = pgrid->FixedCols;
- break;
-
- case VK_LEFT:
- Col--;
- if (fCtrl)
- while (Col > pgrid->FixedCols && !GetCellText(pgrid, Row, Col))
- Col--;
- break;
-
- case VK_UP:
- Row--;
- if (fCtrl)
- while (Row > pgrid->FixedRows && !GetCellText(pgrid, Row, Col))
- Row--;
- break;
-
- case VK_RIGHT:
- Col++;
- if (fCtrl)
- while (Col < pgrid->Cols-1 && !GetCellText(pgrid, Row, Col))
- Col++;
- break;
-
- case VK_DOWN:
- Row++;
- if (fCtrl)
- while (Row < pgrid->Rows-1 && !GetCellText(pgrid, Row, Col))
- Row++;
- break;
-
- case VK_SPACE:
- if (fShift)
- pgrid->SelType |= SEL_COLS;
- if (fCtrl)
- pgrid->SelType |= SEL_ROWS;
- // force selection
- fShift |= fCtrl;
- break;
-
- default:
- return;
- }
-
- Row = limit(Row, pgrid->FixedRows, pgrid->Rows-1);
- Col = limit(Col, pgrid->FixedCols, pgrid->Cols-1);
- pgrid->KeySelRow = Row;
- pgrid->KeySelCol = Col;
- GridScrollToView(pgrid, hwnd, Row, Col);
- if (!fShift) {
- if (!SetGridRowCol(hctl, pgrid, hwnd, Row, Col))
- SetGridSel(hctl, hwnd, TRUE, Row, Col, Row, Col);
- }
- else {
- SHORT StartRow = pgrid->Row;
- SHORT StartCol = pgrid->Col;
-
- if (pgrid->SelType & SEL_ROWS) {
- StartCol = pgrid->FixedCols;
- Col = pgrid->Cols-1;
- }
- if (pgrid->SelType & SEL_COLS) {
- StartRow = pgrid->FixedRows;
- Row = pgrid->Rows-1;
- }
- SetGridSel(hctl, hwnd, TRUE, StartRow, StartCol, Row, Col);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // GridKeyUp
- //---------------------------------------------------------------------------
- VOID NEAR GridKeyUp
- (
- HCTL hctl,
- HWND hwnd,
- USHORT VKKey
- )
- {
- hctl = hctl;
- hwnd = hwnd;
- VKKey = VKKey;
- }
-
-
- //---------------------------------------------------------------------------
- // NewFont
- //---------------------------------------------------------------------------
- VOID NEAR NewFont
- (
- PGRID pgrid,
- HWND hwnd
- )
- {
- SHORT i;
- TEXTMETRIC tm;
- HDC hdc = CreateIC("Display", NULL, NULL, NULL);
-
- if (pgrid->hFont)
- SelectObject(hdc, pgrid->hFont);
- GetTextMetrics(hdc, &tm);
- DeleteDC(hdc);
- pgrid->DefHeight = tm.tmHeight + 2;
- pgrid->DefWidth = pgrid->DefHeight * 5 / 2;
-
- // resize the defaulted rows and columns if initialized
- if (pgrid->Rows && pgrid->Cols) {
- for (i = 0; i < pgrid->Rows; i++)
- if (ROW(i)->fDefHeight)
- ROWHEIGHT(i) = pgrid->DefHeight;
- for (i = 0; i < pgrid->Cols; i++)
- if (COL(i).fDefWidth)
- COLWIDTH(i) = pgrid->DefWidth;
-
- SizeGrid(pgrid, hwnd);
- InvalidateRect(hwnd, NULL, FALSE);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // GetClipText
- //---------------------------------------------------------------------------
- HSZ NEAR GetClipText
- (
- PGRID pgrid
- )
- {
- HANDLE hseg;
- _segment segClip;
- CHAR _based(segClip) * _based(segClip) * hClip;
- SHORT Row;
- SHORT Col;
- SHORT cb;
- SHORT ClipLen;
- SHORT CellLen;
- BHSTR bhStr;
-
- segClip = pgrid->segClip;
- if (segClip == NULL) {
- hseg = GlobalAlloc(GHND, 1000);
- if (!hseg)
- return NULL;
- pgrid->segClip = segClip = (_segment)GlobalLock(hseg);
- LocalInit(segClip, 16, (USHORT)GlobalSize(hseg));
- }
-
- _asm
- {
- push ds
- mov ds,segClip
- }
- hClip = (CHAR _based(segClip) * _based(segClip) *)
- LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, cb = 500);
- _asm
- {
- pop ds
- }
- if (!hClip)
- return NULL;
-
- ClipLen = 0;
-
- for (Row = pgrid->SelTopRow; Row <= pgrid->SelBottomRow; ++Row) {
- for (Col = pgrid->SelLeftCol; Col <= pgrid->SelRightCol; ++Col) {
- bhStr = GetCellText(pgrid, Row, Col);
- CellLen = bhStr ? lstrlen((LPSTR)*bhStr) : 0;
- if (ClipLen+CellLen+2 > cb) {
- _asm
- {
- push ds
- mov ds,segClip
- }
- hClip = (CHAR _based(segClip) * _based(segClip) *)
- LocalReAlloc((HANDLE)hClip, cb += CellLen+2000,
- LMEM_MOVEABLE | LMEM_ZEROINIT);
- _asm
- {
- pop ds
- }
- if (!hClip) {
- GlobalFree(LOWORD(GlobalHandle(pgrid->segClip)));
- pgrid->segClip = NULL;
- return NULL;
- }
- }
- if (CellLen){
- lstrcpy((LPSTR)(*hClip)+ClipLen, (LPSTR)*bhStr);
- ClipLen += CellLen;
- }
- if (Col < pgrid->SelRightCol) {
- *((LPSTR)(*hClip)+ClipLen) = '\t';
- ++ClipLen;
- }
- }
- if (Row < pgrid->SelBottomRow) {
- *((LPSTR)(*hClip)+ClipLen) = '\r';
- ++ClipLen;
- }
- }
-
- return (HSZ)MAKELONG(hClip, segClip);
- }
-
-
- //---------------------------------------------------------------------------
- // SetClipText
- //---------------------------------------------------------------------------
- ERR NEAR SetClipText
- (
- HCTL hctl,
- HWND hwnd,
- LPSTR pszText
- )
- {
- SHORT Row;
- SHORT Col;
- LPSTR pszScan;
- CHAR chSave;
- ERR err = 0;
- PGRID pgrid = GRIDDEREF(hctl);
-
- // start at the upper left of the selection region
- Row = pgrid->SelTopRow;
- Col = pgrid->SelLeftCol;
- pszScan = pszText;
- for (;;) {
- // look for terminator to cell string
- while (*pszScan && *pszScan != '\t' && *pszScan != '\r')
- ++pszScan;
- // save it, and change to NULL
- chSave = *pszScan;
- *pszScan = 0;
- // set text for this cell and advance to next
- if (Col <= pgrid->SelRightCol)
- err = SetCellText(hctl, hwnd, Row, Col++, pszText);
- // restore original terminator
- *pszScan = chSave;
- if (err)
- // exit if unable to set a cell
- return err;
- if (chSave == '\r' || chSave == 0) {
- if (chSave == '\r' && *(pszScan+1) == '\n')
- ++pszScan;
- // end of the line (row) for supplied text
- while (Col <= pgrid->SelRightCol) {
- // clear any remaining selected cols in the row
- SetCellText(hctl, hwnd, Row, Col, NULL);
- ++Col;
- }
- // continue with start of next row
- Col = pgrid->SelLeftCol;
- if (Row == pgrid->SelBottomRow)
- // finished with last row, so exit
- return 0;
- ++Row;
- }
- // advance to next cell string
- if (chSave)
- ++pszScan;
- pszText = pszScan;
- }
- }
-
- //---------------------------------------------------------------------------
-