UBBFriend: Email This Page to Someone!
  Computer Workshop User Forums
  Third Party Tools
  Egrid32 and EZGUI

Post New Topic  Post A Reply
profile | register | preferences | faq | search

next newest topic | next oldest topic
Author Topic:   Egrid32 and EZGUI
Jeffrey Smith
Member
posted 04-02-2009 03:03 PM     Click Here to See the Profile for Jeffrey Smith     Edit/Delete Message Reply w/Quote
Does anybody else use Egrid32?

I have spent a lot of time creating a universal include file that creates an Excel like navigation for any grid. Some of the features include:

*Control key navigation to get to the end of rows or columns of data.
*Shift key to increase selection size
*Undo and Redo
*Cut - Copy - Paste internally and from Excel
*Speed Data Entry
*Code for handeling merged cells

It's not perfect and could use some polishing, but it's a great place to start. If you're interested, let me know. I'm also interested in any changes you would add to improve it.

Does anybody else have something to share relating to Egrid32?

Jeff

Chris Boss
Administrator
posted 04-02-2009 05:25 PM     Click Here to See the Profile for Chris Boss     Edit/Delete Message Reply w/Quote
I know there are a few EZGUI users that do use EGrid.

Feel free to post some source code examples (in the source code forum) of implimenting EGrid in EZGUI. Just don't post an proprietary code (ie. Includes that come with EGrid). Anyone who has Egrid will have the includes that come with it.

Jeffrey Smith
Member
posted 04-14-2009 04:03 PM     Click Here to See the Profile for Jeffrey Smith     Edit/Delete Message Reply w/Quote
Ok, here goes

Here is the main include file for EGridNav (save it as Egrid_Navigate.inc):

code:



TYPE EgridCoord
X1 AS LONG 'Right or left edge of rectange
Y1 AS LONG 'Top or bottom of rectange
X2 AS LONG 'Right or left edge of rectange
Y2 AS LONG 'Top or bottom of rectange
X3 AS LONG 'Temporary store the X1 value
Y3 AS LONG 'Temporary store the X2 value
X4 AS LONG 'Temporary store the Y1 value
Y4 AS LONG 'Temporary store the Y2 value
SX AS LONG 'Column to scroll to after navigation
SY AS LONG 'Row to scroll to after navigation
END TYPE


TYPE MergeCoord
X1P AS LONG 'Position of left most cell in merged cell for X1
X2P AS LONG 'Position of left most cell in merged cell for X2
Y1P AS LONG 'Position of top most cell in merged cell for Y1
Y2P AS LONG 'Position of top most cell in merged cell for Y2
X1R AS LONG 'Position of right most cell in merged cell for X1
X2R AS LONG 'Position of right most cell in merged cell for X2
Y1R AS LONG 'Position of bottom most cell in merged cell for Y1
Y2R AS LONG 'Position of bottom most cell in merged cell for Y2
X1M AS LONG 'X1 is merged
X2M AS LONG 'X2 is merged
Y1M AS LONG 'Y1 is merged
Y2M AS LONG 'Y2 is merged
END TYPE


GLOBAL RC() AS RECT 'Used by EGridNav to store selected rectangles
GLOBAL egHndl AS LONG 'Handle of current open EGrid
GLOBAL gSel AS LONG 'Number of range selections in the current EGrid
GLOBAL gUndo() AS LONG 'Used by EGridNav to store the state of the grid
GLOBAL egResult AS LONG 'General return long
GLOBAL egUndo AS INTEGER 'Track which Egrid State we are on
GLOBAL egNumUndo AS INTEGER 'Total Undo states saved
GLOBAL egMaxUndo AS INTEGER 'Maximum undo states
GLOBAL EndKey AS BYTE 'Store the toggle state of the End Key
GLOBAL GridChanges AS INTEGER 'Tracks changes to indicate if grid needs to be saved
GLOBAL g AS EgridCoord 'Store the current Rect coordinates and share with all
GLOBAL Speed AS EgridCoord 'Store the coordinates for Speed Data Entry
GLOBAL EnterKey AS BYTE 'Toggle Speed Entry
GLOBAL gChecked AS LONG 'number of checked boxes, mainly for a statusbar
GLOBAL F2Key AS BYTE 'Toggle the F2Key for Cell Edits
GLOBAL EgridStat AS BYTE 'Reset certain items of the grid when EgridNav is called; 0=Reset All; 1=MaxRows and MaxCols; 3=??
GLOBAL EGCC AS EgridCoord 'Store Cut/Copy Area
GLOBAL TimerID AS LONG 'ID For Cut/Copy Timer
GLOBAL CellEdit AS BYTE 'Track if a cell is being edited
GLOBAL egFN AS STRING 'Store the current form name on which the grid resides
GLOBAL egID AS LONG 'Store the current ID of the Grid
GLOBAL CP AS CellProfile 'User Type holding Cell Profile info from EGrid32
GLOBAL EGN AS EgridNotify PTR 'Holds current settings of grid
GLOBAL egMaxCol AS LONG 'The last visible column
GLOBAL egMaxRow AS LONG 'The last visible row
GLOBAL egMinCol AS LONG 'The first visible column
GLOBAL egMinRow AS LONG 'The first visible row
GLOBAL egCols AS LONG 'The Last Column (visible or not)
GLOBAL egRows AS LONG 'The Last Row (visible or not)
GLOBAL egShift AS LONG 'Shift key status
GLOBAL egControl AS LONG 'Control Key Status
GLOBAL egMC AS MergeCoord 'Provide coordinates of TL and BR cells in merged cell for a multi-cell selection

DECLARE FUNCTION EGRIDNAV(Cval&, FN AS STRING) AS LONG
DECLARE FUNCTION egGetClipBoardText() AS STRING
DECLARE FUNCTION egCELLHASTEXT(BYVAL X AS LONG, BYVAL Y AS LONG) AS BYTE
DECLARE FUNCTION egGETCELLTEXT(BYVAL X AS LONG, BYVAL Y AS LONG) AS STRING
DECLARE FUNCTION egGETCHECK(BYVAL X AS LONG, BYVAL Y AS LONG, XType AS BYTE) AS BYTE
DECLARE FUNCTION EgridMaxCols() AS LONG
DECLARE FUNCTION EgridMaxRows() AS LONG
DECLARE FUNCTION egSMR(Msg AS LONG, wparm AS LONG, lparm AS LONG) AS LONG

DECLARE SUB egGetRect()
DECLARE SUB egShowRect(Scroll AS BYTE)
DECLARE SUB EgridViewPort(BYVAL gRC AS RECT, vCols AS INTEGER, vRows AS INTEGER)
DECLARE SUB EGRIDPASTE()
DECLARE SUB EGRIDCUTCOPY(Del AS BYTE)
DECLARE SUB EGridDelete()
DECLARE SUB SaveUndo(After AS BYTE)
DECLARE SUB EGridUndo()
DECLARE SUB EGridRedo()
DECLARE SUB EgridUndoErase()
DECLARE SUB EGRIDROWS(InsDel AS INTEGER, Y1 AS LONG, Y2 AS LONG, UseUndo AS BYTE)
DECLARE SUB EgridSetCheck()
DECLARE SUB EgridSpeedEntry()
DECLARE SUB CLEARCUTCOPYFRAME()
DECLARE SUB egMerged()
DECLARE SUB egFixMerge()
DECLARE SUB egSM(Msg AS LONG, wparm AS LONG, lparm AS LONG)
DECLARE SUB EgridMinMaxColRow()
DECLARE SUB EgridHeaderText(ColID AS LONG, RowID AS LONG, Caption AS STRING, FColor AS LONG, HAlign AS STRING, VAlign AS STRING, SizeinInches AS SINGLE)


'--------------------------------- Grid Navigation -------------------------
'Return True if all functions have been handled manually
'Return False if more processing is needed by EGrid32
FUNCTION EGridNav(Cval&, FN AS STRING) AS LONG

LOCAL Selection AS LONG 'Current rectangle
LOCAL X AS LONG
LOCAL Y AS LONG
LOCAL TCell AS BYTE 'Control navigation parm
LOCAL CCell AS BYTE 'Control navigation parm
LOCAL LCell AS BYTE 'Control navigation parm
LOCAL gSTOP AS INTEGER 'Control navigation parm
LOCAL NCode AS LONG 'Windows event notification for grid
LOCAL Pt AS POINTAPI 'Cursor X/Y
LOCAL CHText AS INTEGER 'Cell Has Text
LOCAL CMerged AS INTEGER 'Cell is Merged
'------------------------
STATIC Expanding AS LONG 'rectangle expanding
STATIC vCols AS INTEGER
STATIC vRows AS INTEGER
STATIC xFN AS STRING 'Store the last Form Name for comparison
STATIC xID AS LONG 'Store the last Egrid ID for comparison

EZ_GetNotify CVal&, egHndl, egID, NCode
EGN = CVal&
egFN = FN

