在Delphi(DirectX)中获取所有显示器的当前/原生屏幕分辨率

4
我们的Delphi应用程序可以在多个DirectX窗口上运行,通常在多个屏幕上。到目前为止,用户必须使用支持的分辨率下拉列表指定全屏分辨率。如果他可以使用“当前”这样的设置,那将非常好,它将是窗口所在屏幕的分辨率。
我们正在使用带有Clootie DirectX标头的Delphi。有人能给我一个提示,我将如何编写一个使用DirectX、WinAPI或Delphi方法的方法来获取窗口所在当前屏幕的分辨率吗?
此致敬礼, thalm
最终解决方案:
好的,Delphi 2007 MultiMon.pas 对于GetMonitorInfo返回垃圾,所以我找到了这种方法,对我有效,直接使用winAPI:
function GetRectOfMonitorContainingRect(const R: TRect): TRect;
{ Returns bounding rectangle of monitor containing or nearest to R }
type
  HMONITOR = type THandle;
  TMonitorInfo = record
    cbSize: DWORD;
    rcMonitor: TRect;
    rcWork: TRect;
    dwFlags: DWORD;
  end;
const
  MONITOR_DEFAULTTONEAREST = $00000002;
var
  Module: HMODULE;
  MonitorFromRect: function(const lprc: TRect; dwFlags: DWORD): HMONITOR; stdcall;
  GetMonitorInfo: function(hMonitor: HMONITOR; var lpmi: TMonitorInfo): BOOL; stdcall;
  M: HMONITOR;
  Info: TMonitorInfo;
begin
  Module := GetModuleHandle(user32);
  MonitorFromRect := GetProcAddress(Module, 'MonitorFromRect');
  GetMonitorInfo := GetProcAddress(Module, 'GetMonitorInfoA');
  if Assigned(MonitorFromRect) and Assigned(GetMonitorInfo) then begin
    M := MonitorFromRect(R, MONITOR_DEFAULTTONEAREST);
    Info.cbSize := SizeOf(Info);
    if GetMonitorInfo(M, Info) then begin
      Result := Info.rcMonitor;
      Exit;
    end;
  end;
  Result := GetRectOfPrimaryMonitor(True);
end;

但我想知道 GetMonitorInfo、GetMonitorInfoA 和 GetMonitorInfoW 之间有什么区别?有人能解释一下吗? - thalm
好的,找到了,它是A代表ANSI字符串,W代表宽字符串... - thalm
3个回答

9
var
  MonInfo: TMonitorInfo;
begin
  MonInfo.cbSize := SizeOf(MonInfo);
  GetMonitorInfo(MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST), @MonInfo);
  ShowMessage(Format('Current resolution: %dx%d',
              [MonInfo.rcMonitor.Right - MonInfo.rcMonitor.Left,
               MonInfo.rcMonitor.Bottom - MonInfo.rcMonitor.Top]));

2
请查看我的帖子获取完整的解决方案,它只能直接使用winAPI工作,因为delphi 2007在这里似乎存在错误。 - thalm
需要注意的是,这个解决方案完全独立于问题并且可以自行运行。也就是说,在这里使用的 GetMonitorInfo 是来自 Windows API 的实际 GetMonitorInfo 而不是在问题中实现的 GetMonitofInfo 函数。为了避免其他人像我一样浪费一整个早上来解决这个问题。 - Atreide

3

TCustomForm.Monitor 做了你说的事情,但 OP 想要获取它们所有。此外,GetDeviceCaps 函数通常用于获取许多属性和许多设备类型。无论如何,我在这里没有投票。 - user532231
Screen.Monitors可以获取所有的显示器。但据我了解,OP想要获取当前的屏幕,即引用:“如果他可以使用像“current”这样的设置,那将是窗口所在屏幕的分辨率,这将非常好”,而Form.Monitor就提供了这个功能? - ain

1

首先使用EnumDisplayDevices获取所有监视器名称的列表,参见this Delphi 的usenet帖子。请注意,您需要的是DeviceName而不是DeviceString

然后对于每个监视器,使用EnumDisplaySettings(lpDisplayDevice.DeviceName, ENUM_CURRENT_SETTINGS, lpDevMode)来获取当前设置。在这里,您也可以将NULL用作设备名称,这意味着:“NULL值指定运行调用线程的计算机上的当前显示设备。”这通常应该对应于用户当前使用的监视器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接