Screenshot mit SWT

Status
Nicht offen für weitere Antworten.

tbo007

Mitglied
Hallo, ich bin am verzweifeln.

Ich bin Betreuer für eine Eclipse RCP App. Ein Nutzer hat sich jetzt eine Screenshot Funktion gewünscht.
Folgendermaßen habe ich das implementiert ( Auszug):
Code:
      GC screenGC = new GC(shell); // shell ist das aktuelle Fenster
      
      Rectangle shellSize = shell.getBounds();
      screenshot = new Image(shell.getDisplay(), shellSize);
      screenGC.copyArea(screenshot, 0, 0);
      screenGC.dispose();

Das Image enthält aber nur das Fenster ohne Menubar, dafür aber mit Windows Taskleiste.

Wenn ich statt shell.getBounds() shellgetClientArea() mache habe ich logischerweise das "nackte" Fenster ohne Menubar und Taskleiste.

Wie kriege ich einen Shell Screenshot mit Menubar ohne Taskleiste, halt nur die Shell?

Ich habe bald keine Idee mehr, wie ich meinem Chef erklären kann, warum so eine läpsche Geschichte so lange dauert.

Vielen Dank im Voraus
 
nein eigendlich nicht.. :)

entnommen aus dem Buch RichClientEntwicklung mit Eclipse 3.2

Das ist zwar eigendlich zum Drucken der Widgets gedacht, sollte sich aber auch für eine Hardcopy implementieren lassen:

Code:
private static class PrinterFonts extends HashMap<FontData, Font> {
		private Printer printer;

		/**
		 * Konstruktor
		 * 
		 * @param printer –
		 *            Drucker
		 */
		PrinterFonts(Printer printer) {
			super();
			this.printer = printer;
		}

		/**
		 * Liefert einen Druckerfont
		 * 
		 * @param data –
		 *            Fontdaten, für welche ein Font benötigt wird
		 * @return – Font
		 */
		Font getFont(FontData data) {
			Font font = get(data);
			if (font == null) {
				font = new Font(printer, data);
				put(data, font);
			}
			return font;
		}