'------------------ Reset some values if it's not the current grid
IF xFN <> egFN OR (xID <> egID AND xFN = egFN) THEN ' OR EgridStat = 0
xFN = egFN 'Save the last form name
xID = egID
EgridMinMaxColRow
g.X1 = egMinCol
g.Y1 = egMinRow
g.X2 = g.X1
g.Y2 = g.Y1
g.SX = 1 : g.SY = 1
egFixMerge
g.SX = g.X1 : g.SY = g.Y1
egShowRect(1)
EGRIDUNDOERASE
GridChanges = 0
egUndo = 0
egNumUndo = 0
egMaxUndo = 100 : DIM gUndo(egMaxUndo+1)
EGCC.X1 = -1
EnterKey = 0
EndKey = 0
END IF

EgridStat = 1

egControl = EZ_GetKeyState(%EZK_CTRL, 1) AND 1 'Get Control key status
egShift = EZ_GetKeyState(%EZK_SHIFT, 1) AND 1 'Get Shift key status



'()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
SELECT CASE NCode


'---------- Get the number of visible columns and rows
CASE %EGN_ABOUTDRAWINGCELLS
CALL EgridViewPort(@EGN.CurrRC,vCols, vRows)

'---------- Just before a cell is opened for edit
CASE %EGN_STARTEDEDITION
CellEdit = 1
CALL CLEARCUTCOPYFRAME()

'---------- Just before a cell edit is complete, save undo
CASE %EGN_FINISHEDIT
CALL SaveUndo(0)
INCR GridChanges

'---------- Just after a cell edit is complete, save undo
CASE %EGN_EDITIONCLOSED
CellEdit = 0
F2Key = 0
CALL SaveUndo(1)

'---------- Highlight columns and rows when header is clicked
CASE %EGN_HEADERLEFTCLICK
IF @EGN.CELL.X = 0 THEN 'User selected a Row Header - with shift held, range can be changed
IF egShift THEN
g.X1 = 1 : g.X2 = egMaxCol : g.Y2 = @EGN.CELL.Y 'Multiple Rows
ELSE
g.X1 = 1 : g.Y1 = @EGN.CELL.Y : g.X2 = egMaxCol : g.Y2 = g.Y1 'Single Row
END IF

ELSEIF @EGN.CELL.Y = 0 THEN 'User selected a Column Header - with shift held, range can be changed
IF egShift THEN
g.Y1 = 1 : g.X2 = @EGN.Cell.X : g.Y2 = egMaxRow 'Multiple Columns
ELSE
g.X1 = @EGN.Cell.X : g.Y1 = 1 : g.X2 = g.X1 : g.Y2 = egMaxRow 'Single Column
END IF
END IF
CALL egShowRect(0)
FUNCTION = %TRUE

'---------- Range is starting to be expanded with little tab at bottom right of selection
CASE %EGN_STARTEXPANDING
Expanding = 1

'---------- Create a Pop-up menu when a header is right-clicked
CASE %EGN_HEADERRIGHTCLICK
IF @EGN.CELL.X = 0 THEN 'User selected a row header
CALL GETCURSORPOS(Pt)
EZ_DoPopupMenu egFN, EZ_SetMouseXY(Pt.X, Pt.Y) , 1550, "Insert Rows|Delete Rows|", "S"
END IF
FUNCTION = %TRUE
EXIT FUNCTION

'---------- 'Create a pop up menu here
CASE %EGN_CELLRIGHTCLICK
CALL GETCURSORPOS(Pt)
EZ_DoPopupMenu egFN, EZ_SetMouseXY(Pt.X, Pt.Y) , 1500, "Cut|Copy|Paste|Delete|", "S"
FUNCTION = %TRUE
EXIT FUNCTION

'---------- Update the number of checkboxes checked - mainly for statusbar
CASE %EGN_CHECKBOXSTATECHANGED
IF @EGN.WPARAM > 0 THEN
INCR gChecked
ELSE
DECR gChecked
END IF

'----------
CASE %EGN_LEFTDOUBLECLICK 'Open a cell for edit when double click
IF CellEdit = 1 AND @EGN.Key = %FALSE THEN EXIT FUNCTION
IF @EGN.Cell.X > 0 AND @EGN.Cell.Y > 0 THEN
g.X1 = @EGN.Cell.X : g.Y1 = @EGN.Cell.Y
g.X2 = g.X1 : g.Y2 = g.Y1
egFixMerge
egShowRect(0)
CALL CLEARCUTCOPYFRAME()
egSM %EG_OPENEDITION, g.X1, g.Y1
F2Key = 1
FUNCTION = %TRUE
EXIT FUNCTION
END IF

'----------- 'Clear selections if clicked without Control or SHIFT pressed
CASE %EGN_CELLLEFTCLICK 'but only if the range is not being expanded with little tab

IF egControl=0 AND egShift=0 AND Expanding=0 AND CellEdit = 0 THEN
gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT
END IF
'Make the selection with Left Click and Shift Held. Store Rect in RC()
IF egShift AND CellEdit = 0 THEN
g.X2 = @EGN.Cell.X
g.Y2 = @EGN.Cell.Y
g.SX = g.X2 : g.SY = g.Y2
egFixMerge
g.SX = egMC.X2P : g.SY = egMC.Y2P
CALL egShowRect(1)
FUNCTION = %TRUE
END IF


'---------- Range expanded with little tab at bottom right of selection
CASE %EGN_FINISHEXPANDING
g.X1 = @EGN.Selec.SX1 : g.Y1 = @EGN.Selec.SY1
g.X2 = @EGN.Selec.SX2 : g.Y2 = @EGN.Selec.SY2
egShowRect(0)
Expanding = 0

'---------- Clear selections with cursor without Control and Shift pressed
CASE %EGN_KEYDOWN
IF egShift=0 AND egControl= 0 AND CellEdit = 0 AND EndKey=0 THEN
SELECT CASE @EGN.Key
CASE %VK_UP
egMerged
IF egmc.Y1P - 1 > 0 THEN g.Y1 = egmc.Y1P - 1
g.Y2 = g.Y1
g.X2 = g.X1
egFixMerge
g.SX = egMC.X1P : g.SY = egMC.Y1P
CASE %VK_DOWN
egMerged
IF egMC.Y1R+1 <= egMaxRow THEN g.Y1 = egMC.Y1R+1
g.Y2 = g.Y1
g.X2 = g.X1
egFixMerge
g.SX = egMC.X1P : g.SY = egMC.Y1R
CASE %VK_LEFT
egMerged
IF egmc.X1P - 1 > 0 THEN g.X1 = egmc.X1P - 1
g.X2 = g.X1
g.Y2 = g.Y1
egFixMerge
g.SX = egMC.X1P : g.SY = egMC.Y1R
CASE %VK_RIGHT
egMerged
IF egmc.X1R+1 <= egMaxCol THEN g.X1 = egmc.X1R+1
g.X2 = g.X1
g.Y2 = g.Y1
CALL egFixMerge
g.SX = egMC.X1R : g.SY = egMC.Y1R
CASE ELSE
EXIT IF
END SELECT


egShowRect(1)
FUNCTION = %TRUE
EXIT FUNCTION
END IF

'The following code allows one to use the control-cursor to get to the end of columns or rows.
'Either to the end of a set of non-empty cells or the end of a set of empty cells.
'With the Shift pressed also, one can increase the selection. The Endkey can be pressed
'before the cursor to achieve the same movement.
'-----------------------------------------------------------------------------------------
IF egControl OR EndKey THEN
SELECT CASE @EGN.Key
'===============================(Control Up)======================================
CASE %VK_UP 'Control-Up OR End Up
IF g.Y2 = 1 OR F2Key THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
g.X3 = g.X1 : g.X4 = g.X2
g.Y3 = g.Y1 : g.Y4 = g.Y2
IF egShift THEN
egMerged
ELSE
g.Y2 = g.Y1
egMerged
g.Y2 = egmc.Y1R
END IF

TCell = egCELLHASTEXT(egmc.X2P,egmc.Y2P) 'Set the status of beginning cell contents
LCell = TCell
gStop = -1 'indicate first iteration
DO
egMerged
IF egmc.Y2P - 1 > 0 THEN g.Y2 = egmc.Y2P - 1
egMerged
CCell = egCELLHASTEXT(egmc.X2P,egmc.Y2P)

IF TCell = 0 AND CCell = 1 THEN
gStop = 2
ELSEIF TCell = 1 AND CCell = 1 AND LCell = 0 THEN
gStop = 3
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = -1 THEN
'Keep Going
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = 0 THEN
INCR g.Y2
gStop = 5
ELSEIF egmc.Y2P = 1 THEN
gStop = 1
ELSE
gStop = 0
END IF
LCell = CCell
IF gStop > 0 THEN
EXIT LOOP
END IF
LOOP

egMerged
IF egShift = 0 THEN
g.Y1 = g.Y2
g.X1 = g.X2
ELSEIF egShift THEN
'I dunno
END IF
CALL egFixMerge
g.SX = egMC.X2R : g.SY = egMC.Y2P
CALL egShowRect(1)
EndKey = 0
FUNCTION = %TRUE
EXIT FUNCTION

