Reputation: 31
I use software that mirrors my PC to the TV. Works well, but the transfer crashes when transferring screensavers.
One of the screensavers offers the option to start it in its own window - so the mirroring works perfectly. So I'm looking for a way to start the screensaver in its own window (a Form, for example) and then transfer it to the television.
Unfortunately, the first attempt doesn't work; I probably don't get the right handle to the screensaver. Starting with the "/P"
parameter didn't work, either.
Can someone help me? The OS is "Windows 11".
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
hMyApp: hwnd; //Handle auf das Window welches man im Form braucht
vWinHnd: hwnd;
VExePfad: string;
vParam: string;
begin
if Key = ord(32) then
begin
try
vWinHnd := Form1.Handle;
vParam := '/P ' + inttostr(vWinHnd) ;
vExePfad := 'C:\Windows\System32\Bubbles.scr';
ShellExecute(0,
nil,
PChar(vExePfad),
//PChar(vParam),
nil,
nil,
SW_MINIMIZE );
application.ProcessMessages;
hMyApp := GetwindowDc(0);
form1.Caption := 'Handle ' + inttostr(hMyApp);
Windows.SetParent(hMyApp, vWinHnd); //Parent mit Windows.SetParent
ShowWindow(hMyApp, SW_MAXIMIZE);
finally
Releasedc(0, hMyApp);
end;
end;
if Key = ord(27) then
begin
Application.Terminate;
end;
end;
UPDATE
I now tried the following (without SetParent
and ShowWindow
, using "/P"
and "/p"
), but that didn't work either:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
hMyApp: hwnd; //Handle auf das Window welches man im Form braucht
vWinHnd: hwnd;
VExePfad: string;
vParam: string;
begin
if Key = ord(32) then
begin
try
vWinHnd := self.Handle;
vParam := '/p ' + inttostr(vWinHnd) ;
vExePfad := 'C:\Windows\System32\Bubbles.scr';
ShellExecute(0,
'open',
PChar(vExePfad),
PChar(vParam),
nil,
SW_SHOWMAXIMIZED);
//application.ProcessMessages;
//hMyApp := GetForegroundWindow();
//Windows.SetParent(vWinHnd,hMyApp ); //Parent mit Windows.SetParent
form1.Caption := vParam;
//ShowWindow(hMyApp, SW_SHOWMAXIMIZED );
finally
// Releasedc(0, hMyApp);
end;
end;
if Key = ord(27) then
begin
Application.Terminate;
end;
end;
Upvotes: 1
Views: 154
Reputation: 31
Remy Lebeau said the answer in a comment:
Then the screensaver is likely not implemented correctly, as all screensavers are expected to handle the
/p
parameter for displaying a preview in the OS's own configuration screen. The only other things I can suggest is 1) try using'/p:<hwnd>'
instead of'/p <hwnd>'
, and 2) try usingCreateProcess()
instead ofShellExecute()
.
Here is the code that works thanks to him.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
vWinHnd: hwnd;
VExePfad: string;
vParam: string;
SI: TStartupInfo;
PI: TProcessInformation;
begin
if Key = ord(32) then
begin
try
vWinHnd := self.Handle;
vParam := '/p ' + inttostr(vWinHnd);
vExePfad := 'C:\Windows\System32\Bubbles.scr';
ZeroMemory(@SI, SizeOf(SI));
SI.cb := SizeOf(SI);
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_SHOWMAXIMIZED;
if CreateProcess(nil, PChar(vExePfad + ' ' + vParam),
nil,
nil,
False,
0,
nil,
nil,
SI,
PI) then
begin
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
Form1.FormStyle := fsNormal;
end;
end;
if Key = ord(27) then
begin
Application.Terminate;
end;
end;
end.
Upvotes: 2