2014-10-10 10 views
2

다른 응용 프로그램이 화면에 표시되지 않도록 화면의 일부분을 예약하는 Windows 도킹 가능한 응용 프로그램을 빌드하려고합니다.Windows에서 Java 응용 프로그램 jna 도킹

나는 JNI와 JNA를 사용해 보았습니다. 위의 코드는 제가 가지고있는 정도를 보여줍니다.

package jnadock; 

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.platform.win32.ShellAPI; 
import com.sun.jna.platform.win32.ShellAPI.APPBARDATA; 
import com.sun.jna.platform.win32.WinDef.DWORD; 
import com.sun.jna.platform.win32.WinDef.HWND; 
import com.sun.jna.platform.win32.WinDef.UINT_PTR; 
import com.sun.jna.platform.win32.WinUser; 
import com.sun.jna.win32.StdCallLibrary; 
import com.sun.jna.win32.W32APIFunctionMapper; 
import com.sun.jna.win32.W32APITypeMapper; 
import java.util.HashMap; 
import java.util.Map; 
import javax.swing.JFrame; 


public class JNADock { 

private HWND hWndGlobal; 
private final String frameTitle = "Dockable frame"; 

public interface Shell32 extends StdCallLibrary { 

    final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() { 
     private static final long serialVersionUID = 1L; 

     { 
      put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); 
      put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); 
     } 
    }; 

    public Shell32 INSTANCE = (Shell32) Native.loadLibrary("Shell32", Shell32.class, WIN32API_OPTIONS); 

    UINT_PTR SHAppBarMessage(DWORD dwMessage, APPBARDATA pData); 

} 

public interface User32 extends StdCallLibrary { 

    final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() { 
     private static final long serialVersionUID = 1L; 

     { 
      put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); 
      put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); 
     } 
    }; 

    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, WIN32API_OPTIONS); 

    boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg); 

    int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount); 

    HWND FindWindowA(String winClass, String title); 
} 

public static void main(String[] args) { 
    JNADock jna = new JNADock(); 
} 

public JNADock() { 
    JFrame frame = new JFrame(frameTitle); 
    frame.setSize(600, 100); 

    frame.addWindowListener(new WindowAdapter() { 
     public void windowClosing(WindowEvent e){ 
      appbarRemove(); 
     } 
    }); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 

    appbarSetPos(); 


    final User32 user32 = User32.INSTANCE; 

    hWndGlobal = user32.FindWindowA(null, frameTitle); 

    appbarNew() ; 
    appbarSetPos(); 
    frame.setLocation(0,0); 
} 

private void appbarNew() { 

    APPBARDATA data = new APPBARDATA.ByReference(); 
    data.cbSize.setValue(data.size()); 
    int WM_USER = 0x0400; 
    data.hWnd = hWndGlobal; 
    data.uCallbackMessage.setValue(WM_USER + 1); 

    UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_NEW), data); 
    System.out.println("result: " + result); 
} 

private void appbarSetPos() { 
    APPBARDATA data = new APPBARDATA.ByReference(); 
    data.cbSize.setValue(data.size()); 
    data.uEdge.setValue(ShellAPI.ABE_TOP); 

    data.rc.top = 0; 
    data.rc.left = 0; 
    data.rc.bottom = 100; 
    data.rc.top = 600; 

    UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_SETPOS), data); 
    System.out.println("result: " + result); 
} 

private void appbarRemove(){ 
    APPBARDATA data = new APPBARDATA.ByReference(); 
    data.cbSize.setValue(data.size()); 
    int WM_USER = 0x0400; 
    data.hWnd = hWndGlobal; 
    data.uCallbackMessage.setValue(WM_USER + 1); 

    UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_REMOVE), data); 
    System.out.println("result: " + result); 
} 
} 

실행하면 프레임이 표시되지만 내가 잘못하고있는 것의 오류나 힌트는 인쇄되지 않습니다.

방금 ​​JNA를 사용하기 시작 했으므로 루키 오류를 범할 수 있습니다. 담배를 피우십시오.

+0

귀하의'User32' 라이브러리를 호출하는 새로운 AppBar를 제거하는 것을 잊지 마세요. JNA의'platform.jar'에서 제공되는 라이브러리의 버전에서 쉽게 파생되는 것을 알 수 있습니다. – technomage

+0

@technomage 끝났지 만 "제공되는 라이브러리의 버전에서 간단히 파생된다"고 말할 때 나는 당신을 쫓지 않을 것입니다. 다시이 분야에 대한 저의 경험 부족을 용서하십시오. – Neikon

+0

JNA는 Shell32, User32 등의 버전을 제공합니다. 그 platform.jar 패키지에. 라이브러리 인터페이스를 파생시킨 경우 정의 할 인터페이스 메소드가 적습니다. – technomage

답변

2

SHAppBarMessage(ABM_SETPOS)으로 전화하기 전에 SHAppBarMessage(ABM_NEW)을 호출하는 새 AppBar을 초기화해야합니다. 끝에

private void appbarNew() { 

    APPBARDATA data = new APPBARDATA.ByReference(); 
    data.cbSize.setValue(data.size()); 
    int WM_USER = 0x0400; 
    data.hWnd = hWndGlobal; 
    data.uCallbackMessage.setValue(WM_USER + 1); 

    UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_NEW), data); 
    System.out.println("result: " + result); 

} 

는 Shell32``와 같은 방법으로 초기화한다 SHAppBarMessage(ABM_REMOVE)


Related docs from Microsoft Dev Center

+0

힌트를 주셔서 감사하지만 여전히 예상대로 작동하지 않습니다. 코드를 업데이트했습니다. 임 ABM_NEW 시도 할 때 0지고. – Neikon

+0

여기에서 성공적으로 테스트 한 코드 스 니펫을 게시했습니다. https://gist.github.com/681fb27eea39404e86c5.git - Win7 (64 비트) - Java6 - jna-platform 4.1.0 – bsorrentino

+0

시간 내 주셔서 대단히 감사합니다. ! – Neikon