More SIGrid Issues

Started by Fred Harris, May 01, 2006, 05:35:43 PM

Previous topic - Next topic

Fred Harris

From my reading of the SIGrid documentation it does appear that the internal construction of the grid is an array of edit controls.  See the documentation of the siSelectedRowCol type, one of the fields of which is the windows handle of the edit control element.  There is almost certainly a string array riding behind the array of text boxes, and I expect internally within the dll GetWindowText() calls load this array.  Further, I expect that the array is not loaded with the contents of a text box (cell element) until the focus moves out of any given cell.  And I'd be willing to bet that the siGetCell() function call retrieves data from the array, not from the text box.  For this reason, if an siGetCell() call is made after a user types into a cell, but before the focus is moved to another cell, the siGetCell() call will fail to retrieve the cell contents (it has not yet been retrieved into the array with an internal GetWindowText() call.

    Is this significant?  I believe so.  I discovered it by typing some data into a cell behind which I had an array of bools riding which informed my program that data tied to a database had been altered.  I had left the cursor in a field into which I had just entered data and clicked the 'Submit' button, and while my bool indicated data had been entered into a field, the siGetCell() call failed to retrieve the value.  So you can easily demonstrate this to yourself I am placing a program below for anyone to try.  Forgive me for not making it a firefly program, but rather a simple Sdk style program to conserve space.  The program creates a grid and a button.  When you click the button an siGetCell() call retrieves the contents of the cell at row 1, col 1.  Try entering a few numbers in the cell, leave the cursor in the cell, then click the 'Retrieve Col 1' button.  Then move the focus to another cell and click the button again.

    I'm wondering what folks might think of this?  Is there something I'm not seeing?  Below is the promised code...



#Compile Exe
%NOANIMATE         = 1  ' Animate control
%NOBUTTON          = 1  ' Button
%NOCOMBO           = 1  ' Combo box
%NOCOMBOEX         = 1  ' ComboBoxEx
%NODATETIMEPICK    = 1  ' Date/time picker
%NODRAGLIST        = 1  ' Drag list control
%NOEDIT            = 1  ' Edit control
%NOFLATSBAPIS      = 1  ' Flat scroll bar
%NOHEADER          = 1  ' Header control
%NOHOTKEY          = 1  ' HotKey control
%NOIMAGELIST       = 1  ' Image APIs
%NOIPADDRESS       = 1  ' IP Address edit control
%NOLIST            = 1  ' List box control
%NOLISTVIEW        = 1  ' ListView control
%NOMENUHELP        = 1  ' Menu help
%NOMONTHCAL        = 1  ' MonthCal
%NOMUI             = 1  ' MUI
%NONATIVEFONTCTL   = 1  ' Native Font control
%NOPAGESCROLLER    = 1  ' Pager
%NOPROGRESS        = 1  ' Progress control
%NOREBAR           = 1  ' Rebar control
%NOSTATUSBAR       = 1  ' Status bar
%NOTABCONTROL      = 1  ' Tab control
%NOTOOLBAR         = 1  ' Tool bar
%NOTOOLTIPS        = 1  ' Tool tips
%NOTRACKBAR        = 1  ' Track bar
%NOTRACKMOUSEEVENT = 1  ' Track Mouse Event
%NOTREEVIEW        = 1  ' TreeView

%IDC_GRID          = 1  'Grid Control ID
%IDC_BUTTON        = 2  'Button Control ID
#Include "Win32Api.inc"
#Include "Commctrl.inc"
#Include "Sigrid.inc"
Global ghInst As Long
Global strColSetup As String
Global hMainWnd,hGridWnd,dwGrdStyle As Dword
Global hFont,cFont,gFont As Long
Global pszStr As Asciiz Ptr

