Я пишу программу на 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";}}