Auf Desktop zeichnen...

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

es muß nicht unbedingt aufflimmern. wenn du mit gdi auf eine surface zeichnet, dann meldet die surface das sie refresht werden muß (das kann man selbst auch auslösen mit invalidaterect). wenn du nun auf die desktop surface gezeichnet hast, dann signalisiert die surface windows, dass der desktop "dreckig" ist. wenn windows nun *immer* vor dem anzeigen den desktop neu zeichnet, wenn dieser invalidated ist, dann wird deine änderung niemals auch nur ein frame lang angezeigt.

ich vermute stark, dass das tatsächlich so ist, denn sonst gäbe es beim schnellen verschieben von fenstern "schmutz" auf dem desktop.
Benutzeravatar
Daniel P.
Beiträge: 333
Registriert: 06.12.2005 21:49
Kontaktdaten:

Beitrag von Daniel P. »

Nö, habe anscheinend was falsch gemacht. Das Beispiel von uweb funktioniert nun. Allerdings verstehe ich nicht, warum hWndDesktop drei mal unterschiedliche Werte zugewiesen bekommt und das auch nur so funktioniert. Ist irgendwie wirr. Dieser "Dreck" entsteht übrigens nur dann, wenn ich ständig auf den Desktop malen will (also in einer Schleife) und dann ein Fenster darüber ziehe. Dann bleibt der Text nicht im Hintergrund und verschmiert so an der Border vom Fenster in das Fenster hinein. Ist irgendwie bescheiden, die GDI - zumindest für sowas. Oder kann man das umgehen?

Gruß
Gruß, Daniel :? | In der Realität ist die Wirklichkeit ganz anders...

PB 4.10 (Windows XP SP 2)
Benutzeravatar
Daniel P.
Beiträge: 333
Registriert: 06.12.2005 21:49
Kontaktdaten:

Beitrag von Daniel P. »

Folgender Code erzeugt mit Hilfe der GDI-Region-Funktionen ein lila Viereck auf dem Desktop, das ständig neugezeichnet wird:

Code: Alles auswählen

Structure COLORREF
  byRed.b
  byGreen.b
  byBlue.b
EndStructure

hWndDesktop = FindWindowEx_(hWndDesktop, 0, "Progman", "Program Manager")
hWndDesktop = FindWindowEx_(hWndDesktop, 0, "SHELLDLL_DefView", 0)
hWndDesktop = FindWindowEx_(hWndDesktop, 0, "SysListView32", 0)

hDCDesktop = GetDC_(hWndDesktop)

Dim RgnColor.COLORREF(0)
RgnColor(0)\byRed = 100
RgnColor(0)\byGreen = 100
RgnColor(0)\byBlue = 100

hRGN = CreateRectRgn_(200,200,250,250)
brush = CreateSolidBrush_(RgnColor(0))

Repeat
filled = FillRgn_(hDCDesktop,hRGN,brush)
Delay(10)
Until 0

End
Faszinierender Weise verschmiert dieses Viereck im Gegensatz zum Text nicht in anderen Fenstern. Irgendwie ist das total :freak: . Kann mir das einer mal erklären? Ich werde mir heute abend mal GDI+ angucken. Das soll laut SDK um einiges besser sein als das "normale" GDI. Außerdem unterstützt es Alpha-Blending und vielleicht verschmieren da nicht die Text-Beispiele, die ich auf den Desktop malen will. Könnte mir jemand erklären, was es genau mit diesen drei hWndDesktops au sich hat. Das ist das Einzige, was ich nicht verstehe...

Gruß
Gruß, Daniel :? | In der Realität ist die Wirklichkeit ganz anders...

PB 4.10 (Windows XP SP 2)
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Lt. MSDN sieht die FindWindowEx-Funktion wie folgt aus:

Code: Alles auswählen

HWND FindWindowEx(      
    HWND hwndParent,
    HWND hwndChildAfter,
    LPCTSTR lpszClass,
    LPCTSTR lpszWindow
);
Mit den hWndDesktops hat es folgendes auf sich:
Der Desktop selbst ist ein Window der Klasse SysListView32. Sein Parent gehört zur SHELLDLL_DefView-Klasse und hat wiederum einen Parent der Progman-Klasse mit dem Fenster-Titel "Program Manager".