Function WndProc(Byval hWnd As Long,Byval wMsg As Long,Byval wParam As Long,Byval lParam As Long) Export As Long
 Local Grids As siGridSetup
 Static hButton As Dword
 Local strText As String
 Local iErr As Long

 Select Case wMsg
   Case %WM_CREATE
     hButton=CreateWindow("button","Retrieve Col #1",%WS_CHILD Or %WS_VISIBLE,175,310,200,30,hWnd,%IDC_BUTTON,ghInst,0)
     strColSetup= _
     "Tree #:50:^" & _       'Tree #
     "|Species:50:^" & _     'Species
     "|Dbh:30:^" & _         'Dbh
     "|Logs:35:^" & _        'Logs
     "|% Cull:45:^" & _      '% Cull
     "|Grade:50:^:" & _      'Grade
     "|Volume:50:^" & _      'Volume
     "|Block:45:^" & _       'Block
     "|BkCtr:45:^" & _       'BkCtr
     "|RealSp:45:^" & _      'RealSp
     "|Suffix:45:^" & _      'Suffix
     "|CruID:35:^"           'CruID
     pszStr=Strptr(strColSetup)
     dwGrdStyle=%WS_CHILD Or %WS_TABSTOP Or %WS_VISIBLE Or %WS_CLIPCHILDREN Or %SI_GRID_ROWCOUNTER Or %SI_GRID_HSCROLL _
     Or %SI_GRID_VSCROLL Or %SI_GRID_FIXEDROW
     Call InitCommonControls()
     Grids.RowCount=1                        :Grids.ColCount=12
     Grids.CurrentCol=1                      :Grids.CurrentRow=1
     Grids.FirstRow = 1                      :Grids.FirstCol = 1
     Grids.BackColor = RGB(255,255,255)      :Grids.FixedBackColor = RGB(192,192,192)
     Grids.DividerColor = RGB(128,128,128)   :Grids.ForeColor = RGB(0,0,0)
     Grids.FixedForeColor = RGB(0,0,0)       :Grids.WorkSpaceColor = RGB(192,192,192)
     Grids.SelBackColor = RGB(0,0,128)       :Grids.SelForeColor = RGB(255,255,255)
     Grids.GridFont=gFont                    :Grids.RowHeight=20
     Grids.FixedRowHeight=18                 :Grids.ColDelimiter=Asc("|")
     Grids.CurRowBackColor=RGB(200,200,225)  :Grids.CurRowForeColor = RGB(0,0,200)
     hGridWnd=CreateWindow("SIGrid",@pszStr,dwGrdStyle,0,0,543,300,hWnd,%IDC_GRID,ghInst,ByVal VarPtr(Grids))
     Call siSetRowCount(hGridWnd,200,0)
     WndProc=0
     Exit Function
   Case %WM_COMMAND
     If Lowrd(wParam)=%IDC_BUTTON Then
        strText="strText="
        strText=strText & siGetCell(hGridWnd,1,1,iErr)
        If iErr=0 Then
           strText=strText & "  iErr=SUCCESS"
        Else
           strText=strText & " iErr=" & Str$(iErr)
        End If
        MsgBox(strText)
     End If
     WndProc=0
     Exit Function
   Case %WM_DESTROY
     Call DeleteObject(hFont)
     Call DeleteObject(cFont)
     Call DeleteObject(gFont)
     Call PostQuitMessage(0)
     WndProc=0
     Exit Function
 End Select

 WndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function

Function WinMain(Byval hIns As Long,Byval hPrev As Long,Byval lpCL As Asciiz PTR,Byval iS As Long) As Long
 Local winclass As WndClassEx
 Local szAppName As Asciiz*20
 Local Msg As tagMsg

 Call LoadLibrary("sigrid.dll")
 ghInst=hIns
 szAppName="Form17"
 winclass.cbSize=Sizeof(WndClassEx)
 winclass.style=%CS_HREDRAW Or %CS_VREDRAW
 winclass.lpfnWndProc=Codeptr(WndProc)
 winclass.cbClsExtra=0
 winclass.cbWndExtra=0
 winclass.hInstance=hIns
 winclass.hIcon=LoadIcon(%NULL, Byval %IDI_APPLICATION)
 winclass.hCursor=LoadCursor(%NULL, Byval %IDC_ARROW)
 winclass.hbrBackground=GetStockObject(%LTGRAY_BRUSH)
 winclass.lpszMenuName=%NULL
 winclass.lpszClassName=Varptr(szAppName)
 winclass.hIconSm=LoadIcon(hIns,Byval %IDI_APPLICATION)
 Call RegisterClassEx(winclass)
 hFont=CreateFont(14,0,0,0,%FW_BOLD,0,0,0,%ANSI_CHARSET,%OUT_DEFAULT_PRECIS,%CLIP_DEFAULT_PRECIS,%PROOF_QUALITY,%DEFAULT_PITCH,"Arial")
 cFont=CreateFont(14,0,0,0,%FW_NORMAL,0,0,0,%ANSI_CHARSET,%OUT_DEFAULT_PRECIS,%CLIP_DEFAULT_PRECIS,%PROOF_QUALITY,%DEFAULT_PITCH,"Arial")
 gFont=CreateFont(14,0,0,0,%FW_NORMAL,0,0,0,%ANSI_CHARSET,%OUT_DEFAULT_PRECIS,%CLIP_DEFAULT_PRECIS,%PROOF_QUALITY,%DEFAULT_PITCH,"Arial")
 hMainWnd=CreateWindow(szAppName,"SIGrid Problem?",%WS_OVERLAPPEDWINDOW Or %WS_CLIPCHILDREN,50,50,555,380,%HWND_DESKTOP,%NULL,hIns,Byval 0)
 Call ShowWindow(hMainWnd,iS)
 Call UpdateWindow(hMainWnd)
 While GetMessage(Msg,%NULL,0,0)
   Call TranslateMessage(Msg)
   Call DispatchMessage(Msg)
 Wend

 WinMain=msg.wParam