'================================(Control Down)====================================
CASE %VK_Down 'Control-Down OR End Down
IF g.Y2 = egMaxRow OR F2Key THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
g.X3 = g.X1 : g.X4 = g.X2
g.Y3 = g.Y1 : g.Y4 = g.Y2
IF egShift THEN
egMerged
ELSE
g.Y2 = g.Y1
g.X2 = g.X1
egMerged
END IF

TCell = egCELLHASTEXT(egmc.X2P,egmc.Y2P)
LCell = TCell
gStop = -1 'indicate first iteration
DO
egMerged
IF egmc.Y2R + 1 <= egMaxRow THEN g.Y2 = egmc.Y2R + 1
egMerged
CCell = egCELLHASTEXT(egmc.X2P,egmc.Y2P)

IF TCell = 0 AND CCell = 1 THEN
gStop = 2
ELSEIF TCell = 1 AND CCell = 1 AND LCell = 0 THEN
gStop = 3
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = -1 THEN
'Keep Going
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = 0 THEN
DECR g.Y2
gStop = 5
ELSEIF egmc.Y2R => egMaxRow THEN
gStop = 1
ELSE
gStop = 0
END IF
LCell = CCell
IF gStop > 0 THEN
EXIT LOOP
END IF
LOOP
egMerged

IF egShift = 0 THEN
g.Y1 = g.Y2
g.X1 = g.X2
ELSEIF egShift THEN
'I dunno
END IF
egFixMerge
g.SX = egMC.X2R : g.SY = egMC.Y2R
CALL egShowRect(1)
EndKey = 0
FUNCTION = %TRUE
EXIT FUNCTION

'===========================(Control Left)==================================
CASE %VK_Left 'Control-Left OR End Left
IF g.X2 = 1 OR F2Key THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
g.X3 = g.X1 : g.X4 = g.X2
g.Y3 = g.Y1 : g.Y4 = g.Y2
IF egshift THEN
egMerged
ELSE
g.X2 = g.X1
g.Y2 = g.Y1
egMerged
END IF

TCell = egCELLHASTEXT(egmc.X2P,egMC.Y2P)
LCell = TCell
gStop = -1 'indicate first iteration
DO
egMerged
IF egmc.X2P - 1 > 0 THEN g.X2 = egmc.X2P - 1
egMerged
CCell = egCELLHASTEXT(egmc.X2P,egMC.Y2P)

IF TCell = 0 AND CCell = 1 THEN
gStop = 2
ELSEIF TCell = 1 AND CCell = 1 AND LCell = 0 THEN
gStop = 3
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = -1 THEN
'Keep Going
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = 0 THEN
INCR g.X2
gStop = 5
ELSEIF egmc.X2P = 1 THEN
gStop = 1
ELSE
gStop = 0
END IF
LCell = CCell
IF gStop > 0 THEN
EXIT LOOP
END IF
gStop = 0
LOOP

egMerged
IF egShift = 0 THEN
g.X1 = g.X2
ELSEIF egshift THEN
'i dunno
END IF
egFixMerge
g.SX = egMC.X2P : g.SY = egMC.Y2P
CALL egShowRect(1)
EndKey = 0
FUNCTION = %TRUE
EXIT FUNCTION

'=================================(Control Right)========================
CASE %VK_Right 'Control-Right OR End Right
IF g.X2 = egMaxCol OR F2Key THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
IF egshift THEN
egMerged
ELSE
g.X2 = g.X1
g.Y2 = g.Y1
egMerged
END IF

TCell = egCELLHASTEXT(egmc.X2P,g.Y2)
LCell = TCell
gStop = -1 'indicate first iteration
DO
egMerged
IF egmc.X2R + 1 <= egMaxCol THEN g.X2 = egmc.X2R +1
egMerged
CCell = egCELLHASTEXT(egmc.X2P,g.Y2)

IF TCell = 0 AND CCell = 1 THEN
gStop = 2
ELSEIF TCell = 1 AND CCell = 1 AND LCell = 0 THEN
gStop = 3
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = -1 THEN
'Keep Going
ELSEIF TCell = 1 AND CCell = 0 AND LCell = 1 AND gStop = 0 THEN
DECR g.X2
gStop = 5
ELSEIF egmc.X2R => egMaxCol THEN
gStop = 1
ELSE
gStop = 0
END IF
LCell = CCell
IF gStop > 0 THEN
EXIT LOOP
END IF
LOOP

egMerged
IF egShift=0 THEN
g.X1 = g.X2
ELSE
'I dunno
END IF
egFixMerge
g.SX = egMC.X2R : g.SY = egMC.Y2P
CALL egShowRect(1)
EndKey = 0
FUNCTION = %TRUE
EXIT FUNCTION

END SELECT
END IF 'End of Control-Cursor

'-------------------------------(Extra Control Key Navigation)---------------------------------
IF egControl THEN 'Still in the keydown area
SELECT CASE @EGN.Key

CASE %VK_Home 'Control-Home moves to Cell A1
g.X2 = egMinCol: g.Y2 = egMinRow
IF egShift = 0 THEN 'with shift off, selection is not extended
g.X1 = g.X2 : g.Y1 = g.Y2
END IF
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
CALL egShowRect(1)

CASE %VK_End 'Control-End moves to bottom right corner
g.X2 = egMaxCol : g.Y2 = egMaxRow
IF egShift = 0 THEN 'With shift, selection is extended
g.X1 = egMaxCol: g.Y1 = egMaxRow
END IF
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
CALL egShowRect(1)

CASE 45 'User hit Ctr-Ins (insert rows)
CALL EGRIDROWS(1,0,0,1)
FUNCTION = %TRUE
EXIT FUNCTION
CASE 46 'User hit Ctrl-Del (delete rows)
CALL EGRIDROWS(-1,0,0,1)
FUNCTION = %TRUE
EXIT FUNCTION
CASE 67 'User hit Ctrl-C (copy)
IF F2Key = 0 THEN CALL EGridCutCopy(0)
EXIT FUNCTION
CASE 86 'User hit Ctrl-V (paste)
IF F2Key = 0 THEN CALL EGRIDPASTE()
EXIT FUNCTION
CASE 88 'User hit Ctrl-X (Cut)
IF F2Key = 0 THEN CALL EGRIDCUTCOPY(1)
EXIT FUNCTION
CASE 89 'User hit CTRL-Y (Redo)
CALL EGridRedo()
EXIT FUNCTION
CASE 90 'User hit Ctrl-Z (Undo)
CALL EgridUndo()
EXIT FUNCTION
END SELECT
END IF 'end of Control key code
'+++++++++++++++++++++ End of the Control Key navigation

'-------------------------------(Key Down Area Without Control Key or Shift Key)----------------------------
'Still in the keydown area

'------------------------ User hit Down when editing a cell
SELECT CASE @EGN.key
CASE %VK_Down

IF CellEdit = 1 THEN
CellEdit = 0
egSM %EG_CLOSEEDITION, %TRUE, 0
IF g.Y1 < egMaxRow THEN
g.Y1 = g.Y1 + 1 : g.Y2 = g.Y1
egFixMerge
g.SX = egMC.X1P : g.SY = EGMC.Y1P
CALL egShowRect(1)
END IF
FUNCTION = %TRUE
END IF

'------------------------ 'User hit UP when editing a cell
CASE %VK_Up
IF CellEdit = 1 THEN
CellEdit = 0
egSM %EG_CLOSEEDITION, %TRUE, 0
IF g.Y1 > 1 then
g.Y1 = g.Y1 - 1 : g.Y2 = g.Y1
egFixMerge
g.SX = egMC.X1P : g.SY = EGMC.Y1P
CALL egShowRect(1)
END IF
FUNCTION = %TRUE
END IF

'------------------------ 'User hit RIGHT when editing a cell
CASE %VK_Right
IF CellEdit = 1 AND F2Key = 0 THEN 'If they are editing a cell after pressing F2 then ignore
CellEdit = 0
egSM %EG_CLOSEEDITION, %TRUE, 0
IF g.X1 < egMaxCol THEN
g.X1 = g.X1 + 1 : g.X2 = g.X1
egFixMerge
g.SX = egMC.X1P : g.SY = EGMC.Y1P
CALL egShowRect(1)
END IF
FUNCTION = %TRUE
END IF

'------------------------ 'User hit LEFT when editing a cell
CASE %VK_LEFT
IF CellEdit = 1 AND F2Key = 0 THEN 'If they are editing a cell after pressing F2 then ignore
CellEdit = 0
egSM %EG_CLOSEEDITION, %TRUE, 0
IF g.X1 > 1 THEN
g.X1 = g.X1 - 1 : g.X2 = g.X1
egFixMerge
g.SX = egMC.X1P : g.SY = EGMC.Y1P
CALL egShowRect(1)
END IF
FUNCTION = %TRUE
END IF

