我在Access数据库中有一个表单(Access 2013)。在此表单上是TextBox
,用户可以在其中输入文本。
通过单击按钮,我想对TextBox
中的文本(例如插入文本)进行一些处理。为此,我使用属性
SelStart
中的SelLength
和TextBox
确定将新文本放在何处。
但是不幸的是,两个属性(SelStart
和SelLength
)都是VBA Integer
值,这意味着只要我的TextBox
中的文本长度小于Integer .MaxValue(= 32.767)SelStart
是正确的,但是一旦我超过Integer。MaxValueSelStart
就会跳转zu Integer.MinValue(= -32.768)并从该数字开始计数。因此,如果我的文本长度为40.000,则SelStart
给出-25.535。
是否有任何方法可以获取SelStart
和SelLength
的正确值,而不管字符串的长度如何?也许使用API函数而不是错误的Access属性?
答案 0 :(得分:2)
听起来像是无符号整数。
VBA不支持无符号类型,因此当符号位被置位(对于2字节整数,一旦值超过(2 ^ 15)-1),它突然变为负数。但是,您可以使用基础功能来使用它们。
前一段时间,我已经编写了这些函数以使用无符号整数,您可以使用它将long转换为无符号整数并返回:
Public Function LongToUInt(lIn As Long) As Integer
If lIn >= 2 ^ 16 Then Exit Function 'Overflow, might want to raise an error
If lIn < 0 Then Exit Function 'Unsigned type doesn't support negatives, might want to raise an error
If lIn > (2 ^ 15) - 1 Then 'Set sign bit, then store remainder in an integer
LongToUInt = (-2 ^ 16) + lIn
Else
LongToUInt = lIn
End If
End Function
Public Function UIntToLong(iIn As Integer) As Long
'No checks, an UINT always fits inside a long
If iIn < 0 Then
UIntToLong = iIn + 2 ^ 16
Else
UIntToLong = iIn
End If
End Function
实施它们:
Textbox.SelStart = LongToUInt(40000)
Dim theStart As Long
theStart = UIntToLong(Textbox.SelStart)
如Gustav所指出的,如果值大于(2 ^ 16)-1(无符号2字节整数的最大值),则仍然存在溢出问题
答案 1 :(得分:2)
将此作为单独的答案发布,因为它是完全不同的
您可以将SendMessage
WinAPI函数与EM_GETSEL
常量一起使用,以选择当前活动的控件。
声明:
(由于我们不使用字符串,因此,不管您使用SendMessageA还是SendMessageW,这些声明仅适用于VBA7)
Public Declare Function SendMessage Lib "User32.dll" Alias "SendMessageW" (ByVal hWnd As LongPtr, ByVal Msg As Integer, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Public Declare Function GetFocus Lib "User32.dll" () As LongPtr
Public Const EM_SETSEL As Integer = &HB1
Public Const EM_GETSEL As Integer = &HB0
实施:
Public Sub GetSelection()
Dim StartSel As Long
Dim EndSel As Long
Dim hWnd As LongPtr
hWnd = GetFocus
SendMessage hWnd, EM_GETSEL, VarPtr(StartSel), VarPtr(EndSel)
Debug.Print StartSel
Debug.Print EndSel
End Sub
这将打印当前活动控件的选择。
我已验证,对于选择了第32768个字符的文本框,结果与我的第一个解决方案相同(StartSel = UIntToLong(Control.SelStart)
= True,EndSel = UIntToLong(Control.SelStart + Control.SelLength)
也是如此。
我建议使用该WinAPI解决方案之外的另一种解决方案,因为该解决方案使用当前处于活动状态的控件,并且如果使用了错误的控件,使用外部API调用且没有错误,则不会出现任何错误。
此解决方案确实支持超过2 ^ 16个字符的文本框,但是如果出现这种情况,Access表现得很挑剔,我建议不要对此类大型文本框使用内置的文本框控件。