# An beliebige Stelle des Bildschirms zeichnen



## boehmi (19. Jul 2010)

Hi Leute,

ich möchte eine Anwendung schreiben, mit der ich auf meinem Bildschirm malen kann, aber ohne dass dabei die Fenster im Hintergrund versteckt werden, oder einfach nur ein Screenshot gemacht wird.
Das heißt, der Javaframe soll entweder minimiert sein, oder unsichtbar, oder etwas vergleichbares.

Zunächst dachte ich ich kann es mit einem maximierten 100% transparenten Fenster und irgendeiner Art von Canvas lösen, aber leider scheint das mit Java6 noch nicht so richtig zu klappen:
http://www.java-forum.org/awt-swing-swt/103355-awtutilities-access-restriction.html

Meint ihr das ist in Java überhaupt machtbar und wenn ja, wie? 

Danke im voraus


----------



## Kr0e (20. Jul 2010)

Mit C++ wärs ein kinderspiel. Ca. 50 Zeilen Code...

Mit Java ist etwas derartiges nicht möglich.


----------



## boehmi (20. Jul 2010)

Okay... ich hab kein Problem damit C++ zu nehmen.
Hast du einen Link, Source oder Stichwort nach dem ich weiter suchen kann?

Danke

Grüße


----------



## Kr0e (20. Jul 2010)

Keinen Link aber ich sag dir, wie es etwa geht:

Bei C++ musst du mit der WinAPI arbeiten, um bei der WinAPI iwas zu zeichnen brauchst
du sogenannte Handles. Ganz stumpf jetzt:

Das Handle des Desktops ist "0". Wenn du dir einen Grafikkontext mit Hwnd=0 erstellen lässt,
kannst du machen was du willst auf dem Desktop... 

Denk dran, dass der Desktop ab und zu neugezeichnet wird. Darauf musst du entsprechend reagieren und ggf.
deinen Text oder was auch immer erneut painten.

Gruß,

Chris


----------



## boehmi (20. Jul 2010)

Male ich denn damit auch über andere Fenster oder nur auf dem Desktop-Fenster?

Auch wenns das jetz nich mehr ins Javaforum gehört


----------



## Kr0e (20. Jul 2010)

Damit malst du eiskalt über alles drüber was es gibt. C++ an die Macht !

Jedes Progamm wird wohl nur als Childwindow vom Desktop gewertet...


----------



## Bierhumpen (20. Jul 2010)

Davon abgesehen ist das C und nicht C++ ...


----------



## XHelp (20. Jul 2010)

Man kann auch aus Java (mit jni) WinAPI verwenden


----------



## Ebenius (21. Jul 2010)

Kr0e hat gesagt.:


> Denk dran, dass der Desktop ab und zu neugezeichnet wird. Darauf musst du entsprechend reagieren und ggf. deinen Text oder was auch immer erneut painten.


Nicht nur das, man müsste natürlich auch dann immer neu zeichnen, wenn irgendein anderes Fenster neu gezeichnet wird.

Ebenius


----------



## Kr0e (21. Jul 2010)

"Davon abgesehen ist das C und nicht C++ ... "

unnötiger kommentar


----------



## Tomate_Salat (21. Jul 2010)

Kr0e hat gesagt.:


> "Davon abgesehen ist das C und nicht C++ ... "
> 
> unnötiger kommentar



Naja, wenn ich an die letzten Posts von Bierhumpen denke....war da nie ein sinnvoller dabei. Meine C/C++-Kenntnisse sind nicht gerade die besten, aber ich finde es doch schon interessant, wie er von der Theorie komplett auf C schließt x). Soweit ich weis ist das mit C++ ebendso lösbar. 

Naja, es kann doch vieles geben was einen repaint auslöst, ich denke mal:

Programmstart
Ordner öffnen/verschieben
Programme verschieben
F5 drücken
Startleiste öffnen
Fehlermeldungen

... wie gesagt, meine Kenntnisse in C/C++ sind nicht die besten, aber bevor wir hier jz alle fälle aufzählen, da gibts doch hoffentl. einen repaintListener oder sowas 

MFG

Tomate_Salat


----------



## Kr0e (21. Jul 2010)

hi!

Ja, oder man zeichnet alle 30 ms mit einem timer z.b. Wäre glaub cih das einfacshte. Verbraucht jetzt nicht soooo die Megaresourcen... Bierhumpen hat zwar recht, dass die WinAPI mit C geschrieben ist und nicht mit C++.

Aber zu sagen, dass ist C und nicht C++ ist genauso unsinnig wie das Java6 und nicht Java5. Mit Java6 kann man alles machen, was mit Java5 möglich war. und mit c++ kann mann ALLES machen was mit C möglich ist und eben noch MEHR.

Hätte es den C++ Standard damals schon gegeben, wäre auch die WinAPI in C++ geschrieben.


@Tomaten_Salat:
RepaintListener beim Desktop registrieren ist ne gute Idee. Müsste ja machbar sein, da wir ja das Handle kennen. (0 eben)


----------



## Tomate_Salat (21. Jul 2010)

naja, alle 30ms einen repaint auszulösen, ist eine Möglichkeit, aber wenn es einen listener gibt, würde ich doch eher diese vorziehen. Sonst klingt das eher nach Plan B ^^.


----------



## Kr0e (21. Jul 2010)

Wenn nicht eher nach Notfallplan D)


----------



## Tomate_Salat (21. Jul 2010)

nope, das wäre: Bluescreen faken und darauf zeichnen :lol:


----------



## maki (21. Jul 2010)