'------------------------ 'User hit TAB
CASE 9
IF F2Key = 1 THEN EXIT FUNCTION
IF CellEdit = 1 THEN 'If they are editing a cell after pressing F2 then ignore
CellEdit = 0
egSM %EG_CLOSEEDITION, %TRUE, 0
END IF
egMerged
IF egShift THEN
IF egmc.X1P-1 > 0 THEN
g.X1 = egmc.X1P-1
g.X2 = g.X1
END IF
ELSE
IF egMC.X1R+1 <= egMaxCol THEN
g.X1 = egMC.X1R + 1 : g.X2 = g.X1
END IF
END IF
egFixMerge
g.SX = egMC.X1P : g.SY = EGMC.Y1P
CALL egShowRect(1)
FUNCTION = %TRUE
EXIT FUNCTION

'--------------------------(Speed Entry)---------------------
'Use a menu or a button to toggle this on or off and Call EgridSpeedEntry.
'Highlighting a single column before calling EgridSpeedEntry will move the cursor down after enter.
'Highlighting multiple columns before calling EgridSpeedEntry will move the cursor across the columns,
' and then down to the next row.
'If the cell is empty, the cursor will move to the next row

CASE 13 'User pressed ENTER while editing a Cell and Speed Entry is on
IF EnterKey = 0 THEN EXIT FUNCTION
IF CellEdit = 1 THEN
egSM %EG_CLOSEEDITION, %TRUE, 0
CellEdit = 0
END IF
'If you want to ignore cell contents during speed entry, make CHText=1
CHText = egCELLHASTEXT(g.X1,g.Y1) 'Cell Has Text
egMerged 'Cell Merged Status

IF CHText > 0 THEN
IF egMC.X1R < Speed.X2 THEN
g.X1 = egMC.X1R+1 : g.X2 = g.X1
ELSEIF egMC.X1R => Speed.X2 THEN
g.X1 = Speed.X1 : g.X2 = g.X1
g.Y1 = MIN(egMC.Y1R+1, egMaxRow)
g.Y2 = g.Y1
END IF
ELSEIF CHText = 0 THEN
g.X1 = Speed.X1 : g.X2 = g.X1
g.Y1 = MIN(egMC.Y1R+1, egMaxRow)
g.Y2 = g.Y1
END IF
egFixMerge
g.SX = g.X1 : g.SY = g.Y1
CALL egShowRect(1)
FUNCTION = %TRUE
EXIT FUNCTION
'------------------------ User pressed escape
CASE 27
CALL CLEARCUTCOPYFRAME()

'------------------------ 'User pressed the spacebar in a checkbox cell
CASE 32
IF CellEdit = 0 AND (egSMR( %EG_GETCOLUMNFUNCTION, g.X1, 0) = %EG_CheckBox OR egSMR( %EG_GETCONTROLTYPE, g.X1, g.Y1) = %EG_CheckBox) THEN
CALL EGridSetCheck
END IF

'------------------------ 'Page Up - With shift held the selection range can be changed
CASE 33
IF egControl THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
g.Y2 = MAX(g.Y2 - vRows+1,egMinRow)
IF egShift = 0 THEN
g.Y1 = g.Y2
g.X1 = g.X2
END IF
egFixMerge
g.SY = g.Y2
egShowRect(1)
FUNCTION = %TRUE
EXIT FUNCTION

'------------------------ 'Page Down - With shift held the selection range can be changed
CASE 34
IF egControl THEN
FUNCTION = %TRUE
EXIT FUNCTION
END IF
g.Y2 = MIN(g.Y2 + vRows-1,egMaxRow)
IF egShift = 0 THEN
g.Y1 = g.Y2
g.X1 = g.X2
END IF
egFixMerge
g.SY = g.Y2
egShowRect(1)
FUNCTION = %TRUE
EXIT FUNCTION


'------------------------ 'Delete contents from all the simulated selections.
CASE 46
IF ISFALSE(egControl) THEN
CALL EGridDelete
FUNCTION = %TRUE
EXIT FUNCTION
END IF

'------------------------ 'F2 - Switch between cell navigate and grid navigate
CASE 113
IF F2Key = 1 THEN
F2Key = 0 'User has switched to grid navigation
ELSE
F2Key = 1 'User has switched to cell navigation
END IF
FUNCTION = %TRUE
EXIT FUNCTION

'------------------------ 'Home - Move to beginning of Row
CASE 36
IF egControl=0 AND F2Key = 0 THEN
g.X2 = egMinCol
IF egShift = 0 THEN 'Shift is off, no range extension
g.X1 = g.X2
g.Y1 = g.Y2
END IF
egFixMerge
egShowRect(1)
END IF

END SELECT

'Still in the Key Down Area


'everything below should have the shift key pressed, the control not pressed and not editing a cell
IF egShift = 0 OR egControl OR F2Key THEN EXIT FUNCTION


SELECT CASE @EGN.Key 'Test if beyond boundaries
CASE %VK_UP
g.Y3 = g.Y1 : g.Y4 = g.Y2
egMerged
IF egmc.Y2P - 1 > 0 THEN g.Y2 = egmc.Y2P - 1
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
egShowRect(1)

CASE %VK_DOWN
g.Y3 = g.Y1 : g.Y4 = g.Y2
egMerged
IF egmc.Y2R + 1 <= egMaxRow THEN g.Y2 = egmc.Y2R + 1
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
egShowRect(1)

CASE %VK_LEFT
g.X3 = g.X1 : g.X4 = g.X2
egMerged
IF egmc.X2P - 1 > 0 THEN g.X2 = egmc.X2P - 1
IF g.X4 > g.X3 AND g.X2 < g.X1 THEN g.X1 = g.X4
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
CALL egShowRect(1)

CASE %VK_RIGHT
g.X3 = g.X1 : g.X4 = g.X2
egMerged
IF egmc.X2R + 1 <= egMaxCol THEN g.X2 = egMC.X2R + 1
egFixMerge
g.SX = g.X2 : g.SY = g.Y2
egShowRect(1)
CASE ELSE
EXIT FUNCTION
END SELECT
FUNCTION = %TRUE
EXIT FUNCTION




'=============================(Key is Released)================================================================
CASE %EGN_KeyUp

'------------------- 'EndKey toggle
'It is best to display the Endkey status on the status bar
IF @EGN.Key = 35 AND egControl=0 THEN
IF EndKey = 1 THEN
EndKey = 0
ELSE
EndKey = 1
END IF
END IF
FUNCTION = %TRUE
EXIT FUNCTION


'------------------- 'Store current cell in RC() if Control and Shift not pressed
IF egControl = 0 AND egShift = 0 THEN
SELECT CASE @EGN.Key
CASE %VK_UP, %VK_DOWN, %VK_LEFT, %VK_RIGHT
gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT
CALL egGetRect()
EXIT FUNCTION
END SELECT
END IF


'=============================(Mouse Button Release)=======================================
CASE %EGN_RELEASEMOUSEBUTTON
IF @EGN.key = %WM_RBUTTONUP THEN
END IF

IF @EGN.key = %WM_LBUTTONUP THEN
IF egControl THEN ' Add selections when Control is pressed using mouse
INCR gSel : REDIM PRESERVE RC(0 TO gSel) AS GLOBAL RECT
egSM %EG_INTERNALSELECT, 0, 0
egSM %EG_GETINTERNALSELECTION, VARPTR(RC(gSel)), 0
ELSEIF egShift THEN
'Do Nothing - Don't fall into the ELSE trap
ELSE ' Else, remove all selections.
gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT ' add the current cell back into the array
CALL egGetRect()
Call egShowRect(0)
END IF
END IF
egSM %EG_REFRESHALL, 0, 0

CASE %EGN_ABOUTREFRESHING
STATIC C AS INTEGER
IF EGCC.X1 > 0 THEN
egSM %EG_INTERNALSELECTTL, EGCC.X1, EGCC.Y1
egSM %EG_INTERNALSELECTBR, EGCC.X2, EGCC.Y2
egSM %EG_SIMULATESELECTION, RGB(255,0,0), %EG_MOVINGFRAME OR %EG_DottedFrame OR %EG_NOOVERLAY OR %EG_FORCEFRAME

END IF


'----------------- Draw all selections stored.
CASE %EGN_ALLCELLSDRAWN
FOR Selection = 1 TO gSel
egSM %EG_INTERNALSELECTTL, RC(Selection).NLEFT, RC(Selection).NTOP
egSM %EG_INTERNALSELECTBR, RC(Selection).NRIGHT, RC(Selection).NBOTTOM
egSM %EG_SIMULATESELECTION, 0, 0
NEXT Selection

CASE ELSE

END SELECT


END FUNCTION
'---------------


'-------------------------(egMerged)----------------------------------------------
'Test if Cell is merged
'Store values in egMC UDT
'egMC.X1P = Position of left most cell in merged cells for X1
'egMC.X2P = Position of left most cell in merged cells for X2
'egMC.Y1P = Position of top most cell in merged cells for Y1
'egMC.Y2P = Position of top most cell in merged cells for Y2
'egMC.X1R = Position of right most cell in merged cells for X1 (range)
'egMC.X2R = Position of right most cell in merged cells for X2 (range)
'egMC.Y1R = Position of bottom most cell in merged cells for Y1 (range)
'egMC.Y2R = Position of bottom most cell in merged cells for Y2 (range)
' If corner is not merged (range=0), return the Position value
'egMC.X1M = merge status for X1
'egMC.X2M = merge status for X2
'egMC.Y1M = merge status for Y1
'egMC.Y2M = merge status for Y2
SUB egMERGED()


