-1

I am working with Delphi 10.4.2 in Windows 10 (virtualized in Parallels) on a dual monitor system. To recreate the problem on a multi-monitor system, create a new Windows VCL Application and place two buttons on the form: btnPrimaryMonitor and btnSecondaryMonitor. Then insert this code by creating click handlers for the two buttons:

procedure TForm1.btnPrimaryMonitorClick(Sender: TObject);
begin
  RepositionFormToMonitor(0);
  EnableDisableButtons;
end;

procedure TForm1.RepositionFormToMonitor(const aMonitor: Integer);
const
  offset = 2;
begin
  Self.Width := Screen.Monitors[aMonitor].Width - offset;
  Self.Height := Screen.Monitors[aMonitor].Height - offset;

  Self.Top := Screen.Monitors[aMonitor].Top;
  Self.Left := Screen.Monitors[aMonitor].Left;
end;

procedure TForm1.btnSecondaryMonitorClick(Sender: TObject);
begin
  RepositionFormToMonitor(1);
  EnableDisableButtons;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  EnableDisableButtons;
  Self.BorderStyle := bsNone;
  Self.FormStyle := fsStayOnTop;
  RepositionFormToMonitor(0);
end;

procedure TForm1.EnableDisableButtons;
begin
  btnPrimaryMonitor.Enabled := (Self.Monitor.MonitorNum = 1);
  btnSecondMonitor.Enabled := (Self.Monitor.MonitorNum = 0);
end;

This works perfectly, but as soon as I set offset = 1 or offset = 0 the screen becomes black!

The purpose of the code is to reposition the maximized stay-on-top Form from the primary monitor to the secondary monitor by clicking on the btnSecondMonitor button and then back to the primary monitor by clicking on the btnPrimaryMonitor button.

How can this problem be avoided?

AmigoJack
  • 5,234
  • 1
  • 15
  • 31
user1580348
  • 5,721
  • 4
  • 43
  • 105

1 Answers1

1

A few issues:

  1. You should not set WindowState to wsMaximized. In fact, you shouldn't touch this property at all.

  2. Setting BoundsRect will set Left, Top, Width, and Height, so there is no need to set Left and Top separately.

  3. To go back to the primary monitor, just set the form's BoundsRect.

Here's an example:

Create a new VCL project. Set the main form's BorderStyle to bsNone.

Then add the following code:

procedure TForm1.FormCreate(Sender: TObject);
begin
  for var i := 0 to Screen.MonitorCount - 1 do
  begin
    var btn := TButton.Create(Self);
    btn.Parent := Self;
    btn.Caption := i.ToString;
    btn.Tag := i;
    btn.OnClick := MonitorButtonClick;
    btn.Top := 8;
    btn.Left := 8 + (btn.Width + 8) * i;
  end;
end;

procedure TForm1.MonitorButtonClick(Sender: TObject);
begin
  BoundsRect := Screen.Monitors[(Sender as TButton).Tag].BoundsRect;
end;

