Autor |
Beitrag |
Gewuerzgurke
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Mo 13.04.09 13:57
Hallo, ich weis, zum Thema Bildschirmschoner gibt es schon zahlreiche Themen aber ich habe trotzdem noch einige offene Fragen, die noch nicht geklärt wurden oder die ich nicht gefunden habe:
1. Wo speichert der Bildschirmschoner seine Einstellungen?
Ich habe bereits den Starfield-Schoner von Windows untersucht, konnte aber nach ändern der Einstellungen (also Sternanzahl und Geschwindigkeit) keine Änderungen an der Registry feststellen - aber wo sonst werden diese Informationen gespeichert?
2. Wie kann man den Namen des Bildschirmschoners verändern?
Mein eigener Schoner heißt 'Starfield2.scr' und ist im Menü (Eigenschaften -> Bildschirmschoner) unter dem Namen Starfield2 aufgelistet - logisch. Der 'Original-Starfield-Schoner' aber heißt in system32 'ssstars.scr', im Menü aber steht Starfield - wie kann das sein?
3. Wie kann man die Vorschau einstellen?
Beim Öffnen des Menüs wird der Schoner mit dem Parameter /p aufgerufen. Dadurch soll der Schoner als Vorschau gestartet werden - aber wie geht das? Ich habe dazu nur ein Beispiel in C++ gefunden. Muss man ein Fenster erstellen, das dann immer die Position der Vorschaubox hat, mit DirectX auf die Box rendern (per Handle) oder ganz anders?
Danke schonmal für jede Antwort...
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 13.04.09 14:07
Also die Einstellungen werden sicherlich irgendwo in der Registry zu finden sein, jedenfalls solltest du sie dort ablegen.
Zum Namen: Hast du denn deiner Anwendung einen Titel gegeben? Ich muss mal schauen, aber ich vermute doch, dass der verwendet wird.
Und zur Vorschau: Wenn du ein Beispiel in C++ hast, dann schau doch einfach da nach wie das dort gemacht wird.
Soweit ich mich erinnere bekommst du mit /p auch ein Handle auf dem du zeichnen sollst.
|
|
turboPASCAL
      
