2011-02-04 11 views
3

Runtime#addShutdownHook(Thread)がWindows [1]で機能しないため、JNAを使用してJavaでWM_QUERYENDSESSIONメッセージを捕捉してシャットダウンメソッドを実行できます。私はこれがJNIWrapperで実装されているのを見てからこれを行うことができますが、私はJNAベースのソリューションを持っていたいと思います。JNAでWM_QUERYENDSESSIONメッセージを処理する方法

JNIWrapperソリューション

import java.io.File; 
import java.io.RandomAccessFile; 

import javax.swing.JFrame; 

import com.jniwrapper.win32.Msg; 
import com.jniwrapper.win32.ui.WindowMessage; 
import com.jniwrapper.win32.ui.WindowMessageListener; 
import com.jniwrapper.win32.ui.WindowProc; 
import com.jniwrapper.win32.ui.Wnd; 

public class ShutdownJNIWrapper { 

    public static void main(String[] args) { 
     final JFrame frame = new JFrame("Shutdown Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 

     Wnd frameHandle = new Wnd(frame); 
     WindowProc frameWindowProc = new WindowProc(frameHandle); 
     frameWindowProc.addMessageListener(new WindowMessageListener() { 
      public boolean canHandle(WindowMessage windowMessage, boolean beforeWindowProc) { 
       return windowMessage.getMsg() == Msg.WM_QUERYENDSESSION && beforeWindowProc; 
      } 

      public int handle(WindowMessage windowMessage) { 
       doSomething(); 

       return 0; 
      } 

      private void doSomething() { 
       final File file = new File("shutdown-jniwrapper.txt"); 

       try { 
        RandomAccessFile raf = new RandomAccessFile(file, "rw"); 
        raf.writeUTF("quit"); 
        raf.close(); 
       } catch (Exception e) { 
       } 
      } 
     }); 
     frameWindowProc.substitute(); 
    } 
} 

私はのWindowProcコールバックパラメータとして、それを受け入れるのSetWindowLong方法で自分自身がUser32クラスを作成しようとしましたが、私は次の例外を取得:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'SetWindowLong': The specified procedure could not be found. 

at com.sun.jna.Function.<init>(Function.java:179) 
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:344) 
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:324) 
at com.sun.jna.Library$Handler.invoke(Library.java:203) 
at $Proxy0.SetWindowLong(Unknown Source) 
at ShutdownJNA.main(ShutdownJNA.java:34) 

ここです私のUser32クラス:

と入れようとするクラス一緒にすべて:

import javax.swing.JFrame; 
import javax.swing.JPanel; 

import com.sun.jna.Native; 
import com.sun.jna.platform.win32.WinDef.HWND; 
import com.sun.jna.platform.win32.WinDef.LPARAM; 
import com.sun.jna.platform.win32.WinDef.LRESULT; 
import com.sun.jna.platform.win32.WinDef.WPARAM; 


public class ShutdownJNA extends JPanel { 

    public static void main(String[] args) { 
     final JFrame frame = new JFrame("Shutdown Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 

     try { 
      HWND hwnd = new HWND(); 
      hwnd.setPointer(Native.getComponentPointer(frame)); 

      MyUser32.WindowProc proc = new MyUser32.WindowProc() { 
       public LRESULT callback(HWND wnd, int msg, WPARAM param, LPARAM param2) { 
        if (msg == MyUser32.WM_QUERYENDSESSION) {} 

        return new LRESULT(0); 
       } 
      }; 

      MyUser32 user32 = (MyUser32)Native.loadLibrary("user32", MyUser32.class); //$NON-NLS-1$ 
      user32.SetWindowLong(hwnd, MyUser32.GWL_WNDPROC, proc); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

[1] The shutdown hook isn't executed when the application is launched using javaw.exe

答えて

1

は、お使いの環境ではJNAのためのjarファイルがあることを確認してください。 jna.jarとplatform.jarの両方がそこになければなりません。そうしないと、参照は失敗します。もう一つは、あなたがそれらを読み込む予定の場合、あなたがJNAを使用するdllファイルはあなたの環境(user32.dllなど)になければならないということです。

関連する問題