1. Spreadsheet Control
Someone was asking for information on how to create a spreadsheet-type of
control, so here's a small demo. Basically, it creates a hidden control
(drawn off the window) that traps key events. Two real scrollbars are
created; notice that they set the focus back to the hidden grid control
after scrolling. Note that it uses the onMouse and onPaint traps of the
parent window.
I redefined White in Win32Lib as:
White = rgb( 192, 192, 192 )
since it's incorrectly defined. It should use system colors instead.
There are a lot of features that could be added: double buffering, key
handling, using real system colors, selecting rows/columns, resizing
columns, more navigation keys, center the labels... the list goes on and on.
If people are interested, I could develop it more (unless someone else wants
to take it on).
You can create the grid by calling:
createGrid( parent, x, y, rows, cols, maxRows, maxCols )
Data is contained in the global sequence:
gridData
Here's a small demo using the code:
-- BEGIN DEMO --
include win32lib.ew
include grid.ew
constant Win = create( Window, "Grid Demo", 0,
Default, Default, 360, 180, 0 )
-- create the grid
createGrid( Win, 10, 10, 4, 4, 10, 10 )
-- fill grid with data
for y = 1 to 10 do
for x = 1 to 10 do
gridData[y][x] = sprintf( "%d, %d", {x,y} )
end for
end for
WinMain( Win, Normal )
-- END DEMO --
Hope this helps!
-- David Cuny
-- BEGIN GRID.EW --
-- emulated spreadsheet-type grid control
include win32lib.ew
constant
CellCX = 64, -- cell width
CellCY = 20 -- cell height
integer
grid, -- id of grid
gridOwner, -- parent of grid
gridCols, -- number of displayed columns
gridRows, -- number of displayed rows
gridMaxCols, -- max number of columns
gridMaxRows, -- max number of rows
gridX, -- x position of grid
gridY, -- y position of grid
gridCX, -- width of grid
gridCY, -- height of grid
gridV, -- grid vertical scroll bar
gridH, -- grid horizontal scroll bar
cellX, -- current cell x
cellY -- current cell y
global sequence
gridData -- grid cells
global procedure paintGrid()
-- draw the grid control
integer x, y, x1, y1, x2, y2, offsetX, offsetY, thisX, thisY, h, v
sequence size
-- size of font
size = getFontSize( gridOwner )
-- to center text in cell
offsetY = floor( (CellCY - size[2])/2 )
-- cell index
h = getScrollPos( gridH ) - 1
v = getScrollPos( gridV ) - 1
-- cell index
x = 0
y = 0
-- draw each cell
for posY = 0 to gridCY-1 by CellCY do
for posX = 0 to gridCX-1 by CellCX do
x1 = gridX+posX
y1 = gridY+posY
x2 = x1 + CellCX - 1
y2 = y1 + CellCY - 1
-- draw the cell
if x = 0 or y = 0 then
-- background
setPenColor( gridOwner, White )
drawRectangle( gridOwner, True, x1, y1, x2+1, y2+1 )
setPenColor( gridOwner, Gray )
drawRectangle( gridOwner, False, x1, y1, x2, y2 )
-- selected col/row?
if h+x = cellX or v+y = cellY then
-- highlight
setPenColor( gridOwner, BrightWhite )
drawLine( gridOwner, x1, y1, x2, y1 )
drawLine( gridOwner, x1, y1, x1, y2 )
-- shadow
setPenColor( gridOwner, Black )
drawLine( gridOwner, x2, y1, x2, y2 )
drawLine( gridOwner, x1, y2, x2, y2 )
setPenColor( gridOwner, Gray )
drawLine( gridOwner, x2-1, y1+1, x2-1, y2-1 )
drawLine( gridOwner, x1+1, y2-1, x2-1, y2-1 )
end if
else
-- cell
setPenColor( gridOwner, BrightWhite )
drawRectangle( gridOwner, True, x1, y1, x2, y2 )
setPenColor( gridOwner, Gray )
drawLine( gridOwner, x2, y1, x2, y2 )
drawLine( gridOwner, x1, y2, x2, y2 )
-- selected?
if x+h = cellX and y+v = cellY then
setPenColor( gridOwner, Black )
for i = 0 to 1 do
drawRectangle( gridOwner, False, x1+i, y1+i, x2-i,
y2-i )
end for
end if
end if
-- text in the cell
if x = 0 and y = 0 then
-- no text
elsif x = 0 then
setPosition( gridOwner, x1+4, y1+offsetY )
wPrintf( gridOwner, "%d", {y+v} )
elsif y = 0 then
setPosition( gridOwner, x1+4, y1+offsetY )
wPrintf( gridOwner, "%s", "A"+x+h-1 )
else
setPosition( gridOwner, x1+4, y1+offsetY )
wPrintf( gridOwner, "%d,%d", {x+h,y+v} )
end if
-- increment cell index
x += 1
end for
-- increment cell index
x = 0
y += 1
end for
end procedure
procedure paint( integer x1, integer y1, integer x2, integer y2 )
paintGrid()
end procedure
procedure mouse( integer event, integer x, integer y, integer shift )
if event = LeftDown then
-- in the grid?
if x >= gridX and y >= gridY
and x < gridX+gridCX and y < gridY+gridCY then
-- which cell?
x = floor( (x-gridX)/CellCX )
y = floor( (y-gridY)/CellCY )
if x != 0 and y != 0 then
-- cell index
cellX = getScrollPos( gridH ) + x - 1
cellY = getScrollPos( gridV ) + y - 1
end if
-- update the grid
paint( 0, 0, 0, 0 )
-- focus on hidden control
setFocus( grid )
end if
end if
end procedure
procedure keydown( integer keycode, integer shift )
-- key handler for scrollbar
integer h, v
if keycode = VK_HOME then
cellX = 1
cellY = 1
setScrollPos( gridH, 1 )
setScrollPos( gridV, 1 )
elsif keycode = VK_LEFT then
if cellX > 1 then
-- move cell
cellX -= 1
-- need to scroll?
h = getScrollPos( gridH )
if h > cellX then
-- scroll
setScrollPos( gridH, cellX )
else
-- just paint
paintGrid()
end if
end if
elsif keycode = VK_RIGHT then
-- check range
if cellX < gridMaxCols then
-- move cell
cellX += 1
-- need to scroll?
h = getScrollPos( gridH )
if h + gridCols - 1 < cellX then
-- scroll
setScrollPos( gridH, h+1 )
else
-- just paint
paintGrid()
end if
end if
elsif keycode = VK_UP then
if cellY > 1 then
-- move
cellY -= 1
-- need to scroll?
if getScrollPos( gridV ) > cellY then
setScrollPos( gridV, cellY )
else
paintGrid()
end if
end if
elsif keycode = VK_DOWN then
-- check range
if cellY < gridMaxRows then
-- move cell
cellY += 1
-- need to scroll?
v = getScrollPos( gridV )
if v + gridRows - 1 < cellY then
-- scroll
setScrollPos( gridV, v+1 )
else
-- just paint
paintGrid()
end if
end if
end if
-- don't give to the mle
returnValue( True )
end procedure
procedure scrollbar( integer pos )
-- update the grid
paint( 0, 0, 0, 0 )
-- focus on hidden control
setFocus( grid )
end procedure
global procedure createGrid( integer owner, integer x, integer y,
integer rows, integer cols,
integer maxRows, integer maxCols )
-- save values
gridOwner = owner
gridX = x
gridY = y
gridCols = rows
gridRows = cols
gridMaxCols = maxRows
gridMaxRows = maxCols
gridCX = (gridCols+1) * CellCX
gridCY = (gridRows+1) * CellCY
-- allocate space for data
gridData = repeat( repeat( "", gridMaxCols ), gridMaxRows )
-- create controls
grid = create( MleText, "", gridOwner, -10, -10, 5, 5, 0 )
gridV = create( VScroll, "", gridOwner, gridX+gridCX, gridY, 16, gridCY,
0 )
gridH = create( HScroll, "", gridOwner, gridX, gridY+gridCY, gridCX, 16,
0 )
-- scroll range
setScrollRange( gridV, 1, (gridMaxRows - gridRows) + 1 )
setScrollRange( gridH, 1, (gridMaxCols - gridCols) + 1 )
-- selected cell
cellX = 1
cellY = 1
-- set up callbacks
onPaint[gridOwner] = routine_id("paint")
onMouse[gridOwner] = routine_id("mouse")
onKeyDown[grid] = routine_id("keydown")
onScroll[gridH] = routine_id("scrollbar")
onScroll[gridV] = routine_id("scrollbar")
-- draw the control
paintGrid()
end procedure
-- END GRID.EW --
2. Re: Spreadsheet Control
Urgh. There were a few bugs in the code, such as not actually using gridData
to display the code.
I also added system colors and double-buffering, so the display should be
smoother.
-- David Cuny
-- grid.exw
-- emulated spreadsheet-type grid control
include win32lib.ew
constant
CellCX = 64, -- cell width
CellCY = 20 -- cell height
integer
grid, -- id of grid
gridPix, -- image of grid
gridOwner, -- parent of grid
gridCols, -- number of displayed columns
gridRows, -- number of displayed rows
gridMaxCols, -- max number of columns
gridMaxRows, -- max number of rows
gridX, -- x position of grid
gridY, -- y position of grid
gridCX, -- width of grid
gridCY, -- height of grid
gridV, -- grid vertical scroll bar
gridH, -- grid horizontal scroll bar
cellX, -- current cell x
cellY -- current cell y
global sequence
gridData
global procedure paintGrid()
-- draw the grid control
integer x, y, x2, y2, offsetX, offsetY, thisX, thisY, h, v
sequence size
-- size of font
size = getFontSize( gridOwner )
-- to center in cell
offsetY = floor( (CellCY - size[2])/2 )
-- cell index
h = getScrollPos( gridH ) - 1
v = getScrollPos( gridV ) - 1
-- current cell
x = 0
y = 0
-- background
setPenColor( gridPix, getSysColor( COLOR_BTNFACE ) )
drawRectangle( gridPix, True, 1, 1, gridCX, gridCY )
-- draw each cell
for y1 = 0 to gridCY-1 by CellCY do
for x1 = 0 to gridCX-1 by CellCX do
x2 = x1 + CellCX - 1
y2 = y1 + CellCY - 1
-- draw the cell
if x = 0 or y = 0 then
-- background
setPenColor( gridPix, getSysColor( COLOR_BTNFACE ) )
drawRectangle( gridPix, True, x1, y1, x2+1, y2+1 )
setPenColor( gridPix, getSysColor( COLOR_GRAYTEXT ) )
drawRectangle( gridPix, False, x1, y1, x2, y2 )
-- selected col/row?
if h+x = cellX or v+y = cellY then
-- highlight
setPenColor( gridPix, getSysColor( COLOR_BTNHIGHLIGHT )
)
drawLine( gridPix, x1, y1, x2, y1 )
drawLine( gridPix, x1, y1, x1, y2 )
-- shadow
setPenColor( gridPix, getSysColor( COLOR_3DDKSHADOW ) )
drawLine( gridPix, x2, y1, x2, y2 )
drawLine( gridPix, x1, y2, x2, y2 )
setPenColor( gridPix, getSysColor( COLOR_BTNSHADOW ) )
drawLine( gridPix, x2-1, y1+1, x2-1, y2-1 )
drawLine( gridPix, x1+1, y2-1, x2-1, y2-1 )
end if
else
-- cell
setPenColor( gridPix, getSysColor( COLOR_WINDOW ) )
drawRectangle( gridPix, True, x1, y1, x2, y2 )
setPenColor( gridPix, COLOR_GRAYTEXT )
drawLine( gridPix, x2, y1, x2, y2 )
drawLine( gridPix, x1, y2, x2, y2 )
-- selected?
if x+h = cellX and y+v = cellY then
setPenColor( gridPix, getSysColor( COLOR_BTNTEXT ) )
for i = 0 to 1 do
drawRectangle( gridPix, False, x1+i, y1+i, x2-i,
y2-i )
end for
end if
end if
-- text in the cell
if x = 0 and y = 0 then
-- no text
elsif x = 0 then
setPosition( gridPix, x1+4, y1+offsetY )
wPrintf( gridPix, "%d", {y+v} )
elsif y = 0 then
setPosition( gridPix, x1+4, y1+offsetY )
wPrintf( gridPix, "%s", "A"+x+h-1 )
else
setPosition( gridPix, x1+4, y1+offsetY )
wPuts( gridPix, gridData[x+h][y+v] )
end if
-- increment cell index
x += 1
end for
-- increment cell index
x = 0
y += 1
end for
-- copy the pixmap
copyBlt( gridOwner, gridX, gridY, gridPix )
end procedure
procedure paint( integer x1, integer y1, integer x2, integer y2 )
paintGrid()
end procedure
procedure mouse( integer event, integer x, integer y, integer shift )
if event = LeftDown then
-- in the grid?
if x >= gridX and y >= gridY
and x < gridX+gridCX and y < gridY+gridCY then
-- which cell?
x = floor( (x-gridX)/CellCX )
y = floor( (y-gridY)/CellCY )
if x != 0 and y != 0 then
-- cell index
cellX = getScrollPos( gridH ) + x - 1
cellY = getScrollPos( gridV ) + y - 1
end if
-- update the grid
paint( 0, 0, 0, 0 )
-- focus on hidden control
setFocus( grid )
end if
end if
end procedure
procedure keydown( integer keycode, integer shift )
-- key handler for scrollbar
integer h, v
if keycode = VK_HOME then
cellX = 1
cellY = 1
setScrollPos( gridH, 1 )
setScrollPos( gridV, 1 )
elsif keycode = VK_LEFT then
if cellX > 1 then
-- move cell
cellX -= 1
-- need to scroll?
h = getScrollPos( gridH )
if h > cellX then
-- scroll
setScrollPos( gridH, cellX )
else
-- just paint
paintGrid()
end if
end if
elsif keycode = VK_RIGHT then
-- check range
if cellX < gridMaxCols then
-- move cell
cellX += 1
-- need to scroll?
h = getScrollPos( gridH )
if h + gridCols - 1 < cellX then
-- scroll
setScrollPos( gridH, h+1 )
else
-- just paint
paintGrid()
end if
end if
elsif keycode = VK_UP then
if cellY > 1 then
-- move
cellY -= 1
-- need to scroll?
if getScrollPos( gridV ) > cellY then
setScrollPos( gridV, cellY )
else
paintGrid()
end if
end if
elsif keycode = VK_DOWN then
-- check range
if cellY < gridMaxRows then
-- move cell
cellY += 1
-- need to scroll?
v = getScrollPos( gridV )
if v + gridRows - 1 < cellY then
-- scroll
setScrollPos( gridV, v+1 )
else
-- just paint
paintGrid()
end if
end if
end if
-- don't give to the mle
returnValue( True )
end procedure
procedure scrollbar( integer pos )
-- update the grid
paint( 0, 0, 0, 0 )
-- focus on hidden control
setFocus( grid )
end procedure
procedure createGrid( integer owner, integer x, integer y,
integer rows, integer cols,
integer maxRows, integer maxCols )
-- save values
gridOwner = owner
gridX = x
gridY = y
gridCols = rows
gridRows = cols
gridMaxCols = maxRows
gridMaxRows = maxCols
gridCX = (gridCols+1) * CellCX
gridCY = (gridRows+1) * CellCY
-- allocate space for data
gridData = repeat( repeat( "", gridMaxCols ), gridMaxRows )
-- create controls
grid = create( MleText, "", gridOwner, -10, -10, 5, 5, 0 )
gridV = create( VScroll, "", gridOwner, gridX+gridCX, gridY, 16, gridCY,
0 )
gridH = create( HScroll, "", gridOwner, gridX, gridY+gridCY, gridCX, 16,
0 )
gridPix = create( Pixmap, "", 0, 0, 0, gridCX, gridCY, 0 )
-- scroll range
setScrollRange( gridV, 1, (gridMaxRows - gridRows) + 1 )
setScrollRange( gridH, 1, (gridMaxCols - gridCols) + 1 )
-- selected cell
cellX = 1
cellY = 1
-- set up callbacks
onPaint[gridOwner] = routine_id("paint")
onMouse[gridOwner] = routine_id("mouse")
onKeyDown[grid] = routine_id("keydown")
onScroll[gridH] = routine_id("scrollbar")
onScroll[gridV] = routine_id("scrollbar")
-- draw the control
paintGrid()
end procedure
-- demo
constant Win = create( Window, "Grid Demo", 0, Default, Default, 360, 180, 0
)
-- create the grid
createGrid( Win, 10, 10, 4, 4, 10, 10 )
function pick( sequence s )
return s[ rand( length(s) ) ]
end function
-- fill it with data
for y = 1 to 10 do
for x = 1 to 10 do
for i = 1 to 4 + rand(10) do
gridData[y][x] &= pick("qwertyuiopasdfghjklzxcvbnm")
end for
end for
end for
WinMain( Win, Normal )
5. Re: Spreadsheet Control
>From: "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV>
>
>Someone was asking for information on how to create a spreadsheet-type of
>control, so here's a small demo. Basically, it creates a hidden control
>(drawn off the window) that traps key events. Two real scrollbars are
>created; notice that they set the focus back to the hidden grid control
>after scrolling. Note that it uses the onMouse and onPaint traps of the
>parent window.
>
>I redefined White in Win32Lib as:
>
> White = rgb( 192, 192, 192 )
>
>since it's incorrectly defined. It should use system colors instead.
>
>There are a lot of features that could be added: double buffering, key
>handling, using real system colors, selecting rows/columns, resizing
>columns, more navigation keys, center the labels... the list goes on and
>on.
>If people are interested, I could develop it more (unless someone else
>wants
>to take it on).
>
I'm interested! I don't have the know-how to take it over, but I've wished
several times that there was such a thing.
Thanks,
Ben
______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com
6. Re: Spreadsheet Control
Ben Logan replied:
>> If people are interested, I could develop it more
>>(unless someone else wants to take it on).
> I'm interested! I don't have the know-how to take
> it over, but I've wished several times that there
> was such a thing.
Take a look at the code, and let me know if you are still interested, and
what sorts of questions you have about it.
-- David Cuny
7. Re: Spreadsheet Control
- Posted by Prasanta Chakraborty <prasanta at WRITEME.COM>
Apr 19, 2000
-
Last edited Apr 20, 2000
David,
I forgot to mention in my earlier post that I am very much interested
regarding the additional features you mentioned. In fact I have started
modifying the code you have given to add cutomized headers (instead of
A..Z) and also auto adjustment of the cells. I am not sure if I am doing it
the right way, but I will release the code as soon as I have made the
changes. If you have any ideas, can you please convey them to me (you can
send me personal mails also).
Thanks again for the code.
Regards,
Prasanta.