Function IGrid_Refresh(Byval this As IGrid Ptr) As Long
Local iRows,iCols,iCountCells,iIdx,iReturn As Long
Local pGridData As GridData Ptr
Local pGrid As CGrid Ptr
Local pText As ZStr Ptr
Local si As SCROLLINFO
Register i As Long
pGrid=this
#If %Def(%DEBUG)
Print #fp, " Entering IGrid_Refresh()"
#EndIf
pGridData=GetWindowLong(@pGrid.hWndCtrl,0)
iRows=@pGridData.iVisibleRows
iCols=@pGridData.iCols
iCountCells=iRows*iCols
si.cbSize = sizeof(SCROLLINFO)
si.fMask=%SIF_POS
iReturn=GetScrollInfo(@pGrid.hWndCtrl,%SB_VERT,si)
#If %Def(%DEBUG)
Print #fp, " iReturn = " iReturn
Print #fp, " @pGridData.iVisibleRows = " @pGridData.iVisibleRows
Print #fp, " @pGridData.iCols = " @pGridData.iCols
Print #fp, " iCountCells = " iCountCells
Print #fp, " si.nPos = " si.nPos
Print #fp,
Print #fp, " i @pCellHndls[i] @pGridMem[i] @pText @pBackColor[iIdx] @pTextColor[iIdx]"
Print #fp, " =================================================================================="
#EndIf
If iReturn Then
For i=0 To @pGridData.iVisibleRows * @pGridData.iCols - 1
iIdx=iCols*(si.nPos-1)+i
Call SetWindowLong(@pGridData.@pCellHandles[i],0,@pGridData.@pGridMemory[iIdx])
Call SetWindowLong(@pGridData.@pCellHandles[i],8,@pGridData.@pTextColor[iIdx])
Call SetWindowLong(@pGridData.@pCellHandles[i],12,@pGridData.@pBackColor[iIdx])
Call InvalidateRect(@pGridData.@pCellHandles[i], Byval %NULL, %TRUE)
pText=@pGridData.@pGridMemory[i]
#If %Def(%DEBUG)
Print #fp, " " i, @pGridData.@pCellHandles[i], @pGridData.@pGridMemory[i], @pText, Hex$(@pGridData.@pBackColor[iIdx]),Hex$(@pGridData.@pTextColor[iIdx])
#EndIf
Next i
Function=%S_OK
Else
Function=%E_FAIL
End If
#If %Def(%DEBUG)
Print #fp, " Leaving Refresh()"
Print #fp,
#EndIf
End Function
Function IGrid_GetCtrlId(Byval this As IGrid Ptr, Byref iCtrlId As Long) As Long
Local pGridData As GridData Ptr
Local pGrid As CGrid Ptr
pGrid=this
pGridData=GetWindowLong(@pGrid.hWndCtrl,0)
If pGridData Then
iCtrlId=@pGridData.iCtrlId
Function=%S_OK
Else
Function=%E_FAIL
End If
End Function
Function IGrid_GethGrid(Byval this As IGrid Ptr, Byref hGrid As Long) As Long
Local pGrid As CGrid Ptr
pGrid=this
hGrid=@pGrid.hWndCtrl
If hGrid Then
Function=%S_OK
Else
Function=%E_FAIL
End If
End Function
Function IGrid_GethComboBox(Byval this As IGrid Ptr, Byval iCol As Long, Byref hComboBox As Long) As Long
Local pGridData As GridData Ptr
Local pGrid As CGrid Ptr
pGrid=this
pGridData=GetWindowLong(@pGrid.hWndCtrl,0)
If @pGridData.@pCellCtrlTypes[iCol-1]=%GRID_CELL_CTRL_COMBO Then
hComboBox=@pGridData.@pCtrlHdls[iCol-1]
Function=%S_OK
Else
Function=%E_FAIL
End If
End Function
Function IGrid_SetCellAttributes(Byval this As IGrid Ptr, Byval iRow As Long, Byval iCol As Long, Byval iBackColor As Long, Byval iTextColor As Long) As Long
Local pGridData As GridData Ptr
Local iIdx,blnFound As Long
Local pGrid As CGrid Ptr
Register i As Long
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Entering IGrid_SetCellAttributes()"
Print #fp, " this = " this
Print #fp, " iRow = " iRow
Print #fp, " iCol = " iCol
Print #fp, " iBackColor = " Hex$(iBackColor)
Print #fp, " iTextColor = " Hex$(iTextColor)
#EndIf
pGrid=this
pGridData=GetWindowLong(@pGrid.hWndCtrl,0)
If iRow And iCol Then
iIdx=dwIdx(iRow,iCol)
@pGridData.@pTextColor[iIdx] = iTextColor
Else
iIdx=0
End If
#If %Def(%DEBUG)
Print #fp, " @pGridData.iCols = " @pGridData.iCols
Print #fp, " iIdx = " iIdx
Print #fp, " @pGridData.pTextColor = " @pGridData.pTextColor
Print #fp, " @pGridData.@pTextColor[iIdx] = " @pGridData.@pTextColor[iIdx]
Print #fp, " @pGridData.@pCellHandles[iIdx] = " @pGridData.@pCellHandles[iIdx]
Print #fp, " @pGridData.@pCreatedColors[0] = " @pGridData.@pCreatedColors[0]
Print #fp, " @pGridData.@pCreatedBrushes[0] = " @pGridData.@pCreatedBrushes[0]
Print #fp, " i @pGridData.@pCreatedColors[i] iBackColor"
Print #fp, " ============================================================="
#EndIf
'pGridMemory As Dword Ptr 'Will be storing ZStr Ptrs here
'pTextColor As Dword Ptr 'Will be storing RGB values here, i.e., %Red, %Blue, etc
'pBackColor As Dword Ptr 'Will be storing HBRUSHs here. May be zero for default brush.
'pCreatedColors As Dword Ptr 'Colors so far asked for by user per grid instance, e.g., %Red, %Yellow, %Blue, etc.
'pCreatedBrushes As Dword Ptr 'Will be storing created HBRUSHs here. Accumulate them. Numbers such as &HA0556789
For i=1 To @pGridData.@pCreatedColors[0]
#If %Def(%DEBUG)
Print #fp, " " i, Hex$(@pGridData.@pCreatedColors[i]),,,Hex$(iBackColor)
#EndIf
If @pGridData.@pCreatedColors[i]=iBackColor Then
blnFound=%True : Exit For
End If
Next i
If blnFound Then
If iRow And iCol Then
@pGridData.@pBackColor[iIdx] = @pGridData.@pCreatedBrushes[i]
End If
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Got In Where blnFound = %True!"
Print #fp, " @pGridData.@pCreatedBrushes[i] = " Hex$(@pGridData.@pCreatedBrushes[i])
#EndIf
Else
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Got In Where blnFound = %False!"
Print #fp, " @pGridData.@pCreatedBrushes[0] = " @pGridData.@pCreatedBrushes[0] " << Before"
#EndIf
If @pGridData.@pCreatedBrushes[0]<%MAX_COLORS Then ' Test to see if @pGridData.@pCreatedBrushes[0]
Incr @pGridData.@pCreatedBrushes[0] ' is less than 15, i.e., %MAX_COLORS
Incr @pGridData.@pCreatedColors[0]
#If %Def(%DEBUG)
Print #fp, " Will Be Able To Create Another Brush!"
#EndIf
Else
Function=%E_FAIL : Exit Function ' We've already created 15 brushes
#If %Def(%DEBUG)
Print #fp, " Can't Create Another Brush!"
Print #fp, " Leaving IGrid_SetCellAttributes()"
Print #fp,
#EndIf
End If
#If %Def(%DEBUG)
Print #fp, " @pGridData.@pCreatedBrushes[0] = " @pGridData.@pCreatedBrushes[0] " << After"
#EndIf
@pGridData.@pCreatedBrushes[@pGridData.@pCreatedBrushes[0]] = CreateSolidBrush(iBackColor)
@pGridData.@pCreatedColors[@pGridData.@pCreatedColors[0]] = iBackColor
#If %Def(%DEBUG)
Print #fp, " @pGridData.@pCreatedBrushes[@pGridData.@pCreatedBrushes[0]] = " @pGridData.@pCreatedBrushes[@pGridData.@pCreatedBrushes[0]]
#EndIf
If iRow And iCol Then
@pGridData.@pBackColor[iIdx] = @pGridData.@pCreatedBrushes[@pGridData.@pCreatedBrushes[0]]
#If %Def(%DEBUG)
Print #fp, " Have Just Assigned A Newly Created Brush To pBackColor[]"
Print #fp, " @pGridData.@pBackColor[iIdx] = " Hex$(@pGridData.@pBackColor[iIdx])
#EndIf
End If
End If
#If %Def(%DEBUG)
If iRow And iCol Then
Print #fp, " @pGridData.@pTextColor[iIdx] = " Hex$(@pGridData.@pTextColor[iIdx])
End If
Print #fp, " Leaving IGrid_SetCellAttributes()"
Print #fp,
#EndIf
Function=%S_Ok
End Function
Function IGrid_DeleteRow(ByVal this As IGrid Ptr, Byval iRow As Long) As Long
Local iStart,iSize,iCols As Long
Local pGridData As GridData Ptr
Local pGrid As CGrid Ptr
Local hGrid As Dword
Register i As Long
#If %Def(%DEBUG)
Prnt " Entering IGrid_DeleteRow()"
#EndIf
pGrid=this
hGrid=@pGrid.hWndCtrl
pGridData=GetWindowLong(hGrid,0)
#If %Def(%DEBUG)
Prnt " pGrid = " & Str$(pGrid)
Prnt " hGrid = " & Str$(hGrid)
Prnt " pGridData = " & Str$(pGridData)
Prnt " iRow = " & Str$(iRow)
#EndIf
iSize=(@pGridData.iRows-1)*@pGridData.iCols-1
iStart=dwIdx(iRow,1)
iCols=@pGridData.iCols
#If %Def(%DEBUG)
Prnt " iSize = " & Str$(iSize)
Prnt " iStart = " & Str$(iStart)
Prnt " iCols = " & Str$(iCols)
#EndIf
For i=iStart To iSize
@pGridData.@pGridMemory[i] = @pGridData.@pGridMemory[i+iCols]
@pGridData.@pTextColor[i] = @pGridData.@pTextColor[i+iCols]
@pGridData.@pBackColor[i] = @pGridData.@pBackColor[i+iCols]
Next i
iStart=dwIdx(@pGridData.iRows,1)
For i=iStart To iStart+iCols - 1
@pGridData.@pGridMemory[i] = 0
@pGridData.@pTextColor[i] = 0
@pGridData.@pBackColor[i] = 0
Next i
For i=1 To iCols
Call IGrid_SetCellAttributes(this,iRow,i,@pGridData.iSelectionBackColor,@pGridData.iSelectionTextColor)
Next i
#If %Def(%DEBUG)
Prnt " Leaving IGrid_DeleteRow()"
#EndIf
Function=%S_Ok
End Function
Function fnEditSubClass(ByVal hEdit As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Local hCell,hPane,hBase,hGrid As Dword
Local pGridData As GridData Ptr
Local Vtbl,dwPtr As Dword Ptr
Local hr,blnCancel As Long
Local pGrid As CGrid Ptr
Register i As Long
hCell=GetParent(hEdit) : hPane=GetParent(hCell)
hBase=GetParent(hPane) : hGrid=GetParent(hBase)
pGridData=GetWindowLong(hPane,0)
pGrid=@pGridData.pComObj
Select Case As Long wMsg
Case %WM_CHAR
#If %Def(%DEBUG)
Print #fp, " Entering fnEditSubClass"
Print #fp, " Got WM_CHAR Message In fnEditSubClass!"
#EndIf
For i=0 To %MAX_CONNECTIONS-1
If @pGrid.@pISink[i] Then
dwPtr=@pGrid.@pISink[i]
VTbl=@dwPtr
Call Dword @Vtbl[3] Using ptrKeyPress(dwPtr, wParam, lParam, @pGridData.iEditedRow, @pGridData.iEditedCol, blnCancel) To hr
If blnCancel Then
Exit Function
End If
End If
Next i
#If %Def(%DEBUG)
If SUCCEEDED(hr) Then
Print #fp, " Call Dword @Vtbl[3] Using ptrKeyPress() Succeeded!"
End If
#EndIf
If wParam=%VK_RETURN Then
#If %Def(%DEBUG)
Print #fp, " Got WM_CHAR Message %VK_RETURN In fnEditSubClass!"
#EndIf
Call IGrid_FlushData(pGrid)
Call IGrid_Refresh(@pGridData.pComObj)
#If %Def(%DEBUG)
Print #fp, " Leaving fnEditSubClass"
Print #fp,
#EndIf
Exit Function
Else
@pGridData.hCtrlInCell=hEdit
End If
#If %Def(%DEBUG)
Print #fp, " Leaving fnEditSubClass"
Print #fp,
#EndIf
Case %WM_KEYDOWN
#If %Def(%DEBUG)
Print #fp, " Entering fnEditSubClass"
Print #fp, " Got WM_KEYDOWN Message In fnEditSubClass!"
#EndIf
For i=0 To %MAX_CONNECTIONS-1
If @pGrid.@pISink[i] Then
dwPtr=@pGrid.@pISink[i]
VTbl=@dwPtr
Call Dword @Vtbl[4] Using ptrKeyDown(dwPtr, wParam, lParam, @pGridData.iEditedRow, @pGridData.iEditedCol, blnCancel) To hr
If blnCancel Then
Exit Function
End If
End If
Next i
#If %Def(%DEBUG)
If SUCCEEDED(hr) Then
Print #fp, " Call Dword @Vtbl[4] Using ptrKeyDown() Succeeded!"
End If
Print #fp, " Leaving fnEditSubClass"
Print #fp,
#EndIf
Case %WM_PASTE
#If %Def(%DEBUG)
Print #fp, " Got WM_PASTE Message In fnEditSubClass!"
#EndIf
For i=0 To %MAX_CONNECTIONS-1
If @pGrid.@pISink[i] Then
dwPtr=@pGrid.@pISink[i]
VTbl=@dwPtr
Call Dword @Vtbl[7] Using ptrPaste(dwPtr, @pGridData.iEditedCellRow, @pGridData.iEditedRow, @pGridData.iEditedCol) To hr
End If
Next i
#If %Def(%DEBUG)
If SUCCEEDED(hr) Then
Print #fp, " Call Dword @Vtbl[7] Using ptrPaste() Succeeded!"
End If
#EndIf
Case %WM_LBUTTONDBLCLK
#If %Def(%DEBUG)
Print #fp, " Got %WM_LBUTTONDBLCLK Message In fnEditSubClass!"
#EndIf
For i=0 To %MAX_CONNECTIONS-1
If @pGrid.@pISink[i] Then
dwPtr=@pGrid.@pISink[i]
VTbl=@dwPtr
Call Dword @Vtbl[6] Using ptrLButtonDblClk(dwPtr, @pGridData.iEditedCellRow, @pGridData.iEditedRow, @pGridData.iEditedCol) To hr
End If
Next i
#If %Def(%DEBUG)
If SUCCEEDED(hr) Then
Print #fp, " Call Dword @Vtbl[6] Using ptrPaste() Succeeded!"
End If
#EndIf
End Select
Function=CallWindowProc(fnEditWndProc,hEdit,wMsg,wParam,lParam)
End Function
Function EnumGridProc(Byval hWnd As Long, Byval lParam As Dword) As Long
If GetClassLong(hWnd,%GCL_WNDPROC)=lParam Then
#If %Def(%DEBUG)
Print #fp, " Called EnumGridProc() - ", hWnd, lParam
#EndIf
Local pGridData As GridData Ptr
pGridData=GetWindowLong(hWnd,0)
Call IGrid_FlushData(@pGridData.pComObj)
End If
Function=%True
End Function
Function fnCellProc(ByVal hCell As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case As Long wMsg
Case %WM_CREATE
Call SetWindowLong(hCell,0,%NULL)
Function=0 : Exit Function
Case %WM_LBUTTONDOWN
Local iCellBufferPos,iGridMemOffset,iRow,iCol,hr As Long
Local hPane,hBase,hGrid As Dword
Local pGridData As GridData Ptr
Local Vtbl,dwPtr As Dword Ptr
Local si As SCROLLINFO
Local pZStr As ZStr Ptr
Local pGrid As CGrid Ptr
Register i As Long
Register j As Long
#If %Def(%DEBUG)
Print #fp, " Entering fnCellProc - Case WM_LBUTTONDOWN"
#EndIf
hPane=GetParent(hCell)
hBase=GetParent(hPane)
hGrid=GetParent(hBase)
pGridData=GetWindowLong(hPane,0)
Call EnumChildWindows(@pGridData.hParent,CodePtr(EnumGridProc),Byval Codeptr(fnGridProc))
si.cbSize = sizeof(SCROLLINFO)
si.fMask=%SIF_POS
Call GetScrollInfo(hGrid,%SB_VERT,si)
For i=1 To @pGridData.iVisibleRows
For j=1 To @pGridData.iCols
iCellBufferPos = dwIdx(i,j)
If @pGridData.@pCellHandles[iCellBufferPos]=hCell Then
iGridMemOffset = @pGridData.iCols * (si.nPos -1) + iCellBufferPos
pZStr=@pGridData.@pGridMemory[iGridMemOffset]
iRow=i : iCol=j
@pGridData.iEditedCellRow=iRow 'This is the one based row number in the visible grig
@pGridData.iEditedRow=iRow+si.nPos-1 'This is the row in the buffer
@pGridData.iEditedCol=iCol
Exit, Exit
End If
Next j
Next i
#If %Def(%DEBUG)
Print #fp, " iRow = " iRow
Print #fp, " iCol = " iCol
Print #fp, " @pGridData.@pCellCtrlTypes[iCol-1] = " @pGridData.@pCellCtrlTypes[iCol-1]
#EndIf
@pGridData.hCtrlInCell=@pGridData.@pCtrlHdls[iCol-1]
Call SetParent(@pGridData.hCtrlInCell,hCell)
fnEditWndProc=SetWindowLong(@pGridData.hCtrlInCell,%GWL_WNDPROC,CodePtr(fnEditSubClass)) '<<added to fix bad bug
If @pGridData.hFont Then
Call SendMessage(@pGridData.hCtrlInCell,%WM_SETFONT,@pGridData.hFont,%TRUE)
End If
If @pGridData.@pCellCtrlTypes[iCol-1]=%GRID_CELL_CTRL_EDIT Then
Call SetWindowPos(@pGridData.hCtrlInCell,%HWND_TOP,1,0,@pGridData.@pColWidths[iCol-1]-2,@pGridData.iRowHeight,%SWP_SHOWWINDOW)
Call SetWindowText(@pGridData.hCtrlInCell,@pZStr)
Call SetFocus(@pGridData.hCtrlInCell)
End If
If @pGridData.@pCellCtrlTypes[iCol-1]=%GRID_CELL_CTRL_COMBO Then
Call SetWindowPos(@pGridData.hCtrlInCell,%HWND_TOP,1,0,@pGridData.@pColWidths[iCol-1]-2,180,%SWP_SHOWWINDOW)
Call SendMessage(@pGridData.hCtrlInCell,%CB_SETCURSEL,-1,0)
End If
pGrid=@pGridData.pComObj
For i=0 To %MAX_CONNECTIONS-1
If @pGrid.@pISink[i] Then
dwPtr=@pGrid.@pISink[i]
VTbl=@dwPtr
Call Dword @Vtbl[5] Using ptrLButtonDown(dwPtr, @pGridData.iEditedCellRow, @pGridData.iEditedRow, @pGridData.iEditedCol) To hr
#If %Def(%DEBUG)
Print #fp, " hGrid = " hGrid
Print #fp, " dwPtr = " dwPtr
Print #fp, " Vtbl = " Vtbl
#EndIf
End If
Next i
#If %Def(%DEBUG)
Print #fp, " Leaving fnCellProc - Case WM_LBUTTONDOWN" : Print #fp,
#EndIf
Function=0 : Exit Function
Case %WM_PAINT
Local hDC,hFont,hTmp,hBrush,hTmpBr,dwColor As Dword
Local pBuffer As ZStr Ptr
Local ps As PAINTSTRUCT
hDC=BeginPaint(hCell,ps)
pBuffer=GetWindowLong(hCell,0)
hFont=GetWindowLong(hCell,4)
dwColor=GetWindowLong(hCell,8)
hBrush=GetWindowLong(hCell,12)
If hFont Then
hTmp=SelectObject(hDC,hFont)
End If
If dwColor Then
Call SetTextColor(hDC,dwColor)
End If
If hBrush Then
Local rc As RECT
hTmpBr=SelectObject(hDC,hBrush)
Call GetClientRect(hCell,rc)
Call FillRect(hDC,rc,hBrush)
Call SelectObject(hDC,hTmpBr)
End If
Call SetBkMode(hDC,%TRANSPARENT)
Call TextOut(hDC,1,0,@pBuffer,Len(@pBuffer))
If hFont Then
hFont=SelectObject(hDC,hTmp)
End If
Call EndPaint(hCell,ps)
Function=0 : Exit Function
End Select
fnCellProc=DefWindowProc(hCell, wMsg, wParam, lParam)
End Function
Function fnPaneProc(ByVal hPane As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Local si As SCROLLINFO
Register i As Long
Register j As Long
Select Case As Long wMsg
Case %WM_NOTIFY
Local pGridData As GridData Ptr
Local pNotify As HD_NOTIFY Ptr
Local iPos(),iWidth() As Long
Local index,iHt,iRange As Long
Local iCols As Dword
pNotify=lParam
pGridData=GetWindowLong(hPane,0)
Select Case As Long @pNotify.hdr.Code
Case %HDN_TRACK
#If %Def(%DEBUG)
Print #fp, " Entering fnPaneProc() - %HDN_TRACK Case"
#EndIf
If @pGridData.hCtrlInCell Then
Call IGrid_FlushData(@pGridData.pComObj)
Call IGrid_Refresh(@pGridData.pComObj)
End If
If @pGridData.pColWidths Then
@pGridData.@pColWidths[@pNotify.iItem]=@pNotify.@pItem.cxy
End If
iCols=@pGridData.iCols
@pGridData.@pColWidths[iCols]=0
For i=0 To iCols-1
@pGridData.@pColWidths[iCols]=@pGridData.@pColWidths[iCols]+@pGridData.@pColWidths[i]
Next i
si.cbSize = sizeof(SCROLLINFO)
si.fMask = %SIF_RANGE Or %SIF_PAGE Or %SIF_DISABLENOSCROLL
si.nMin = 0 : si.nMax=@pGridData.@pColWidths[iCols]
si.nPage=@pGridData.cx-33
iRange=si.nMax-si.nMin
Call SetScrollInfo(@pGridData.hGrid,%SB_HORZ,si,%TRUE)
If iRange>si.nPage Then 'Original
Call SetWindowPos(@pGridData.hPane,%HWND_TOP,0,0,@pGridData.@pColWidths[iCols],@pGridData.cy,%SWP_NOMOVE Or %SWP_SHOWWINDOW)
Else
Call SetWindowPos(@pGridData.hPane,%HWND_TOP,0,0,@pGridData.@pColWidths[iCols],@pGridData.cy,%SWP_SHOWWINDOW)
End If
Call SetWindowPos(@pGridData.hHeader,%HWND_BOTTOM,0,0,@pGridData.@pColWidths[iCols],@pGridData.iRowHeight,%SWP_NOMOVE Or %SWP_SHOWWINDOW)
#If %Def(%DEBUG)
Print #fp, " si.nMin = " si.nMin
Print #fp, " si.nMax = " si.nMax
Print #fp, " si.nPage = " si.nPage
Print #fp, " @pGridData.@pColWidths[iCols] = " @pGridData.@pColWidths[iCols]
#EndIf
Redim iPos(iCols) As Long
For i=1 To iCols-1
iPos(i)=iPos(i-1)+@pGridData.@pColWidths[i-1]
Next i
If @pGridData.pCellHandles Then
For i=0 To @pGridData.iVisibleRows-1
For j=0 To iCols-1
index=iCols*i+j
iHt=@pGridData.iRowHeight
Call MoveWindow(@pGridData.@pCellHandles[index], iPos(j), iHt+(i*iHt), @pGridData.@pColWidths[j], iHt, %False)
Next j
Next i
Call InvalidateRect(@pGridData.hGrid,Byval %NULL,%TRUE)
End If
Erase iPos()
#If %Def(%DEBUG)
Print #fp, " Leaving fnPaneProc Case" : Print #fp,
#EndIf
Function=0
Exit Function
Case %HDN_ENDTRACK
#If %Def(%DEBUG)
Print #fp, " Entering fnPaneProc() - %END_TRACK Case"
#EndIf
Call InvalidateRect(@pGridData.hGrid,Byval 0,%TRUE)
#If %Def(%DEBUG)
Print #fp, " Leaving %END_TRACK Case"
#EndIf
Function=0 : Exit Function
End Select
Function=0 : Exit Function
End Select
fnPaneProc=DefWindowProc(hPane, wMsg, wParam, lParam)
End Function
Function fnBaseProc(ByVal hBase As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
fnBaseProc=DefWindowProc(hBase, wMsg, wParam, lParam)
End Function
Function fnGridProc_OnCreate(Wea As WndEventArgs) As Long ' This is the procedure which actually creates the grid.
Local iFlds,iHdlCount,iCols,iCtr,iSize As Long ' When this Dll is loaded and DllGetClassObjectImpl() is
Local strParseData(),strFieldData() As BStr ' called, the Sub Initialize() is then called too. This
Local pGridData1,pGridData2 As GridData Ptr ' latter Sub registers (RegisterClassEx()) several Window
Local dwStyle,hButton,hCell,hDC As Dword ' Classes necessary to the grid's creation, such as the
Local pCreateStruct As CREATESTRUCT Ptr ' "Grid", Class, the "Pane" Class, and the "Cell" Class.
Local szText As ZStr*64 ' When a client app holding an IGrid Interface Pointer
Local hdrItem As HDITEM ' makes an IGrid::CreateGrid() member call, the function
Local strSetup As BStr ' IGrid_CreateGrid() is first called, and this latter
Local iPos() As Long ' function makes the CreateWindowEx(..., "Grid", ...)
Register i As Long ' call that triggers invocation of this fnGridProc_OnCreate()
Register j As Long ' WM_CREATE handler, which constructs the grid.
Local rc As RECT
#If %Def(%DEBUG)
Print #fp, " Entering fnGridProc_OnCreate()"
#EndIf
pCreateStruct=Wea.lParam ' A grid consists of many 'child' or subobjects. For example,
Wea.hInst=@pCreateStruct.hInstance ' there is the "Grid" itself, which is something of a "Container"
pGridData1=@pCreateStruct.lpCreateParams ' object. Within the "Grid", and as children of the grid, are
strSetup=@pCreateStruct.@lpszName ' the "Base" object, and the "Pane" object. Then the "Cell"
Call GetClientRect(Wea.hWnd,rc) ' objects become children of the "Pane" object. It is the "Pane"
#If %Def(%DEBUG)
Print #fp, " %WM_USER = " %WM_USER ' object which is involved in horizontal scrolling.
Print #fp, " %WM_APP = " %WM_APP ' It is the header control, i.e., WC_HEADER, which
Print #fp, " hGrid = " Wea.hWnd ' I've used to provide the functionality of resizable
Print #fp, " pGridData1 = " pGridData1 ' grid columns. That control sits atop and becomes a
Print #fp, " Wea.hInstance = " Wea.hInst ' child of the "Pane". Then the "Cell" objects, each
Print #fp, " @pCreateStruct.cx = " @pCreateStruct.cx ' of which are created through a CreateWindowEx() call,
Print #fp, " @pCreateStruct.cy = " @pCreateStruct.cy ' sit underneath the header control, and are also children
Print #fp, " rc.Right = " rc.Right ' of the "Pane". Of course, some of the first real work
Print #fp, " rc.Bottom = " rc.Bottom ' this procedure does is to determine the sizes of things
Print #fp, " @pGridData1.iFontSize = " @pGridData1.iFontSize ' and their locations, given the various parameters sent
Print #fp, " @pGridData1.iFontWeight = " @pGridData1.iFontWeight ' in through the parameter list from the client. After
Print #fp, " @pGridData1.szFontName = " @pGridData1.szFontName ' that is the necessity of dealing with the setup string
Print #fp, " strSetup = " strSetup ' sent in from the client, which contains all the column info.
#EndIf
iCols=ParseCount(strSetup,",")
#If %Def(%DEBUG)
Print #fp, " iCols = " iCols
Print #fp, " @pGridData1.iRows = " @pGridData1.iRows
Print #fp, " @pGridData1.iCols = " @pGridData1.iCols
Print #fp, " @pGridData1.iRowHeight = " @pGridData1.iRowHeight
#EndIf
If iCols<>@pGridData1.iCols Then ' In terms of the strSetup parameter, that is a BSTR passed in from the client
Function=-1 : Exit Function ' with a comma delimited format that contains the initial pixel width of the
End If ' column, the text to display in the header control, the type of control to
pGridData2=GlobalAlloc(%GPTR,sizeof(GridData)) ' be set in the cell when a user clicks on a cell (at this time only edit controls
If pGridData2=0 Then ' or combo boxes), and whether the text in the header control is left oriented,
Function=-1 : Exit Function ' right oriented, or centered (<:>:^). The ':' symbol further is used as the
End If ' delimiter of this information within each comma delimited substring. Note
Call SetWindowLong(Wea.hWnd,0,pGridData2) ' that PowerBASIC's ParseCount / Parse statement functionality is used to seperate
@pGridData2.iCtrlID=@pCreateStruct.hMenu ' the substrings and get at this data. The Parse Statement was broken in PBWin 10,
@pGridData2.cx=@pCreateStruct.cx ' then fixed in update release 10.01. In PBWin 10.02 it also worked, but was again
@pGridData2.cy=@pCreateStruct.cy ' broken in PBWin 10.03. This latter situation only applies to unicode builds
@pGridData2.iCols=iCols ' and on Win 2000/XP machines (for whatever reason). Therefore, I would not
@pGridData2.iRows=@pGridData1.iRows ' recommend using this grid if it is going to be built with PBWin 10.03.
@pGridData2.iRowHeight=@pGridData1.iRowHeight
@pGridData2.iVisibleRows=Fix((rc.Bottom-@pGridData1.iRowHeight)/@pGridData1.iRowHeight)
If @pGridData1.iRows>@pGridData2.iVisibleRows Then 'DANGER! ADDITION!!!
@pGridData2.iRows=@pGridData1.iRows
Else
@pGridData2.iRows=@pGridData2.iVisibleRows+1
@pGridData1.iRows=@pGridData2.iVisibleRows+1
End If 'END DANGER ADDITION
@pGridData2.iPaneHeight=(@pGridData2.iVisibleRows+1)*@pGridData1.iRowHeight
@pGridData2.hGrid=Wea.hWnd
@pGridData2.hParent=GetParent(Wea.hWnd)
@pGridData1.iVisibleRows=@pGridData2.iVisibleRows
#If %Def(%DEBUG)
Print #fp, " pGridData2 = " pGridData2
Print #fp, " @pGridData2.hParent = " @pGridData2.hParent
Print #fp, " @pGridData2.iCtrlID = " @pGridData2.iCtrlID
Print #fp, " @pGridData2.iPaneHeight = " @pGridData2.iPaneHeight
Print #fp, " @pCreateStruct.cy = " @pCreateStruct.cy
Print #fp, " @pGridData1.iRowHeight = " @pGridData1.iRowHeight
Print #fp, " @pGridData2.iVisibleRows = " @pGridData2.iVisibleRows
Print #fp, " @pGridData2.iRows = " @pGridData2.iRows
#EndIf
Redim strParseData(iCols) As BStr
Parse strSetup,strParseData(),"," ' Here is the statement that seems to cause memory corruption on 2000/XP.
@pGridData2.pColWidths=GlobalAlloc(%GPTR,(iCols+1)*%SIZEOF_PTR) 'when 10.03 compiler is used.
If @pGridData2.pColWidths=0 Then
Goto CleanUp
End If
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pColWidths = " @pGridData2.pColWidths
Print #fp,
Print #fp, " i strParseData(i) "
Print #fp, " ============================="
For i=0 To iCols-1
Print #fp, " " i, strParseData(i)
Next i
Print #fp,
#EndIf
@pGridData2.hBase=CreateWindowEx(0,"Base","",%WS_CHILD Or %WS_VISIBLE,0,0,0,0,Wea.hWnd,1499,Wea.hInst,Byval 0) 'Create Base
dwStyle=%WS_CHILD Or %WS_BORDER Or %WS_VISIBLE Or %HDS_HOTTRACK Or %HDS_HORZ
@pGridData2.hPane=CreateWindowEx(0,"Pane","",%WS_CHILD Or %WS_VISIBLE,0,0,0,0,@pGridData2.hBase,%ID_PANE,Wea.hInst,Byval 0) 'Create Pane
@pGridData2.hHeader=CreateWindowEx(0,WC_HEADER,"",dwStyle,0,0,0,0,@pGridData2.hPane,%ID_HEADER,Wea.hInst,Byval 0) 'Create Header Control
Call SetWindowLong(@pGridData2.hPane,0,pGridData2)
@pGridData2.pCellCtrlTypes=GlobalAlloc(%GPTR,(iCols)*%SIZEOF_PTR) 'Set up ptr to buffer in GridData for holding control types for column, i.e.,
If @pGridData2.pCellCtrlTypes=0 Then 'edit controls, none, combo boxes, etc.
Goto CleanUp
End If
@pGridData2.pCtrlHdls=GlobalAlloc(%GPTR,(iCols)*%SIZEOF_PTR)
If @pGridData2.pCtrlHdls=0 Then
Goto CleanUp
End If
#If %Def(%DEBUG)
Print #fp, " @pGridData2.hBase = " @pGridData2.hBase
Print #fp, " @pGridData2.hPane = " @pGridData2.hPane
Print #fp, " @pGridData2.hHeader = " @pGridData2.hHeader
Print #fp, " @pGridData2.pCellCtrlTypes = " @pGridData2.pCellCtrlTypes
Print #fp,
Print #fp, " i @pColWidths[i] iPos(i) szText strFieldData(2), strFieldData(3) Cell Ctrl Type"
Print #fp, " ==========================================================================================================================="
#EndIf
hdrItem.mask=%HDI_FORMAT Or %HDI_WIDTH Or %HDI_TEXT
Redim iPos(iCols) As Long
For i=0 To iCols-1 ' This rather complex code sets up the header control using the data parsed
iFlds=ParseCount(strParseData(i),":") ' from the setup string, such as grid column text strings, initial widths,
Redim strFieldData(iFlds-1) ' justification of text in header control, etc. Note that each of the sub-
Parse strParseData(i), strFieldData(), ":" ' strings parsed from the comma delimited setup string need to be further parsed
@pGridData2.@pColWidths[i]=Val(strFieldData(0)) ' for the sub - sub-strings within them that use the ':' char as a delimiter.
@pGridData2.@pColWidths[iCols]=@pGridData2.@pColWidths[iCols]+@pGridData2.@pColWidths[i]
hdrItem.cxy=@pGridData2.@pColWidths[i]
szText=strFieldData(1)
hdrItem.pszText=Varptr(szText) : hdrItem.cchTextMax=Len(szText)
If strFieldData(2)="<" Then
hdrItem.fmt= %HDF_LEFT
Else
If strFieldData(2)="^" Then
hdrItem.fmt=%HDF_CENTER
Else
hdrItem.fmt=%HDF_RIGHT
End If
End If
hdrItem.fmt=hdrItem.fmt Or %HDF_STRING
Call Header_InsertItem(@pGridData2.hHeader,i,Varptr(hdrItem))
'Call Header_InsertItem(@pGridData2.hHeader,i,hdrItem)
If i Then
iPos(i)=iPos(i-1)+@pGridData2.@pColWidths[i-1]
End If
Select Case strFieldData(3)
Case "none"
@pGridData2.@pCellCtrlTypes[i]=0
Case "edit"
@pGridData2.@pCellCtrlTypes[i]=1
Case "combo"
@pGridData2.@pCellCtrlTypes[i]=2
Case "check"
@pGridData2.@pCellCtrlTypes[i]=3
End Select
#If %Def(%DEBUG)
Print #fp, " " i, @pGridData2.@pColWidths[i], iPos(i), szText, strFieldData(2), ,strFieldData(3), , @pGridData2.@pCellCtrlTypes[i]
#EndIf
Erase strFieldData()
Next i
#If %Def(%DEBUG)
Print #fp,
Print #fp, " i @pGridData2.@pCtrlHdls[i]"
Print #fp, " ==================================="
#EndIf
Local blnEditCreated,iCboCtr As Long '@pGridData2.hCtrlInCell is equal to the hWnd of the edit control
For i=0 To iCols-1 'created in fnGridProc_OnCreate(). Also, GridData::pCtrlHdls[i]
If @pGridData2.@pCellCtrlTypes[i]=%GRID_CELL_CTRL_EDIT Then 'hold the handles of the various edit or combo box controls.
If blnEditCreated=%False Then 'fnEditWndProc is the original edit control WndProc().
dwStyle=%WS_CHILD Or %ES_AUTOHSCROLL
@pGridData2.@pCtrlHdls[i]=CreateWindow("edit","",dwStyle,0,0,0,0,Wea.hWnd,%IDC_EDIT,Wea.hInst,ByVal 0)
@pGridData2.hCtrlInCell=@pGridData2.@pCtrlHdls[i]
blnEditCreated=%True
Else
@pGridData2.@pCtrlHdls[i]=@pGridData2.hCtrlInCell
End If
End If
If @pGridData2.@pCellCtrlTypes[i]=%GRID_CELL_CTRL_COMBO Then
dwStyle=%WS_CHILD Or %CBS_DROPDOWNLIST Or %WS_VSCROLL 'Or %CBS_NOINTEGRALHEIGHT
@pGridData2.@pCtrlHdls[i]=CreateWindow("combobox","",dwStyle,0,0,0,0,Wea.hWnd,%IDC_COMBO+iCboCtr,Wea.hInst,ByVal 0)
Incr iCboCtr
End If
#If %Def(%DEBUG)
Print #fp, " " i, @pGridData2.@pCtrlHdls[i]
#EndIf
Next i
@pGridData2.hCtrlInCell=0
#If %Def(%DEBUG)
Print #fp,
Print #fp, " @pGridData2.@pColWidths[iCols] = " @pGridData2.@pColWidths[iCols]
Print #fp,
#EndIf
Call MoveWindow(@pGridData2.hBase,12,0,rc.right-12,@pGridData2.iPaneHeight,%FALSE)
Call MoveWindow(@pGridData2.hPane,0,0,@pGridData2.@pColWidths[iCols],@pGridData2.iPaneHeight,%FALSE) 'Size Pane
Call MoveWindow(@pGridData2.hHeader,0,0,@pGridData2.@pColWidths[iCols],@pGridData2.iRowHeight,%TRUE) 'Size Header
'Make Verticle Buttons that go at far left in the grid, and which can be clicked to select a grid row
@pGridData2.pVButtons=GlobalAlloc(%GPTR,(@pGridData2.iVisibleRows+1)*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pVButtons = " @pGridData2.pVButtons
Print #fp,
Print #fp, " i @pGridData2.@pVButtons[i] "
Print #fp, " ====================================="
#EndIf
If @pGridData2.pVButtons Then
For i=0 To @pGridData2.iVisibleRows
@pGridData2.@pVButtons[i]=CreateWindow("button","",%WS_CHILD Or %WS_VISIBLE Or %BS_FLAT,0,@pGridData2.iRowHeight*i,12,@pGridData2.iRowHeight,Wea.hWnd,20000+i,Wea.hInst,Byval 0)
#If %Def(%DEBUG)
Print #fp, " " i, @pGridData2.@pVButtons[i]
#EndIf
Next i
Else
Goto CleanUp
End If
'Try To Create Font ' ANSI_CHARSET '%OEM_CHARSET
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Now Gonna Try To Create Font..."
Print #fp, " @pGridData1.szFontName = " @pGridData1.szFontName
#EndIf
If @pGridData1.szFontName<>"" Then
hDC=GetDC(Wea.hWnd)
@pGridData2.hFont=CreateFont _
( _
-1*(@pGridData1.iFontSize*GetDeviceCaps(hDC,%LOGPIXELSY))/72, _
0, _
0, _
0, _
@pGridData1.iFontWeight, _
0, _
0, _
0, _
%ANSI_CHARSET, _
0, _
0, _
%DEFAULT_QUALITY, _
0, _
@pGridData1.szFontName _
)
Call ReleaseDC(Wea.hWnd,hDC)
End If
#If %Def(%DEBUG)
Print #fp, " @pGridData2.hFont = " @pGridData2.hFont
#EndIf
'Try To Make Grid Cells, i.e., "Cell" Class
iHdlCount=@pGridData2.iCols*@pGridData2.iVisibleRows
@pGridData2.pCellHandles=GlobalAlloc(%GPTR, iHdlCount * %SIZEOF_HANDLE)
If @pGridData2.pCellHandles Then
dwStyle=%WS_CHILD Or %WS_VISIBLE Or %WS_BORDER
#If %Def(%DEBUG)
Print #fp,
Print #fp, " i j iPos(j) yLoc hCell"
Print #fp, " ============================================================="
#EndIf
For i=0 To @pGridData2.iVisibleRows-1
For j=0 To @pGridData2.iCols-1
hCell=CreateWindowEx _
( _
0, _
"Cell", _
"", _
dwStyle, _
iPos(j), _
@pGridData2.iRowHeight+(i*@pGridData2.iRowHeight), _
@pGridData2.@pColWidths[j], _
@pGridData2.iRowHeight, _
@pGridData2.hPane, _
%ID_CELL+iCtr, _
Wea.hInst, _
Byval 0 _
)
@pGridData2.@pCellHandles[iCtr]=hCell
Call SetWindowLong(hCell,4,@pGridData2.hFont)
#If %Def(%DEBUG)
Print #fp, " " i, j, iPos(j), @pGridData2.iRowHeight+(i*@pGridData2.iRowHeight), hCell
#EndIf
Incr iCtr
Next j
Next i
'Create Grid Memory
iSize = @pGridData2.iCols * @pGridData2.iRows
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Now Will Try To Create Grid Row Memory!"
Print #fp,
Print #fp, " iSize = " iSize
#EndIf
@pGridData2.pGridMemory=GlobalAlloc(%GPTR,iSize*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pGridMemory = " @pGridData2.pGridMemory
#EndIf
@pGridData2.pTextColor=GlobalAlloc(%GPTR,iSize*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pTextColor = " @pGridData2.pTextColor
#EndIf
If @pGridData2.pTextColor=0 Then
Goto Cleanup
End If
@pGridData2.pBackColor=GlobalAlloc(%GPTR,iSize*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pBackColor = " @pGridData2.pBackColor
#EndIf
If @pGridData2.pBackColor=0 Then
Goto Cleanup
End If
@pGridData2.pCreatedColors=GlobalAlloc(%GPTR,(%MAX_COLORS+1)*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pCreatedColors = " @pGridData2.pCreatedColors
#EndIf
If @pGridData2.pCreatedColors=0 Then
Goto Cleanup
End If
@pGridData2.pCreatedBrushes=GlobalAlloc(%GPTR,(%MAX_COLORS+1)*%SIZEOF_PTR)
#If %Def(%DEBUG)
Print #fp, " @pGridData2.pCreatedBrushes = " @pGridData2.pCreatedBrushes
#EndIf
If @pGridData2.pCreatedBrushes=0 Then
Goto Cleanup
End If
Else
Goto CleanUp
End If
Erase strParseData()
Erase iPos()
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Leaving %WM_CREATE Case" : Print #fp,
#EndIf
Function=0 : Exit Function
CleanUp:
If @pGridData2.pColWidths Then
Call GlobalFree(@pGridData2.pColWidths)
End If
If @pGridData2.pCellCtrlTypes Then
Call GlobalFree(@pGridData2.pCellCtrlTypes)
End If
If @pGridData2.pCtrlHdls Then
Call GlobalFree(@pGridData2.pCtrlHdls)
End If
If @pGridData2.pVButtons Then
Call GlobalFree(@pGridData2.pVButtons)
End If
If @pGridData2.pCellHandles Then
Call GlobalFree(@pGridData2.pCellHandles)
End If
If @pGridData2.pGridMemory Then
Call GlobalFree(@pGridData2.pGridMemory)
End If
If @pGridData2.pTextColor Then
Call GlobalFree(@pGridData2.pTextColor)
End If
If @pGridData2.pBackColor Then
Call GlobalFree(@pGridData2.pBackColor)
End If
If @pGridData2.pCreatedColors Then
Call GlobalFree(@pGridData2.pCreatedColors)
End If
If @pGridData2.pCreatedBrushes Then
Call GlobalFree(@pGridData2.pCreatedBrushes)
End If
If pGridData2 Then
Call GlobalFree(pGridData2)
End If
#If %Def(%DEBUG)
Print #fp,
Print #fp, " Leaving %WM_CREATE Case" : Print #fp,
#EndIf
Function=-1
End Function
continued ...