'Top left corner
egSM %EG_INTERNALSELECTCELL, g.X1, g.Y1
egSM %EG_GETCELLPROFILE, VARPTR(CP), SIZEOF(CP)
IF CP.XRange > 0 THEN
egMC.X1P = CP.XPos
egMC.X1R = CP.XPos + CP.XRange
ELSE
egMC.X1P = g.X1
egMC.X1R = g.X1
END IF
IF CP.YRange > 0 THEN
egMC.Y1P = CP.YPos
egMC.Y1R = CP.YPos + CP.YRange
ELSE
egMC.Y1P = g.Y1
egMC.Y1R = g.Y1
END IF


'bottom right corner
egSM %EG_INTERNALSELECTCELL, g.X2, g.Y2
egSM %EG_GETCELLPROFILE, VARPTR(CP), SIZEOF(CP)
IF CP.XRange > 0 THEN
egMC.X2P = CP.XPos
egMC.X2R = CP.XPos + CP.XRange
ELSE
egMC.X2P = g.X2
egMC.X2R = g.X2
END IF
IF CP.YRange > 0 THEN
egMC.Y2P = CP.YPos
egMC.Y2R = CP.YPos + CP.YRange
ELSE
egMC.Y2P = g.Y2
egMC.Y2R = g.Y2
END IF

'Bottom left corner
egSM %EG_INTERNALSELECTCELL, g.X1, g.Y2
egSM %EG_GETCELLPROFILE, VARPTR(CP), SIZEOF(CP)
IF CP.XRange > 0 THEN
egMC.X1P = CP.XPos
egMC.X1R = CP.XPos + CP.XRange
END IF
IF CP.YRange > 0 THEN
egMC.Y1P = CP.YPos
egMC.Y1R = CP.YPos + CP.YRange
END IF

'Top right corner
egSM %EG_INTERNALSELECTCELL, g.X2, g.Y1
egSM %EG_GETCELLPROFILE, VARPTR(CP), SIZEOF(CP)
IF CP.XRange > 0 THEN
egMC.X2P = CP.XPos
egMC.X2R = CP.XPos + CP.XRange
END IF
IF CP.YRange > 0 THEN
egMC.Y2P = CP.YPos
egMC.Y2R = CP.YPos + CP.YRange
END IF

'Merge Status -----------------
egMC.X1M = 0 : egMC.X2M = 0
egMC.Y1M = 0 : egMC.Y2M = 0

IF egMC.X1P <> egMC.X1R THEN egMC.X1M = 1
IF egMC.X2P <> egMC.X2R THEN egMC.X2M = 1
IF egMC.Y1P <> egMC.Y1R THEN egMC.Y1M = 1
IF egMC.Y2P <> egMC.Y2R THEN egMC.Y2M = 1

END SUB

'----------------------------------- egFixMerge -------------------
'Fix any partially selected merged cells
'I tried using Elias' EG_FIXSELECTION - it was buggy
SUB egFixMerge

CALL egMerged
IF g.X1 > g.X2 THEN
g.X1 = egmc.X1R
g.X2 = egmc.X2P
ELSEIF g.X1 <= g.X2 THEN
g.X1 = egmc.X1P
g.X2 = egmc.X2R
END IF

IF g.Y1 > g.Y2 THEN
g.Y1 = egmc.Y1R
g.Y2 = egmc.Y2P
ELSEIF g.Y1 <= g.Y2 THEN
g.Y1 = egmc.Y1P
g.Y2 = egmc.Y2R
END IF

END SUB

'------------------------------------------(Toggle Checkboxes)-------------------------
'called when a user presses the spacebar in a checkbox cell
'multiple checkboxes can be selected prior to calling
SUB EgridSetCheck()
LOCAL X AS LONG
LOCAL Y AS LONG
LOCAL X1 AS LONG
LOCAL Y1 AS LONG
LOCAL X2 AS LONG
LOCAL Y2 AS LONG
LOCAL Checked AS LONG
LOCAL XType AS LONG '99=no checkbox; 0=cell checkbox; 1=Column checkbox

X1 = MIN(g.X1,g.X2) : Y1 = MIN(g.Y1,g.Y2)
X2 = MAX(g.X2,g.X1) : Y2 = MAX(g.Y2,g.X1)

CALL SaveUndo(0)
FOR X = X1 TO X2
FOR Y = Y1 TO Y2
XType = 99
IF egSMR( %EG_GETHIDEROW, Y, 0) THEN
XType = 88
ELSEIF egSMR(%EG_GETCOLUMNFUNCTION, X, 0) = %EG_CheckBox THEN
Xtype=1
ELSEIF egSMR(%EG_GETCONTROLTYPE, X, Y) = %EG_CheckBox THEN
XType=0
END IF
IF Xtype < 10 THEN
egSM %EG_INTERNALSELECTCELL, X, Y
Checked = egSMR(%EG_GETCHECK, X, Y) 'Current Checked status
IF Checked > 0 THEN
Checked = 0
ELSE
Checked = 1
END IF
egSM %EG_SETCHECK, Checked, XType
IF Checked = 1 THEN INCR gChecked
IF Checked = 0 THEN DECR gChecked
END IF
NEXT Y
NEXT X
egSM %EG_REFRESHALL, 0, 0
CALL SaveUndo(1)

END SUB

'------------------(Get the Checked Status of a Checkbox and return the Type of Checkbox)----
'XType is 99=no checkbox; 0=cell checkbox; 1=Column checkbox
FUNCTION egGETCHECK(BYVAL X AS LONG, BYVAL Y AS LONG, XType AS BYTE) AS BYTE
XType = 99
IF egSMR(%EG_GETCOLUMNFUNCTION, X, 0) = %EG_CheckBox THEN
XType=1
ELSEIF egSMR(%EG_GETCONTROLTYPE, X, Y) = %EG_CheckBox THEN
XType=0
END IF
egGETCHECK = 0
IF XType <> 99 THEN
IF egSMR(%EG_GETCHECK, X, Y) THEN egGETCHECK = 1 'Current Checked status
END IF
END FUNCTION

'----------------------------(Get Rectangle)-----------------------------
'Get the visible selection, store it in RC() and set the coordinates in g.?? UDT
SUB egGetRect()

egSM %EG_INTERNALSELECT, 0, 0
egSM %EG_GETINTERNALSELECTION, VARPTR(RC(gSel)), 0
g.X1 = RC(gSel).nLeft : g.Y1 = RC(gSel).nTop
g.X2 = RC(gSel).nRight: g.Y2 = RC(gSel).nBottom

END SUB

'--------------------------------(Show Rectangle)--------------------------------
'This will save a single rectangle and make it visible
'Specify which X and Y cell you want to scroll to before
' calling this using: g.SX and g.SY
SUB egShowRect(Scroll AS BYTE)
LOCAL jj AS EgridCoord

jj.X1 = MIN(g.X1,g.X2)
jj.X2 = MAX(g.X1,g.X2)
jj.Y1 = MIN(g.Y1,G.Y2)
jj.Y2 = MAX(g.Y1,g.Y2)

egSM %EG_INTERNALSELECTTL, JJ.X1, JJ.Y1
egSM %EG_INTERNALSELECTBR, JJ.X2, JJ.Y2
egSM %EG_INTERNTOVISIBLE, 0, 0

gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT
SETRECT RC(gSel), jj.X1, jj.Y1, jj.X2, jj.Y2
IF Scroll = 1 THEN
IF g.SX < 1 THEN g.SX = g.X2
IF g.SY < 1 THEN g.SY = g.Y2
egSM %EG_SCROLLXTOCELL, g.X1, 0
egSM %EG_SCROLLYTOCELL, 0, G.Y1
egSM %EG_SCROLLXTOCELL, g.X2, 0
egSM %EG_SCROLLYTOCELL, 0, G.Y2
egSM %EG_SCROLLXTOCELL, g.SX, 0
egSM %EG_SCROLLYTOCELL, 0, g.SY
END IF
egSM %EG_REFRESHALL, 0, 0

END SUB
'-------------

'-----------------------(Get Visible Rows and Columns)--------------------------
'Get the visible columns and rows from the current grid
'Helps with Page Up and Page Down
SUB EgridViewPort(BYVAL gRC AS RECT, vCols AS INTEGER, vRows AS INTEGER)

vCols = gRC.nRight - gRC.nLeft + 1 'Visible Columns returned
vRows = gRC.nBottom - gRC.nTop + 1 'Visible Rows returned

END SUB

'------------------------------(Delete Ranges)-----------------------------------
'Delete all the range selections
'Read Only cells will be ignored
SUB EGridDelete
LOCAL Sel AS LONG, X AS LONG, Y AS LONG