Beiträge: 193
Erhaltene Danke: 1
Win XP / Vischda
D6 PE / D2005 PE
|
Verfasst: Mo 13.04.09 18:05
Also ich habe mir vor längerer Zeit mal einen nonVCL-(Template)-Bildschirmschoner gebaut.
In diesem Falle finde ich die verwendung non nonVCL effectiver da man besser Kontrolle
über das Vorgehen in der Anwendung hat.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296:
|
program TemplateScreenSaver;
{$R 'TemplateScreenSaver.RES' 'TemplateScreenSaver.RC'} {$DESCRIPTION 'tPs Template-Screensaver'} {$E scr}
uses Windows, Messages, CommCtrl;
const WndClassName = 'MyScrWndClass'; AppName = 'TemplateScreenSaver';
IDD_DLG = 100; IDC_BTN_OK = 101;
TimerElapse = 100;
type TScreenMode = (scrmStart, scrmPreview, scrmConfig);
var AppHWND: HWND = 0; WndClass: TWndClass; Msg: TMsg; ScreenMode: TScreenMode; WndRect: TRect; ParentWnd: HWND; StartupCursorPos:TPoint;
Counter: Integer = 0 ;
function _StrToInt(Value: String): Integer; var err: Integer; begin Val(Value, Result, err); end;
function _IntToStr(Value: Integer): String; begin Str(Value, Result); end;
procedure OnTimerEvent(hWnd: HWND); var DC: HDC; Pen, oldPen: HPen; OldBKMode: Integer; i : Byte; Txt: String; begin DC := GetDC(AppHWND); case Random(2) of
0: for i := 0 to 255 do begin SetPixel( DC, random(WndRect.Right), random(WndRect.Bottom), RGB(random(256), random(256), random(256))); end;
1: begin Pen := CreatePen(PS_SOLID, 1, RGB(random(256), random(256), random(256))); oldPen := SelectObject(DC, Pen);
MoveToEx( DC, random(WndRect.Right), random(WndRect.Bottom), nil); LineTo( DC, random(WndRect.Right), random(WndRect.Bottom));
SelectObject(DC, oldPen); DeleteObject(Pen); end; end;
Case ScreenMode of scrmStart: Txt := 'Normal'; scrmPreview: Txt := 'Preview'; end;
OldBKMode := SetBKMode(DC, TRANSPARENT); SetTextColor(DC, RGB(255, 0, 0)); TextOut(DC, 5, 5, PChar(Txt), Length(Txt)); SetBKMode(DC, OldBKMode);
ReleaseDC(hWnd, DC); end;
function DlgProc(hDlg: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM): lResult; stdcall; begin Result := 0; if wParam = SC_CLOSE then;
case msg of WM_INITDIALOG:; WM_COMMAND: begin case wParam of IDC_BTN_OK: EndDialog(hDlg, 1); end; end; end; end;
function ScreenSaverProc(hWnd: HWND; uMsg: UINT; wParam: wParam; lParam: LParam): lResult; stdcall; var CurrentPos:TPoint; begin Result := 0;
case uMsg of WM_CREATE: begin if ScreenMode = scrmStart then ShowCursor(FALSE); SetTimer(hWnd, 1, TimerElapse, nil); GetCursorPos(StartupCursorPos); end; WM_DESTROY: begin if ScreenMode = scrmStart then ShowCursor(TRUE); KillTimer(hWnd, 1); DestroyWindow(hWnd); PostQuitMessage(0); end; WM_ACTIVATE: if (wParam = Integer(FALSE)) then PostMessage(hWnd, WM_CLOSE, 0, 0); WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_KEYDOWN: begin if ScreenMode = scrmStart then PostMessage(hWnd, WM_CLOSE, 0, 0); end;
WM_MOUSEMOVE: begin if (ScreenMode = scrmStart) and (Counter >= 10) then begin GetCursorPos(CurrentPos);
If (CurrentPos.X-StartupCursorPos.X < -10) or (CurrentPos.X-StartupCursorPos.X > 10) or (CurrentPos.y-StartupCursorPos.Y < -10) or (CurrentPos.y-StartupCursorPos.Y > 10) then PostMessage(hWnd, WM_CLOSE, 0, 0); end; end;
WM_SYSCOMMAND: Case wParam of SC_MONITORPOWER: ; SC_SCREENSAVE, SC_CLOSE: Result := 0; end;
WM_TIMER: begin if Counter < (1000 div TimerElapse) then inc(Counter); OnTimerEvent(hWnd); end; else Result := DefWindowProc(hWnd, uMsg, wParam, lParam); end; end;
BEGIN InitCommonControls; if ParamCount = 0 then begin ScreenMode := scrmConfig; end else if ParamStr(1)[1] in ['-', '/'] then begin case ParamStr(1)[2] of 'S', 's': ScreenMode := scrmStart; 'P', 'p': ScreenMode := scrmPreview; 'C', 'c': ScreenMode := scrmConfig; end; end;
if System.HPrevInst = 0 then begin ZeroMemory(@WndClass, Sizeof(TWndClass));
with WndClass do begin Style := CS_VREDRAW or CS_HREDRAW or CS_SAVEBITS or CS_DBLCLKS; lpfnWndProc := @ScreenSaverProc; cbClsExtra := 0; cbWndExtra := 0; hbrBackground := GetStockObject(BLACK_BRUSH); lpszMenuName := nil; lpszClassName := WndClassName; hInstance := hInstance; hIcon := LoadIcon(0, IDI_APPLICATION); hCursor := LoadCursor(0, IDC_ARROW); end; RegisterClass(WndClass); end;
if ScreenMode = scrmStart then begin GetClientRect(GetDesktopWindow, WndRect); AppHWND := CreateWindowEx( WS_EX_TOPMOST, WndClassName, AppName, WS_VISIBLE or WS_POPUP , WndRect.Left, WndRect.Top, WndRect.Right, WndRect.Bottom, 0, 0, hInstance, nil); end else if ScreenMode = scrmPreview then begin ParentWnd := _StrToInt(ParamStr(2)); GetClientRect(ParentWnd, WndRect); AppHWND := CreateWindow( WndClassName, AppName, WS_CHILD or WS_VISIBLE, WndRect.Left, WndRect.Top, WndRect.Right, WndRect.Bottom, ParentWnd, 0, hInstance, nil); end else begin DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLG), AppHWND, @DlgProc); PostQuitMessage(0); end;
UpdateWindow(AppHWND);
while GetMessage(msg, 0, 0, 0) do begin TranslateMessage(msg); DispatchMessage(msg); end;
ExitCode := msg.wParam;
END. |
{$DESCRIPTION 'tPs Template-Screensaver'} legt den anzuzeigenden Namen des BS in der Windowsscreensavereinstellungs-Combobox fest.
Einloggen, um Attachments anzusehen!
_________________ Nein, ich bin nicht der turboPASCAL aus der DP, ich seh nur so aus...
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Mo 13.04.09 22:36
Zu 1:
Hm, also ich glaube nicht, dass die Einstellungen in der Registry gespeichert werden, denn das hätte dann unter Anderem den Nachteil, dass nach dem Löschen des Bildschirmschoners ein nutzloser Registry-Eintrag übrig bliebe.
Zu 2:
Wie ist das mit Titel genau gemeint? Application.Title := 'test'; bleibt wirkungslos...
{$DESCRIPTION 'test'} hat bei mir auch nicht funktioniert...
Hab' noch versucht in der ersten Zeile (in der .DPR) statt program Starfield2; program test; zu schreiben, hat aber auch nichts gebracht...
Zu 1 & 2:
Was ich für möglich halte, ist dass jeder Bildschirmschoner in eine Liste eingetragen wird, die sowol einen unabhängigen Namen als auch einen Block mit den Einstellungen enthällt, denn es werden im Menü nicht nur Bildschirmschoner aufgelistet, die sich in system32 befinden, sondern auch Solche, die durch einen Klick auf 'installieren' im Kontextmenü des Explorers zu vermuteter Liste hinzugefügt wurden.
Weis dazu jemand Genaueres?
Zu 3:
Stimmt, wenn /p übergeben wird, dann bekommt man mit ParamStr(2) tatsächlich ein Handle mitgeliefert. Aber was fange ich dann mit diesem Handle an? Wenn ich dieses Handle als Ziel für DirectX angebe, wird zwar die Auflösung auf die entsprechende Größe herabgesetzt, gerendert wird aber weiterhin auf mein eigenes Fenster. Ist ParamStr(2) das Handle eines Panel? Und wenn ja, wie kann ich dann darauf "malen"? Oder ist das anders gedacht?
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 13.04.09 22:39
Gewuerzgurke hat folgendes geschrieben : | Zu 3:
Stimmt, wenn /p übergeben wird, dann bekommt man mit ParamStr(2) tatsächlich ein Handle mitgeliefert. Aber was fange ich dann mit diesem Handle an? |
Das siehst du doch in dem Beispiel wie man es z.B. machen kann. Er hat ein neues Fenster als Anwendungsfenster als Childfenster des angegebenen Parameters erstellt.
Du kannst das natürlich auch mit deinem normalen Fenster per SetWindowLong erledigen, oder in den CreateParams auch.
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 13.04.09 23:09
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Di 14.04.09 12:52
@GTA-Place:
Nein, den Schlüssel HKCU\Software\Microsoft\Windows\CurrentVersion\Screensavers\ gibt es bei mir nicht.
@jaenicke:
Danke, das mit dem Vorschaufenster habe ich hinbekommen, so ähnlich wie hier ( www.delphi-forum.de/viewtopic.php?t=28809).
@turboPASCAL:
{$DESCRIPTION 'tPs Template-Screensaver'} scheint unter XP nicht zu funktionieren. Bei mir steht TemplateScreenSaver. Weis jemand, wie es unter XP heißen muss?
{$E scr} ist übrigens echt praktisch. 
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Di 14.04.09 14:12
Oh, sorry, unter XP ist es:
Quelltext 1:
| HKCU\Software\Microsoft\Screensavers\ |
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Di 14.04.09 19:53
Ich habe nur den Schlüssel HKEY_USERS\S-1-5-21-1826015776-1459285895-896997438-1005\Software\Microsoft\ScreenSavers gefunden... Darin scheinen die Bildschirmschoner tatsächlich ihre Einstellungen zu speichern. Bei mir aber nur Flowerbox, Pipes und Text3D - von Starfield keine Spur; ist ja auch nicht so wichtig. Ich werd' mal prüfen, ob diese Einstellungen nach löschen des Bildschirmschoners mit gelöscht werden.
Ich bin auch noch auf den Schlüssel HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\control.ini gestoßen, darin sind anscheinend auch Informationen über Bildschirmschoner gespeichert.
|
|
Timosch
      
