如何使用WM_COPYDATA使用JNI在Java程序之间发送字符串?

时间:2016-07-22 12:57:18

标签: c winapi java-native-interface

我想使用Windows'在Java程序之间发送一个简单的字符串值。使用JNI共享库使用本机C代码进行数据复制(WM_COPYDATA)。本质上,一个想要启动通信的Java程序可以调用一个本机方法,该方法将设置一个仅消息窗口,另一个Java程序可以通过调用本机方法(存在于同一共享库中)来获取消息。

我知道我没有消息循环而且我不知道如何实现这一点。我已经在网上看过使用WndProc回调函数的示例,但我不知道这是否是一个合适的方法,因为这是一个仅限消息的窗口(即自从我的基于Java应用程序控制台以来没有可见的UI 。

任何有关代码的帮助都将不胜感激。

设置:

JNIEXPORT jint JNICALL Java_WindowsIPC_openDataCopy
  (JNIEnv * env, jobject obj, jstring message) {

 MSG msg;
 WNDCLASS WndClass;
 memset(&WndClass, 0, sizeof(WndClass));
 WndClass.lpfnWndProc = &DefWindowProc;
 WndClass.lpszClassName = L"Class";
 WndClass.hInstance = GetModuleHandle(NULL);

 HWND hwnd;
 LPCTSTR messageString = "A message";

 if (!RegisterClass(&WndClass)) {
   printf("failed to register class: %d\n", GetLastError());
   return -1;
 }

 hwnd = CreateWindowEx(0, WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,  HWND_MESSAGE, NULL, NULL, NULL);
 if (hwnd == NULL) {
   printf("Window Creation failed: %d\n", GetLastError());
   return -1;
 }

 while (GetMessage (&msg, NULL, 0, 0) > 0) {
      TranslateMessage (&msg);
      DispatchMessage (&msg);
 }

  return 0; // success
}

尝试获取消息:

JNIEXPORT jint JNICALL Java_WindowsIPC_getDataCopyMessage
  (JNIEnv * env, jobject obj) {

 HWND hwnd;
 hwnd = FindWindowEx (
    HWND_MESSAGE,
    0,
    0,
    0
 );

 LPCTSTR messageString = "A message";
 COPYDATASTRUCT cds;

 cds.dwData = 1;
 cds.cbData = sizeof(char) * (strlen(messageString) + 1);
 cds.lpData = (char*)messageString;

 if (hwnd == NULL) {
   printf("Couldnt find window: %d\n", GetLastError());
   return -1;
 } else SendMessage(hwnd, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)(LPVOID)&cds);

 LPARAM lParam;
 COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
 LPCTSTR lpszString = (LPCTSTR)(pcds->lpData);
 printf("%s\n", lpszString);

 return 0; // success
}

1 个答案:

答案 0 :(得分:1)

您并非要求FindWindowEx()找到HWND_MESSAGE创建的特定 Java_WindowsIPC_openDataCopy()窗口。您要求它找到第一个可用的 HWND_MESSAGE窗口,该窗口可能属于任何人。您需要在lpszClass参数中指定所需的类名。

此外,您应使用比"Class"更独特的类名。

在接收方,不要将DefWindowProc()本身用于lpfnWndProc。您需要定义自己的windowproc函数。然后,您可以实际处理收到的WM_COPYDATA消息。将任何未处理的邮件传递给DefWindowProc()

尝试更像这样的事情:

LRESULT WINAPI MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  if (Msg == WM_COPYDATA)
  {
    COPYDATASTRUCT* pcds = (COPYDATASTRUCT*) lParam;
    if (pcds->dwData == 1)
    {
      LPCSTR lpszString = (LPCSTR) (pcds->lpData);
      printf("%.*s\n", lpszString, pcds->cbData);
      return TRUE;
    }
  }
  return DefWindowProc(hWnd, Msg, wParam, lParam);
}

JNIEXPORT jint JNICALL Java_WindowsIPC_openDataCopy
  (JNIEnv * env, jobject obj, jstring message)
{
  WNDCLASS WndClass;
  memset(&WndClass, 0, sizeof(WndClass));
  WndClass.lpfnWndProc = &MyWindowProc;
  WndClass.lpszClassName = TEXT("MyWindowsIPCClass");
  WndClass.hInstance = GetModuleHandle(NULL);

  if (!RegisterClass(&WndClass)) {
    printf("failed to register class: %d\n", GetLastError());
    return -1;
  }

  HWND hwnd = CreateWindowEx(0, WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,  HWND_MESSAGE, NULL, NULL, NULL);
  if (hwnd == NULL) {
    printf("Window Creation failed: %d\n", GetLastError());
    return -1;
  }

  MSG msg;
  while (GetMessage (&msg, NULL, 0, 0)) {
    TranslateMessage (&msg);
    DispatchMessage (&msg);
  }

  return 0; // success
}

JNIEXPORT jint JNICALL Java_WindowsIPC_sendDataCopyMessage
  (JNIEnv * env, jobject obj)
{
  HWND hwnd = FindWindowEx (HWND_MESSAGE, 0, TEXT("MyWindowsIPCClass"), 0);
  if (hwnd == NULL) {
     printf("Couldnt find window: %d\n", GetLastError());
     return -1;
  }

  LPCSTR messageString = "A message";

  COPYDATASTRUCT cds;
  cds.dwData = 1;
  cds.cbData = sizeof(char) * (strlen(messageString) + 1);
  cds.lpData = messageString;

  if (SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&cds) != TRUE) {
     printf("Couldnt send message\n");
     return -1;
  }

  return 0; // success
}
相关问题