2016-03-11 34 views
1

我試圖從VBA向C++應用程序發送消息。我在下面的作品中,信息被髮送到我的消息映射(Yay!)。但是,我無法傳遞任何數據。我已經嘗試了幾種不同的方法,就像我的代碼中看到的那樣,但他們中沒有一個似乎在跨越LPARAM。在VBA中爲LParam發送LPARAM變量

任何幫助,將不勝感激!

VBA:

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, _ 
ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ 
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long 

Private Const WM_APP = &H803C& 

Sub Test() 
    Call SetPartNumber(123) 
End Sub 

Sub SetPartNumber(partNumber As Double) 
    Dim result As Long, hwnd As Long 

    partNumber2 = VarPtr(partNumber) 
    hwnd = FindWindow(vbNullString, "Data Collector") 

    result = PostMessage(hwnd, WM_APP, 0, partNumber2) ' attempt using a var pointer 
    result = PostMessage(hwnd, WM_APP, 0, partNumber) ' attempt using just the variable 
End Sub 

我的C++數據收集器:

BEGIN_MESSAGE_MAP(CCellDlg, CDialogEx) 
    ON_MESSAGE(WM_APP + 60, PleasePleaseWork) 
END_MESSAGE_MAP() 

LRESULT CCellDlg::PleasePleaseWork(WPARAM wParam, LPARAM lParam) 
{ 
    double partNumber = LOWORD(lParam); 
    double partNumber1 = HIWORD(lParam); 
    double partNumber2 = wParam; 
    double partNumber3 = lParam; 

    AfxMessageBox("Yay!"); 

    return 0; 
} 
+1

指針是在它們僅發起的過程有效,所以通過'VarPtr'跨進程邊界是沒有意義的。如果您從64位進程發送到另一個64位進程,傳遞「Double」值可能有用。取一個double的下半部分或上半部分仍然沒有意義:這不是浮點值的編碼方式。 – IInspectable

+1

WM_COPYDATA可能是一個更好的選擇,因爲操作系統會爲您處理跨越邊界的複製問題。 –

+0

我很擔心跨不同進程發送內存地址,而你說的話有意義......甚至當我意識到我正在使用PostMessage而不是SendMessage清除內存時更是如此。與SendMessage配對的WM_COPYDATA似乎有訣竅。謝謝! – CassieD

回答

0

鑑於上述意見的建議,我轉而使用WM_COPYDATA。我現在可以將消息發送到另一個應用程序,並且可以傳輸數據。謝謝大家!

VBA

Type COPYDATASTRUCT 
    dwData As Long 
    cbData As Long 
    lpData As Long 
End Type 

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ 
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long 

Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ 
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long 

Private Const WM_COPYDATA = &H4A& 

Sub Test() 
    Call SetPartNumber("123456") 
End Sub 

Sub SetPartNumber(partNumber As String) 
    Dim result As Long, hwnd As Long 

    hwnd = FindWindow(vbNullString, "Data Collector") 

    If hwnd <> 0 Then 
     Dim cds As COPYDATASTRUCT 

     cds.dwData = 0 
     cds.cbData = Len(partNumber) * 2 + 2 
     cds.lpData = StrPtr(partNumber) 

     result = SendMessage(hwnd, WM_COPYDATA, 0, cds) 
    End If 
End Sub 

C++

BEGIN_MESSAGE_MAP(CCell7Dlg, CDialogEx) 
    ON_WM_COPYDATA() 
END_MESSAGE_MAP() 

BOOL CCell7Dlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 
{ 
    // Gathering the data this way did not work for my c++ project 
    // CString recievedText = (LPCSTR)(pCopyDataStruct->lpData); 

    // I have to piece the data together like this instead 
    char* recievedText = (char*) pCopyDataStruct->lpData; 

    double size = pCopyDataStruct->cbData; 

    string gatheredText; 
    for (int i = 0; i < size; ++i) 
    { 
    if (i % 2 == 0) 
     gatheredText+= recievedText; 

    *recievedText++; 
    } 
    return CDialogEx::OnCopyData(pWnd, pCopyDataStruct); 
}