'######################################################
'cFlexGrid类的示例
'这个类是基于MSFlexGrid控件进行扩展增强网格编辑功能
'这些功能的控制在代码里需要三个简单方法进行控制
'.EditCell 开始进行编辑
'.UpdateCell 更新确定的编辑
'######################################################
Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
'/*横向滚动条消息参数
Private Const WM_HSCROLL = &H114
Private Const SB_PAGELEFT = 2
Private Const SB_PAGERIGHT = 3
'/*竖向滚动条消息参数
Private Const WM_VSCROLL = &H115
Private Const SB_PAGEUP = 2
Private Const SB_PAGEDOWN = 3
'/*控件中载的位置
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
'/*内部集合(Collection)
'/*控件、编辑、格式、内容
Private Type ColSettingsType
ctrl As Control
CanEdit As Boolean
sFormat As String
Items As Collection
End Type
'/*定义控件的类型
Private WithEvents mGrid As MSFlexGrid
Private WithEvents mComboBox As
Private WithEvents mTextBox As VB.TextBox
Private mCols() As ColSettingsType
Private mEditCol As Long
Private mEditRow As Long
Private mEditBackcolor As Long
Private mEditForecolor As Long
Private mEditPending As Boolean
Private mLockEvents As Boolean
Private mHighlightedRow As Long
Private mAllowUserResizing As Integer
Public Event AfterEdit(ByVal Row As Long, ByVal Col As Long)
Public Event RequestEdit(ByVal Row As Long, ByVal Col As Long)
Public Event MoveControl(Left As Single, Top As Single, Width As Single, Height As Single)
Public Event ValidateEdit(ByVal Row As Long, ByVal Col As Long, NewData As Variant, Cancel As Boolean)
'返回下一个可编辑的行号
Public Function NextCanEdit() As Integer
Dim I As Integer
For I = 1 To mGrid.Cols
If I > mGrid.Col And mCols(I).CanEdit = True Then
NextCanEdit = I
Exit Function
End If
Next I
'未找到相应结果则返回列
NextCanEdit = mGrid.Col
End Function
'返回上一个可编辑的行号
Public Function PreCanEdit() As Integer
Dim I As Integer
For I = mGrid.Cols To 1 Step -1
If I < mGrid.Col And mCols(I).CanEdit = True Then
PreCanEdit = I
Exit Function
End If
Next I
'未找到相应结果则返回列
PreCanEdit = mGrid.Col
End Function
'/*格式BindColumn 8, TxtEdit, True, "YYYY-MM-DD" , "黑色|白色"
Public Sub BindColumn(Optional ByVal nColumn As Integer, _
Optional ByVal ctrl As Object, _
Optional ByVal CanEdit As Boolean = False, _
Optional ByVal sFormat As String, _
Optional ByVal sListItems As String)
Dim nCount As Integer
Dim sText() As String
'/*定义数组
If UBound(mCols) = 0 Then
ReDim mCols(mGrid.Cols)
ElseIf nColumn > UBound(mCols) Then
ReDim Preserve mCols(nColumn)
End If
'/*当前列加载控件的名称
Set mCols(nColumn).ctrl = ctrl
With mCols(nColumn)
.CanEdit = True
.sFormat = sFormat
Set .Items = New Collection
If Len(sListItems) > 0 Then
sText() = Split(sListItems, "|") '/*按"|"分段
For nCount = LBound(sText) To UBound(sText)
.Items.Add sText(nCount) '/*填充内容
Next nCount
End If
End With
End Sub
Public Function EditCell(ByVal lRow As Long, ByVal lCol As Long) As Boolean
Dim ctlEdit As Control
Dim nCount As Integer
Dim sText As Variant
If lCol < 0 Then Exit Function
If lRow < mGrid.FixedRows Then Exit Function
Set ctlEdit = mCols(lCol).ctrl
If Not ctlEdit Is Nothing Then
Call UpdateCell
RaiseEvent RequestEdit(lRow, lCol)
EditCell = True
With mGrid
mAllowUserResizing = .AllowUserResizing
.AllowUserResizing = flexResizeNone
mEditCol = lCol
mEditRow = lRow
If TypeOf ctlEdit Is ComboBox Then
Set mComboBox = ctlEdit
ctlEdit.Width = .ColWidth(mEditCol) - (.GridLineWidth * Screen.TwipsPerPixelX * 1)
ctlEdit.Left = .ColPos(mEditCol) + .Left + (.GridLineWidth * Screen.TwipsPerPixelX * 1)
ctlEdit.Top = .RowPos(mEditRow) + .Top + (.GridLineWidth * Screen.TwipsPerPixelY * 1)
ctlEdit.Top = ctlEdit.Top + (.RowHeight(mEditRow) - ctlEdit.Height) / 2
RaiseEvent MoveControl(ctlEdit.Left, ctlEdit.Top, ctlEdit.Width, ctlEdit.Height)
If mCols(mEditCol).Items.Count > 0 Then
ctlEdit.Clear
For Each sText In mCols(mEditCol).Items
ctlEdit.AddItem sText
Next sText
End If
For nCount = 0 To ctlEdit.ListCount - 1
If ctlEdit.List(nCount) = mGrid.TextMatrix(mEditRow, mEditCol) Then
ctlEdit.ListIndex = nCount
Exit For
End If
Next nCount
ctlEdit.Visible = True
ctlEdit.SetFocus
End If
If TypeOf ctlEdit Is TextBox Then
Set mTextBox = ctlEdit
ctlEdit.Height = ctlEdit.Height ' - (.GridLineWidth * Screen.TwipsPerPixelY * 1)
ctlEdit.Width = .ColWidth(mEditCol) - (.GridLineWidth * Screen.TwipsPerPixelX * 1)
ctlEdit.Left = .ColPos(mEditCol) + .Left + (.GridLineWidth * Screen.TwipsPerPixelX * 1)
ctlEdit.Top = .RowPos(mEditRow) + .Top + (.GridLineWidth * Screen.TwipsPerPixelY * 1)
ctlEdit.Top = ctlEdit.Top + (.RowHeight(mEditRow) - ctlEdit.Height) / 2
RaiseEvent MoveControl(ctlEdit.Left, ctlEdit.Top, ctlEdit.Width, ctlEdit.Height)
Select Case .ColAlignment(mEditCol)
Case flexAlignRightTop, flexAlignRightCenter, flexAlignRightBottom
ctlEdit.Alignment = vbRightJustify
Case flexAlignCenterTop, flexAlignCenterCenter, flexAlignCenterBottom
ctlEdit.Alignment = vbCenter
Case Else
ctlEdit.Alignment = vbLeftJustify
End Select
ctlEdit.BackColor = mEditBackcolor
ctlEdit.ForeColor = mEditForecolor
ctlEdit.Text = .TextMatrix(mEditRow, mEditCol)
ctlEdit.SelStart = 0
ctlEdit.SelLength = Len(ctlEdit.Text)
ctlEdit.Visible = True
ctlEdit.SetFocus
End If
End With
mEditPending = True
End If
End Function
Public Function UpdateCell() As Boolean
Dim ctlEdit As Control
Dim sValue As String
Dim bCancel As Boolean
UpdateCell = True
If mEditPending Then
Set ctlEdit = mCols(mEditCol).ctrl
If mCols(mEditCol).sFormat <> "" And Len(ctlEdit.Text) > 0 Then
Select Case Mid(mCols(mEditCol).sFormat, 3, 1)
Case "Y" '/*如果是日期类型"YYYY-MM-DD"
If Not IsDate(ctlEdit.Text) Then Exit Function
Case "#" '/*如果是数值类型'#,##0.0000'
If Not IsNumeric(ctlEdit.Text) Then Exit Function
End Select
End If
If mGrid.TextMatrix(mEditRow, mEditCol) <> ctlEdit.Text Then
sValue = ctlEdit.Text
RaiseEvent ValidateEdit(mEditRow, mEditCol, sValue, bCancel)
If bCancel Then
UpdateCell = False
Else
If TypeOf ctlEdit Is ComboBox Then
Set mComboBox = Nothing
End If
If TypeOf ctlEdit Is TextBox Then
Set mTextBox = Nothing
End If
If Len(mCols(mEditCol).sFormat) > 0 Then
sValue = Format$(sValue, mCols(mEditCol).sFormat)
End If
mGrid.TextMatrix(mEditRow, mEditCol) = sValue
ctlEdit.Visible = False
mGrid.Enabled = True
RaiseEvent AfterEdit(mEditRow, mEditCol)
End If
Else
mGrid.Enabled = True
mGrid.SetFocus
ctlEdit.Visible = False
End If
mEditPending = False
mGrid.AllowUserResizing = mAllowUserResizing
End If
End Function
Public Sub ProcessKeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyReturn
If Shift = 0 Then
KeyCode = 0
UpdateCell
End If
Case vbKeyLeft
mGrid.Col = PreCanEdit
If mGrid.ColPos(PreCanEdit) + mGrid.ColWidth(PreCanEdit) < mGrid.Width Then
SendMessage mGrid.hwnd, WM_HSCROLL, SB_PAGELEFT, 0
End If
EditCell mGrid.Row, mGrid.Col
KeyCode = 0
Case vbKeyRight
mGrid.Col = NextCanEdit
If mGrid.ColPos(NextCanEdit) + mGrid.ColWidth(NextCanEdit) > mGrid.Width Then
SendMessage mGrid.hwnd, WM_HSCROLL, SB_PAGERIGHT, 0
End If
EditCell mGrid.Row, mGrid.Col
KeyCode = 0
Case vbKeyUp
If mGrid.Row <= mGrid.FixedRows Then
mGrid.Row = mGrid.FixedRows
Else
mGrid.Row = mGrid.Row - 1
End If
If mGrid.RowPos(mGrid.Row) <= mGrid.RowHeightMin - 50 Then
SendMessage mGrid.hwnd, WM_VSCROLL, SB_PAGEUP, 0
End If
EditCell mGrid.Row, mGrid.Col
KeyCode = 0
Case vbKeyDown
If mGrid.Row = mGrid.Rows - 1 Then
mGrid.Row = mGrid.Rows - 1
Else
mGrid.Row = mGrid.Row + 1
End If
If mGrid.RowPos(mGrid.Row) + mGrid.RowHeightMin >= mGrid.Height - 50 Then
SendMessage mGrid.hwnd, WM_VSCROLL, SB_PAGEDOWN, 0
End If
EditCell mGrid.Row, mGrid.Col
KeyCode = 0
End Select
End Sub
Private Sub mComboBox_KeyDown(KeyCode As Integer, Shift As Integer)
ProcessKeyDown KeyCode, Shift
End Sub
Private Sub mTextBox_KeyDown(KeyCode As Integer, Shift As Integer)
ProcessKeyDown KeyCode, Shift
End Sub
Private Sub mGrid_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyReturn Then
EditCell mGrid.Row, mGrid.Col
End If
End Sub
Private Sub mGrid_MouseDown(KeyCode As Integer, Shift As Integer, X As Single, y As Single)
If (KeyCode = vbLeftButton) Then
EditCell mGrid.MouseRow, mGrid.MouseCol
End If
End Sub
Public Property Let LockEvents(NewValue As Boolean)
mLockEvents = NewValue
End Property
Public Property Get Grid() As Object
Set Grid = mGrid
End Property
Public Property Set Grid(ByVal NewValue As Object)
Set mGrid = NewValue
End Property
Private Sub mComboBox_Validate(Cancel As Boolean)
If Not UpdateCell Then Cancel = True
End Sub
Private Sub mTextBox_Validate(Cancel As Boolean)
If Not UpdateCell Then Cancel = True
End Sub
Private Sub mGrid_Scroll()
mGrid_RowColChange
End Sub
'取内容到文本框等待编辑保证内容最新
Private Sub mGrid_RowColChange()
If Not mLockEvents Then
UpdateCell
End If
End Sub
'/*初始化变量值
Private Sub Class_Initialize()
ReDim mCols(0) '/*定义各列控件,内容等
mEditBackcolor = RGB(0, 191, 255) '/*背景颜色
mEditForecolor = vbWindowText '/*字体颜色
End Sub
[
本帖最后由 zbs112 于 2009-9-1 21:59 编辑 ]