作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下设置:
我有一个 .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
我现在遇到了问题,回调将在工作线程而不是 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/
我是一名优秀的程序员,十分优秀!