0

我为使其工作付出了很多努力(调用win32 API:使用WM_COPYDATA和COPYDATASTRUCT来保存数据的SendMessage)并且由于它现在可以在我的Windows 7计算机上运行,​​我想知道我的映射是否是好的映射以及是否存在我的解决方案没有副作用吗?

这是我的代码:

/**
     * For usage with WM_COPYDATA
     * cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx
     */
    long SendMessage(HWND hWnd, int msg, WPARAM wParam, COPYDATASTRUCT.ByReference lParam);

    int WM_COPYDATA = 0x004A;


//cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx
class COPYDATASTRUCT extends Structure {

    public static class ByReference extends COPYDATASTRUCT implements Structure.ByReference {
    }

    public COPYDATASTRUCT() {
        super();
    }

    public int dwData;
    public long cbData;
    public Pointer lpData;

    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "dwData", "cbData", "lpData" });
    }
}

以及带有 2 个示例的调用代码:

User32Extension.COPYDATASTRUCT.ByReference dataStruct = new User32Extension.COPYDATASTRUCT.ByReference();
        String message = "Hello ! :-) !";
        Memory m = new Memory(message.length() + 1);
        m.setString(0, message);
        dataStruct.dwData = 10;
        dataStruct.cbData = message.length() + 1;
        dataStruct.lpData = m;
        dataStruct.write(); // writes to native memory the structure.
        result = user32.SendMessage(hwndTarget, // target hwnd.
                User32Extension.WM_COPYDATA, // copy data message.
                wparam, // current hwnd
                dataStruct // data by reference here
        );

        User32Extension.COPYDATASTRUCT.ByReference myDataStruct = new User32Extension.COPYDATASTRUCT.ByReference();
        User32Extension.TEST_STRUCT myStruct = new User32Extension.TEST_STRUCT();
        //simple C structure here with 4 fields of C types int, char, char and long.
        myStruct.iNumber = 677;
        myStruct.cCode = 'E';
        myStruct.cCode2 = 'T';
        myStruct.lLong1 = new NativeLong(123456789L);
        myStruct.write();
        LOGGER.trace("myStruct (size=" + myStruct.size() + ")=" + myStruct.toString(true));

        myDataStruct.dwData = 11;
        myDataStruct.cbData = myStruct.size();
        myDataStruct.lpData = myStruct.getPointer();
        myDataStruct.write(); // writes to native memory the structure.
        result = user32.SendMessage(hwndTarget, // target hwnd.
                User32Extension.WM_COPYDATA, // copy data message.
                wparam, // current hwnd
                myDataStruct // data
        );

关键是这段代码与我在网上找到的所有代码相比,COPYDATASTRUCT 属性cbData 的类型为 long。如果我设置为 int,它就不起作用(在遗留 C 应用程序的 WndProc 中未正确接收数据)。将 DWORD 映射到长 java 类型是否正确?使用 NativeLong 会更好吗?

要注意的另一件事是对所有实例化结构(myStruct 和 myDataStruct)的显式调用 Structure.write()。为了在调用 SendMessage api 之前没有空内存是必要的。你觉得正常吗?或者 jna 应该在调用 SendMessage 之前自动调用它?

提前致谢。

4

1 回答 1

0

This native code:

typedef struct tagCOPYDATASTRUCT {
  ULONG_PTR dwData;
  DWORD     cbData;
  PVOID     lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

maps to this JNA Structure definition:

public class COPYDATASTRUCT extends Structure {
    ULONG_PTR dwData;
    DWORD     cbData; // or use "int"
    Pointer   lpData;
}

The first and last fields will be of different size (and the structure will have different alignment/padding) depending on whether you're running 32- or 64-bit.

于 2016-11-03T22:41:46.367 回答