[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

delphi switch a running application to another monitor

Posted on 2014-10-29
9
Medium Priority
?
1,433 Views
Last Modified: 2014-10-31
In Delphi, how can I tell another running application to switch from one monitor to another?
0
Comment
Question by:plumothy
  • 5
  • 4
9 Comments
 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 40411874
Depending on how you set second monitor: mirror, clone, extend first one,....
If you extend windows desktop there is windows api: SetWindowPos
Simply find second app window handle (FindWindow) and set position:
setWindowPos(SecAppHandle, HWND_TOPMOST, x1, y1, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);

Open in new window


width, height with 0 = don't change size - just move
0
 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 40411985
forgot ... x1 is width of first screen (Screen.Width) + x pos on second screen.
0
 

Author Comment

by:plumothy
ID: 40412647
Sinisa Vuk,
Many thanks for your response. Unfortunately, it does not work for me.

My app is running on Monitor[0] while a Powerpoint presentation is being shown on a projector (Monitor[1]) - while displays are in Extended mode.

My app successfully switches the displays to Duplicate mode in order to show itself on the projector and the laptop at the same time.

Then, I want it to switch back to extended mode. This works OK but the slide show window is still on Monitor[0], so I want to put it back on Monitor[1]. Hence my question.

Here is my code after your response:
procedure TfrmMain.actDuplicateDisplaysExecute(Sender: TObject);
begin
  FSlideShowX := Screen.Monitors[0].Width;   // remembers width of primary monitor (was initialised to -1)
  ShellExecute(0, 'open', 'DisplaySwitch.exe', '/clone', '', 0);  // switches display into Duplicate mode
  Application.BringToFront;  // ensures this app comes to the front
end;


procedure TfrmMain.actExtendDisplayExecute(Sender: TObject);
var
  hSlideShowWindow: hwnd;
begin
  if Screen.MonitorCount > 1 then begin      // only execute this if there is more than one monitor
    ShellExecute(0, 'open', 'DisplaySwitch.exe', '/extend', '', 0);  // switch display into Extended mode
    hSlideShowWindow := GetWindowHandle('Slide Show');   // find the powerpoint slide show window handle
    if ((hSlideShowWindow <> 0) and (FSlideShowX > -1)) then begin       // if the slide show window was found and its X position has been previously stored
      SetWindowPos(hSlideShowWindow, HWND_TOPMOST, FSlideShowX, 0, 0, 0, SWP_SHOWWINDOW);  // set the new position of the slide show window
    end;
  end;
end;

Open in new window

Clearly, I am still doing something wrong.
Can you see what it is?
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 40412664
this
SetWindowPos(hSlideShowWindow, HWND_TOPMOST, FSlideShowX, 0, 0, 0, SWP_SHOWWINDOW); 

Open in new window

is wrong. Don't use SWP_SHOWWINDOW - but SWP_NOSIZE instead.
0
 

Author Comment

by:plumothy
ID: 40412845
OK, done that. However, I have noticed that there is a delay of a few seconds after calling DisplaySwitch.exe while Windows actually switches into Extended mode.

This means that my call to SetWindowPos is occurring too early. To test this theory I made it wait 10 seconds (sleep) before calling SetWindwPos.

While this works, it is not very satisfactory. So, I show a message telling the user to click OK after the display has finished switching - then it calls SetWindowPos. This is better, but still not ideal.

Is there a proper way of delaying the call to SetWindowPos until after the display has finished switching?
0
 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 40413347
this is very simple solution - just wait for MonitorCount changes:
var
  scr: TScreen;
  monNum: Integer;
begin
  while True do
  begin
    scr := TScreen.Create(Application);
    try
      monNum := scr.MonitorCount;
    finally
      scr.Free;
    end;
    if monNum > 1 then Break;
    Sleep(100);
    Self.Repaint;
  end;

Open in new window


- you can add Timeout option too - to be safe. TScreen will make list on its creation.
0
 

Author Comment

by:plumothy
ID: 40415158
Sinisa Vuk,

Many thanks for your help. It is almost working as I would like it.

The only issue now is that SetWindowPos doesn't set the Powerpoint slide show window in the same position each time it is called (even though the parameters given to it are always the same).

When my application's main form is created I store the width of the primary monitor in a field called FSlideShowX (which is 720 on my laptop).

The user starts their slide show and eventually switches to my app and presses a hot key to get it to call "DisplaySwitch.exe /clone". They do what they need to do in my app and when it is time, they press another hot key to switch back to extended mode. I wait for the switch using your code (with a timeout) and then call:
SetWindowPos(hSlideShowWindow, HWND_TOPMOST, FSlideShowX, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER);

Open in new window

The user can switch between them as often as they need to.

That works except each successive call to SetWindowPos puts the slideshow in a slightly different position. It gradually creeps down and to the right even though the X and Y values being passed to it are always 720 and 0 respectively.

Do you have any idea what might be causing that?
0
 
LVL 28

Accepted Solution

by:
Sinisa Vuk earned 2000 total points
ID: 40415179
try use another api function:

var
  r: TRect;
begin
  GetWindowRect(PPHandle, r);
  MoveWindow(PPHandle, 0, 0, (r.Right-r.Left), (r.Bottom-r.Top), True);

Open in new window

0
 

Author Closing Comment

by:plumothy
ID: 40415346
Sinisa Vuk

That now works perfectly - thank you.

I did not use GetWindowRect because the laptop and projector might have different resolutions. Instead, I used the BoundRect of the 2nd monitor after switching to extended display mode.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
There are more than twenty applications to turn Webcam into home and  small business security. Let's discuss one of the most easy ones to install. If you do not have already installed the drivers to the pc for your webcam, you'll need to do that …
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Planning to migrate your EDB file(s) to a new or an existing Outlook PST file? This video will guide you how to convert EDB file(s) to PST. Besides this, it also describes, how one can easily search any item(s) from multiple folders or mailboxes…
Suggested Courses

613 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question