我正在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";}}