CALL SaveUndo(0)
FOR Sel = 1 TO gSel
FOR X = RC(Sel).Nleft TO RC(Sel).NRight
FOR Y = RC(Sel).NTop TO RC(Sel).NBottom
IF egSMR(%EG_GETREADONLY, X, Y) = 0 AND egSMR(%EG_GETCOLUMNREADONLY, X, 0) = 0 THEN
egSM %EG_InternalSelectCell, X,Y
egSM %EG_DELETECONTENTS, %EG_TEXT OR %EG_FORMULA, 0
INCR GridChanges
END IF
NEXT Y
NEXT X
NEXT Sel
egSM %EG_REFRESHALL, 0, 0
CALL SaveUndo(1)

END SUB


'-------------------------------------------(PASTE)---------------------------
'This is compatible with Excel - text only
'You may paste from: A single column to multiple columns
' A single row to multiple rows
' A single cell to multiple cells
' Multiple columns and rows to a single cell
' Dependant on the destination rectangle
SUB EgridPaste()

LOCAL ClipText AS STRING
LOCAL X1 AS LONG
LOCAL Y1 AS LONG
LOCAL X2 AS LONG
LOCAL Y2 AS LONG
LOCAL pX2 AS LONG
LOCAL pY2 AS LONG
LOCAL X AS LONG
LOCAL Y AS LONG
LOCAL PCols AS LONG
LOCAL PRows AS LONG
LOCAL sDel AS STRING
LOCAL Count AS LONG
LOCAL A AS STRING
LOCAL N AS LONG
LOCAL L AS LONG
LOCAL Z AS LONG
LOCAL SelCols AS LONG
LOCAL SelRows AS LONG
LOCAL PasteMode AS INTEGER

ClipText = egGetClipBoardText()
IF ClipText = "" THEN EXIT SUB

X1 = MIN(g.X1,g.X2) : Y1 = MIN(g.Y1,g.Y2)
X2 = MAX(g.X2,g.X1) : Y2 = MAX(g.Y2,g.Y1)

SelCols = X2 - X1 +1
SelRows = Y2 - Y1 +1

PRows = TALLY(ClipText,ANY $LF)
sDel = $TAB & $LF
Count = TALLY(ClipText, ANY sDel) 'Number of Cells
PCols = Count \ PRows 'number of columns

IF (X1 + PCols -1) > egMaxCol OR (Y1 + PRows -1) > egMaxRow THEN
egResult = EZ_MSGBOX(egFN, "Data cannot be pasted beyond the boundaries of the sheet{!}","Pasting beyond boundaries","")
EXIT SUB
END IF


'Determine how the data can be pasted
IF PCols > 1 AND PRows > 1 THEN 'Paste all cells starting at top left of selection
PasteMode = 1
pX2 = X1+PCols-1 : pY2 = Y1+PRows-1
ELSEIF PCols = 1 AND PRows = 1 THEN 'Paste a single cell to all the selected cells
PasteMode = 2
pX2 = g.X2 : pY2 = g.Y2
ELSEIF PCols = 1 AND PRows > 1 THEN 'Paste a single Column into multiple columns
PasteMode = 3
pX2 = g.X2 : pY2 = Y1+PRows-1
ELSEIF PCols > 1 AND PRows = 1 THEN 'Paste a Single Row into multiple rows
PasteMode = 4
pX2 = X1+PCols-1 : pY2 = g.Y2
END IF


'Don't paste into protected cells
FOR X = X1 TO pX2
FOR Y = Y1 TO pY2
IF egSMR(%EG_GETREADONLY, X, Y) <> 0 OR egSMR(%EG_GETCOLUMNREADONLY, X, 0) <> 0 THEN
egResult = EZ_MSGBOX(egFN, "At least one of the cells in the range is protected{!}","Pasting Into Protected Cells","")
EXIT SUB
END IF
NEXT Y
NEXT X

INCR GridChanges
CALL SaveUndo(0)

sDel = $TAB & CHR$(13) & CHR$(10)
X = X1 : Y = Y1
L = 1

SELECT CASE PasteMode
CASE 1 'Paste all cells starting at top left of selection
FOR Z = 1 TO Count
N = INSTR(L,ClipText,ANY sDel)
A = REMOVE$(MID$(ClipText,L,N-L),ANY sDel)
egSM %EG_INTERNALSELECTCELL, X, Y
egSM %EG_SETCELLTEXTWF, STRPTR(A), LEN(A)
IF MID$(ClipText,N,1) = $TAB THEN
INCR X
L = N + 1
ELSEIF MID$(ClipText,N,1) = CHR$(13) THEN
INCR Y
L = N + 2
X = X1
END IF
NEXT Z

CASE 2 'Paste a single cell to all the selected cells
N = INSTR(L,ClipText,ANY sDel)
A = REMOVE$(MID$(ClipText,L,N-L),ANY sDel)
FOR Y = Y1 TO Y2
FOR X = X1 TO X2
egSM %EG_INTERNALSELECTCELL, X, Y
egSM %EG_SETCELLTEXTWF, STRPTR(A), LEN(A)
NEXT X
NEXT Y

CASE 3 'Paste a single Column into multiple columns
FOR X = X1 TO X2
Y = Y1
L = 1
FOR Z = 1 TO Count
N = INSTR(L,ClipText,ANY sDel)
A = REMOVE$(MID$(ClipText,L,N-L),ANY sDel)
egSM %EG_INTERNALSELECTCELL, X, Y
egSM %EG_SETCELLTEXTWF, STRPTR(A), LEN(A)
IF MID$(ClipText,N,1) = $TAB THEN
'We shouldn't have tabs
ELSEIF MID$(ClipText,N,1) = CHR$(13) THEN
INCR Y
L = N + 2
END IF
NEXT Z
NEXT X

CASE 4 'Paste a Single Row into multiple rows
FOR Y = Y1 TO Y2
X = X1
L = 1
FOR Z = 1 TO Count
N = INSTR(L,ClipText,ANY sDel)
A = REMOVE$(MID$(ClipText,L,N-L),ANY sDel)
egSM %EG_INTERNALSELECTCELL, X, Y
egSM %EG_SETCELLTEXTWF, STRPTR(A), LEN(A)
IF MID$(ClipText,N,1) = $TAB THEN
INCR X
L = N + 1
ELSEIF MID$(ClipText,N,1) = CHR$(13) THEN
'We shouldn't have any linefeeds
END IF
NEXT Z
NEXT Y


CASE ELSE
END SELECT

'Highlight the area that was pasted
g.X1 = X1 : g.Y1 = Y1 : g.X2 = pX2 : g.Y2 = pY2
CALL egShowRect(0)
CALL SaveUndo(1)


END SUB

'--------------------------------------(Get Clipboard Text)-------------------------------
FUNCTION egGetClipBoardText() AS STRING

LOCAL A AS STRING, ClipResult AS LONG

'Changed the code to use the new clipboard commands in PB 9 instead of the API
CLIPBOARD GET TEXT TO A ,ClipResult
IF ClipResult <> 0 THEN
egGetClipBoardText = A
ELSE
egGetClipBoardText = ""
END IF


'----------------------- Use this code directly with API -----------
' LOCAL hMem AS DWORD
' LOCAL lpMem AS ASCIIZ PTR
' IF ISCLIPBOARDFORMATAVAILABLE(%CF_TEXT) THEN '%CF_Text is API constant for text data with LF$
' IF ISFALSE(OPENCLIPBOARD(%NULL)) THEN EXIT FUNCTION
' hMem = GETCLIPBOARDDATA(%CF_TEXT)
' lpMem = GLOBALLOCK(hMem)
' FUNCTION = @lpMem
' GLOBALUNLOCK hMem
' CLOSECLIPBOARD
' ELSE
' FUNCTION = ""
' END IF
END FUNCTION

'--------------------------------(Cut and Copy)----------------------------------
'If Del is TRUE then it will delete the cells after sending to the clipboard
SUB EGRIDCUTCOPY(Del AS BYTE)

LOCAL X AS LONG
LOCAL Y AS LONG
LOCAL CutTxt AS STRING
LOCAL X1 AS LONG
LOCAL Y1 AS LONG
LOCAL X2 AS LONG
LOCAL Y2 AS LONG
LOCAL NewRow AS BYTE
LOCAL CC AS INTEGER
LOCAL hTimer AS DWORD

IF gSel > 1 THEN
egResult = EZ_MSGBOX(egFN, "Please select only one range at a time for this command to work{!}","Multiple Ranges Not Allowed","")
EXIT SUB
END IF

X1 = MIN(g.X1,g.X2) : Y1 = MIN(g.Y1,g.Y2)
X2 = MAX(g.X2,g.X1) : Y2 = MAX(g.Y2,g.Y1)

FOR Y = Y1 TO Y2 'Put the text in a single string
NewRow = 1
CC = 0
FOR X = X1 TO X2
IF CC > 0 AND NewRow = 0 THEN 'Add tab before next cell
CutTxt = CutTxt & CHR$(9)
END IF
CutTxt = CutTxt & egGETCELLTEXT(X,Y)
NewRow = 0
INCR CC
NEXT Y
CutTxt = CutTxt & CHR$(13,10) 'Add linefeed before next row
NEXT X


EZ_SetClipboardFormat 0 'Set the clipboard for Text
EZ_SetClipboard CutTxt

