Community
Participate
Working Groups
If you try to capture a screenshot image by using a GC built from a display, the secondary monitor is not captured correctly if it is at left or above the primary monitor. Paste and run the following example: public class MonitorTest { private static Image img; public static void main(String[] args) { final Display display = Display.getDefault(); final Shell shell = new Shell(display); shell.setSize(800, 600); shell.setMaximized(true); shell.open(); shell.setLayout(new GridLayout()); Button capture = new Button(shell, SWT.PUSH); capture.setText("Capture!"); capture.setLayoutData(new GridData()); shell.layout(); final ScrolledComposite composite = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); final Canvas canvas = new Canvas(composite, SWT.NONE); composite.setContent(canvas); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (img != null) { e.gc.drawImage(img, 0, 0); } } }); capture.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (img != null) { img.dispose(); } Rectangle bounds = display.getBounds(); img = new Image(display, bounds.width, bounds.height); GC gc = new GC(display); gc.copyArea(img, 0, 0); gc.dispose(); canvas.setSize(bounds.width, bounds.height); canvas.redraw(); shell.layout(); } }); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } if (img != null) { img.dispose(); } } } In this example, pressing the "Capture!" button, captures a full screenshot and displays it into a canvas bellow it. In Windows control panel, video settings, drag the secondary monitor to the left of the primary monitor and run the capture. The resulting image will contain the primary monitor screenshot followed by a blank area to the right. A similar behavior happens when you move the secondary monitor on top of the primary. I can reproduce this in Windows Vista, SWT 3.4 M5. There is at least 1 another case confirmed in Windows XP, where a user got into this through screenshot capture facility from Mylyn, which relies on this SWT facility (see bug#219171).
*** Bug 219171 has been marked as a duplicate of this bug. ***
I got this using the mylyn feature, on eclipse 3.3.1: Version: 3.3.1.1 Build id: M20071023-1652 mylyn feature: org.eclipse.mylyn (2.2.0.I20071220-1700) "Mylyn"
This is correct. The origin of the display is not 0,0 in that configuration. This is how APP code should look like. import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class PR219716 { private static Image img; public static void main(String[] args) { final Display display = Display.getDefault(); final Shell shell = new Shell(display); shell.setSize(800, 600); shell.setMaximized(true); shell.open(); shell.setLayout(new GridLayout()); Button capture = new Button(shell, SWT.PUSH); capture.setText("Capture!"); capture.setLayoutData(new GridData()); shell.layout(); final ScrolledComposite composite = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); final Canvas canvas = new Canvas(composite, SWT.NONE); composite.setContent(canvas); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { if (img != null) { e.gc.drawImage(img, 0, 0); } } }); capture.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (img != null) { img.dispose(); } Rectangle bounds = display.getBounds(); System.out.println(bounds); img = new Image(display, bounds.width, bounds.height); GC gc = new GC(display); gc.copyArea(img, bounds.x, bounds.y); gc.dispose(); canvas.setSize(bounds.width, bounds.height); canvas.redraw(); shell.layout(); } }); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } if (img != null) { img.dispose(); } } }
Wow, this is surprising! I don't have 2 monitors set up right now, but I presume from the code modifications, the x/y values from Display.getBounds() come negative, right? Silenio, it would be good if you can document this case in the Display.getBounds() javadoc, since this behavior is not intuitive. Mik/Steffen, I'll reopen the original Mylyn bug and post a patch in there.
Yes, I changed the javadoc of Display.getBounds() and Monitor.getBounds() to say that the origin can be negative.