java-native-access / jna

Java Native Access
Other
8.49k stars 1.67k forks source link

Implement DwmExtendFrameIntoClientArea #1430

Open ghost opened 2 years ago

ghost commented 2 years ago

STOP! Read this before creating an issue.

This is not a Question and Answer forum. For general questions and support, use the JNA users' group. Please search message history there and on existing issues for duplicates. You may also find answers on the Using the Library section of the project home page or in the FAQ.

Do NOT file an issue if you:

All of these questions belong on the mailing list.

If you are certain you are reporting a bug, or you have a feature request that is not of the form "please map this API function", then you may open an issue.

Provide complete information about the problem

  1. Version of JNA and related jars: jna-plat = 5.11.0 & jna = 5.11.0
  2. Version and vendor of the java virtual machine: Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86) Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
  3. Operating system Windows 10 212h
  4. System architecture (CPU type, bitness of the JVM) 64 and 64
  5. Complete description of the problem: User32.INSTANCE.DwmExtendFrameIntoClientArea doesnt exist
  6. Steps to reproduce: User32.INSTANCE.DwmExtendFrameIntoClientArea
dbwiddis commented 2 years ago

From the FAQ

JNA is missing function XXX in its platform library mappings

No, it's not, it's just waiting for you to add it :)

public interface MyUser32 extends User32 {
    // DEFAULT_OPTIONS is critical for W32 API functions to simplify ASCII/UNICODE details
    MyUser32 INSTANCE = (MyUser32)Native.load("user32", W32APIOptions.DEFAULT_OPTIONS);
    void ThatFunctionYouReallyNeed();
}

In your case, put HRESULT DwmExtendFrameIntoClientArea(HWND hWnd, MARGINS pMarInset) in place of void ThatFunctionYouReallyNeed(), and map the MARGINS structure:

@FieldOrder({ "cxLeftWidth", "cxRidghtWidth", "cyTopHeight", "cyBottomHeight" })
class MARGINS extends Structure {
  public int cxLeftWidth;
  public int cxRightWidth;
  public int cyTopHeight;
  public int cyBottomHeight;
}

JNA is a user-supported library. Functionality like the above is only added when users who need it contribute. Please submit a PR with these changes and we'll include it in the next version.

ghost commented 2 years ago

Wow thankyou!

ghost commented 2 years ago

image github undefined buttons

ghost commented 2 years ago

I did end up getting an error while calling and read through the FAQ

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'DwmExtendFrameIntoClientArea': The specified procedure could not be found.

    at com.sun.jna.Function.<init>(Function.java:252)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:600)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:576)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:562)
    at com.sun.jna.Library$Handler.invoke(Library.java:243)
    at net.skylix.elixor.elixorFX.$Proxy2.DwmExtendFrameIntoClientArea(Unknown Source)
    at net.skylix.elixor.elixorFX.ElixorFX.init(ElixorFX.java:65)
    at com.github.skylixgh.hello.MyApp.main(MyApp.java:104)

But I didn't find much.

package net.skylix.elixor.elixorFX;

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.W32APIOptions;
import net.skylix.elixor.elixorFX.jna.MARGINS;

import javax.swing.*;

import static com.sun.jna.platform.win32.WinUser.*;

interface EUser32 extends User32 {
    EUser32 INSTANCE = Native.load("user32", EUser32.class, W32APIOptions.DEFAULT_OPTIONS);
    HRESULT DwmExtendFrameIntoClientArea(HWND hwnd, MARGINS pMarInset);
}

public class ElixorFX {
    /**
     * Extended client area example
     */
    public static void init() {
        ModJFrame frame = new ModJFrame();
        frame.setVisible(true);

        HWND hwin = frame.getHWND();

//        if (message == WM_ACTIVATE)
//        {
//            // Extend the frame into the client area.
//            MARGINS margins;
//
//            margins.cxLeftWidth = LEFTEXTENDWIDTH;      // 8
//            margins.cxRightWidth = RIGHTEXTENDWIDTH;    // 8
//            margins.cyBottomHeight = BOTTOMEXTENDWIDTH; // 20
//            margins.cyTopHeight = TOPEXTENDWIDTH;       // 27
//
//            hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
//
//            if (!SUCCEEDED(hr))
//            {
//                // Handle the error.
//            }
//
//            fCallDWP = true;
//            lRet = 0;
//        }
        // we will implement the code above

        // Listen for messages
        MSG msg = new MSG();
        int WM_ACTIVATE = 0x0006;

        System.out.println("WM_ACTIVATE");

        // Extend the frame into the client area.
        MARGINS margins = new MARGINS() {{
            cxLeftWidth = 8;
            cxRightWidth = 8;
            cyBottomHeight = 20;
            cyTopHeight = 27;
        }};

        WinNT.HRESULT hr = EUser32.INSTANCE.DwmExtendFrameIntoClientArea(hwin, margins);

        while (User32.INSTANCE.GetMessage(msg, hwin, 0, 0) != 0) {
            User32.INSTANCE.TranslateMessage(msg);
            User32.INSTANCE.DispatchMessage(msg);

            if (msg.message == WM_QUIT) {
                break;
            } else if (msg.message == WM_ACTIVATE) {}
        }
    }

    public static class ModJFrame extends JFrame {
        public ModJFrame() {
            super();
        }

        public HWND getHWND() {
            HWND hwnd = new HWND();
            hwnd.setPointer(Native.getComponentPointer(this));

            return hwnd;
        }
    }
}

I think I did everything right

dbwiddis commented 2 years ago

The User32 in the FAQ template is just an example. The Windows API tells you it's in Dwmapi.dll. This library is not yet mapped in JNA so you'd extend Library rather than a JNA superclass.

ghost commented 2 years ago

sorry, im a newbie with native stuff, any docs here that could guide me on how to implement new methods for Library and how to point it to the DLL

dbwiddis commented 2 years ago

This extended discussion really belongs on the mailing list. But just change your EUser32 interface to a Dwmapi interface (extending StdCallLibrary), and load the "dwmapi" native library. There are numerous examples to look at here.