IF EGCC.X1 > 0 THEN CALL ClearCutCopyFrame()
EGCC.X1 = g.X1 : EGCC.Y1 = g.Y1
EGCC.X2 = g.X2 : EGCC.Y2 = g.Y2
EZ_StartTimer egFN, TimerID, 0.2

IF Del = %TRUE THEN

'Don't cut protected cells
FOR X = X1 TO X2
FOR Y = Y1 TO Y2
IF egSMR(%EG_GETREADONLY, X, Y) <> 0 OR egSMR(%EG_GETCOLUMNREADONLY, X, 0) <> 0 THEN
egResult = EZ_MSGBOX(egFN, "At least one of the cells in the range is protected{!}","Deleting Protected Cells","")
EXIT SUB
END IF
NEXT Y
NEXT X

INCR GridChanges
CALL SaveUndo(0)
egSM %EG_INTERNALSELECT ,0, 0
egSM %EG_DELETECONTENTS, %EG_TEXT OR %EG_FORMULA, 0

CALL SaveUndo(1)
END IF

egSM %EG_REFRESHALL, 0, 0
END SUB

'-------------------------------(Save Undo)-------------------------------------
'Used by EGridNav to save the state of the grid. Call before and after changes
'It dynamically erases grid states that are no longer needed
'You will need to erase any leftover grid states by calling EgridUndoErase before closing app
SUB SaveUndo(After AS BYTE)
LOCAL j AS INTEGER

IF egUndo + 1 > egMaxUndo THEN
CALL GLOBALFREE(gUndo(1))
ARRAY DELETE gUndo(1), 0
END IF
IF After = 0 THEN
egUndo = MIN(egUndo+1,egMaxUndo)
IF gUndo(egUndo) THEN
CALL GLOBALFREE(gUndo(egUndo))
gUndo(egUndo) = 0
END IF
FOR j = egUndo+1 TO egNumUndo
IF gUndo(j) THEN CALL GLOBALFREE(gUndo(j))
gUndo(j) = 0
NEXT j
egNumUndo = egUndo
gUndo(egUndo) = Grid_GetDataStream(egHndl,%EG_COMPRESSED )
ELSE
IF egUndo + 1 > (egMaxUndo+1) THEN
CALL GLOBALFREE(gUndo(1))
ARRAY DELETE gUndo(1), 0
END IF
INCR egNumUndo
gUndo(egNumUndo) = Grid_GetDataStream(egHndl)
END IF

END SUB


'-----------------------------(UNDO)---------------------------------
SUB EGridUndo
LOCAL VL AS LONG, HL AS LONG, MLC AS LONG

IF egUndo > 0 THEN
IF gUndo(0) = 1 THEN DECR egUndo
gUndo(0) = -1
HL = egSMR(%EG_GETLOCKHORZSIZES, 0, 0)
VL = egSMR(%EG_GETLOCKVERTSIZES, 0, 0)
MLC = egSMR(%EG_GETMARGINLINESCOLOR, 0, 0)
Grid_SetDataStream(egHndl, gUndo(egUndo),%EG_APPLYPROPERTIES OR %EG_RESTORESELECTION OR %EG_RESTOREPOSITION)
egSM %EG_SETMODIFY, %TRUE, 0
'-----------------------------------------------------------------------------------------------
'For some reason I'm having problems with Egrid32 remembering the following settings on the grid
'The GetMarginLineColor doesn't work - Put in your own color until Elias fixes this
egSM %EG_SETLOCKHORZSIZES, HL, 0
egSM %EG_SETLOCKVERTSIZES, VL, 0
egSM %EG_SETMARGINLINESCOLOR, Cadet_Blue, 0
'-----------------------------------------------------------------------------------------------
DECR egUndo
gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT
CALL egGetRect()
egShowRect(1)
END IF

END SUB


'----------------------------(REDO)----------------------------------
SUB EGridRedo
LOCAL HL AS LONG
LOCAL VL AS LONG

IF egNumUndo > egUndo THEN
IF gUndo(0) = -1 THEN INCR egUndo
gUndo(0) = 1
INCR egUndo
HL = egSMR(%EG_GETLOCKHORZSIZES, 0, 0)
VL = egSMR(%EG_GETLOCKVERTSIZES, 0, 0)
Grid_SetDataStream(egHndl, gUndo(egUndo),%EG_APPLYPROPERTIES OR %EG_RESTORESELECTION OR %EG_RESTOREPOSITION)
egSM %EG_SETMODIFY, %TRUE, 0
egSM %EG_SETLOCKHORZSIZES, HL, 0
egSM %EG_SETLOCKVERTSIZES, VL, 0
gSel = 1 : REDIM RC(gSel) AS GLOBAL RECT
CALL egGetRect()
egShowRect(0)
END IF

END SUB


'---------------------------(Erase All the Grid States after Closing the Grid)----------------
'-------------------- Call this before closing your application to free up all undo's --------
SUB EgridUndoErase
LOCAL X AS LONG

FOR X = 1 TO egNumUndo
IF gUndo(X) THEN CALL GLOBALFREE(gUndo(X))
gUndo(X) = 0
NEXT X
egUndo = 0
egNumUndo = 0

END SUB


'----------------------------------(Insert or Delete Rows)--------------------------------
SUB EGRIDROWS(InsDel AS INTEGER, Y1 AS LONG, Y2 AS LONG, UseUndo AS BYTE)
'Positive value inserts rows; negative value deletes rows
'IF Y1 and Y2 are <> 0 then use them instead of g.Y1 and g.Y2

LOCAL Y AS LONG
LOCAL X AS LONG
LOCAL RowCnt AS LONG

IF gSel > 1 THEN
MSGBOX "You must select a single range for this operation"
EXIT SUB
END IF

IF Y1 = 0 AND Y2 = 0 THEN
Y1 = g.Y1 : Y2 = g.Y2
END IF
RowCnt = Y2 - Y1 + 1

IF InsDel > 0 THEN 'Make sure no data will be lost
FOR Y = egMaxRow-RowCnt+1 TO egMaxRow
FOR X = 1 TO egMaxCol
IF egCELLHASTEXT(X,Y) THEN
egResult = EZ_MSGBOX(egFN, "Nonblank cells cannot be shifted off the boundaries of the sheet{!}","Insert Error","")
EXIT SUB
END IF
NEXT X
NEXT Y
END IF

INCR GridChanges
IF UseUndo > 0 THEN CALL SaveUndo(0)
egSM %EG_SETAMOUNT, RowCnt, 0
IF InsDel < 0 THEN
egSM %EG_DELETEROW, Y1, %FALSE
ELSEIF InsDel > 0 THEN
egSM %EG_INSERTROW, Y1, %FALSE
END IF
egSM %EG_SETAMOUNT, 1, 0


CALL egShowRect(0) 'Select the same rows
IF UseUndo > 0 THEN CALL SaveUndo(1)

END SUB


'-------------------------------------(Does the Cell have contents?)-------------------------
FUNCTION egCELLHASTEXT(BYVAL X AS LONG, BYVAL Y AS LONG) AS BYTE
LOCAL CellFlags&

CellFlags& = egSMR(%EG_GETCELLFLAGS,X,Y)
IF (CellFlags& AND %EG_HasText) = %EG_HasText THEN egCELLHASTEXT = 1

END FUNCTION


'------------------------------------------(Get Cell Text)---------------------------
'Send the Coordinates of the cell and get cell text in return
FUNCTION egGETCELLTEXT(BYVAL X AS LONG, BYVAL Y AS LONG) AS STRING
LOCAL ST AS StringType

egSM %EG_INTERNALSELECTCELL, X, Y
egSM %EG_GETCELLTEXT, 0, VARPTR(ST)
egGETCELLTEXT = PEEK$(ST.Sptr, ST.Length)

END FUNCTION

'--------------------------------(Toggle Speed Entry)----------------------------------------
'Call this to toggle speed entry on and off
SUB EGRIDSPEEDENTRY()
EnterKey = ABS(EnterKey -1)
IF EnterKey > 0 THEN Speed.X1 = MIN(g.X1,g.X2) : Speed.X2 = MAX(g.X2,g.X1)
END SUB


'Stop the cut/copy frame display
SUB CLEARCUTCOPYFRAME()
EZ_StopTimer egFN, TimerID
EGCC.X1 = -1
egSM %EG_REFRESHALL, 0, 0
END SUB

'------------------------- Get Row and Column Info --------------------
'Find the last non-hidden row and column
SUB EgridMinMaxColRow()
DIM X AS LONG, Y AS LONG

egMaxCol = egSMR(%EG_GETMAXCOLUMNS, 0, 0)
egCols = egMaxCol 'visible or not
'IF the last column is hidden then make max cols one less
DO
IF egSMR(%EG_GETHIDECOLUMN, egMaxCol, 0) THEN
egMaxCol = egMaxCol - 1
ELSE
EXIT LOOP
END IF
LOOP

egMinCol = 1
DO
IF egSMR(%EG_GETHIDECOLUMN, egMinCol, 0) THEN
egMinCol = egMinCol + 1
ELSE
EXIT LOOP
END IF
LOOP

