JNA-使用JavaFX的User32.dll回调

时间:2018-09-23 14:24:19

标签: java javafx callback jna user32

我正在JNA和JavaFX的帮助下编写Java程序。 在我的程序中,我将调用外部库CommLib.dll和Windows库User32.dll。 CommLib库的方法需要指向窗口的指针,例如,与该窗口进行通讯:

boolean SymbolX_PassPointers(long handle);

我在代码中处理了这个问题。 但是我对回调有问题。我应该一直检查我的程序是否有新消息(回调)。 在这种情况下,我想使用User32库中的函数:

int GetMessageA(WinUser.MSG lpMsg, HWND hWnd, int wMsgFilterMin, int wMsgFilterMax);

并按如下方式使用:

MSG msg = new MSG();
User32.INSTANCE.GetMessageA(msg, pointer, 0, 0)

但是我有一个问题,因为我只收到一条时间为0的消息。 有没有办法一直检查此回调并在收到新消息时采取措施?我是否应该创建新线程并例如每2秒检查一次此功能?但是这种解决方案很愚蠢。 也许我需要在第二个线程中进行一些循环,以检查是否有新消息发送到窗口? 我在下面添加我的代码:

Main.java

public class Main extends Application {
private Stage stage;
@Override
public void start(Stage primaryStage) throws Exception {

    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
    Parent root = (Parent) fxmlLoader.load();
    Scene scene = new Scene(root);
    primaryStage.setTitle("MyWindow");
    primaryStage.setScene(scene);
    primaryStage.show();
    Controller controller = new Controller();
    controller = fxmlLoader.getController();
    this.stage = primaryStage;
    controller.setStage(stage);
}
public static void main(String[] args) {
    launch(args);
}

Controller.java

public class Controller implements Initializable {
private Stage stage;
public void setStage(Stage stage) {
    this.stage = stage;
}

@FXML
private Button btn_Initialize;
@Override
public void initialize(URL location, ResourceBundle resources) {
    String librarypath = "C:/Users/Krystian/IdeaProjects/CommLibInJava/lib";
    System.setProperty("jna.library.path", librarypath);
    btn_Initialize.setOnAction(event -> {
        CommLib com = new CommLib(stage);
        com.mapComm();

        String result = User32Mapping.getMessage();
        System.out.println(result);
    });}}

CommLib.java

public interface CommLib extends Library {
boolean SymbolX_PassMethodCalls(long handle, Pointer commLibDataChangeProc);
boolean SymbolX_PassPointers(long handle);
boolean CommLib_AddIOManager(String host);
boolean CommLib_AddAlarmServer(String host);
boolean SymbolX_Advise( long handle, String plc, String tagName);
boolean SymbolX_AdviseAlarm( long handle, String plc, String tagName, String host);}

CommLibMapping.java

public class CommLibMapping {
private Stage stage;
private boolean result;
public void mapComm(){
    CommLib mapping = (CommLib) Native.loadLibrary("CommLib", CommLib.class);

    String title = stage.getTitle();
    //get pointer for stage
    WinDef.HWND hWnd = User32Mapping.getStagePointer(stage.getTitle());
    Pointer pointer = hWnd.getPointer();
    long peer = Pointer.nativeValue(pointer);
    //map pointer to CommLib library
    result = mapping.SymbolX_PassPointers(peer);
    System.out.println("CommLib - Result of mapping:"+ result);
    System.out.println("Id of Window: "+peer);
    System.out.println(mapping);
    boolean res = mapping.CommLib_AddAlarmServer("10.0.0.0")
}

CommLibMapping(Stage stage){
    this.stage = stage;
}}

User32.java

public interface User32 extends StdCallLibrary, WinDef {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
int WM_GETTEXT = 0x000d;
int WM_GETTEXTLENGTH = 0x000e;

HWND FindWindowA(String lpClassName, String lpWindowName);
int GetMessageA(WinUser.MSG lpMsg, HWND hWnd, int wMsgFilterMin, int wMsgFilterMax);
int RegisterWindowMessageA(String str);}

User32Mapping.java

public class User32Mapping implements WinDef, WinUser{
private static HWND pointer = null;
public static HWND getStagePointer(String stageName){
    if(pointer==null){
        HWND hWnd = User32.INSTANCE.FindWindowA(null, stageName);
        pointer = hWnd;
    }
    return pointer;
}
public static String getMessage(){
    MSG msg = new MSG();
    int WM_COMMLIBX = User32.INSTANCE.RegisterWindowMessageA("WM_COMMLIBX");
    System.out.println("Registered Window Message: "+WM_COMMLIBX);
    if(User32.INSTANCE.GetMessageA(msg, pointer, 0, 0)!=0)
    {
            return "Message: "+msg.wParam.toString();
    }
    return "No data";}}

0 个答案:

没有答案