delphiwinapi

How would I code an array of PHYSICAL_MONITOR in Delphi?


I am trying to make Delphi talk to the WinAPI function GetPhysicalMonitorsFromHMONITOR().

How would I setup the needed data structure?

Currently, I have:

  LPPHYSICAL_MONITOR = record
    hPhysicalMonitor: THandle;
    szPhysicalMonitorDescription: array [0..127] of WideChar;
  end;
  PLPPHYSICAL_MONITOR = ^LPPHYSICAL_MONITOR;

However, the function expects an array – and I need an array, when I dereference the Pointer structure in order to get first, second ... monitor.

This is what I have for the function itself:

function GetPhysicalMonitorsFromHMONITOR(hMonitor: HMONITOR;
   dwPhysicalMonitorArraySize: DWORD;
   pPhysicalMonitorArray: PLPPHYSICAL_MONITOR): Boolean;
   stdcall; external 'Dxva2.dll' Name 'GetPhysicalMonitorsFromHMONITOR';

Solution

  • Per the same documentation you linked to:

    To get the required size of the array, call GetNumberOfPhysicalMonitorsFromHMONITOR.

    So, get the array size first, then allocate the array, then pass the array to GetPhysicalMonitorsFromHMONITOR(). The same documentation you linked to even provides an example of that (in C, which can easily be translated to Delphi).

    Try something like this:

    const
      PHYSICAL_MONITOR_DESCRIPTION_SIZE = 128;
    
    type
      PHYSICAL_MONITOR = record
        hPhysicalMonitor: THandle;
        szPhysicalMonitorDescription: array[0..PHYSICAL_MONITOR_DESCRIPTION_SIZE-1] of WideChar;
      end;
      LPPHYSICAL_MONITOR = ^PHYSICAL_MONITOR;
    
    function GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor: HMONITOR;
      pdwNumberOfPhysicalMonitors: LPDWORD): BOOL;
      stdcall; external 'Dxva2.dll' name 'GetNumberOfPhysicalMonitorsFromHMONITOR';
    
    function GetPhysicalMonitorsFromHMONITOR(hMonitor: HMONITOR;
      dwPhysicalMonitorArraySize: DWORD;
      pPhysicalMonitorArray: LPPHYSICAL_MONITOR): BOOL;
      stdcall; external 'Dxva2.dll' name 'GetPhysicalMonitorsFromHMONITOR';
    
    function DestroyPhysicalMonitors(dwPhysicalMonitorArraySize: DWORD;
      LPPHYSICAL_MONITOR pPhysicalMonitorArray): _BOOL;
      stdcall; external 'Dxva2.dll' name 'DestroyPhysicalMonitors';
    
    var
      hMonitor: HMONITOR;
      cPhysicalMonitors, I: DWORD;
      pPhysicalMonitors: array of PHYSICAL_MONITOR;
    begin
      // Get the monitor handle.
      hMonitor = ...;
    
      // Get the number of physical monitors.
      if not GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, @cPhysicalMonitors) then
        RaiseLastOSError;
    
      if cPhysicalMonitors = 0 then
        Exit;
    
      // Allocate the array of PHYSICAL_MONITOR structures.
      SetLength(pPhysicalMonitors, cPhysicalMonitors);
    
      // Get the array.
      if not GetPhysicalMonitorsFromHMONITOR(hMonitor, cPhysicalMonitors, @pPhysicalMonitors[0]) then
        RaiseLastOSError;
      try
        for I := 0 to cPhysicalMonitors-1 do
        begin
          // Use pPhysicalMonitors[I] as needed.
        end;
      finally
        // Close the monitor handles.
        DestroyPhysicalMonitors(cPhysicalMonitors, @pPhysicalMonitors[0]);
      end;
    end;