1. Spreadsheet Control
- Posted by "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV> Apr 18, 2000
- 508 views
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
- Posted by "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV> Apr 18, 2000
- 503 views
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 )
3. Re: Spreadsheet Control
- Posted by "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV> Apr 18, 2000
- 474 views
The line: wPuts( gridPix, gridData[x+h][y+v] ) should be: wPuts( gridPix, gridData[y+v][x+h] ) -- David Cuny
4. Re: Spreadsheet Control
- Posted by Prasanta Chakraborty <prasanta at WRITEME.COM> Apr 18, 2000
- 486 views
- Last edited Apr 19, 2000
David, I was asking for it. thanks very much for the code. Hope we will be able to see it in your future version of WIN32LIB (am I asking too much!). Regards, Prasanta.
5. Re: Spreadsheet Control
- Posted by Ben Logan <wbljr79 at HOTMAIL.COM> Apr 19, 2000
- 541 views
>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
- Posted by "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV> Apr 19, 2000
- 471 views
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
- 509 views
- 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.