在 Delphi 7 中使用 TScreen

2024-05-05

我的 Delphi-7 应用程序显示:

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

并且,如果选择了第二台显示器,还可以:

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

当应用程序在我的 WinXP-Pro PC 上运行时,我转到“控制面板/显示/设置”,然后更改第二个显示器的设置(添加或删除它)。

然后,我单击“刷新”按钮以显示 4 个(或 6 个)参数的新值,但发生了意外情况:Screen.DesktopWidth 和 Screen.DesktopHeight 显示正确的新值,但其他 2 个(或 4 个)参数的值参数非常错误。

就像 Screen.Monitors[0].Width = 5586935 ,而它应该是 1680 。

在 Delphi 7 中使用 TScreen 有一些特殊规则吗?


来到这里是因为连接或断开显示器或 USB 显示设备时 TScreen 的刷新问题(错误)。 @Dave82 的答案对我不起作用。函数 MonitorFromWindow 的结果必须返回另一个值(未知/无效值)以强制更新 TScreen 对象。

下面的这个作弊就可以做到这一点:

确保 multimon 位于uses clause:

uses
 multimon;

将其添加到界面(表格的)一部分

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

将其添加到执行(表格的)一部分

    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's 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;

自定义表单(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;

希望当有人正在寻找这个时它会有所帮助。当您想要检测显示设备设置更改(分辨率和方向)时,请捕获 WM_DISPLAYCHANGE 事件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Delphi 7 中使用 TScreen 的相关文章

随机推荐