Проблема при изменении размера кадра AWT / Swing с использованием Win32 - PullRequest
0 голосов
/ 05 февраля 2020

Я использую 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, но я не знаю, в чем проблема. Кто-нибудь может мне помочь?

...