问题
I'm trying to build a Windows dockable application that reserves a section of the screen to prevent other applications from show in that space.
I have try using JNI and JNA. The code above shows how far I have got.
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);
}
}
When executed, the frame is shown but no error or hint of what I'm doing wrong is printed.
Note that I just started using JNA and I could be committing rookie mistakes. Feel free to smoke them out.
回答1:
Before you call SHAppBarMessage(ABM_SETPOS)
you have to initialize a new AppBar calling SHAppBarMessage(ABM_NEW)
as show below.
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);
}
At the end don't forget to remove the new AppBar calling SHAppBarMessage(ABM_REMOVE)
Related docs from Microsoft Dev Center
来源:https://stackoverflow.com/questions/26301979/docking-a-java-application-jna-on-windows