2013-04-01 13 views
5

EDIT - zobacz Aktualizacja na koniecTrzeba rozwiązać Hmonitor -> devicename (lub devicename -> Hmonitor) w oknach

To jest dla Delphi 7.0 Budowanie 4,453

Podsumowanie

Potrzebuję móc pobrać właściwość Handle z obiektu TMonitor (element w tablicy Monitors w komponencie TScreen), który jest HMONITOR, i przekształcić go w ciąg znaków, który będzie używany w wywołaniach do EnumDisplaySettings jako parametr lpszDeviceName.

(moim celem końcowym jest uzyskanie listy ustawień urządzenia z danej wartości HMONITOR, przekazując rozstrzygniętą nazwę lpszDeviceName do wywołań do ustawień EnumDisplaySettings).

Szczegółowe informacje

Jak wspomniano powyżej, Screen.Monitors [x] Obiekt .Handle jest typu Hmonitor i jest zwykle używany do przekazywania do funkcji, która zwraca GetMonitorInfo, informacje o geometrii, ale nie lpszDeviceName . (uwaga: istnieje struktura TMonitorInfoEx, która ma pole szDevice, ale wydaje się, że nie wypełnia się w moim systemie, mimo że ustawiam pole cbSize na odpowiedni rozmiar).

Alternatywnie, jeśli mogę użyć szDeviceName uzyskać równoważną wartość Hmonitor, mogę podłączyć go do następujących funkcji, które mogłyby go używać w stosunku (I włożona wezwanie do fikcyjnej funkcji zwanej hMonitorFromDeviceName w kodzie poniżej), aby wskazać sposób jego użycia.

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; 

Aktualizacja

Dzięki David Heffernan, ja testowałem jego rozwiązanie, a tutaj jest funkcją próbki, aby uzyskać nazwę monitora z danego uchwytu:

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; 

Odpowiedz

5

myślę że musisz wywoływać niepoprawnie GetMonitorInfo. Ten kod:

{$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. 

produkuje to wyjście na moim komputerze:

 
\\.\DISPLAY1 
\\.\DISPLAY2 

Podejrzewam, że wezwanie do GetMonitorInfo zawodzi w jakiś sposób, a być może nie są sprawdzanie wartości zwracanej za błędy.


Po poszukiwanej QualityCentral Podejrzewam, że padły ofiarą znanego błędu w starszych wersjach Delphi: QC#3239. To jest zgłaszane naprawione w wersji 10.0.2124.6661, która jest Delphi 2006.


Twoje komentarze potwierdzają tę diagnozę. Aby rozwiązać problem, potrzebujesz nowej definicji TMonitorInfoEx.Oto jeden, który będzie działał na pre-Unicode Delphi:

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

Jeśli dodać, że do powyższego kodu (zanim zadeklarować zmienne oczywiście), to wierzę, że problem można rozwiązać.


Jako ciekawy bok, nawet w XE3 te elemencie nie zostały przetłumaczone poprawnie: QC#114460. Wprawdzie błąd jest raczej łagodny, ponieważ dotyczy tylko PMonitorInfoExA i TMonitorInfoExA, ale błąd przyłapał mnie podczas próby rozwiązania problemu w tym pytaniu!

+0

Po uruchomieniu tego w moim systemie otrzymuję "parametr jest niepoprawny" podniesiony jako wyjątek. – unsynchronized

+0

To się dzieje, gdy 'cbSize' jest niepoprawny. Jaką wartość cbSize widzisz pod debuggerem? I którą wersję Delphi masz? Coś tu jest nie tak. Jestem pewien, że możemy dojść do sedna i to połączenie API zadziała. –

+0

Używam delphi 7, a Writeln (Format ("TMonitorInfoEx =% d TMonitorInfo =% d", [Sizeof (TMonitorInfoEx), sizeof (TMonitorInfo)])) output: TMonitorInfoEx = 76 TMonitorInfo = 40 – unsynchronized