【问题标题】:FireMonkey Application with Multiple Monitors具有多个监视器的 FireMonkey 应用程序
【发布时间】:2023-03-31 11:17:01
【问题描述】:

我需要为正在显示我的应用程序的监视器获取屏幕比例。多平台运行时 TPlatFormServices 有一个名为 IFMXScreenService 的服务,它返回屏幕比例 (GetScreenScale)。

问题是它只为主监视器返回它。我需要为正在运行我的应用程序的监视器获取它。

下面是我获取IFMXScreenService 的C++ 代码。如何修改它以获得我的活动监视器的屏幕服务?

if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXScreenService)) == true)
{
  pScreenService_ = TPlatformServices::Current->GetPlatformService(__uuidof(IFMXScreenService));
}                         

【问题讨论】:

  • FireMonkey 不支持您的要求。没有针对每个监视器的IFMXScreenService 接口。你将不得不使用特定于平台的 API 来获得你想要的东西。例如,在 Windows 上,从 FMX.Platform.Win.FormToHWND() 获取 FireMonkey 表单的 HWND,然后将 HWND 传递给 Win32 API MonitorFromWindow()GetMonitorInfo() 函数,然后根据该信息自行计算比例。

标签: firemonkey c++builder multiple-monitors


【解决方案1】:

目前,我只是在 Windows 下作弊,并将以下例程添加到我的基本表单类中:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TFormBase::GetScaleFactor()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

double TFormBase::GetScaleFactor(void)
{
    double fScale = 0.0;
    #ifdef WIN32
    TPoint objTopLeft = TPoint(Left,Top);
    HMONITOR hMonitor = MonitorFromPoint(objTopLeft,MONITOR_DEFAULTTONULL);
    if (hMonitor != NULL)
    {
        DEVICE_SCALE_FACTOR nScaleFactor;
        if (GetScaleFactorForMonitor(hMonitor,&nScaleFactor) == S_OK)
        {
            fScale = static_cast<double> ((static_cast<int> (nScaleFactor))) / 100.0;
        }
    }

    if (fScale == 0.0)
    {
        fScale = ScreenService->ScreenScale;
    }
    #else
    fScale = ScreenService->ScreenScale;
    #endif

    return fScale;
}

【讨论】:

    【解决方案2】:

    我不知道如何在 C++ Builder 中,在 Delphi 中我这样做如下

    function GetScreenshotZoom(APoint: TPoint): Single; overload;
    var
      Monitor: HMonitor;
      DpiX, DpiY: Cardinal;
    begin
      if TOSVersion.Check(6, 3) then
      begin
        Monitor := Winapi.MultiMon.MonitorFromPoint(APoint, MONITOR_DEFAULTTONEAREST);
        GetDPIForMonitor(Monitor, MDT_Default, DpiX, DpiY);
        Result := DpiX / StandardDpi;
      end
      else
        Result := 1;
    end;
    

    【讨论】:

      【解决方案3】:
      uses Winapi.ShellScaling, Winapi.ShlObj, Winapi.MultiMon;
      
      function GetScreenScale(sc:integer): Single;
      var
        Monitor: HMonitor;
        Scale: DEVICE_SCALE_FACTOR;
        p:TPoint;
      begin
        result:=1;
        p.X:=Screen.Displays[sc].BoundsRect.Left;
        p.Y:=Screen.Displays[sc].BoundsRect.Top;
        Monitor:=MonitorFromPoint(p,MONITOR_DEFAULTTONULL);
        if (GetScaleFactorForMonitor(sc,Scale)=S_OK) then
        begin
          result:=(100.0 / Integer(Scale));
          if result=0 then
            result:=1;
        end;
      end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多