		/**
		 * Entsorgt alle Fonts
		 */
		void dispose() {
			for (Font font : values())
				font.dispose();
		}
	}

	@SuppressWarnings("serial")
	/**
	 * Repositorium für Farben
	 */
	private static class PrinterColors extends HashMap<RGB, Color> {

		private Printer printer;

		/**
		 * Konstruktor
		 * 
		 * @param printer -
		 *            Drucker
		 */
		PrinterColors(Printer printer) {
			super();
			this.printer = printer;
		}

		/**
		 * Liefert eine Druckerfarbe
		 * 
		 * @param rgb -
		 *            RGB-Wert
		 * @return - Druckerfarbe
		 */
		Color getColor(RGB rgb) {
			Color color = get(rgb);
			if (color == null) {
				color = new Color(printer, rgb);
				put(rgb, color);
			}
			return color;
		}

		/**
		 * Entsorgt alle Farben
		 */
		void dispose() {
			for (Color color : values())
				color.dispose();
		}
	}

	private PrinterFonts printerFonts;

	private PrinterColors printerColors;

	/**
	 * Druckt ein Control-Element
	 * 
	 * @param control –
	 *            das zu druckende Element
	 * @param printer –
	 *            der Drucker
	 * @param marginX –
	 *            Abstand von der linken Kante in Zoll
	 * @param marginY –
	 *            Abstand von der Oberkante in Zoll
	 * @param borders –
	 *            true, wenn Umrahmungen gewünscht sind
	 * @param fill –
	 *            true, wenn Flächen ausgefüllt werden sollen
	 */
	public void print(Control control, Printer printer, float marginX,
			float marginY, boolean borders, boolean fill) {
		// Grafikkontext und Repositorien anfertigen
		GC gc = new GC(printer);
		printerFonts = new PrinterFonts(printer);
		printerColors = new PrinterColors(printer);
		// Druckerauflösung ermitteln
		Point dpi = printer.getDPI();
		// drucken
		print(control, gc, dpi, (int) (dpi.x * marginX),
				(int) (dpi.y * marginY), borders, fill);
		// Aufräumen
		printerColors.dispose();
		printerFonts.dispose();
		gc.dispose();
	}

	/**
	 * Druckt ein Widget mitsamt seiner Kindelemente
	 * 
	 * @param w –
	 *            das zu druckende Widget
	 * @param gc –
	 *            der grafische Kontext
	 * @param dpi –
	 *            Druckerauflösung
	 * @param offX –
	 *            X-Offset in Pixel
	 * @param offY –
	 *            Y-Offset in Pixel
	 * @param borders –
	 *            true, wenn Umrahmungen gewünscht sind
	 * @param fill –
	 *            true, wenn Flächen ausgefüllt werden sollen
	 */
	private void print(Widget w, GC gc, Point dpi, int offX, int offY,
			boolean borders, boolean fill) {
		// Das Widget ausdrucken
		Rectangle printBounds = null;
		if (w instanceof Control)
			printBounds = printControl((Control) w, gc, dpi, offX, offY,
					borders, fill);
		else if (w instanceof TreeItem) {
			TreeItem item = (TreeItem) w;
			printBounds = printItem(item, gc, dpi, offX, offY, fill);
		} else if (w instanceof TableItem) {
			TableItem item = (TableItem) w;
			printItem(item, gc, dpi, offX, offY, fill);
		}
		// Die Kindelemente ausdrucken
		if (printBounds != null) {
			if (w instanceof TreeItem) {
				TreeItem item = (TreeItem) w;
				for (TreeItem child : item.getItems()) {
					print(child, gc, dpi, printBounds.x, printBounds.y,
							borders, fill);
				}
			} else {
				Rectangle oldClip = gc.getClipping();
				gc.setClipping(printBounds.x, printBounds.y, printBounds.width,
						printBounds.height);
				if (w instanceof Tree) {
					gc.setClipping(printBounds.x, printBounds.y,
							printBounds.width, printBounds.height);
					Tree tree = (Tree) w;
					for (TreeItem child : tree.getItems()) {
						print(child, gc, dpi, printBounds.x, printBounds.y,
								borders, fill);
					}
				} else if (w instanceof Table) {
					Table table = (Table) w;
					for (TableItem child : table.getItems()) {
						print(child, gc, dpi, printBounds.x, printBounds.y,
								borders, fill);
					}
				} else if (w instanceof Composite) {
					gc.setClipping(printBounds.x, printBounds.y,
							printBounds.width, printBounds.height);
					Composite composite = (Composite) w;
					for (Control child : composite.getChildren()) {
						print(child, gc, dpi, printBounds.x, printBounds.y,
								borders, fill);
					}
				}
				gc.setClipping(oldClip);
			}
		}
	}

	/**
	 * Druckt ein TableItem
	 * 
	 * @param item –
	 *            das zu druckende TableItem
	 * @param gc –
	 *            der grafische Kontext
	 * @param dpi –
	 *            Druckerauflösung
	 * @param offX –
	 *            X-Offset in Pixel
	 * @param offY –
	 *            Y-Offset in Pixel
	 * @param fill –
	 *            true, wenn Flächen ausgefüllt werden sollen
	 */
	private void printItem(TableItem item, GC gc, Point dpi, int offX,
			int offY, boolean fill) {
		int columns = Math.max(1, item.getParent().getColumnCount());
		for (int i = 0; i < columns; i++) {
			// Umrandung und Ausfüllen
			Rectangle printBounds = renderArea(item.getDisplay(), gc, offX,
					offY, dpi, item.getBounds(i), null, (fill) ? item
							.getBackground() : null);
			// Text
			printText(gc, item.getText(), printBounds, item.getFont(), item
					.getForeground(), false);
		}
	}

	/**
	 * Druckt ein TreeItem
	 * 
	 * @param item –
	 *            das zu druckende TreeItem
	 * @param gc –
	 *            der grafische Kontext
	 * @param dpi –
	 *            Druckerauflösung
	 * @param offX –
	 *            X-Offset in Pixel
	 * @param offY –
	 *            Y-Offset in Pixel
	 * @param fill –
	 *            true, wenn Flächen ausgefüllt werden sollen
	 * @return -Druckbereich des Widgets
	 */
	private Rectangle printItem(TreeItem item, GC gc, Point dpi, int offX,
			int offY, boolean fill) {
		int columns = Math.max(1, item.getParent().getColumnCount());
		Rectangle printBounds = null;
		for (int i = 0; i < columns; i++) {
			// Umrandung und Ausfüllen
			Rectangle bounds = renderArea(item.getDisplay(), gc, offX, offY,
					dpi, item.getBounds(), null, (fill) ? item.getBackground()
							: null);
			if (printBounds == null)
				printBounds = bounds;
			// Text
			printText(gc, item.getText(), bounds, item.getFont(), item
					.getForeground(), false);
		}
		return printBounds;
	}

	/**
	 * Druckt ein Control-Element
	 * 
	 * @param control –
	 *            das zu druckende Control-Element
	 * @param gc –
	 *            der grafische Kontext
	 * @param dpi –
	 *            Druckerauflösung
	 * @param offX –
	 *            X-Offset in Pixel
	 * @param offY –
	 *            Y-Offset in Pixel
	 * @param borders –
	 *            true, wenn Umrahmungen gewünscht sind
	 * @param fill –
	 *            true, wenn Flächen ausgefüllt werden sollen
	 * @return -Druckbereich des Widgets
	 */
	private Rectangle printControl(Control control, GC gc, Point dpi, int offX,
			int offY, boolean borders, boolean fill) {
		if (!control.isVisible())
			return null;
		// Umrandung und Ausfüllen
		Display display = control.getDisplay();
		Rectangle printBounds = renderArea(display, gc, offX, offY, dpi,
				control.getBounds(),
				(borders && hasBorder(control)) ? getColors().getColor(
						FormColors.BORDER) : display
						.getSystemColor(SWT.COLOR_WHITE), (fill) ? control
						.getBackground() : null);
		// Text – ExpandableComposites replizieren den Text in einem
		// Kindelement; wir verhindern den doppelten Ausdruck
		if (!(control instanceof ExpandableComposite)) {
			// Per Java-Reflection
			Class<? extends Control> clazz = control.getClass();
			try {
				Method m = clazz.getMethod("getText", (Class[]) null);
				String text = (String) m.invoke(control, (Object[]) null);
				printText(gc, text, printBounds, control.getFont(), control
						.getForeground(), (control.getStyle() & SWT.WRAP) != 0);
			} catch (Exception e) {
			}
		}
		return printBounds;
	}

	/**
	 * Druckt den Widget-Text
	 * 
	 * @param gc –
	 *            der grafische Kontext
	 * @param text –
	 *            Text
	 * @param bounds –
	 *            Druckbereich
	 * @param font –
	 *            Display-Font
	 * @param color –
	 *            Display-Farbe
	 * @param wrap –
	 *            true, wenn Text umgebrochen werden soll
	 */
	private void printText(GC gc, String text, Rectangle bounds, Font font,
			Color color, boolean wrap) {
		Rectangle oldClip = gc.getClipping();
		gc.setClipping(bounds);
		text = text.trim();
		if (text != null && text.length() > 0) {
			gc.setForeground(printerColors.getColor(color.getRGB()));
			gc.setFont(printerFonts.getFont(font.getFontData()[0]));
			Point extent = gc.textExtent(text);
			if (extent.x <= bounds.width || !wrap)
				gc.drawText(text, bounds.x, bounds.y, true);
			else {
				int ty = 0;
				while (true) {
					int wordBreak = -1;
					boolean whiteSpace = false;
					for (int i = 0; i < text.length(); i++) {
						char c = text.charAt(i);
						if (Character.isWhitespace(c)) {
							if (!whiteSpace) {
								wordBreak = i;
								whiteSpace = true;
							}
							if (c == '\n')
								break;
						} else
							whiteSpace = false;
						if (gc.textExtent(text.substring(0, i)).x > bounds.width) {
							if (wordBreak < 0)
								wordBreak = i;
							break;
						}
					}
					if (wordBreak < 0) {
						gc.drawText(text, bounds.x, bounds.y + ty, true);
						break;
					}
					gc.drawText(text.substring(0, wordBreak), bounds.x,
							bounds.y + ty, true);
					text = text.substring(wordBreak).trim();
					ty += gc.getFontMetrics().getHeight();
					if (ty > bounds.height)
						break;
				}
			}
		}
		gc.setClipping(oldClip);
	}

	/**
	 * Umrahmungen und Füllungen
	 * 
	 * @param display –
	 *            die Display-Instanz
	 * @param gc –
	 *            der grafische Kontext
	 * @param offX –
	 *            X-Offset in Pixeln
	 * @param offY –
	 *            Y-Offset in Pixeln
	 * @param dpi –
	 *            Druckerauflösung
	 * @param bounds –
	 *            zu füllender/umrahmender Bereich
	 * @param borderColor –
	 *            Rahmenfarbe oder null
	 * @param fillColor –
	 *            Füllfarbe oder null
	 * @return – der Druckbereich des Widgets
	 */
	private Rectangle renderArea(Display display, GC gc, int offX, int offY,
			Point dpi, Rectangle bounds, Color borderColor, Color fillColor) {
		// Bildschirmauflösung ermitteln
		Point screenDPI = display.getDPI();
		// Positionen umrechnen
		int x = offX + bounds.x * dpi.x / screenDPI.x;
		int y = offY + bounds.y * dpi.y / screenDPI.y;
		int width = bounds.width * dpi.x / screenDPI.x;
		int height = bounds.height * dpi.y / screenDPI.y;
		// Bereich füllen
		if (fillColor != null) {
			gc.setBackground(printerColors.getColor(fillColor.getRGB()));
			gc.fillRectangle(x, y, width, height);
		}
		// Bereich umrahmen
		if (borderColor != null) {
			gc.setForeground(printerColors.getColor(borderColor.getRGB()));
			int pixX = dpi.x / screenDPI.x;
			int pixY = dpi.y / screenDPI.y;
			gc.drawRectangle(x - pixX, y - pixY, width + pixX, height + pixY);
		}
		// Anfangsposition zurückgeben
		return new Rectangle(x, y, width, height);
	}

	/**
	 * Ermittelt, ob eine Umrahmung gezeichnet werden soll
	 * 
	 * @param c –
	 *            das Control-Element
	 * @return – true, wenn das Element eine Umrahmung hat
	 */
	public boolean hasBorder(Control c) {
		boolean inactiveBorder = false;
		boolean textBorder = false;
		if (c.getEnabled() == false && !(c instanceof CCombo))
			return false;
		if ((c.getStyle() & SWT.BORDER) != 0)
			return true;
		if (c instanceof Hyperlink)
			return false;
		Object flag = c.getData(KEY_DRAW_BORDER);
		if (flag != null) {
			if (flag.equals(Boolean.FALSE))
				return false;
			if (flag.equals(TREE_BORDER))
				inactiveBorder = true;
			else if (flag.equals(TEXT_BORDER))
				textBorder = true;
		}
		if (getBorderStyle() == SWT.BORDER) {
			if (!inactiveBorder && !textBorder)
				return false;
			if (c instanceof Text || c instanceof Table || c instanceof Tree)
				return false;
		}
		if (!inactiveBorder
				&& (c instanceof Text || c instanceof CCombo || textBorder))
			return true;
		if (inactiveBorder || c instanceof Table || c instanceof Tree)
			return true;
		return false;
	}

