-2

Delphi 5 does not have a built-in function to set a Form on a monitor where a previous Form is opened in the case of dual monitors. For this, I have imported windows dll. I searched for this and found MonitorFromWindow() and MonitorFromPoint().

I implemented MonitorFromWindow() but am not able to implement MonitorFromPoint().

How do I get the monitor and set my Form on it?

function MonitorFromWindow(hwnd: HWND; dwFlags: DWORD): HWND; stdcall; external 'User32.dll';

procedure TSmForm.AfterCreateForm(Session: ISmSession; SmHelpContext: TDM_Int32; IsDLL: Boolean);
type
  HMONITOR = type THandle;
var
  MBMonitor: HMONITOR;
const
  MONITOR_DEFAULTTONEAREST = $00000002;
begin
  //If you decide to remove the next two lines, make sure no one use this function and assume init of SmSession is here (like ScriptMaintanance etc.).
  if SmSession<>Session then
    SmSession := Session;
  if SmHelpContext > 0 then
    HelpContext := SmHelpContext;
  //Following lines ensure that if the form resides in a dll, its icon is the same as the host application's
  if (IsDLL) then
  begin
    if (Icon.Empty) and (ParentHWND <> 0) then
      SendMessage(Handle, WM_SETICON, 1, SendMessage(ParentHWND, WM_GETICON, 1, 0));
  end;

  MBMonitor := MonitorFromWindow(Self.Handle, MONITOR_DEFAULTTONEAREST);

  //HWND_NOTOPMOST
  SetWindowPos(Self.Handle, MBMonitor, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end { of TSmForm.AfterCreateForm } ;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • What specific problem are you having with the code you've posted? It makes no effort to translate MonitorFromPoint, so how do you know you can't do it? – Ken White May 08 '17 at 12:39
  • `function MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWORD): HMONITOR; stdcall; external user32` it really could hardly be any easier. Have you tried anything at all? I have told you so many times that if header translations are too hard from you then you can use the translations from the JEDI libraries. Neglecting error handling is a bad policy too. Don't ignore errors. – David Heffernan May 08 '17 at 13:43
  • I can't use JEDI Libraries because it is not allowed to use 3 party libraries in our application. – user7424581 May 08 '17 at 14:35
  • Oh for heaven's sake. Read the code there, and copy what you need. But ok, now I see that you've done that. You did it wrong though. It returns an HMONITOR, not a HWND. Your lack of error checking is killing you. Why don't you try to learn and understand some of this code. – David Heffernan May 08 '17 at 17:17
  • **public void Concatenate([MarshalAs(UnmanagedType.IUnknown)] Form f1) //LPWStr { var screen1 = Screen.FromPoint(Cursor.Position); f1.StartPosition = FormStartPosition.Manual; f1.Left = screen1.Bounds.Left + screen1.Bounds.Width / 2 - f1.Width / 2; f1.Top = screen1.Bounds.Top + screen1.Bounds.Height / 2 - f1.Height / 2; }** I tried this in c# but not able to implement in delphi 5. Please help with code @Ken White sir – user7424581 May 09 '17 at 12:48
  • I don't care what you tried in C#. The question at hand here is what have you tried yourself to port `MonitorFromPoint` to **Delphi**? – Ken White May 09 '17 at 12:56
  • please guide about it. what should i do in above code – user7424581 May 09 '17 at 13:01
  • actually i am not getting what to do to take form on proper monitor where previous form opened. i know to where call those function but don't know how to write them. Please help @KenWhite – user7424581 May 23 '17 at 07:07
  • Utter rubbish! I gave you [the answer](https://stackoverflow.com/a/41954280/224704) - _that it **is supported** in D5_ the first time you asked the question. You even commented that you got it working in a brand new project. The issue was that your project is doing some abnormal WinAPI handling that's conflicting with standard Delphi behaviour. – Disillusioned May 23 '17 at 17:03
  • Possible duplicate of [Dual monitor issue](https://stackoverflow.com/questions/41950680/dual-monitor-issue) – Disillusioned May 23 '17 at 17:04
  • @KenWhite sir i found a solution but now problem with TOpenDialog of windows please see question [link](https://stackoverflow.com/questions/44385904/how-to-position-pop-up-topendialog-always-on-monitor-where-my-application-form) – user7424581 Jun 08 '17 at 06:16

2 Answers2

1

MonitorFromWindow() returns an HMONITOR, not an HWND. And you can't pass an HMONITOR to SetWindowPos(), like you are trying to do. It accepts only HWNDs. To position an HWND on a particular monitor, simply move the HWND to coordinates that are within the monitor's rectangle of the virtual screen. If you have an HMONITOR from a previous HWND, use GetMonitorInfo() to retrieve the monitor's screen rectangle, and then you can position your target HWND within that rectangle using SetWindowPos().

Read MSDN for more details:

About Multiple Display Monitors

Positioning Objects on Multiple Display Monitors

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • please provide sample code for Monitorfrompoint. I tried it but not succeeded. @Remy – user7424581 May 09 '17 at 11:38
  • @user7424581 if you are having trouble doing something, please [edit] your question to show what you have tried, and explain what you expect from it and why it not working for you. – Remy Lebeau May 09 '17 at 15:17
  • actually i am not getting what to do to take form on proper monitor where previous form opened. i know to where call those function but don't know how to write them. Please help @Remy – user7424581 May 23 '17 at 07:02
0
Monitor:=   screen.Forms[Screen.FormCount-1].Monitor;
Self.Left := Monitor.Left + ((Monitor.Width - Self.Width) div 2);
Self.Top :=  Monitor.Top + ((Monitor.Height - Self.Height) div 2);