2013-04-01 7 views
5

EDIT - Visualizza Aggiornamento a finenecessario risolvere Hmonitor -> DeviceName (o devicename -> Hmonitor) in finestre

Questo è per Delphi 7.0 Build 4,453

Sommario

Devo essere in grado di prendere la proprietà Handle da un oggetto TMonitor (un elemento nell'array Monitors nel componente TScreen) che è un HMONITOR e trasformarlo nella stringa che usereste nelle chiamate a EnumDisplaySettings come parametro lpszDeviceName.

(il mio obiettivo finale è ottenere un elenco di impostazioni del dispositivo da un determinato valore HMONITOR, passando il lpszDeviceName risolto in chiamate a EnumDisplaySettings).

informazioni

Come accennato in precedenza, i Screen.Monitors [x] proprietà .Handle è di tipo Hmonitor e viene normalmente utilizzato per passare nella funzione GetMonitorInfo, che restituisce, informazioni geometriche, ma non lpszDeviceName . (nota: c'è una struttura TMonitorInfoEx che ha un campo szDevice, ma non sembra essere stata compilata sul mio sistema, anche se sto impostando il campo cbSize sulla dimensione appropriata).

alternativa, se posso usare uno szDeviceName per ottenere il valore Hmonitor equivalente, ho potuto collegarlo alla seguente funzione, che utilizzerebbe in un confronto (ho inserito una chiamata alla funzione fittizia chiamata hMonitorFromDeviceName nel codice seguente) per indicare come verrebbe utilizzato.

function GetMonitorDeviceName(hmon : HMONITOR) : string; 
var 
    DispDev : TDisplayDevice; 
    deviceName : string; 
    nDeviceIndex : integer; 
begin 
    Result := ''; 

    FillChar(DispDev, sizeof(DispDev),0); 
    DispDev.cb := sizeof(DispDev); 

    nDeviceIndex := 0; 
    while (EnumDisplayDevices(nil, nDeviceIndex, DispDev, 0)) do 
    begin 

    if (hMonitorFromDeviceName(DispDev.DeviceString) = hmon) then 
    begin 
     Result := StrPas(DispDev.DeviceString); 
     exit; 
    end; 

    inc(nDeviceIndex); 

    end; 
end; 

Aggiornamento

grazie a David Heffernan, ho provato la sua soluzione, e qui è una funzione di esempio per ottenere il nome del monitor da un dato manico:

function GetMonitorName(hmon : HMONITOR) : string; 
type 
    TMonitorInfoEx = record 
    cbSize: DWORD; 
    rcMonitor: TRect; 
    rcWork: TRect; 
    dwFlags: DWORD; 
    szDevice: array[0..CCHDEVICENAME - 1] of AnsiChar; 
end; 
var 
    DispDev : TDisplayDevice; 
    deviceName : string; 
    monInfo : TMonitorInfoEx; 
begin 
    Result := ''; 

    monInfo.cbSize := sizeof(monInfo); 
    if GetMonitorInfo(hmon,@monInfo) then 
    begin 

    DispDev.cb := sizeof(DispDev); 
    EnumDisplayDevices(@monInfo.szDevice, 0, DispDev, 0); 
    Result := StrPas(DispDev.DeviceString); 

    end; 
end; 

risposta

5

penso che devi chiamare GetMonitorInfo in modo errato. Questo codice:

{$APPTYPE CONSOLE} 

uses 
    SysUtils, MultiMon, Windows, Forms; 

var 
    i: Integer; 
    MonitorInfo: TMonitorInfoEx; 
begin 
    MonitorInfo.cbSize := SizeOf(MonitorInfo); 
    for i := 0 to Screen.MonitorCount-1 do 
    begin 
    if not GetMonitorInfo(Screen.Monitors[i].Handle, @MonitorInfo) then 
     RaiseLastOSError; 
    Writeln(MonitorInfo.szDevice); 
    end; 
    Readln; 
end. 

produce questo risultato sulla mia macchina:

 
\\.\DISPLAY1 
\\.\DISPLAY2 

ho il sospetto che la chiamata a GetMonitorInfo sta fallendo in qualche modo e forse non stanno controllando il valore di ritorno per gli errori.


aver cercato QualityCentral Ho il sospetto che sei caduto vittima di un bug noto nelle vecchie versioni di Delphi: QC#3239. Questo è riportato risolto nella versione 10.0.2124.6661 che è Delphi 2006.


vostre osservazioni confermano questa diagnosi. Per risolvere il problema avrai bisogno di una nuova definizione TMonitorInfoEx.Ecco uno che funziona sul vostro pre-Unicode Delphi:

type 
    TMonitorInfoEx = record 
    cbSize: DWORD; 
    rcMonitor: TRect; 
    rcWork: TRect; 
    dwFlags: DWORD; 
    szDevice: array[0..CCHDEVICENAME - 1] of AnsiChar; 
    end; 

Se si aggiunge che il codice di cui sopra (prima di dichiarare le variabili ovviamente), allora credo che risolverà il problema.


Come interessante a parte, anche in XE3, queste le strutture non sono state tradotte correttamente: QC#114460. Ammetto che l'errore è piuttosto benevolo in quanto riguarda solo lo PMonitorInfoExA e lo TMonitorInfoExA, ma l'errore mi ha sorpreso mentre cercavo di risolvere il problema in questa domanda!

+0

quando eseguo questo sul mio sistema ottengo "il parametro non è corretto" sollevato come eccezione. – unsynchronized

+0

Ciò accade quando 'cbSize' non è corretto. Quale valore di cbSize vedi sotto il debugger? E quale versione di Delphi hai? C'è qualcosa di sbagliato qui. Sono sicuro che possiamo andare fino in fondo e che la chiamata all'API funzionerà per te. –

+0

sto usando delphi 7 e Writeln (Formato ('TMonitorInfoEx =% d TMonitorInfo =% d', [Sizeof (TMonitorInfoEx), sizeof (TMonitorInfo)])) output: TMonitorInfoEx = 76 TMonitorInfo = 40 – unsynchronized