Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

delphi switch a running application to another monitor

Posted on 2014-10-29
9
Medium Priority
?
1,254 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

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

In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
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 …
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

927 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