Bitte freundlich bleiben, Blödsinn wird hier von allen Seiten geschrieben(speziell was C/C++ und die Win32 API betrifft, Petzold hilft, MFC übrigens auch), das hilft weder dem TS noch dem Forum, bei Interesse kann man ja einen eigenen Thread dafür aufmachen, wobei sich mir der Sinn aber nicht erschliesst hier über C/C++ und die Win32 API zu diskutieren.

Da die Antworten weg von Java und hin zu irgendetwas anderem gehen verschiebe ich mal.


----------



## Runtime (21. Jul 2010)

Man kann ein JFrame oder ein JDialog machen und es mit AWTUtilities transparent machen. Dann noch always on top auf true setzen. Alles was auf diesem Fenster gezeichnet wird, ist dann auf dem Bildschirm sichtbar.


----------



## Tomate_Salat (21. Jul 2010)

Wäre schön wenn es so ginge, aber meiner Erfahrung nach, haben die Componenten auf dem JFrame die gleiche Transparentz. Wenn du weist wie man das umgehen kann, bitte posten, würde mich interessieren.


----------



## Kr0e (21. Jul 2010)

Bedeutet denn Transparenz, dass man dahinter liegende Programme "Anklicken" kann ? Ich wäre mir da nicht sicher,
habs aber uach ncoh nciht ausprobiert. ICh meine is ja cool, dass man sowas was anzeigen lassen kann, aber wenn dann alle Programme quasi inaktiv sind, da sie ja hinter dem ersten Frame liegen, bringt das ja nicht soo viel.


Gruß,

Chris


----------



## Runtime (22. Jul 2010)

@ Tomate Salat:
Wenn man setWindowOpacity aufruft, ist alles weg, wenn man es aber mit setWindowOpaque macht, ist nur der Hintergrund weg.
@ kr0e:
Ich versteh nicht was du meinst.


----------



## Kr0e (22. Jul 2010)

Naja, du willst doch "auf den Desktop" zeichnen, in dem du ein ganz normales Fesnter nimmst, es transparent machst und dann darauf zeichnest und AlwaysOnTop auf true setzt. Meine Frage war: Können dann Programm die dahinter sind (z.b. ein Explorerfenster) angeklickt werden ? bzw können programme überhaupt noch benutzt werden ? Denn wenn das immer OnTop ist, hat ja uach dieses Windows den Focus...


----------



## Runtime (22. Jul 2010)

Wenn man ein Fenster auf alwaysOnTop setzt, ist es immer oben, hat aber nicht immer den Fokus. (Unter Windows jedenfalls, ich weiss nicht wie es auf Mac ist.) Wenn man neben die Stellen, auf denen gezeichnet wurden, klickt, kann alles dahinter noch benutzt werden.


----------



## Tomate_Salat (22. Jul 2010)

```
final JFrame frame			= new JFrame("test");
		
		AWTUtilities.setWindowOpaque(frame, true);
		AWTUtilities.setWindowOpacity(frame, 0.4F);
		
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel panel			= new JPanel();
		panel.setLayout(null);
		
		JButton button			= new JButton("hallo");
		button.setLocation(10, 10);
		button.setSize(100, 20);
		
		panel.add(button);
		frame.add(panel);
		frame.setSize(300, 300);

		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				frame.setVisible(true);
			}
		});
```
macht bei mir trotzdme alles transparent :-/


----------



## Wildcard (22. Jul 2010)

Dafür nimmt man besser SWT, dann muss man nicht auf Sun spezifische Klassen zurückgreifen.


----------



## maki (22. Jul 2010)

*zurück verschoben*


----------



## Runtime (23. Jul 2010)

Du musst setOpaque false setzen, nicht true. Diesen Fehler mache ich auch immer.  Und wahrscheinlich solltest du alles direkt auf das Fenster adden, nicht zuerst auf ein JPanel. Leider
ist AWTUtilities in kuenftigen Versionen nicht mehr verfuegbar.


----------



## Tomate_Salat (23. Jul 2010)

Schreib mal ein KSKB bitte, bei mir funktioniert das komplett nicht wie es deiner Meinung nach gehn sollte.


----------



## Runtime (23. Jul 2010)

```
import com.sun.awt.AWTUtilities;
import javax.swing.JFrame;

public class KSKB {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setAlwaysOnTop(true);
        frame.setLayout(null);
        frame.setSize(500, 500);
        frame.setUndecorated(true);
        JButton button = new JButton("blabla");
        button.setBounds(100, 100, 100, 50);
        frame.add(button);
        AWTUtilities.setWindowOpaque(frame, false);
        frame.setVisible(true);
    }

}
```
Das sollte funktionieren.


----------



## Tomate_Salat (23. Jul 2010)

Interessant. Selten so glücklich mich geirrt zu haben.

*Edit+Spielerei:*
Hier ein kleine KSKB wie das mit dem Zeichnen aussehen könnte 


```
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.sun.awt.AWTUtilities;
 
public class KSKB {
 
    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setAlwaysOnTop(true);
        frame.setLayout(null);
        frame.setSize(500, 500);
        frame.setUndecorated(true);
        JPanel panel	= new JPanel()
        {
        	@Override
        	protected void paintComponent(Graphics g)
        	{
        		Graphics2D g2d	= (Graphics2D) g.create();
        		
        		BasicStroke bs	= new BasicStroke(5.F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);        		
        		
        		g2d.setStroke(bs);
        		
        		g2d.setColor(Color.BLUE);
        		g2d.drawLine(0, 0, 100, 100);
        		g2d.drawLine(100, 100, 200, 50);
        		g2d.dispose();
        	}
        };        
        panel.setBounds(100, 100, 200, 200);
        frame.add(panel);
        AWTUtilities.setWindowOpaque(frame, false);
        SwingUtilities.invokeLater(new Runnable()
		{
			
			@Override
			public void run()
			{
				frame.setVisible(true);
			}
		});        
    }
 
}
```


----------

