Database Programming Techniques > Postponing Illegal Operations in Grid Events |
During most of the grid events, database and other system operations are still pending, and certain operations are not allowed within these grid events. To circumvent such limitations, you can use the PostMsg method in conjunction with the PostEvent event to postpone operations which are illegal within the grid events. If the PostMsg method is called, the grid will fire the PostEvent event with the MsgId of the corresponding PostMsg invocation after all pending operations are completed. You can then safely perform all desired operations in the PostEvent event.
For example, suppose it is necessary to keep the rows of a Recordset in sorted order based upon a particular column, say Column 2. Whenever a cell in Column 2 is edited, or a new row is added, it is then necessary to Refresh the Data control so the new data will be placed in the correct order in the Recordset. A reasonable approach to this problem is to include a flag variable to determine that a Refresh is needed in the grid's BeforeUpdate event:
Example Title |
Copy Code
|
---|---|
' Global flag variable. Dim refreshNeeded As Boolean Private Sub Form_Load() ' Initialize flag variable. refreshNeeded = False End Sub Private Sub TDBGrid1_BeforeUpdate(Cancel As Integer) refreshNeeded = TDBGrid1.Columns(2).DataChanged Or _ (TDBGrid1.AddNewMode = dbgAddNewPending) End Sub |
A convenient place to perform the Data control Refresh is within the grid's AfterUpdate event. However, it is not possible to perform the Refresh method within the AfterUpdate event because database operations are still pending, and the Refresh method will fail. Instead of performing the Refresh, you can call the PostMsg method with an arbitrary numeric argument (1, in the following example) in the AfterUpdate event. After all pending database operations are completed, the grid will fire the PostEvent event. You can then check for the numeric argument and perform the Refresh operation safely:
Example Title |
Copy Code
|
---|---|
Private Sub TDBGrid1_AfterUpdate() If refreshNeeded Then ' Reset flag variable. refreshNeeded = False ' Post a message with MsgId = 1. TDBGrid1.PostMsg 1 End If End Sub Private Sub TDBGrid1_PostEvent(ByVal MsgId As Integer) Select Case MsgId Case 0 Exit Sub Case 1 Data1.Refresh Case 2 ' Process other postponed operations. End Select End Sub |
The PostMsg and PostEvent combination in the preceding example postpones the Refresh until the PostEvent event—after all pending database operations have completed.
If the PostMsg argument is zero, the grid will fire the PostEvent event with an argument of zero, but all other pending posted events will be discarded. Since refreshing the Data control makes all other posted events irrelevant anyway, the preceding example can be simplified as follows:
Example Title |
Copy Code
|
---|---|
Private Sub TDBGrid1_AfterUpdate() If refreshNeeded Then ' Reset flag variable. refreshNeeded = False ' Post a message with Id = 0. TDBGrid1.PostMsg 0 End If End Sub Private Sub TDBGrid1_PostEvent(ByVal MsgId As Integer) Select Case MsgId Case 0 Data1.Refresh Case 1 ' Process other postponed operations. End Select End Sub |
When the PostMsg method is called with a numeric argument, the grid uses the Windows API function PostMessage to place a message in the Windows message queue. The numeric argument is passed along with it. When the grid retrieves the posted Windows message, it fires the PostEvent event with the numeric argument of the corresponding PostMsg method.
Please note that execution of the Visual Basic DoEvents function will cause the Windows message queue to be processed, thus causing execution of the PostEvent events before the DoEvents returns.