Using TScreen in Delphi 7

My Delphi-7 application displays:

Screen.DesktopWidth Screen.DesktopHeight Screen.Monitors[0].Width Screen.Monitors[0].Height 

and, if a second monitor is selected, also:

 Screen.Monitors[1].Width Screen.Monitors[1].Height 

With the application running on my WinXP-Pro PC, I go to the control panel / display / settings and change the settings for the second monitor (add or remove it).

Then I click the Refresh button to display the new values ​​for the parameters 4 (or 6), and something unexpected happens: Screen.DesktopWidth and Screen.DesktopHeight show the correct new values, but the values ​​of the other 2 (or 4) are very incorrect parameters.

Like Screen.Monitors [0] .Width = 5586935, whereas it should be 1680.

Are there special rules for using TScreen in Delphi 7?

+7
source share
3 answers

Thanks to TLama, I found a workaround for the TScreen issue in Delphi 7.

Source code that "caused" the problem:

 LabMon1.Caption := ' Mon 1: ' + IntToStr (Screen.Monitors[0].Width) + ' x ' + IntToStr (Screen.Monitors[0].Height); if (Screen.MonitorCount = 1) then LabMon2.Caption := ' Mon 2: -' else LabMon2.Caption := ' Mon 2: ' + IntToStr (Screen.Monitors[1].Width) + ' x ' + IntToStr (Screen.Monitors[1].Height); 

I needed to add only 1 line of code to solve it:

 LabMon1.Caption := ' Mon 1: ' + IntToStr (Monitor.Width) + ' x ' + IntToStr (Monitor.Height) ; LabMon1.Caption := ' Mon 1: ' + IntToStr (Screen.Monitors[0].Width) + ' x ' + IntToStr (Screen.Monitors[0].Height); if (Screen.MonitorCount = 1) then LabMon2.Caption := ' Mon 2: -' else LabMon2.Caption := ' Mon 2: ' + IntToStr (Screen.Monitors[1].Width) + ' x ' + IntToStr (Screen.Monitors[1].Height); 

So thanks again TLama , for the great contribution to this thread issue!

0
source

The same thing happens if you switch the user during the launch of your program. After the switch, the Screen.Monitors array contains invalid values. We use this line of code

 Screen.MonitorFromWindow(0, mdNull); 

to make the Screen object refresh lists.

0
source

Came here due to an update problem (error) of TScreen when connecting or disconnecting a monitor or USB display device. Answer @ Dave82 does not work for me. The result of the MonitorFromWindow function should return a different value (unknown / invalid value) in order to force the TScreen object to be updated.

This cheat below does the trick:

Make sure multimon is in use :

 uses multimon; 

Add this to part of the interface (form)

 protected procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE; 

Add this to the implementation part (forms)

  function cheatMonitorFromWindow(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall; begin // Does nothing, returns zero to force invalidate Result:=0; end; procedure TForm1.WMDeviceChange(var Msg: TMessage); var iCurrDisplayCount : LongInt; iNewDisplayCount : LongInt; pMonitorFromWinProc : TMonitorFromWindow; begin iCurrDisplayCount:=Screen.MonitorCount; // Force monitor update, fix bug in customform, won't update at display change. // This a hack/cheat to multimon MonitorFromWindow func, it fakes the result. // This is required to tell customform.getMonitor() to update the TScreen object. pMonitorFromWinProc:=MonitorFromWindow; // Backup pointer to dynamic assigned DLL func MonitorFromWindow:=cheatMonitorFromWindow; // Assign cheat func monitor; // call the monitor property that calls customform.getMonitor and cheatfunc MonitorFromWindow:=pMonitorFromWinProc; // restore the original func // ========== iNewDisplayCount:=Screen.MonitorCount; if( iCurrDisplayCount <> iNewDisplayCount ) then begin // Display count change! end; end; 

What happens inside customform (code in Forms.pas)?

 function TCustomForm.GetMonitor: TMonitor; var HM: HMonitor; I: Integer; begin Result := nil; HM := MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST); for I := 0 to Screen.MonitorCount - 1 do if Screen.Monitors[I].Handle = HM then begin Result := Screen.Monitors[I]; Exit; end; //if we get here, the Monitors array has changed, so we need to clear and reinitialize it for i := 0 to Screen.MonitorCount-1 do TMonitor(Screen.FMonitors[i]).Free; Screen.FMonitors.Clear; EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(Screen.FMonitors)); for I := 0 to Screen.MonitorCount - 1 do if Screen.Monitors[I].Handle = HM then begin Result := Screen.Monitors[I]; Exit; end; end; 

Hope this helps when someone is looking for it. If you want to detect changes in display device settings (resolution and orientation), intercept the WM_DISPLAYCHANGE event.

0
source

All Articles