Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi Eigener Bildschirmschoner in Delphi (https://www.delphipraxis.net/66581-eigener-bildschirmschoner-delphi.html)

TOC 31. Mär 2006 18:29


Eigener Bildschirmschoner in Delphi
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hi!

Seit ewigen Zeiten hatte ich schon Lust mal einen eigenen Bildschirmschoner zu programieren. Schwierig dabei ist eigentlich nur das diese Bildschirmschoner auf den ersten Blick keine normalen Programm zu sein scheinen da sie mit der Dateierweiterung "*.scr" enden und nicht mit "*.exe". Auch ist in der Windows32DeveloperHelp dieses Kapitel "ScreenSaver" über die ScreenSaver.library nicht gerade leicht verständlich, und, wie ich herausgefunden habe, geht´s auch viel einfacher!

Durch Zufall habe ich im Netz folgenden Artikel gefunden : http://www.mindspring.com/~cityzoo/scrnsavr.html Dort wurde erklärt das ein Bildschirmschoner von Windows aus mit bestimmten Parametern über die Kommandozeile gestartet wird. Allerdings wurde auch gesagt das immer nur ein Bildschirmschoner laufen darf und das man über die Variable "hPrevInst" abfragen könnte ob das Programm schon gestartet wurde... funktioniert leider nicht denn:

Zitat:

Zitat von Die Windows32DeveloperHelp
...However, in a Win32-based application, hPrevInstance is always NULL.
Therefore, you cannot determine if another instance of your application
has been started simply by examining hPrevInstance. This article gives you
a method you can use...

Aber ich habe folgenden Trick herausgefunden: Ich suche mit der Windows-Funktion "FindWindow(ClassName,WindowName:PChar):HWnd" einfach die Liste aller Fenster ab und finde ich ein Bildschirmschoner-Fenster von meinem eigenen ScreenSaver dann schicke ich ihm eine Nachricht (mit SendMessage) das das Programm sich doch bitte beenden soll. Wenn sich das Programm beendet schickt es mir eine "0" als Antwort, wenn es sich nicht beenden will weil es im Modus "/s" gestartet wurde eine 1, und dann beendet sich das zweite aufgerufene Programm selbst. Ungewöhnlicher Trick, ich weis, aber es klappt. Dazu muss man das Delphi-Hauptprogramm, das normalerweise vom Delphi-Compiler automatisch erzeugt wird, ein klein wenig abändern:

Delphi-Quellcode:
program LinesScreenSaver;

uses
  Forms,
  Windows,
  Messages,
  Main in 'Main.pas' {MainForm},
  Screen in 'Screen.pas' {ScreenForm},
  Configuration in 'Configuration.pas' {ConfigForm},
  Graphic in 'Graphic.pas';

{$R *.RES}

Var
  Wnd:HWnd;

begin
  // Testen ob der Bildschirmschoner schon läuft
  Wnd:=FindWindow('TMainForm','ScreenSaver');
  // Wenn ja...
  If Wnd<>0 then Begin
    // ...dann Nachricht senden das er sich beenden soll
    // Wenn er sich nicht beenden will (Modeus "/s")
    If SendMessage(Wnd,wm_User,0,0)=1
    // Dann brech das Programm eiskalt ab!
    Then Halt(0);
  End;

  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.CreateForm(TScreenForm, ScreenForm);
  Application.CreateForm(TConfigForm, ConfigForm);
  // Diese Zeile verhindert das das Hauptfenster angezeigt wird!
  Application.ShowMainForm:=false;
  Application.Run;
end.
So. Das war der erste notwendige Trick. Interessant ist auch das man durch die Zeile "Application.ShowMainForm:=false" verhindern kann das das Hauptfenster angezeigt wird.

Parameter
=========

Windows startet einen ScreenSaver mit drei möglichen Parametern (ParamStr(1) und (2):

Code:
ParamStr1  ParamStr2  Bedeutung

"/s"                 Bildschirmschoner im Vollbild-Modus starten

"/c:N"               Es wurde auf "Einstellungen" gedrückt und soll das
                      Konfigurations-Fenster angezeigt werden

"/p"      "N"       Der Bildschirmschoner wurde gestartet und soll
                      seine Grafik im verkleinerten Beispielfenster anzeigen
So. Das "N" ist jeweils ein Fensterhandle, klever nich? Und zwar ist es im Modus "/c:N" das Handle des Fensters in dem man unter "Bildschirmschoner" auf "Einstellungen" und "Testen" drücken und einen Bildschirmschoner auswählen kann; aber dummerweise nur das Händel des PageControl-Objekts und nicht das Händel des Hauptfensters. Nun ja, ich hol mir dann einfach mit der Funktion "GetParent(Wnd:HWnd):HWnd" das Händel des übergeordneten Fensters und sperre dieses Fenster mit "EnableWindow(Wnd:HWnd; Enable:Boolean):Boolean" bevor ich das Konfigurations-Fenster aufrufe. Natürlich muss man das Fenster wieder entsperren wenn das Konfigurieren beendet ist.
Dieses Sperren ist notwendig damit der Anwender nicht einfach auf "Ok", "Abbruch" oder "Übernehmen" drücken kann während das Konfigurations-Fenster sichtbar ist. Dies hätte nämlich unangenehme Folgen...

So. Das "N" im Modus "/p" ist interessanterweise das Fensterhändle dieser verkleinerten Darstellung des Bildschirmschoners! Nun, wenn man ein Fensterhändel hat dann kann man sich mit der Funktion "GetDC(Wnd:HWnd):HDC" den DeviceContext des Fensters holen und in dieses hineinzeichnen. Und genau das macht mein Bildchirmschoner: Gesteuert von einem Timer wird alle N Millisekunden ein neues Bild in eine Bitmap gezeichnet, und dieses Bild wird dann mit "StrecthBlt()" in das verkleinerte Fenster gezeichnet. Das ist schon der ganze Trick. Wird das Fenster "Eigenschaften von Anzeige" geschlossen dann wird dieser DC natürlich ungültig, der Bildschirmschoner bemerkt dies und beendet sich selbst. Klever, nich?

Also, das ganze hört sich mal wieder komplizierter an als es im Grunde genommen ist, weil: Das ganze Gefummel braucht dich kaum zu interessieren! Im Archiv findest Du zwei verschiedene Versionen, eine für Delphi 3.0 und eine für Delphi 7.0. Enthalten sind darin jeweils zwei Ordner mit Quellcodes, nämlich "Empty ScreenSaver" und "Lines ScreenSaver". Wenn Du nun Deinen eigenen Bildschirmschoner schreiben willst dann nimm den QuellCode von "Empty ScreenSaver" als Basis. Ich hab aus diesem Programm fast alles entfernt was nicht notwendig ist. Es gibt nur ZWEI Units in denen Du etwas ändern musst: "Configuration" und "Graphic". Von allen anderen Units solltest Du Deine Finger weglassen, Änderungen sollten hier nur erfahren Delphi-Programmierer machen!

Ich habe versucht das alles ordentlich und modular zu programmieren:

In der Unit "Configuration" must Du nur zu Deinem eigenen Bildschirmschoner passend entsprechende Einstellungen ermöglichen, und mit "LoadConfig" und "SaveConfig" kannst Du Deinen Code einbinden der diese Einstellungen dann in einem IniFile abspeichert bzw. lädt. Das IniFile selbst wird automatisch erzeugt, darum brauchst Du Dich nit zu kümmern!

In der Unit "Graphic" ist alles enthalten was mit dem Zeichnen der Grafik zu tun hat. Dort findest Du 4 Prozeduren die Du Deinen Vorstellungen gemäss ändern must:

InitGraphic
Hier kannst Du Speicher besorgen und Objekte erzeugen die Du für Deine Grafik
benötigst. Diese Funktion wird beim Programmstart automatisch aufgerufen.

ClearGrafik
Hier kannst (bzw. MUSST!) Du den Speicher und die Objekte wieder freigeben.
Diese Prozedur wird nur vor dem Programmende automatisch aufgerufen.

NewGraphic
Diese Prozedur wird beim Programmstart automatisch aufgerufen und auch dann wenn
der Anwender im Konfigurationsfenster irgendwelche Einstellungen geändert hat. Du
kanst hier also irgendwelche Eigenschaften Deiner Grafik ändern, Variablen neu
initialieren etc. .

PaintGraphic
Dies ist die Hauptzeichenfunktion die vom Timer alle N Millisekunden aufgerufen
wird und die Bild für Bild eine neue Grafik zeichnet. Du zeichnest im Hintergrund auf eine BitMap
die Dir übergeben wird. Um das Kopieren dieser Bitmap ins Hauptfenster
oder verkleinerte Fenster brauchst Du Dich nit zu kümmern, dies
übernimmt die Prozedur "Flip" aus der Unit "Screen" und geht voll automatisch.

So. Ich hoffe das Euch dieer Roman hier nit zu lang und kompliziert war. Und ich hoffe das Ihr jetzt alle wie wild beginnt Eure eigenen Bildschirmschoner zu basteln! Ich hab versucht Euch dies so einfach wie möglich zu machen :drunken: !

Die Programme sind GiftWare, und, logischerweise, OpenSource!

Das ganze sollte ab Windows ´95 laufen, getestet habe ich es erfolgreich mit Windows ´98 SE und XP. Das Programm verwendet nur Standard-Delphi-Komponenten und schreibt im übrigen NIX in die System-Registrierung!

Ach ja: Vergesst blos nicht Euren Bildschirmschoner ins Verzeichniss "C\Windows" zu kopieren und seine Dateierweiterung von "*.exe" in "*.scr" zu ändern, sonst klappt das ganze nämlich nit!

--[Edit]-------------------------------

In den alten Versionen der Programme im Anhang befand sich in der Uses-Clausel der Unit Screen irrtümlicherweise noch ein Bezug auf IdleTimer, dies habe ich nun geändert.

Eine neue Version des LinesScreenSavers, der Delphi-Objekte anstalle der Old-Style-Objekte verwendet ist in Arbeit aber leider noch nicht ganz fertig, kommt aber demnächst :roll: !

Grüsse von TOC :stupid: !

Nicodius 31. Mär 2006 18:59

Re: Eigener Bildschirmschoner in Delphi
 
gehört schon fast in tutorial find ich :)


danke sehr gut geschrieben!


:thumb:

grüße Nico


edit// und ja er macht süchtig :mrgreen:

TOC 31. Mär 2006 19:05

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Zitat:

Zitat von Nicodius

danke sehr gut geschrieben!

grüße Nico
edit// und ja er macht süchtig :mrgreen:

Cool, freut mich das er Dir gefällt :???: !

Grüsse von TOC :cyclops: !

zynax421 31. Mär 2006 19:30

Re: Eigener Bildschirmschoner in Delphi
 
Ich hab zwar nur die Hälfte verstanden von dem was geschrieben wurde, aba meinen Trick zum Screensavererstellen hab ich net raußgeslesen.
Wenn ich jetzt was doppelt erzähl, tut so als ob der Beitrag hier net steht. lol
Ich schreib nen Programm mit Delphi, die .exe kopier ich in C:/Windows/system32/ und nen sie in .scr um. Wichtig is das der Dateiname mit ss anfängt (für Screensaver). Der Name folgt darauf.
Also mögliche Dateinamen sind zm Beispiel: "sscars.scr" "ssurlaub.scr" oder "ssbildschirmschoner.scr".
Den Screensaver kann man dann aufm Desktop unter Rechtklick/Eigenschaften/Bildschirmschoner auswählen.
Ich hoff der Tipp hat was gebracht.

TOC 31. Mär 2006 19:40

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Zitat:

Zitat von zynax421
Ich hab zwar nur die Hälfte verstanden von dem was geschrieben wurde, aba meinen Trick zum Screensavererstellen hab ich net raußgeslesen.
Wenn ich jetzt was doppelt erzähl, tut so als ob der Beitrag hier net steht. lol
Ich schreib nen Programm mit Delphi, die .exe kopier ich in C:/Windows/system32/ und nen sie in .scr um. Wichtig is das der Dateiname mit ss anfängt (für Screensaver). Der Name folgt darauf.
Also mögliche Dateinamen sind zm Beispiel: "sscars.scr" "ssurlaub.scr" oder "ssbildschirmschoner.scr".
Den Screensaver kann man dann aufm Desktop unter Rechtklick/Eigenschaften/Bildschirmschoner auswählen.
Ich hoff der Tipp hat was gebracht.

Durch ausprobieren hab ich herausgefunden das der Name des ScreenSAvers eigentlich kein grosse Rolle spielt. Man nuss nur die Dateierweiterung auf "*.scr" ändern und das ganze ins Verzeichnis "c/windows" kopieren. Dann kann man ihn über "Eigenschaften von Anzeige/Bildschirmschoner" aktivieren und konfigurieren.

Ein Bildschirmschoner muss seine verkleinerte Darstellung anzeigen können und die Kommandozeile auf "/S" oder "/C" oder "/P" überprüfen und dann entsprechend reagieren. Das ist schon ein gewisser Programmieraufwand.

Grüsse von TOC!

TOC 17. Apr 2006 19:38

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Es gibt ein UpDate! Hier kommt ScreenSaver V 1.1!

Also, es hat mich genervt das in Windows 98 und Windows XP die Grösse des verkleinerten Beispielfensters unterschiedlich ist, bei XP um ein Pixel in X und Y grösser!
Naja. Die neue Version holt sich mit der Windoofs-Funktion 'GetClientRect(Wnd:HWnd; Rect:TRect):Boolean' nun also die aktuelle Grösse vom Fenster, anstatt einen festen Wert zu verwenden.
Ich denke das ist die bessere Lösung.

Sonst hat sich nix geändert!

Grüsse von TOC!

stz 22. Apr 2006 13:05

DANKE!
 
super,
vielen Dank!

Endlich hat mal jemand alle meine Probleme mit Bildschirmschonern gelöst :-D :-D

TOC 23. Apr 2006 16:15

Re: DANKE!
 
Hi!

Zitat:

Zitat von stz
super,
vielen Dank!

Endlich hat mal jemand alle meine Probleme mit Bildschirmschonern gelöst :-D :-D

Hey, cool das sich mal jemand drüber freut!

Wie gesagt, du brauchst nur zwei Units vom 'Empty ScreenSaver' für Deinen eigenen Bildschirmschoner abzuändern :stupid: !

Grüse von TOC!

DP-Maintenance 23. Apr 2006 16:47

DP-Maintenance
 
Dieses Thema wurde von "Chakotay1308" von "Open-Source" nach "Tutorials und Kurse" verschoben.
Passt eher zu den Tutorials.

Koolance 30. Jun 2006 13:41

Re: Eigener Bildschirmschoner in Delphi
 
Ich muss dir auch meinen Dank aussprechen, ich habe zuerst einen Screensaver unter Verwendung von TScreensaver programmiert. Der hat aber auf diversen Computern Probleme gemacht. Heute habe ich deinen getestet und ein bisschen angepasst und ein bisschen angepasst und er läuft einfach super. :hello:

Noch eine kleine Anmerkung. Ich habe in mit Delphi 2006 kompiliert und zuerst kam die Fehlermeldung das die IdleTimer.dcu nicht gefunden wird. Nachdem ich IdleTimer aus den Uses entfernt habe ließ er sich kompilieren.

stz 30. Jun 2006 17:23

Re: Eigener Bildschirmschoner in Delphi
 
Zitat:

Zitat von TOC
Ach ja: Vergesst blos nicht Euren Bildschirmschoner ins Verzeichniss "C\Windows" zu kopieren und seine Dateierweiterung von "*.exe" in "*.scr" zu ändern, sonst klappt das ganze nämlich nit!

Hi, noch ein paar kleine Hinweise:

Im Dateiexplorer kann man im Kontextmenü eines Bildschirmschoners installieren auswählen. Dabei ist es egal, in welchem Ordner der Bildschirmschoner sich befindet. Nach dem Installieren taucht er automatisch in der Liste der Bildschrimschoner auf, als würde er sich im Ordner %WINDIR% oder %WINDIR%\system32 befinden.

Wer das oben Zitierte nicht immer mit der Hand machen möchte, kann in der Delphi IDE unter Projekt -> Optionen -> Anwendung -> Ausgabe eine Erweiterung der Zieldatei eintragen ("scr") und unter Projekt -> Optionen -> Verzeichnisse/Bindungen ein Ausgabeverzeichnis (z.B. "C:\Windows\").
Das war jetzt D2005, alle anderen müssen halt suchen ;-)

Gruß
Malte

TOC 30. Jun 2006 17:57

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Zitat:

Zitat von Koolance
Ich muss dir auch meinen Dank aussprechen, ich habe zuerst einen Screensaver unter Verwendung von TScreensaver programmiert. Der hat aber auf diversen Computern Probleme gemacht. Heute habe ich deinen getestet und ein bisschen angepasst und ein bisschen angepasst und er läuft einfach super. :hello:

Noch eine kleine Anmerkung. Ich habe in mit Delphi 2006 kompiliert und zuerst kam die Fehlermeldung das die IdleTimer.dcu nicht gefunden wird. Nachdem ich IdleTimer aus den Uses entfernt habe ließ er sich kompilieren.

Es freut mich das ich Dir mit dem Tutorial weiterhelfen konnte.

Der TIdleTimer ist eine meiner selbstgebastelten Komponenten. Meine Kompos findest Du hier: Meine (Tocs) Delphi-Komponenten als Paket. Das Problem: Einige Delphi-Versionen vergessen beim Installieren eines Pakets den Suchpfad für die Bibliothek zu erweitern. Bei D3 kein Problem, aber bei D7 Personal muss man diesen Pfad auf die *.dcu´s von Hand entsprechend erweitern! Der Idle-Timer ist wesentlich schneller als ein normaler TTimer!

Grüsse von TOC!

TOC 9. Jul 2006 15:55

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Also, ich hab´s extra nochmal gecheckt! Ürsprünglich verwendete mein ScreenSaver einen TIdle-Timer, eine meiner selbstgebastelten Komponenten. Hinterher habe ich diesen Timer rausgeworfen damit der ScreenSaver von meinen Komponenten unabhängig wird und über "Application.OnIdle" wird nun eine Timersteuerung simuliert. Nur hab ich vergessen den TIdleTimer aus der Uses-Klausel zu entfernen, sorry :cry: ! Schmeisst diese "Uses IdleTimer" einfach aus dem Quellcode raus, dann könnt ihr den ScreenSaver kompilieren!

Grüsse von TOC :stupid: !

Catbytes 9. Jul 2006 16:44

Re: Eigener Bildschirmschoner in Delphi
 
Hi,

oder man nimmt einfach die gute Kompo von Jon Baker.

Klick mich

TOC 10. Jul 2006 17:44

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Hab mir TScreenSaver grad mal runtergeladen, das muss ich mir mal ansehen!

Danke für den Link!

Grüsse von TOC!

Privateer3000 23. Mai 2008 12:51

Re: Eigener Bildschirmschoner in Delphi
 
Hallo
hab mir das Tut angesehen und wollte
das ganze testen, allerdings wird die
IdleTimer.dcu vermisst...

Warum?

TOC 25. Mai 2008 11:39

Re: Eigener Bildschirmschoner in Delphi
 
Hi!

Zitat:

Zitat von Privateer3000
Hallo
hab mir das Tut angesehen und wollte
das ganze testen, allerdings wird die
IdleTimer.dcu vermisst...

Warum?

Sorry das ich erst so spät antworte.

IdleTimer ist eine meiner selbsgebastelten Komponenten die ich in den Programmen anfangs noch verwendet habe. Später habe ich diese Komponente gelöscht und den Timer in das Programm selbst eingebaut, habe aber vergessen in der Unit Screen das 'Uses IdleTimer' zu entfernnen :oops: ! Naja, und da meine Komponenten in meinem Delphi natürlich installiert sind gabs beim compilieren und Testen keinen Fehler...

Wie auch immer. Ich habe ganz am Anfang von diesem Thread nun also die neuen Programme angehängt in denen dieser Fehler behoben ist. Du kannst sie Dir runterladen oder in der Version die Du schon hast einfach 'IdleTimer' aus der Uses-Klausel der Unit 'Screen' entfernen, dann sollte alles klappen.

Grüsse von TOC :stupid: !

rollstuhlfahrer 25. Mai 2008 13:46

Re: Eigener Bildschirmschoner in Delphi
 
hi,

hab dein Tutorial gelesen, aber meiner Meingung nach fehlt noch was: Wie benenne ich einen Bildschirmschoner?
1.) Nach dem Dateiname,
2.) nicht nach dem Dateiname, nämlich so

Zitat:

Zitat von Bornemaxx
Quelle: http://www.delphipraxis.net/internal...=812925#812925
Code:
STRINGTABLE
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
{
1,    "Mein Bildschirmschoner"
}

rollstuhlfahrer
PS: ein Verweis auf http://www.delphipraxis.net/internal...t.php?t=123031 wäre nicht schlecht

MuTzE.Y85 13. Sep 2012 15:17

AW: Eigener Bildschirmschoner in Delphi
 
Schon sehr alt, aber ich hab da mal ne Frage :)


Ich hab ein Problem mit meinem Bildschirmschoner.
Das Problem ist, dass die Preview, wenn einmal ausgewählt, IMMER angezeigt wird. Auch wenn ein anderer Bildschirmschoner gewählt wird.
Woran liegt das? Bei dir klappt das ohne Probleme. An welcher Stelle muss ich denn meinem Schoner sagen, dass er aufhören soll?

Hat das was mit dem Sendmessage zu tun? Sowas nutze ich nämlich (noch) nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz