2

I am able to take screenshot of foreground image using below code

void startScreencapture(){
    RECT dimensionsOfWindow = new RECT();
    User32.INSTANCE.GetWindowRect(User32.INSTANCE.GetForegroundWindow(), dimensionsOfWindow );//now in the dimensionsOfWindow you have the dimensions
    Robot robot = new Robot();
    buf = robot.createScreenCapture( dimensionsOfWindow.toRectangle() );
}

public interface User32 extends StdCallLibrary {
    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
    HWND GetForegroundWindow();  // add this
    int GetWindowTextA(PointerType hWnd, byte[] lpString, int nMaxCount);
    public boolean GetWindowRect(HWND hWnd, RECT rect);
}

I am getting foreground screenshots like below enter image description here

If you notice, the screenshot has some extra image at the border of the window.

I do not want extra image part with my screenshot.

Is it possible to somehow manipulate

User32.INSTANCE.GetForegroundWindow()

so that I get the screenshot without the extra part?

I feel like answer in this link should work. What is the difference between GetClientRect and GetWindowRect in WinApi?

But when I replace GetWindowRect with GetClientRect I get below screenshot: enter image description here

Ideally I should have got screenshot of only the foreground application.

Edit: Daniel Widdis kindly found a similar question for me: getwindowrect-returns-a-size-including-invisible-borders

This has a possible answer i.e. get the border thickness in Windows 10 and adjust this thickness to get the screenshot I want. But this answer uses DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT)); which is possibly C code.

If I can find how to find border thickness in Java, it would solve my problem.

Pramod
  • 768
  • 1
  • 12
  • 27
  • 1
    Possible duplicate of [GetWindowRect returns a size including "invisible" borders](https://stackoverflow.com/questions/34139450/getwindowrect-returns-a-size-including-invisible-borders) – Daniel Widdis Apr 15 '19 at 17:20
  • 1
    The whole purpose of JNA is to make C code accessible! :) If the function is not already built in to JNA you can add an interface to declare it. – Daniel Widdis Apr 16 '19 at 14:31

1 Answers1

3

GetClientRect:

The client coordinates specify the upper-left and lower-right corners of the client area. Because client coordinates are relative to the upper-left corner of a window's client area, the coordinates of the upper-left corner are (0,0).

This is a relative coordinate system.

You should also call the ClientToScreen to convert the Client coordinate to screen coordinate.

Notice that ClientToScreen only receive the parameter of POINT(not a RECT), and you can find the POINT class here.

EDIT:

GetWindowRect will get a "extra" size. However, GetClientRect does exactly not include it(and other extra information like title bar, window border, etc).

Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • 1
    This doesn't answer the user's question which is how to get rid of the (transparent) border. – Daniel Widdis Apr 16 '19 at 03:45
  • I did try with ClientToScreen but it requires int POINT. I tried with passing it RECT.LEFT and RECT.RIGHT. But the results were the same. – Pramod Apr 16 '19 at 05:44
  • @Daniel Widdis, GetClientRect does exactly not include (invisible) boundaries and Title bar, window border, etc. – Drake Wu Apr 16 '19 at 06:17
  • 2
    @Promod, You need to new 2 `POINT`s: {left,top} and {right,botom} to get from client coordinate to screen coordinate. but not only passing the `int`. BTW [DwmGetWindowAttribute](https://learn.microsoft.com/en-us/windows/desktop/api/dwmapi/nf-dwmapi-dwmgetwindowattribute) you metioned in question is a win32api. – Drake Wu Apr 16 '19 at 06:24
  • @DrakeWu-MSFT Tried as you mentioned but it still doesn't work. sample code: `User32.INSTANCE.ClientToScreen(hwnd, dimensionsOfWindow.left); User32.INSTANCE.ClientToScreen(hwnd, dimensionsOfWindow.right); User32.INSTANCE.ClientToScreen(hwnd, dimensionsOfWindow.top); User32.INSTANCE.ClientToScreen(hwnd, dimensionsOfWindow.bottom);` – Pramod Apr 16 '19 at 06:47
  • 5
    No, you should `POINT pt1 = new Point (RECT.LEFT, RECT.TOP);` and then `User32.INSTANCE.ClientToScreen(hwnd, pt1)`; the same as pt2 (RECT.RIGHT, RECT.BOTOM). Finally, reset the RECT value of `dimensionsOfWindow` according to the POINT. – Drake Wu Apr 16 '19 at 06:50
  • That did it. I thank you for your time and humility for answering my question. – Pramod Apr 16 '19 at 09:54
  • @DrakeWu-MSFT thanks for clarifying. I think I must have missed the distinction of client vs. window when first reading. – Daniel Widdis Apr 16 '19 at 14:31
  • Thanks @DrakeWu-MSFT. But using `DwmGetWindowAttribute` didn't solve my issue. Using `ClientToScreen` as suggested by you did. Can you please add that in answer. I haven't found any answer mentioning how to use POINT in their answers. Basically I was not able to use `DwmGetWindowAttribute `. – Pramod Apr 18 '19 at 07:53
  • @Promod Have you test the sample in this [link](https://www.programcreek.com/java-api-examples/index.php?api=com.sun.jna.platform.win32.WinDef.POINT)? using the [POINT](https://java-native-access.github.io/jna/4.2.0/com/sun/jna/platform/win32/WinDef.POINT.html) class in com.sun.jna.platform.win32.WinDef.POINT – Drake Wu Apr 18 '19 at 09:28
  • @DrakeWu-MSFT Yes. I used exact same thing in my code and it worked. – Pramod Apr 18 '19 at 09:46
  • @Promod changed it. And can't you get the function `DwmGetWindowAttribute` or it doesn't work? – Drake Wu Apr 18 '19 at 10:01
  • @DrakeWu-MSFT I could get the function. I tried creating an abstract method for it in interface but couldn't think of what parameter should I pass in e.g `DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT));` What should I pass in place of `DWMWA_EXTENDED_FRAME_BOUNDS` and ` sizeof(RECT)` in Java? – Pramod Apr 18 '19 at 10:15
  • @Promod `DWMWA_EXTENDED_FRAME_BOUNDS` = 9 and `sizeof(RECT)` = 16, You can try to pass `9` and `16` directly. – Drake Wu Apr 18 '19 at 10:29
  • @DrakeWu-MSFT ok. thanks for the help. My current code is working so I won't touch that. But this is quite useful for people with same issues. – Pramod Apr 18 '19 at 10:36