I'm developing a Java app which will take a screen shot, I have 3 monitors in my office, so I want my app to be able to take a screen shot of the display I'm interested in. What it can do now is to take a screen shot of each screen and save the 3 files. But I don't want to get 3 file each time I run my Java app. Therefore I want to know if there is a way to detect from which screen my Java app is run, and only take the screen shot of that screen, but my question got no answer : How to determine in which monitor my Java app is running?
I thought about creating a shortcut of my Java app's jar file on desktop, then set it's property's target to : "C:\Program Files\AdoptOpenJDK\jdk-8.0.222.10-hotspot\bin\javaw.exe" -jar C:\Dir_Screen_Shoter\dist\Screen_Shoter.jar
Then I pinned the shortcut to Windows task bar, looking like this :
But the problem is : no matter from which display [ it shows up on every display ] I clicked it, my app always runs [ opens ] on the center [main ] display, so my question is : is there a way I can run this app on the display I clicked it, and that it can detect which monitor it is running from ?
I thought about something like : shift-click, alt-click or hold down ctrl then click on the app on tack bar, but it won't detect all those, so what is a good solution so when I run the app, it will know which display to take a screen shot, it's easy if my app opens a window and let user choose which monitor to act on, but I do not want that, I just want it to take a screen shot without opening an application window.
I've found some related questions, but none of them answers my question :
Show JFrame in a specific screen in dual monitor configuration
How to detect the current display with Java?
[ I tried this one, but it always show device Id == 1 ]
My app looks like this so far :
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Screen_Shoter extends JPanel
{
static Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
static JFrame frame=new JFrame("Screen_Shoter");
static int W=screenSize.width,H=screenSize.height;
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String Result="Screen_Size : "+W+" x "+H+"\n",Dir_Screenshots="C:/Dir_Screenshots/",Screen_Shot_File_Name=Dir_Screenshots+format.format(new Date()).replace("-","_").replace(" ","_").replace(":","_")+"_.png";
JLabel infoLabel=new JLabel();
public Screen_Shoter() // Get ScreenShots From Multiple Monitors
{
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gDevs=ge.getScreenDevices();
if (!new File(Dir_Screenshots).exists()) new File(Dir_Screenshots).mkdirs();
int defaultScreenIndex=getScreenIndex();
Out("defaultScreenIndex = "+defaultScreenIndex+"\n");
for (GraphicsDevice gDev : gDevs)
{
DisplayMode mode=gDev.getDisplayMode();
Rectangle bounds=gDev.getDefaultConfiguration().getBounds();
Out("[ "+gDev.getIDstring()+" ] Min : ( "+bounds.getMinX()+" , "+bounds.getMinY()+" ) ; Max : ( "+bounds.getMaxX()+" , "+bounds.getMaxY()+" ) W = "+mode.getWidth()+" , H = "+mode.getHeight());
try
{
Robot robot=new Robot();
BufferedImage image=robot.createScreenCapture(new Rectangle((int)bounds.getMinX(),(int)bounds.getMinY(),(int)bounds.getWidth(),(int)bounds.getHeight()));
ImageIO.write(image,"png",new File(Screen_Shot_File_Name.replace(".png",gDev.getIDstring().replace("\\","")+".png")));
}
catch (AWTException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
}
infoLabel.setFont(new Font("Times New Roman",0,15));
infoLabel.setForeground(new Color(0,0,218));
infoLabel.setText("<html>"+Result.replace("\n","<P>")+"</html>");
add(infoLabel);
}
int getScreenIndex()
{
int myScreenIndex=-1;
GraphicsConfiguration config=frame.getGraphicsConfiguration();
GraphicsDevice myScreen=config.getDevice();
GraphicsEnvironment env=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] allScreens=env.getScreenDevices();
for (int i=0;i<allScreens.length;i++)
{
if (allScreens[i].equals(myScreen))
{
myScreenIndex=i;
break;
}
}
Out("frame : "+frame.getBounds());
return myScreenIndex;
}
private static void showOnScreen(int screen,Window frame)
{
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd=ge.getScreenDevices();
GraphicsDevice graphicsDevice;
if (screen>-1 && screen<gd.length) graphicsDevice=gd[screen];
else if (gd.length>0) graphicsDevice=gd[0];
else throw new RuntimeException("No Screens Found");
Rectangle bounds=graphicsDevice.getDefaultConfiguration().getBounds();
int screenWidth=graphicsDevice.getDisplayMode().getWidth();
int screenHeight=graphicsDevice.getDisplayMode().getHeight();
frame.setLocation(bounds.x+(screenWidth-frame.getPreferredSize().width)/2,bounds.y+(screenHeight-frame.getPreferredSize().height)/2);
// frame.setLocation(bounds.x,bounds.y);
frame.setVisible(true);
}
private void out(String message)
{
System.out.print(message);
Result+=message;
}
private void Out(String message)
{
System.out.println(message);
Result+=message+"\n";
}
// Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
static void createAndShowGUI()
{
final Screen_Shoter demo=new Screen_Shoter();
frame.add(demo);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setBounds(0,0,600,178);
frame.setLocationRelativeTo(null);
frame.setVisible(true); // For test only
// showOnScreen(0,frame);
}
public static void main(String[] args)
{
// Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } });
}
}