windows程式設計用WM_COPYDATA進行兩程序間傳輸大量資料
阿新 • • 發佈:2019-01-27
現在有個需求需要在兩程序間大量傳遞資料,而在windows程式下兩個程序間進行通訊 可以有多個方法:
1、管道(未命名管道、命名管道)
2、共享記憶體
3、訊息佇列
不過上述實現起來比較麻煩,現在我們來講解如何使用sendMessage來傳輸大量資料。
LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
sendmessage如上所述,可以知道其中wParam 以及lParam兩個引數可以傳遞少量資料,要用來傳遞大量資料,我們只需要把Msg變數指定為WM_COPYDATA就可以了。
其中WM_COPYDATA傳遞的是一個結構體資料為:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;//一個整數,可以用來充當標識
DWORD cbData;//lpData大小
PVOID lpData;//要傳輸的資料
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
為了我們可以在接收端容易處理傳遞的大量資料。我們可以傳輸一個規範化的結構體,然後再賦值給lpData成員變數。
例如我們可以定義一個一般的結構體資料(主要要規劃好結構體的成員變數):
typedef struct __MessageContent { DWORD dwAttribute; BOOL bDisplay; BOOL bTrim; TCHAR lpszText[MAX_PATH]; TCHAR lpszDescribe[MAX_PATH]; TCHAR lpszUrl[MAX_PATH]; TCHAR lpszImage[MAX_PATH]; } MessageContent;
資訊接收方一般要先於資訊傳送方存在,否則資訊傳送方無法找到需要傳送資料的物件。
資訊接收方程式碼 示例:
/* 資訊接收方,並處理資料 */ #include<windows.h> #include<tchar.h> LPCTSTR g_szWindowClassName = __TEXT("ExampleDemo"); LPCTSTR g_szWindowClassTitle = __TEXT("Hello"); typedef struct __MessageContent { DWORD dwAttribute; BOOL bDisplay; BOOL bTrim; TCHAR lpszText[MAX_PATH]; TCHAR lpszDescribe[MAX_PATH]; TCHAR lpszUrl[MAX_PATH]; TCHAR lpszImage[MAX_PATH]; } MessageContent; MessageContent* g_mcMessageContent = NULL; LRESULT CALLBACK HiddenWindowProcess(__in HWND hwnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam); /** * @brief 應用程式主函式 * @param hInstance 模組 * @param cmdLineArgs 命令列引數 */ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLineArgs, _In_ int) { WNDCLASS wcWindowClass = { 0 }; wcWindowClass.style = CS_HREDRAW | CS_VREDRAW; wcWindowClass.lpfnWndProc = HiddenWindowProcess; wcWindowClass.cbClsExtra = 0; wcWindowClass.cbWndExtra = 0; wcWindowClass.hInstance = hInstance; wcWindowClass.hIcon = NULL; wcWindowClass.hCursor = ::LoadCursor(NULL, IDC_ARROW); wcWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcWindowClass.lpszMenuName = NULL; wcWindowClass.lpszClassName = g_szWindowClassName; if (::RegisterClass(&wcWindowClass) == 0) return -1; ::CreateWindow(g_szWindowClassName, g_szWindowClassTitle, WS_OVERLAPPED, 0, 0, 1, 1, NULL, NULL, hInstance, NULL); MSG msg = { 0 }; while (::GetMessage(&msg, NULL, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return -1; } /** * @brief 處理通知視窗訊息 * @param uMsg包含傳送的訊息 */ LRESULT CALLBACK HiddenWindowProcess(__in HWND hwnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam) { switch (uMsg) { case WM_COPYDATA: { COPYDATASTRUCT * cdsMessageDataStruct = (COPYDATASTRUCT*)lParam; if (!cdsMessageDataStruct || sizeof(cdsMessageDataStruct) == 0) return E_FAIL; g_mcMessageContent = (MessageContent *)cdsMessageDataStruct->lpData; MessageBox(NULL, sizeof(*g_mcMessageContent) > 0 ? L"TRUE":L"FALSE",L"Title",MB_OK); ////////////////// //現在可以處理傳過來的資料或者呼叫寫好的函式進行處理。 } break; default: return ::DefWindowProc(hwnd, uMsg, wParam, lParam); } return S_OK; }
資訊傳送方程式碼示例:
/*
資訊傳送方
*/
#include<windows.h>
#include<tchar.h>
typedef struct __MessageContent
{
DWORD dwAttribute;
BOOL bDisplay;
BOOL bTrim;
TCHAR lpszText[MAX_PATH];
TCHAR lpszDescribe[MAX_PATH];
TCHAR lpszUrl[MAX_PATH];
TCHAR lpszImage[MAX_PATH];
} MessageContent;
int WINAPI wWinMain(_In_ HINSTANCE hInstance , _In_opt_ HINSTANCE , _In_ LPWSTR cmdLineArgs , _In_ int)
{
//測試用例,可以從服務端獲取
DWORD dwAttribute = 10;
BOOL isDisplay =FALSE;
BOOL isTrim = FALSE;
LPCTSTR lpszText = _T("熱點");
LPCTSTR lpszDescribe = _T("實時新聞");
LPCTSTR lpszUrl = _T("http://www.baidu.com");
LPCTSTR lpszImage = _T("http://www.nipic.com/topic/show_27085_1.html");
MessageContent messageContent = { 0 };
messageContent.dwAttribute = 10;
messageContent.bDisplay = isDisplay;
messageContent.bTrim = isTrim;
_tcscpy_s(messageContent.lpszText,MAX_PATH,lpszText);
_tcscpy_s(messageContent.lpszDescribe,MAX_PATH,lpszDescribe);
_tcscpy_s(messageContent.lpszUrl,MAX_PATH,lpszUrl);
_tcscpy_s(messageContent.lpszImage,MAX_PATH,lpszImage);
COPYDATASTRUCT toastContentMessage = { 0 };
toastContentMessage.lpData = (PVOID)&messageContent;
toastContentMessage.cbData = sizeof(messageContent);
//需要確定對方(資訊接收方)的視窗名稱與標題
HWND hToastWin = ::FindWindow(__TEXT("ExampleDemo") , __TEXT("Hello"));
if (hToastWin == NULL)
{
return false;
}
::SendMessage(hToastWin , WM_COPYDATA , 0 , (LPARAM)&toastContentMessage);
return 0;
}
使用結構體不僅擴大了傳送資料的量,而且還解決了傳輸資料處理的問題,規範化了傳輸資料的格式。