我正在尝试构建一个Windows可停靠应用程序,该应用程序会保留屏幕的一部分,以防止其他应用程序显示在该空间中。
我尝试使用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 :(得分: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);
}
最后,请不要忘记删除调用SHAppBarMessage(ABM_REMOVE)