egMaxRow = egSMR(%EG_GetMaxRows, 0, 0)
egRows = egMaxRow 'visible or not
'If the last row is hidden then make max rows one less
DO
IF egSMR(%EG_GETHIDEROW, egMaxRow, 0) THEN
egMaxRow = egMaxRow - 1
ELSE
EXIT LOOP
END IF
LOOP

egMinRow = 1
DO
IF egSMR(%EG_GETHIDEROW, egMinRow, 0) THEN
egMinRow = egMinRow + 1
ELSE
EXIT LOOP
END IF
LOOP

END SUB


'Return the last column not hidden
FUNCTION EgridMaxCols() AS LONG
LOCAL MaxCols AS LONG
MaxCols = egSMR(%EG_GETMAXCOLUMNS, 0, 0)
'IF the last column is hidden then make max rows one less
DO
IF egSMR(%EG_GETHIDECOLUMN, MaxCols, 0) THEN
MaxCols = MaxCols - 1
ELSE
EXIT LOOP
END IF
LOOP
EgridMaxCols = MaxCols
END FUNCTION


'Return the last row not hidden
FUNCTION EgridMaxRows() AS LONG
LOCAL MaxRows AS LONG
MaxRows = egSMR(%EG_GetMaxRows, 0, 0)
'If the last row is hidden then make max rows one less
DO
IF egSMR(%EG_GETHIDEROW, MaxRows, 0) THEN
MaxRows = MaxRows - 1
ELSE
EXIT LOOP
END IF
LOOP
EgridMaxRows = MaxRows
END FUNCTION


'Send a message to the grid and return the response
'I simply got tired of typing out the whole command with the form name and ID
FUNCTION egSMR(Msg AS LONG, wparm AS LONG, lparm AS LONG) AS LONG
egSMR = EZ_SendMessageR(egFN, egID, Msg, wparm, lparm)
END FUNCTION

'Send a message to the grid
SUB egSM(Msg AS LONG, wparm AS LONG, lparm AS LONG)
EZ_SendMessage(egFN, egID, Msg, wparm, lparm)
END SUB


'---------------------------------- Header Formatting -------------------------------
'Format Column or Row Headers
SUB EgridHeaderText(ColID AS LONG, RowID AS LONG, Caption AS STRING, FColor AS LONG, HAlign AS STRING, VAlign AS STRING, SizeinInches AS SINGLE)

LOCAL MyText AS STRING, ACom AS STRING, SizeinPixels AS LONG

MyText = Caption
HAlign = UCASE$(HAlign) 'Left, Right, Center
VAlign = UCASE$(VAlign) 'Top, Bottom, Center

egSM %EG_INTERNALSELECTTL, ColID, RowID
egSM %EG_SETCELLTEXT, STRPTR(MyText), LEN(MyText)
ACom = "CELL.HALIGN(" & STR$(ColID) & "," & STR$(RowID) & ")=" & HAlign
egSM %EG_SETSTRINGDATA, STRPTR(ACom), LEN(ACom)
ACom = "CELL.VALIGN(" & STR$(ColID) & "," & STR$(RowID) & ")=" & VAlign
egSM %EG_SETSTRINGDATA, STRPTR(ACom), LEN(ACom)

egSM %EG_SETCELLFONTCOLOR, FColor, 0
egSM %EG_SETCELLBOLDMODE, %TRUE, 0
egSM %EG_SETSPECIALSETTINGS, %TRUE, 0

IF SizeinInches > 0 THEN
SizeinPixels = Grid_XInches2Pixels(SizeinInches)
IF ColID > 0 THEN
egSM %EG_SETCOLUMNSIZE, ColID, SizeinPixels
ELSEIF RowID > 0 THEN
egSM %EG_SETROWSIZE, RowID, SizeinPixels
END IF
END IF

END SUB


In the control properties for each EGrid control in the visual designer you will need to turn on EZ_notify so that the following similar sub is generated. This gets called automatically by the grid.

code:



SUB VTS_EGRIDMAIN_Notify(BYVAL CVal&, Cancel&)

CANCEL& = EGRIDNAV(Cval&, "VTS") 'Excel navigation and more

SELECT CASE EndKey
CASE 0
EZ_SetSBText "VTS", %VTS_STATUSBAR, 3, "", ""
CASE 1
EZ_SetSBText "VTS", %VTS_STATUSBAR, 3, "END", ""
END SELECT

SELECT CASE GridChanges
CASE 1
EZ_SetSBText "VTS", %VTS_STATUSBAR, 1, "Not Saved", ""
CASE ELSE
EZ_SetSBText "DE", %VTS_STATUSBAR, 1, "Ready", ""
END SELECT

END SUB


You will need to set a couple of variables needed by EGridNav before formatting your grid. You'll need to do this in the EZ_Loaded section of the form. I called a sub to fromat the grid. egFN is the current form name and egID is the grid ID.

code:


SUB VTS_LOADING

LOCAL Result&
LOCAL CW AS SINGLE
LOCAL OVERLAY AS LONG
LOCAL X AS LONG
LOCAL ST AS StringType
LOCAL CL1 AS STRING
LOCAL CL2 AS STRING
LOCAL CL3 AS STRING
LOCAL hFont&
LOCAL Y AS LONG
LOCAL J AS LONG
GLOBAL A AS STRING

egFN = "VTS"
egID = %VTS_EGRIDMAIN

StopEvents = 1
egSM(%EG_SETDRAWNOTIFY, 0 , 0) 'Stop notification of cells drawn

EZ_LoadCursor "#W", 50
EgridMinMaxColRow

OVERLAY = &H0FEEDE7
CW = 0.85

'Make the gridlines invisible
egSMR(%EG_SETEGRIDSTATE, %FALSE, 0)
'Set the Margin Line Color
egSMR(%EG_SETMARGINLINESCOLOR, Cadet_Blue, 0)
'Set the Grid Focus Colors
egSMR(%EG_SETFOCUSCOLOR1, Dark_Turquoise, 0)


'Make the top and row headers black text
egSMR(%EG_SETCOLHEADERFCOLOR, %BLACK, 0) '%BLUE
egSMR(%EG_SETROWHEADERFCOLOR, %BLACK, 0)

'Don't allow scrolling with the shift key
egSMR(%EG_SETSHIFTMOVEMENT, %FALSE, 0)
'Selection Overlay Color and Selection Frame Color
egSMR(%EG_SETOVERLAYCOLOR, Light_Blue, 0)
egSMR(%EG_SETFRAMESTYLE, 1.5, %BLUE)

'Make the selected headers darker
CL1 = "HEADER.SELECT1="& STR$(Old_Gold) &"|"
egSM %EG_SETSTRINGDATA, STRPTR(CL1), LEN(CL1)
'Make the background header COLOR grey
CL1 = "HEADER.NORMAL1="& STR$(Silver)
egSM %EG_SETSTRINGDATA, STRPTR(CL1), LEN(CL1)


'Related to expanding the cell selection with the little tab at the bottom right of the selection
egSMR(%EG_SETEXPANSION, %TRUE, 0)
'Prevent resizing the column and row widths
'egSMR(%EG_SETLOCKHORZSIZES, %TRUE, 0)
egSMR(%EG_SETLOCKVERTSIZES, %TRUE, 0)


'Set the default row height
egSMR(%EG_SETDEFAULTROWHEIGHT, 19, 0)
'Row height for the header
egSMR(%EG_SETROWSIZE, 0, 22)

'Refresh on Scroll
egSMR(%EG_SETREPAINTONSCROLL, %TRUE, 0)
'.... more specific to my grid



You will need the API loaded and Egrid_Navigate.inc loaded

code:



#INCLUDE ONCE "C:\PBWin90\WinAPI\Win32API.inc"
#INCLUDE ".\Include\EGrid_Navigate.inc"

All the Subs and Functions are explained in the Include File. If you have questions, I'll be happy to help.

Jeff

Andrew W Lindsay
Member
posted 07-03-2009 07:32 PM     Click Here to See the Profile for Andrew W Lindsay     Edit/Delete Message Reply w/Quote
Jeff,

Do you have a non-EZGUI version of this include file?

Regards

Andrew

Jeffrey Smith
Member
posted 07-06-2009 07:21 PM     Click Here to See the Profile for Jeffrey Smith     Edit/Delete Message Reply w/Quote
I don't have a version without EZGUI commands. There aren't that many EZGUI commands to change. Most of the commands for the grid are EGrid commands. It shouldn't take you too long to convert it. I may be able to help if you get stuck.

Jeff

Jeffrey Smith
Member
posted 07-06-2009 07:41 PM     Click Here to See the Profile for Jeffrey Smith     Edit/Delete Message Reply w/Quote
Andrew,

I created a snippet for Elias. This snippet was an older version of what I published above. The snippet can be viewed in the Egrid designer and then the designer generates powerbasic code. You can use that as an example or a template, but use the latest code above.

Jeff

All times are EST (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | Computer Workshop ( EZGUI ) Home Page

Copyright 2000 to 2007 Christopher R. Boss

Powered by: Ultimate Bulletin Board, Version 5.44
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.