End Function




Fred Harris

Fred Harris

If my suppositions above are correct, and one can obtain the windows handles of the underlying edit controls, then one should be able to get the edit control contents directly from the individual cells with
GetWindowText() calls.  I'll try that now.  I'm sensitive about issues such as this because in my organization we just recently abandoned a piece of software into which millions of dollars had been sunk, but which routinely lost data, as could occur through the above situation (I can't spell phenononmen).

Fred Harris

Fred Harris

OK, just solved the problem without resorting to anything complicated or difficult.  In the above code, if you place the following function call right beneath the %WM_COMMAND case statement and before the call to siGetCell(), it will force the grid to 'save' the cell contents to its internal buffer so that it can be retrieved by a siGetCell() call:

Call siGoToCell(hGridWnd,-1,-1)        

Sorry if I caused a fuss!

Fred Harris

Fred Harris

Bert Mercier posted under the clearing grid post his thoughts on a minimal or simple grid, as I did also.  Bert wrote:

'My definition of a simple grid
Number of colums and rows as required in the program
Cell identification to write to or read from
Font to be used
Formating(Left, right and center)'

Everyone might not agree with this (no one may agree with this) but I do myself have one more requirement, and that is that the grid not echo input to the cells, but rather leave that to the developer to determine whether the input validates.  If it does, then let the developer draw the character.  This is how the MSFlexGrid operates and I like it.  With this type of validation it doesn't take the user long to re-think what he/she is doing.

My knowledge of windows subclassing is perhaps not up to the task as I'm at a loss in terms of subclassing the SIGrid control.  I thought the purpose of subclassing a windows control was to obtain the address of its window proceedure so that messages could be intercepted?  What do you end up with if a control has many constituent simpler controls within it as has a grid control?  Wouldn't you need the handles and addresses of the constituent edit controls within it if in fact it was constituted like that?

TechSupport

Hi Fred,

You should definately send your ideas to Chris Bristow because I am sure that he is your best bet for resolving the issue. A month or so ago I did subclass an siGrid in order to trap some stuff (the thread in this forum is titled "Arrrrrgh" by JR Heathcoat - he was having trouble intercepting the right mouse button, I think....). Nevertheless, it was my experience that SIGrid is not an array of textboxes but rather one textbox that gets reused whenever a cell gets focus. When a cell gets focus the textbox is moved to the cell and covers it. I expect that the text is then simply placed into the textbox. I can't remember if Chris Bristow made changes to the DLL recently but I seem to remember something about a change to allow subclassing the textbox easier without a crash.

.... like I say, Chris is you best bet. He could probably make the modifications for you easily rather than us resorting to slimy hacks to get the job done. :)

Fred Harris

Yep!

    That adds up.  The one type, I believe siSelectedRowCol has a member HwndEdit which kept coming up with the same exact hwnd for every cell to which focus was set.  I thought I was doing something wrong or the grid wasn't filling out the structure (type) correctly, but that would add up if there is only one text box!  That thought hadn't occurred to me as when I made grids I used an array of text boxes, but for combo boxes I always just moved it into position as Chris apparently is doing with the text box.  Well, I bet I can subclass that edit box and get the behaviour I want, but I'll certainly contact Chris too after I'm done with this war of ripping apart a rather large app and changing grids!  Thanks for the info.

Fred

Haakon Birkeland

Here is the link for the download //www.rvalois.com.br/downloads/free/rvlv/ as Paul explained it is just a single textbox that superimpose the selected cell. With all the messages available you should have no problem intercepting the location and all allowed keystrokes.

Bert

Just relocate the new control class in the libmain to the init and destroy for cleanup, if you decide to include the code in your program
Haakon 8o)