簡體   English   中英

從本機C DLL調用回調到VB6

[英]Invoke callback into VB6 from native C DLL

我正在嘗試獲取本機C函數來調用VB6應用程序中的回調。 在VB中,代碼如下所示:

Private Declare Sub StartUp Lib "library.dll" (ByVal cbAddress As Long)

Public Sub MySub
    Call StartUp(AddressOf MyCallback)
End Sub

Public Sub MyCallback(ByVal str As String)
' Use str in UI
End Sub

當我從VB6 IDE運行此程序時,一切正常:調用回調,並且可以使用str參數沒有問題。 但是,當我將VB6應用程序編譯為exe時,調用回調時該應用程序將崩潰。 從我在谷歌搜索中可以看出,這似乎是某種線程問題。 有人建議使用Win32 SendMessage避免這種線程問題。 我不太清楚該怎么做。 我會在回調中調用SendMessage嗎? 我如何在主線程上收到此消息? 另外,如何將字符串傳遞給SendMessage?

編輯:我剛剛發現: Vb6應用程序可以在IDE中工作,但可執行文件崩潰

但是,我最初的問題仍然存在。

Edit2:我也應該包括在C代碼中。 這是定義和調用回調的方式:

typedef void (__stdcall *FUNCPTR)(BSTR);
int wslen = MultiByteToWideChar(CP_ACP, 0, cstr, strlen(cstr), 0, 0);
BSTR bstr = SysAllocStringLen(0, wslen);
MultiByteToWideChar(CP_ACP, 0, cstr, strlen(cstr), bstr, wslen);
((FUNCPTR) _cbAddress)(bstr);
SysFreeString(bstr);

同樣,當從IDE調用時,這很好用...

顯然,最理想的選擇是確保回調始終在VB應用程序的主線程上發生。 否則,您將不得不對應用程序中的窗口使用SendMessage()來利用Window自身在Windows之間的編組能力。

以前,我編寫了一個VB應用程序,該應用程序從DLL進行了回調,該DLL用於與遠程控件集成。 但是DLL使用了另一個線程來與硬件集成。 在我的回調中,我使用帶有WM_COPYDATA SendMessage()將數據編組到主VB線程,該線程由子類化代碼拾取。

當然,由於您正在編寫C DLL,而您只是在傳遞回ASCII文本,因此您可以跳過幾個步驟,而不必編寫回調過程或具有子類代碼。 只需使用SetWindowText() API調用將文本直接寫到TextBox 確保在始終加載的表單上使用Visible = False創建此TextBox 然后,您只需要使用以下代碼:

BOOL WINAPI SetWindowText(
  _In_      HWND hWnd,
  _In_opt_  LPCTSTR lpString
);

HWND m_hWndTextBox

void StartUp(HWND hWndTextBox)
{
    m_hWndTextBox = hWndTextBox;
    // other stuff
}

void Callback(char *cstr) {
    SetWindowText(m_hWndTextBox, cstr);
}

和VB代碼:

' Form "Form1" with text box "Text1".

Private Declare Sub StartUp Lib "library.dll" (ByVal hWndTextBox As Long)

Public Sub MySub
    Call StartUp(Text1.hWnd)
End Sub

Private Sub Text1_Change()
    DoStuffWithDLLUpdateString Text1.Text
End Sub

而且,您甚至不必將字符串轉換為BSTR-VB會為您執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM