Я использую JNA
для вызова библиотеки Win32 (WinAPI)
. Я привязываю свой WinProc
к моей рамке без границ. WinProc
прослушивание параметра WM_NCHITTEST
для определения границы под мышью и возврата ее идентификатора для возможности изменения размера. Возвращает правильный номер, но размер окна не может быть изменен. Курсор просто не меняется.
import com.sun.jna.Native;
import com.sun.jna.platform.win32.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import static com.sun.jna.platform.win32.WinUser.GWL_WNDPROC;
public class WindowsConfigurator {
private Frame frame;
private WinDef.HWND hwnd;
private BaseTSD.LONG_PTR baseWndProc;
public WindowsConfigurator(Frame frame){
this.frame = frame;
new Thread(()-> {
hwnd = new WinDef.HWND(Native.getWindowPointer(frame));
WndProc listener = new WndProc();
this.baseWndProc = MyUser32.instance.GetWindowLongPtr(hwnd, GWL_WNDPROC);
MyUser32.instance.SetWindowLongPtr(hwnd, GWL_WNDPROC, listener);
}).start();
}
public interface MyUser32 extends StdCallLibrary
{
MyUser32 instance = Native.load("user32", MyUser32.class, W32APIOptions.UNICODE_OPTIONS);
BaseTSD.LONG_PTR SetWindowLongPtr(WinDef.HWND hWnd, int nIndex, WinUser.WindowProc proc);
BaseTSD.LONG_PTR GetWindowLongPtr(WinDef.HWND hWnd, int nIndex);
WinDef.LRESULT CallWindowProc(BaseTSD.LONG_PTR proc, WinDef.HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam);
}
public class WndProc implements WinUser.WindowProc {
public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
try {
int WM_NCHITTEST = 0x0084;
int WM_MOUSEMOVE = 0x0200;
int HTLEFT = 10;
int HTRIGHT = 11;
int HTBOTTOMRIGHT = 17;
int HTBOTTOM = 15;
int HTBOTTOMLEFT = 16;
int HTTOP = 12;
int HTTOPLEFT = 13;
int HTTOPRIGHT = 14;
int border_width = 10;
if (uMsg == WM_NCHITTEST || uMsg == WM_MOUSEMOVE) {
Dimension frameSize = frame.getSize();
Point screenPoint = MouseInfo.getPointerInfo().getLocation();
Point framePoint = new Point(screenPoint.x - frame.getX(), screenPoint.y - frame.getY());
// Borders
Rectangle bottom = new Rectangle(border_width, frameSize.height - border_width, frameSize.width - 2 * border_width, border_width);
Rectangle bottom_left = new Rectangle(0, frameSize.height - border_width, border_width, border_width);
Rectangle bottom_right = new Rectangle(frameSize.width - border_width, frameSize.height - border_width, border_width, border_width);
Rectangle right = new Rectangle(frameSize.width - border_width, border_width, border_width, frameSize.height - 2 * border_width);
Rectangle top_right = new Rectangle(frameSize.width - border_width, 0, border_width, border_width);
Rectangle top = new Rectangle(border_width, 0, frameSize.width - 2 * border_width, border_width);
Rectangle top_left = new Rectangle(0, 0, border_width, border_width);
Rectangle left = new Rectangle(0, border_width, border_width, frameSize.height - 2 * border_width);
HashMap<Integer, Rectangle> boxes = new HashMap<Integer, Rectangle>() {{
put(HTTOPLEFT, top_left);
put(HTBOTTOMLEFT, bottom_left);
put(HTBOTTOMRIGHT, bottom_right);
put(HTTOPRIGHT, top_right);
put(HTBOTTOM, bottom);
put(HTRIGHT, right);
put(HTTOP, top);
put(HTLEFT, left);
}};
for (Map.Entry<Integer, Rectangle> hitBox : boxes.entrySet()) {
if (hitBox.getValue().contains(framePoint)) {
System.out.println(hitBox.getKey());
return new WinDef.LRESULT(hitBox.getKey());
}
}
}
}catch (Exception ex){
ex.printStackTrace();
}
return MyUser32.instance.CallWindowProc(baseWndProc, hWnd, uMsg, wParam, lParam);
}
}
}
Код создания кадра:
import javax.swing.*;
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame("Test window"){{
setBounds(100, 100, 400, 400);
setUndecorated(true);
add(new JButton("test"));
}};
frame.setVisible(true);
new WindowsConfigurator(frame);
}
}
Самое странное, что другие коды возврата работают хорошо.
Вот пример в WinProc
слушатель:
for (Map.Entry<Integer, Rectangle> hitBox : boxes.entrySet()) {
if (hitBox.getValue().contains(framePoint)) {
System.out.println(hitBox.getKey());
return new WinDef.LRESULT(2); // <-------- 2 = ability to drag window (Work fine)
}
}
Я думаю, что это связано с окном AWT, но я не знаю, в чем проблема. Кто-нибудь может мне помочь?