If this code doesn't work properly on your system, you probably have some problem with that Windows system. This should work flawlessly.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • (The Q was rewritten while this A was written, so the A doesn't exactly match the new Q.) – Andreas Rejbrand Jul 29 '21 at 09:35
  • The code in the Q doesn't use `wsMaximized`. Have you tried the code in the Q? Set `offset = 2` or `offset = 1`. – user1580348 Jul 29 '21 at 11:07
  • Your code creates the same black screen problem as the code in my Q. Have you really TRIED and USED your code on your system? In your code, switching to the second monitor does work. But then switching back to the primary monitor makes the screen black. Have you really used your code in this way? – user1580348 Jul 29 '21 at 11:18
  • @user1580348: [The first version of your Q](https://stackoverflow.com/revisions/68571555/1) (which was the one I saw) used `wsMaximized`. Yes, of course I have tried this code! I never publish code at SO without first testing it extensively. This works perfectly on my four-monitor system. And on all other systems on which I have done similar things in the past. If you are able to, test this on a different Windows system. I bet it will work perfectly there. – Andreas Rejbrand Jul 29 '21 at 11:45
  • 1
    Here's a video: https://privat.rejbrand.se/vclmons.mov – Andreas Rejbrand Jul 29 '21 at 11:51
  • (And just for the record, I didn't downvote your Q.) – Andreas Rejbrand Jul 29 '21 at 11:52
  • I have tried your code on another computer with Windows 7. On that Windows 7 computer (with the same two monitors), it works flawlessly. So why it does not work on my Windows 10 system? Could anybody try it out on a **Windows 10** system? – user1580348 Jul 29 '21 at 13:01
  • I really don't think the problem is Windows 10, because Microsoft usually has excellent compatibility between its OS versions. But let's wait for some other Win 10 user to test it. Instead, I think there is something strange with your particular Win 10 system. Maybe you have installed some "desktop enhancers" or "power toys" or have a very strange graphics driver. – Andreas Rejbrand Jul 29 '21 at 13:04
  • @AndreasRejbrand Your video shows only three monitors, not four. Maybe you can't count...? :D Now make it a GIF. – AmigoJack Jul 29 '21 at 13:10
  • @AmigoJack: The fourth one is so far away it would have made the video less instructive (since all monitors would have been too small). https://privat.rejbrand.se/fourmonitors.jpg – Andreas Rejbrand Jul 29 '21 at 13:20
  • FYI, I don't use any "desktop enhancers" or "power toys" (except the Delphi IDE ;-) – user1580348 Jul 29 '21 at 13:47
  • Dear Andreas, I have now tried the program with your code on **ANOTHER** Windows 10 system (as a VM on the same Parallels where I run my main Windows 10 with Delphi). And the black screen error occurs also on this other Windows 10! So this is proof that Windows 10 causes the black screen error: On Windows 7: It works. On Windows 10 twice: Problem. – user1580348 Jul 29 '21 at 14:14
  • @user1580348: Likely related to the VM thing. As a workaround, does it help to `Invalidate` immediately after `BoundsRect := ...`? – Andreas Rejbrand Jul 29 '21 at 14:16
  • @AmigoJack: Do you happen to have a multimonitor Windows 10 system? – Andreas Rejbrand Jul 29 '21 at 14:17
  • Do you mean `Self.Invalidate`? – user1580348 Jul 29 '21 at 14:18
  • Yes. `Invalidate` and `Self.Invalidate` has the exact same effect in a method. – Andreas Rejbrand Jul 29 '21 at 14:20
  • I wasn't explicitly sure you referred to the form. I always use redundant scope prefixes. It makes things clearer. – user1580348 Jul 29 '21 at 14:22
  • I have found the cause of the black screen error: There is a strange "full-screen mode" - I don't know whether this "full-screen mode" is provided by Parallels or by the Mac system or by another program. However, when I touched the upper edge of my secondary monitor, a monitor-wide menu dropped down with an option to leave the full-screen mode which I did. After that the error did not occur again. – user1580348 Jul 29 '21 at 14:42
  • 1
    Yes, I knew it wasn't a Windows or VCL problem! – Andreas Rejbrand Jul 29 '21 at 14:53
  • However, this "full-screen mode" IMO makes no sense when using the VM in COHERENCE mode. Here is the documentation about the "full-screen mode" in Parallels: https://download.parallels.com/desktop/v10/docs/pt_BR/Parallels%20Desktop%20User's%20Guide/33242.htm – user1580348 Jul 29 '21 at 15:06
  • It seems that when running the VM in COHERENCE mode then Parallels provides this full-screen mode separately for each application window that has its size expanded to the full monitor screen. That was the cause for the **offset** value in my Q causing the error: When offset is 0 or 1 then Parallels interprets this as a MAXIMIZED window and automatically sets the full-screen mode for this application (if the full-screen mode is activated in the VM configuration which has numerous corner cases and exceptions). This seems to interact with the Mac graphics driver and then causes the error. – user1580348 Jul 29 '21 at 15:31
  • In general, working with remote desktops, virtual machines, etc. often causes issues that aren't present when running a local, native, physical Windows machine. – Andreas Rejbrand Jul 29 '21 at 15:34
  • As the operating systems are becoming more and more part of the CLOUD, they are not any more "native" or "physical" as they were a few years ago. I imagine that Microsoft could "outsource" even parts of the KERNEL to the cloud one day... – user1580348 Jul 29 '21 at 15:42
  • 2
    @user1580348 I'd always mention when operating on VMs because every of those are far from perfect. Just try a different virtualization software to check your black screen problem and please put those crucial details into your questions next time to make them halfway reproducible. – AmigoJack Jul 29 '21 at 15:59
  • As soon as Windows 11 becomes officially available in the consumer market I will buy a small cheap W11 machine for the sole purpose of testing my software. But then I will run out of available network switch ports... – user1580348 Jul 29 '21 at 16:16
  • I would expect a lot of gratitude for the work of people like me investing a lot of time and resources into the research of the behavior of Delphi programs inside virtual machines. This is precious inestimable knowledge. – user1580348 Jul 29 '21 at 17:22
  • 2
    "I would expect a lot of gratitude ..." Well, next time it would help if you actually mentioned from the outset that you are using a VM in your q ... – MartynA Jul 30 '21 at 07:25
  • @MartynA You should work on your social behavior - MICRO-AGGRESSIONS are destructive and don't help. Take an example from Andreas' exemplary social behavior. – user1580348 Jul 30 '21 at 13:08