
I just got back from vacation and thought I'd share my sense of happiness at being back in a really nice familiar place ^_^
Here is the current (very uncompleted) code for xGrid. I haven't even gotten the cell formatting finished in the demo app so it'd be best if you just dropped xGrid.pb into your own app and tested it. I'll continue updating as I can. Still a lot to add and I DO plan on adding to it so please don't think it just died.
Here are some code snippets from a couple parts.
Code: Select all
;{ Header Text and Cell Dividing Lines
lPen = CreatePen_(#PS_SOLID, 1, RGB(128, 128, 128))
; Create the pen to draw the dividing lines.
SelectObject_(HandleImage, lPen)
; Select the pen for usage.
SetTextColor_(HandleImage, RGB(0, 0, 0)) : SetBkMode_(HandleImage, #TRANSPARENT)
; Set text properties. Black text.
HoldHeight = -Int((10 * GetDeviceCaps_(HandleImage, #LOGPIXELSY)) / 72)
; Convert the height to pixels.
CellFont = CreateFont_(HoldHeight,0,0,0,0,0,0,0,0,0,0,0,0,"Arial")
; Create the font we'll use to draw the text in the headers.
SelectObject_(HandleImage, CellFont)
; And select it for use.
;/ Column Text.
xg_CellRectFromLocation(*xGrid, *xGrid\CellBoundaries\Left, -1, @TempRect)
; Store the rectangular dimensions of the leftmost column.
If *xGrid\Arrays\ColumnWidth : HoldSize = MemorySize(*xGrid\Arrays\ColumnWidth) : EndIf
; Only need to call this once for column drawing so store the size of the column width array if it exists.
For LoopColumn = *xGrid\CellBoundaries\Left To *xGrid\CellBoundaries\Right
; Loop through the visible columns.
CaughtColumn = #False
; This will be True if a custom width exists for the next column. False if using the default width.
If LoopColumn > 25 : CellText = Chr(65 + Int(LoopColumn / 26) - 1)+Chr(65 + (LoopColumn - (26 * Int(LoopColumn / 26)))) : Else : CellText = Chr(65 + LoopColumn) : EndIf
; Store the column header. Handle any double characters "AA", "AB", etc...
If TempRect\Right < *xGrid\Width + *xGrid\OffsetPosition\X : MoveToEx_(HandleImage,TempRect\Right - *xGrid\OffsetPosition\X, 0, 0) : LineTo_(HandleImage, TempRect\Right - *xGrid\OffsetPosition\X, *xGrid\Height) : EndIf
; We're only drawing right cell boundaries for the columns so no need to draw it if it's beyond our viewable area.
DrawText_(HandleImage, @CellText, Len(CellText), @HoldRect, #DT_NOCLIP | #DT_NOPREFIX | #DT_SINGLELINE | #DT_CALCRECT)
; Calculate the width and height needed for the text.
TextPosition\X = TempRect\Left + Int(((TempRect\Right - TempRect\Left) - HoldRect\Right) / 2) - *xGrid\OffsetPosition\X
TextPosition\Y = TempRect\Top + Int(((TempRect\Bottom - TempRect\Top) - HoldRect\Bottom) / 2)
; Store the centered text coordinates.
MoveToEx_(HandleImage, TextPosition\X, TextPosition\Y, 0)
; Move our drawing cursor to the center of the cell.
If TextPosition\X < *xGrid\OffsetPosition\X + *xGrid\HeaderWidth
; Text intersects row number column. Clip it.
HandleClip = CreateRectRgn_(*xGrid\HeaderWidth, 0, TempRect\Right - *xGrid\OffsetPosition\X, *xGrid\HeaderHeight)
SelectClipRgn_(HandleImage, HandleClip)
;
ElseIf TempRect\Bottom - TempRect\Top < HoldRect\Bottom Or TempRect\Right - TempRect\Left < HoldRect\Right
; Text is wider than width of the cell. Clip it.
HandleClip = CreateRectRgn_(TempRect\Left - *xGrid\OffsetPosition\X, TempRect\Top - *xGrid\OffsetPosition\Y, TempRect\Right - *xGrid\OffsetPosition\X, TempRect\Bottom - *xGrid\OffsetPosition\Y)
SelectClipRgn_(HandleImage, HandleClip)
;
EndIf
;
DrawText_(HandleImage, @CellText, Len(CellText), @HoldRect, #DT_NOCLIP | #DT_NOPREFIX | #DT_SINGLELINE)
; Draw the column header text.
If HandleClip : SelectClipRgn_(HandleImage, 0) : DeleteObject_(HandleClip) : HandleClip = 0 : EndIf
;
If LoopColumn = *xGrid\MaxColumns : Break : EndIf
; Break when we've reached the last column.
TempRect\Left = TempRect\Right
; The next column's left boundary is the right boundary of the current column.
If *xGrid\Arrays\ColumnWidth
;
*Position = *xGrid\Arrays\ColumnWidth
;
While *Position - *xGrid\Arrays\ColumnWidth < HoldSize
;
If PeekL(*Position) = *xGrid\ActiveSheet And PeekL(*Position + 4) = LoopColumn + 1
; Found a custom width for the next column.
TempRect\Right = TempRect\Left + PeekL(*Position + 8)
; Set the next right boundary location.
CaughtColumn = #True
;
Break
; Exit our loop.
EndIf
;
*Position + 12
;
Wend
;
If CaughtColumn = #False : TempRect\Right = TempRect\Left + #xGrid_DefaultCellWidth : EndIf
; If no custom width exists for the next column, use the default cell width.
Else
; No custom widths exist.
TempRect\Right = TempRect\Left + #xGrid_DefaultCellWidth
; Set cell dimensions to the next column.
EndIf
;
Next LoopColumn
;
GreyArea\X = TempRect\Right
; Store the right value of the last column drawn. We'll use this to check if the non-editable area is visible.
Code: Select all
If Message = #WM_KEYDOWN Or Message = #WM_KEYUP Or Message = #WM_CHAR Or Message = #WM_COMMAND
; Only need to call this code once for the three messages.
If _xGrid_Focused
; Make sure we have a valid grid handle stored. If not, a grid is not focused.
HoldSize = MemorySize(_xGrid_List)
;
*Position = _xGrid_List
;
While *Position - _xGrid_List < HoldSize
;
If PeekL(*Position + 8) = _xGrid_Focused : *xGrid = PeekL(*Position) : Break : EndIf
;
*Position + 12
;
Wend
;
If *xGrid
;
xg_LastGoodCell(*xGrid, @rGrid, #True)
; Call the last good cell function simply to find the top left most cell and the bottom right most cell. We'll use this
; to determine the new rectangular range to select.
If rGrid\Left = rGrid\Right And rGrid\Top = rGrid\Bottom
; Only one cell is selected.
HoldPosition\X = rGrid\Left : HoldPosition\Y = rGrid\Top
;
Else
; Multiple cells are selected.
If rGrid\Left < *xGrid\MouseDownSelectedCell\X
;
If rGrid\Top < *xGrid\MouseDownSelectedCell\Y
HoldPosition\X = rGrid\Left : HoldPosition\Y = rGrid\Top
Else
HoldPosition\X = rGrid\Left : HoldPosition\Y = rGrid\Bottom
EndIf
;
Else
;
If rGrid\Top < *xGrid\MouseDownSelectedCell\Y
HoldPosition\X = rGrid\Right : HoldPosition\Y = rGrid\Top
Else
HoldPosition\X = rGrid\Right : HoldPosition\Y = rGrid\Bottom
EndIf
;
EndIf
;
EndIf
;
EndIf
;
EndIf
;
EndIf
;
Code: Select all
Procedure.l xg_PointerFromNumber(GadgetNumber.l)
;
*Position = _xGrid_List
;
HoldSize = MemorySize(_xGrid_List)
;
While *Position - _xGrid_List < HoldSize
;
If PeekL(*Position + 4) = GadgetNumber : ProcedureReturn PeekL(*Position) : EndIf
;
*Position + 12
;
Wend
;
ProcedureReturn 0
;
EndProcedure
Hummm... well, mainly I just want to put this out there for people to test it in their own projects while I update stuff. It's still buggy and a lot of things are missing so I wouldn't recommend using it in a major-ish project just yet ^_^
Have fun with it and remember - credit where credit is due, please.
Download here: http://www.seijin.net/Storage/xGrid-Code.rar
EDIT:
Forgot to mention something. In the following week I will add (in no particular order) - formula support, copy/pasting, simple save/open (as time permits), column/row insertion/deletion, sheet deletion, optimizations, optimizations and optimizations

So please, don't post code bits you've modified as I'm still in the process of ironing out my own 'official' version ^_^