设置如下:
我有一个.Net Dll,它有一个称为LicenceVerifier的异步方法
方法完成时将触发一个事件。
public class LicenceVerifier
{
private readonly ILicence _licence;
private readonly int _programkey;
public delegate void LicencedCheckedEventHandler(object sender, LicenceVerifierResultArgs args);
public event LicencedCheckedEventHandler LicencedChecked;
public LicenceVerifier(int programKey)
{
_programkey = programKey;
_licence = GetLicensing();
}
public void IsValidLicenceAsync()
{
new Task(() =>
{
LicenceVerifierResult valid = LicenceVerifierResult.NotAvailable;
if (_licence != null)
valid = _licence.IsValid(_programkey);
LicencedChecked(this, new LicenceVerifierResultArgs(valid));
}).Start();
}
在C ++方面,它看起来是这样的:
void __stdcall CheckLicenseAsyncVb(int iPrgKey, int cbAddress)
{
LicenceVerifierCallback^ callback = gcnew LicenceVerifierCallback();
callback->lCallbackAddress = cbAddress;
callback->callbackType = VB;
//.Net object
LicenceVerifier^ licenceVerifier = gcnew LicenceVerifier(iPrgKey);
licenceVerifier->LicencedChecked += gcnew LicenceVerifier::LicencedCheckedEventHandler(callback, &LicenceVerifierCallback::handler);
licenceVerifier->IsValidLicenceAsync();
}
C ++端的处理程序:
public ref class LicenceVerifierCallback
{
public:
CallbackType callbackType;
long lCallbackAddress;
void(*callbackFunction)(int);
void handler(System::Object^ sender, LicenceVerifierResultArgs^ e)
{
if(callbackType == VB)
ExecuteCallbackVb(convertResult(e->Result));
if(callbackType == C)
ExecuteCallbackC(callbackFunction, convertResult(e->Result));
};
int convertResult(LicenceVerifierResult verifierResult)
{
if(verifierResult == LicenceVerifierResult::Available)
return 0;
return 1;
}
void ExecuteCallbackVb(int result)
{
typedef void ( *FUNCPTR) (int iResult);
FUNCPTR callBackFunction;
callBackFunction = (FUNCPTR)lCallbackAddress;
callBackFunction(result);
};
vb6:
Private Sub LicenceCheck_Click()
Call CheckLicenseAsyncVb(20110, AddressOf ResultCallback)
End Sub
Public Declare Sub CheckLicenseAsyncVb Lib "LicensingIntfd.dll" Alias "_CheckLicenseAsyncVb@8" (ByVal prgKey As Long, ByVal address As Long)
Public Sub ResultCallback(ByVal result As Long) '
'MsgBox "I'll be never a friend of vb6: " & result
End Sub
我现在遇到了问题,回调将在workerthread中而不是UI线程中运行,这意味着显示消息框的vb6调用将失败。
我可以简单地在回调方法中写入变量,然后在UI线程中轮询该变量以进行更改。虽然不是很喜欢这个主意。
任何人都有一个更清洁的解决方案的主意,可能是让c ++方面已经在UI线程中执行了回调(如何?)?
任何帮助深表感谢。
最佳答案
这是如何使用隐藏的静态窗口将WM_USER发布到UI线程上,从而在wParam
中传递结果
// VC6
LRESULT CALLBACK RedirectWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
class LicenceVerifierVbCallback
{
LPVOID m_cbAddress;
HWND m_hWnd;
WNDPROC m_pOrigWndProc;
public:
LicenceVerifierVbCallback(LPVOID cbAddress)
{
m_cbAddress = cbAddress;
m_hWnd = CreateWindow("STATIC", NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0);
SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
m_pOrigWndProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)RedirectWndProc);
}
~LicenceVerifierVbCallback()
{
DestroyWindow(m_hWnd);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_USER)
ExecuteCallbackVb((int)wParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void ExecuteCallbackVb(int result)
{
// ToDo: impl
}
void handler(LPVOID sender, LPVOID e)
{
WPARAM wParam = 0; // wParam = convertResult(e->Result)
PostMessage(m_hWnd, WM_USER, wParam, 0);
}
};
LRESULT CALLBACK RedirectWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LicenceVerifierVbCallback *pthis = (LicenceVerifierVbCallback *)GetWindowLong(hwnd, GWL_USERDATA);
if (pthis != NULL)
return pthis->WndProc(hwnd, msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
关于c# - 在UI线程中从C++回调到vb6,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21723670/