Beiträge: 1314
Debian Squeeze, Win 7 Prof.
D7 Pers
|
Verfasst: Di 14.04.09 21:38
Gewuerzgurke hat folgendes geschrieben : | Ich habe nur den Schlüssel HKEY_USERS\S-1-5-21-1826015776-1459285895-896997438-1005\Software\Microsoft\ScreenSavers gefunden... Darin scheinen die Bildschirmschoner tatsächlich ihre Einstellungen zu speichern. |
Ist genau das gleiche. HKCU verweist ja bloß auf einen Teil von HKEY_USERS.
_________________ If liberty means anything at all, it means the right to tell people what they do not want to hear. - George Orwell
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Fr 17.04.09 18:13
Jetzt bleiben nur noch die Fragen offen, ob Einstellungen nichtmehr verwendeter Bildschirmschoner gelöscht werden (sollten) und wie {$DESCRIPTION 'tPs Template-Screensaver'} unter XP heißen muss... 
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 17.04.09 18:18
Gewuerzgurke hat folgendes geschrieben : | Jetzt bleiben nur noch die Fragen offen, ob Einstellungen nichtmehr verwendeter Bildschirmschoner gelöscht werden (sollten) |
Das macht ja das Setup, mit dem der installiert wurde, normalerweise, genau wie bei jeder anderen Software auch. Dafür gibts ja die Uninstallfunktion in der Systemsteuerung.
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Fr 17.04.09 20:20
Ja, schon, nur rentiert es sich überhaupt, wegen einer einzigen "SCR-Datei" gleich ein Uninstaller mitzuliefern?
Zu blöd aber auch, dass Windows eine Funktion "installieren" anbietet, aber keine Funktion "deinstallieren", die die Registy-Einträge löscht. Auch wenn's nur ein paar ... dutzend Bytes sind
Aber ich hab' mir gedacht, ich biete im Menü für die Einstellungen einen "Link" zum Deinstallieren an. Bleibt aber immer noch zu klären, wo Windows speichert welche Schoner installiert sind. Ich such nochmal in der Registry... 
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 17.04.09 20:34
Gewuerzgurke hat folgendes geschrieben : | Ja, schon, nur rentiert es sich überhaupt, wegen einer einzigen "SCR-Datei" |
Ich biete einfach immer ein Setup oder ein Zip an, das Setup wird meistens auch recht gut angenommen.
Aber das ist ja auch gar nicht nötig. Du kannst doch dein eigenes Programm als Uninstaller eintragen, wenn du die Einstellungen setzt, und dabei dein Programm mit /u starten zum Beispiel.
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Sa 18.04.09 10:13
Zitat: | Du kannst doch dein eigenes Programm als Uninstaller eintragen |
Ja, das ist auch eine gute Idee - nur müsste sich die EXE, bzw. SCR dann selber löschen. Aber wie geht das?
|
|
jakobwenzel
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: Sa 18.04.09 10:43
Zum Beispiel über ne .bat-Datei: Die können sich anschließend selber löschen. 
_________________ I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Sa 18.04.09 12:35
Mit einer BAT? Nur wie kann ich mit write einen Absatz schreiben? Hab' mal für's Erste folgende Procedure zum erstellen der BAT-Datei:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TFormKonfiguration.Deinstallieren(Sender: TObject); var VUninstaller : textfile; VUninstallerInhalt : string; begin VUninstallerInhalt := 'DEL ' + paramstr(0) + ' /f'; createFile( PChar(paramstr(0) + '_h5g8sh39kghdbejtr5h.bat'), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_NEW, FILE_FLAG_OVERLAPPED, 0); assignfile( VUninstaller, PChar(paramstr(0) + '_h5g8sh39kghdbejtr5h.bat')); rewrite(VUninstaller); write(VUninstaller,VUninstallerInhalt); closefile(VUninstaller); end; |
Nur brauche ich noch Absätze, um mehrere Befehle in die BAT zu packen (TASKKILL, etc.). ... + #13 + ... geht nicht, da kommt nur so ein leeres Kästchen...
|
|
jakobwenzel
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: Sa 18.04.09 12:47
WriteLn ist dein Freund, der normale Zeilenumbruch unter Windows wäre #13#10
_________________ I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
|
|
Gewuerzgurke 
      
Beiträge: 152
Win XP
Lazarus
|
Verfasst: Sa 18.04.09 16:23
So, ich habe die Procedure jetzt erweitert, sodass der Batch-File dann folgenden Inhalt hat:
Quelltext 1: 2: 3:
| TASKKILL /im Starfield2.scr DEL C:\Projekte\Pascal\Starfield2\Starfield2.scr /f DEL C:\Projekte\Pascal\Starfield2\Starfield2.scr_h5g8sh39kghdbejtr5h2.bat /f |
Dieser Batch-File führt zwar theoretisch die richtigen Schritte durch, nur praktisch schlägt die zweite Zeile fehl, mit der Bergründung "Der Zugriff wurde verweigert!". Anscheinend wartet TASKKILL nicht bis die entsprechende Anwendung vollstängig beendet und die Datei wieder freigegeben wird. Was kann man da machen?
TASKKILL /f /im Starfield2.scr hilft übrigens nicht.
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 18.04.09 16:49
Nix mit taskkill, mach einfach eine Schleife, die solange läuft wie die Datei existiert (if exist ... goto ...), und beende das Programm normal nach dem Aufruf der Batchdatei.
|
|
|