Du fängst bei deiner Suche nach dem Desktop-Handle natürlich umgekehrt an: Du suchst Dir das Window der Progman-Klasse mit dem Titel "Program Manager", dann suchst Du seinen Child, die Klasse "SHELLDLL_DefView", und letztendlich dessen Child der Klasse "SysListView32" - den Handle des Desktops.

Deshalb übergibst Du bei jeder FindWindowEx() auch den vorher ermittelten hWndDesktop als Parameter.
Benutzeravatar
Daniel P.
Beiträge: 333
Registriert: 06.12.2005 21:49
Kontaktdaten:

Beitrag von Daniel P. »

Aha :shock: ... und woher weis man sowas :allright:
Gruß, Daniel :? | In der Realität ist die Wirklichkeit ganz anders...

PB 4.10 (Windows XP SP 2)
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Woher man das weiß? Hierher: http://www.codeproject.com/tips/TransIcon.asp :D
Benutzeravatar
Daniel P.
Beiträge: 333
Registriert: 06.12.2005 21:49
Kontaktdaten:

Beitrag von Daniel P. »

Naja, aber sowas muss man auch erst mal finden. Ich habe mir jetzt für alle Fälle Spy++ besorgt. Wer weis, vielleicht brauch ich ja mal wieder ein besonderes Window-Handle :lol:
Habe mal gestern abend die gdiplus.dll zerpflückt. Da sind ja 630 Funktionen drinn :shock: Das dauert, bis ich da durchblicke. Vor allem, weil im SDK GDI+ über ein C++-Wrapper-Klasse läuft und ich in PB damit nicht wirklich viel anfangen kann. Aber zum Glück gibt es Verweise auf die verwendeten DLL-Funktionen...

Gruß
Gruß, Daniel :? | In der Realität ist die Wirklichkeit ganz anders...

PB 4.10 (Windows XP SP 2)
Benutzeravatar
Daniel P.
Beiträge: 333
Registriert: 06.12.2005 21:49
Kontaktdaten:

Beitrag von Daniel P. »

So, ich möchte gerne den "PureBoard-Anfänger-Orden" verliehen bekommen. Ich habe nähmlich gerade herausgefunden, wie man ein Fenster erzeugt, das durchklickbar ist und das sich verhält, wie eine aufgeklebte Grafik.
:bounce:
Das Zauberwort heißt "Layered Window":

Code: Alles auswählen

#WS_EX_LAYERED = $80000

If OpenWindow(0,0,0,320,240,#PB_Window_SystemMenu | #PB_Window_ScreenCentered,"LayeredWindow")

  SetWindowLong_(WindowID(0),#GWL_EXSTYLE,#WS_EX_LAYERED | #WS_EX_TRANSPARENT)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Layered Windows sind IMHO dafür da, um Fenster mit einer gewissen Transparenz angezeigen zu können. Laut SDK ignoriert Windows Eingaben für ein Layered Window und reicht sie an das darunter liegende Fenster weiter, sobald es den erweiterten Fenster-Style #WS_EX_TRANSPARENT erhält. Ausprobiert - es klappt. Wie ich das herausgefunden habe? Nun, mit Winspector, die bessere Hälfte von Spy++. Mit diesem Programm versteht man auch, warum man 3 Handles ermitteln muss, um auf den Desktop zu kommen und ganz nebenbei kann man schauen, wie zum Beispiel Samurize es schaft, ein Fenster zu erstellen, das durchklickbar ist (einfach mal die Fenstereigenschaften ausgelesen und im SDK nachgeschlagen 8) ). Aber dass das dann so einfach wird, hätte ich jetzt nicht gedacht. Vorteil ist nun, dass man in seinem eigenen Fenster arbeiten kann und nicht den Umweg über den Desktop nehmen muss, allerdings die gleichen Ergebnisse erzielt (die Border ausblenden und den Fensterhintergrund auf transparent setzen, fettisch :D ).
Allerdings habe ich noch ein kleines Problem. Und zwar muss nach SetWindowLong_() das Fenster neu gezeichnet werden, damit es auch den neuen Style sofort erhält. Ansonsten wird es erst dann neugezeichnet, wenn ich versuche, es mit der Maus zu verschieben. Kann man schön an diesem Beispiel sehen:

Code: Alles auswählen

If OpenWindow(0,0,0,320,240,#PB_Window_SystemMenu | #PB_Window_ScreenCentered,"Test")

  SetWindowLong_(WindowID(0),#GWL_EXSTYLE,GetWindowLong_(WindowID(0),#GWL_EXSTYLE)|#WS_EX_TOOLWINDOW)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Nun wollte ich es mit der RedrawWindow_()-Funktion neuzeichnen. Allerdings passiert nüscht, obwohl der Aufruf korrekt ist (laut SDK). Könntet ihr mir da eventuell weiter helfen :freak:

Danköö

P.S.: Funktionert nur unter Winows 2000/XP und 2003 glaube ich auch noch ;)
Gruß, Daniel :? | In der Realität ist die Wirklichkeit ganz anders...

PB 4.10 (Windows XP SP 2)
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

Beitrag von uweb »

Zunächst mal : Super !
Mein Kompliment !

Ich weiß Dir zwar im Moment auch keinen Rat, aber
So, ich möchte gerne den "PureBoard-Anfänger-Orden" verliehen bekommen.
ich könnte Dir mein altes Pflaster anbieten.

Glaube mir : Ich weiß wie steinig der Weg ist.
Um so mehr freut es mich für Dich.

Sind es nicht genau diese Momente für die wir uns so quälen ?
Sei es nun im Sport, im Beruf oder am Puter :
Man muß die Erfolge feiern wie sie fallen !
Also gönne Dir heute abend mal etwas.
Benutzeravatar
125
Beiträge: 1322
Registriert: 19.09.2004 16:52
Wohnort: Neu Wulmstorf (Hamburg)
Kontaktdaten:

Beitrag von 125 »

Top!
Nur eine Frage hab ich noch, funzt ja alles Super, aber wie gibt man jetz was auf dem transparenten Window aus, weil alles was ich draufschreibe wird doch auch transparent oder?

Code: Alles auswählen

ExamineDesktops()

Procedure SetWinTransparency(win,level) 
  If level>=0 And level<=100 
        SetWindowLong_(WindowID(win),#GWL_EXSTYLE,GetWindowLong_(WindowID(win),#GWL_EXSTYLE)|$00080000) ; #WS_EX_LAYERED = $00080000 
        SetLayeredWindowAttributes_(WindowID(win),0,255*level/100,2) 
  EndIf 

EndProcedure 
  OpenWindow(1,0,0,DesktopWidth(0),DesktopHeight(0),"PaintonDesk")
  HideWindow(1,1)
  OpenWindow(0,0,0,DesktopWidth(0),DesktopHeight(0),"PaintonDesk",#PB_Window_BorderLess) 
  SetWindowLong_(WindowID(0),#GWL_HWNDPARENT,WindowID(1))
  SetWinTransparency(0,0)
  SetWindowLong_(WindowID(0),#GWL_EXSTYLE,#WS_EX_LAYERED | #WS_EX_TRANSPARENT)
  SetWindowPos_(WindowID(0),#HWND_BOTTOM,0,0,0,0,#SWP_NOMOVE|#SWP_NOREPOSITION|#SWP_NOSIZE)  
  
Repeat

hDC = GetDC_(WindowID(0)) 

text$ = "Das ist ein Test" 

SetBkMode_(hDC,#TRANSPARENT) 
TextOut_(hDC,200,200,text$,Len(text$)) 
ReleaseDC_(WindowID(0),hDC)

Until WaitWindowEvent()=#PB_Event_CloseWindow 
mfg
125
Bild
BildDas ist Tux. Kopiere Tux in deine Signatur und hilf ihm so auf seinem Weg zur Weltherrschaft.
Antworten