我的软件现在如何运作:
我有一个C ++ ATL对象和一个VB6客户端应用程序。 COM对象有一个函数Find
,它搜索数据库并通过回调函数报告匹配。当用户使用其Change事件将文本输入TextBox,传递文本和回调函数的地址时,我从VB6调用Find
函数。回调函数输出与ListBox的匹配,进行DoEvents
调用,并返回一个值,指示搜索是否应该继续。
我想要完成的任务:
当用户在搜索已经运行时更改搜索字段中的文本时,我想取消正在运行的搜索,清空ListBox,然后使用更新后的文本启动一个新文件。
我遇到的问题:
因为在回调函数的DoEvents
调用期间触发了TextBox的Change事件,所以在回调可以返回“取消”代码之前,新搜索会堆叠在第一个上面。当这个新搜索匹配时,它会调用回调,取回取消代码,然后结束,此时将恢复先前的搜索。
如何在自动开始新搜索之前取消旧搜索?
代码:
Private Sub txtFind_Change()
lvResults.ListItems.Clear
m_customer.CancelFind #' Not useful
frmMain.appData.Licfile.Find(txtFind.Text, AddressOf FindCallback, ObjPtr(m_customer))
End Sub
Public Function CancelFind()
If m_bFindRunning Then: m_bCancelFind = True
End Function
Public Function FindCallback(ByVal foundItem As Boolean, _
ByVal finished As Boolean, _
ByVal index As Long) As Long
Dim record As zLicFileRecord
Dim resultstr As String
Dim error As Long
If foundItem Then
frmMain.appData.Licfile.Read(index, record)
RaiseEvent SearchResult(index, record)
DoEvents
Else
If Not finished Then
RaiseEvent SearchProgress(index, frmMain.appData.Licfile.RecordCount)
DoEvents
Else
RaiseEvent SearchFinished
End If
End If
If m_bCancelFind Then
FindCallback = 1
m_bCancelFind = False
End If
End Function
STDMETHODIMP CzLicenseFile::Find(BSTR find,
LONG callbackFunction /* fnFindCallback */,
LONG context,
LONG* win32Error)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CHECK_PTR(win32Error);
if (!callbackFunction)
{
*win32Error = ERROR_NO_CALLBACK_ACTIVE;
RETURN_OK;
}
fnFindCallback pfnCallback = reinterpret_cast<fnFindCallback>(callbackFunction);
try
{
DWORD recordCount;
get_RecordCount(reinterpret_cast<LONG*>(&recordCount));
if (recordCount == static_cast<DWORD>(-1))
{
*win32Error = ERROR_READ_FAULT;
RETURN_OK;
}
QuickMatcher matcher(std::wstring(find, ::SysStringLen(find)));
for (size_t i = static_cast<size_t>(startIndex); i < recordCount; ++i)
{
LicenseFileRecord const& item = m_fileBuf.Get(i);
bool match = matcher.match(item);
if (match)
{
if (pfnCallback)
{
LONG result = pfnCallback(VTRUE, VFALSE, i, context);
if (result != 0)
{
break;
}
}
}
else if (i % 1000 == 0)
{
if (pfnCallback)
{
LONG result = pfnCallback(VFALSE, VFALSE, i, context);
if (result != 0)
{
break;
}
}
}
}
}
catch (AutoWinError const& e)
{
*win32Error = e.error();
RETURN_OK;
}
if (pfnCallback)
{
pfnCallback(VFALSE, VTRUE, -1, context);
}
*win32Error = ERROR_SUCCESS;
RETURN_OK;
}
答案 0 :(得分:1)
我用函数和Timer
对象解决了这个问题。 txtFind_Change
现在调用此函数:
Public Sub StartSearch()
Dim error As Long
lvResults.ListItems.Clear
If Not m_customer Is Nothing Then
If Not m_customer.FindRunning Then
error = frmMain.appData.Licfile.Find(txtFind.Text, AddressOf FindCallback, ObjPtr(m_customer))
Else
m_customer.CancelFind
TimerSearchRestart.Interval = 50
TimerSearchRestart.enabled = True
End If
End If
End Sub