JNA - User32.dll обратные вызовы с JavaFX - PullRequest
0 голосов
/ 23 сентября 2018

Я пишу программу на Java с помощью JNA и JavaFX.В моей программе я вызываю внешнюю библиотеку CommLib.dll и Windows Library 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 секунды?Но это решение глупо.Может быть, мне нужен цикл во 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";}}
...