Gruß mw
 

tbo007

Mitglied
Hilft mir leider nicht, da dadurch mein Problem nicht gelöst wird, dass die Menubar nicht mitgedruckt wird. Trotzdem Danke und hat einer noch eine andere Idee?

Ich hatte auch mal ausprobiert einen Screenshot vom Display zu machen und dann den Bereich der Shell auszuschneiden, allerdings führt das zu Problemen, wenn das Bild maximiert (Windows) wird oder wenn eine Ecke der Shell nicht auf dem Monitor zu sehen ist.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
L JavaFX JavaFX Screenshot Machen AWT, Swing, JavaFX & SWT 6
F Screenshot eines JPanel AWT, Swing, JavaFX & SWT 3
F AWT Robot Klasse Screenshot nach Pixelmustern in bestimmten Radius um Bildschirmmittelpunkt absuchen AWT, Swing, JavaFX & SWT 13
K Screenshot AWT, Swing, JavaFX & SWT 6
A AWT Beim (mehrmaligen) Screenshot machen läuft der Speicher voll AWT, Swing, JavaFX & SWT 2
0 2D-Grafik Screenshot von ScrollBar-Inhalt AWT, Swing, JavaFX & SWT 2
N screenshot machen ohne Robots? AWT, Swing, JavaFX & SWT 9
F Screenshot vom Desktop machen? AWT, Swing, JavaFX & SWT 2
C JList: Eintrag anklicken & JTextfield mit Text aus MySQL füllen? (Screenshot dabei) AWT, Swing, JavaFX & SWT 8
G GUI Screenshot AWT, Swing, JavaFX & SWT 5
T Screenshot ist verschoben. AWT, Swing, JavaFX & SWT 3
D Robot: Screenshot vom Desktop Hintergrund möglich ? AWT, Swing, JavaFX & SWT 3
H Screenshot abhängig von Grafikkarte? AWT, Swing, JavaFX & SWT 15
A Screenshot eines best. Fensters AWT, Swing, JavaFX & SWT 5
R Screenshot von fremder Anwendung AWT, Swing, JavaFX & SWT 4
H Was ist das für eine Komponente ? (Screenshot) AWT, Swing, JavaFX & SWT 8
A Screenshot einer Anwendung erstellen AWT, Swing, JavaFX & SWT 14
M Bildschirnkoordinaten und Screenshot? AWT, Swing, JavaFX & SWT 2
R JPanel als Screenshot in eine Datei schreiben AWT, Swing, JavaFX & SWT 3
D Zoom problem!!! (brauche screenshot...) plz help thx AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben