Been playing with the DataGrid control to see if it could be usable in a project of mine. It's not a bad control, just a bit under-powered.
Caveat: The code and this posting is 99% focused on using the Data Grid without bound data. In other words, how to use the control without having a database to connect to.
This control is unicode aware and has a professional appearance. It can be very useful in many cases as a simple spreadsheet or to display subsets of databases. There are a few drawbacks to using this control.
1. It requires a bound list. Unlike its older counterpart, the DBGrid which could create its own internal collection of data, this control requires a data source. However, if you are connecting to an established DB, then not much to worry about. If you want to display your own custom data (no database), you can still do that via disconnected recordsets. They aren't that difficult, but you lose the advantage of SQL that could be used with a real DB. Here is a good example of using that other grid control: DBGrid, provided by dilettante
2. The multiselect feature is 'simple' vs. 'extended'. You can't use the shift key to select a range of rows
3. It has no OLE drag/drop feature.
4. The scrollbar does not respond to mouse wheels.
Most of those deficiencies can be overcome.
In the sample project provided, you will find a class: cGridEx. Lot's of comments provided too. This class extends the DataGrid control a bit. It does offer workarounds for extended mutliselection and dragging records from the control. I did not include code to drag stuff into the DataGrid; but you could do that with lots of elbow grease. The mouse wheel is not addressed in the cGridEx class since that workaround requires subclassing, but shown below one way to handle it.
As far as the bound data... The class has an option that can help generate an empty ADO recordset where you fill in the data and assign the recordset to the data grid. Populating a recordset is not rocket science -- use your favorite method. Remember that Excel & CSVs can be loaded into recordsets also (nearly automatically), allowing you to view them via a DataGrid. Also, recordsets can be persisted to file.
To handle the mouse wheel, the cGridEx class has a function to be called from subclassing. Here is an example I am using (not included in the zip file)
1. In a bas module, include this code and the API declarations:
2. After attaching the data grid control to the cGridEx class, subclass the control
3. Remember to unsubclass the control before it is destroyed -- else a crash will occur, if you or VB sets the grid's cGridEx class to nothing before the control is unloaded by VB.
Edited: For a slightly different version, see post #5 below.
Caveat: The code and this posting is 99% focused on using the Data Grid without bound data. In other words, how to use the control without having a database to connect to.
This control is unicode aware and has a professional appearance. It can be very useful in many cases as a simple spreadsheet or to display subsets of databases. There are a few drawbacks to using this control.
1. It requires a bound list. Unlike its older counterpart, the DBGrid which could create its own internal collection of data, this control requires a data source. However, if you are connecting to an established DB, then not much to worry about. If you want to display your own custom data (no database), you can still do that via disconnected recordsets. They aren't that difficult, but you lose the advantage of SQL that could be used with a real DB. Here is a good example of using that other grid control: DBGrid, provided by dilettante
2. The multiselect feature is 'simple' vs. 'extended'. You can't use the shift key to select a range of rows
3. It has no OLE drag/drop feature.
4. The scrollbar does not respond to mouse wheels.
Most of those deficiencies can be overcome.
In the sample project provided, you will find a class: cGridEx. Lot's of comments provided too. This class extends the DataGrid control a bit. It does offer workarounds for extended mutliselection and dragging records from the control. I did not include code to drag stuff into the DataGrid; but you could do that with lots of elbow grease. The mouse wheel is not addressed in the cGridEx class since that workaround requires subclassing, but shown below one way to handle it.
As far as the bound data... The class has an option that can help generate an empty ADO recordset where you fill in the data and assign the recordset to the data grid. Populating a recordset is not rocket science -- use your favorite method. Remember that Excel & CSVs can be loaded into recordsets also (nearly automatically), allowing you to view them via a DataGrid. Also, recordsets can be persisted to file.
To handle the mouse wheel, the cGridEx class has a function to be called from subclassing. Here is an example I am using (not included in the zip file)
1. In a bas module, include this code and the API declarations:
Code:
Private Declare Function DefSubclassProc Lib "comctl32.dll" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowSubclass Lib "comctl32.dll" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
Private Const WM_DESTROY As Long = &H2
Private Const WM_MOUSEWHEEL As Long = &H20A
Private Const WHEEL_DELTA As Long = 120
Public Sub UnSubclassGrid(hWnd As Long, Key As cGridEx)
RemoveWindowSubclass hWnd, AddressOf pvWndProc, ObjPtr(Key)
End Sub
Public Sub SubclassGrid(hWnd As Long, Key As cGridEx)
SetWindowSubclass hWnd, AddressOf pvWndProc, ObjPtr(Key), 0&
End Sub
Private Function pvWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, _
ByVal uIdSubclass As cGridEx, ByVal dwRefData As Long) As Long
If uMsg = WM_MOUSEWHEEL Then
wParam = (wParam And &HFFFF0000) \ &H10000
uIdSubclass.ScrollGrid wParam \ -WHEEL_DELTA
Else
If uMsg = WM_DESTROY Then UnSubclassGrid hWnd, uIdSubclass
pvWndProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
End If
End Function
Code:
' for example, in Form_Load
Set m_GridEx = New cGridEx
m_GridEx.Attach DataGrid1
SubclassGrid DataGrid1.hWnd, m_GridEx
Code:
' for example, in Form_Unload
Set DataGrid1.DataSource = Nothing
UnSubclassGrid DataGrid1.hWnd, m_GridEx