Recent

Author Topic: Getting monitor names  (Read 4946 times)

regs

  • Jr. Member
  • **
  • Posts: 53
Getting monitor names
« on: July 24, 2016, 04:29:18 pm »
this gives some unreadable mess

Code: Pascal  [Select][+][-]
  1. var
  2.   iCurrentMonitor: Integer;
  3.   MonitorInfo: TMonitorInfoEx;
  4. begin
  5.   for iCurrentMonitor := 0 to Screen.MonitorCount-1 do
  6.   begin;
  7.  
  8.      with Screen.Monitors[iCurrentMonitor] do begin
  9.        MonitorInfo.cbSize := SizeOf(MonitorInfo);
  10.        GetMonitorInfo(Screen.Monitors[iCurrentMonitor].Handle, @MonitorInfo);
  11.        Label1.Caption := Label1.Caption + ': ' +  StrPas(MonitorInfo.szDevice) + ' | ' +  IntToStr(Width) +  'x' + IntToStr(Height) + #10;
  12.      end;
  13.   end;
  14. end;

There is EnumDisplayMonitors, didn't try it though, yet it's Windows only. Is there any universal function or something for Linux?
« Last Edit: July 24, 2016, 04:45:30 pm by regs »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Getting monitor names
« Reply #1 on: July 24, 2016, 06:17:27 pm »
I believe win32 widgetset has a small mistake in the ANSI part in its GetMonitorInfo procedure:
Code: Pascal  [Select][+][-]
  1. //\lcl\interfaces\win32\win32winapi.inc
  2. function TWin32WidgetSet.GetMonitorInfo(hMonitor: HMONITOR; lpmi: LCLType.PMonitorInfo): Boolean;
  3. var
  4.   LocalInfo: TMonitorInfoExW;
  5. begin
  6.   if (lpmi <> nil) and (lpmi^.cbSize >= SizeOf(TMonitorInfoEx)) then
  7.   begin
  8.     if UnicodeEnabledOS then
  9.     begin
  10.       LocalInfo.cbSize := SizeOf(TMonitorInfoExW);
  11.       Result := MultiMon.GetMonitorInfo(hMonitor, @LocalInfo);
  12.       lpmi^.rcMonitor := LocalInfo.rcMonitor;
  13.       lpmi^.rcWork := LocalInfo.rcWork;
  14.       lpmi^.dwFlags := LocalInfo.dwFlags;
  15.       PMonitorInfoEx(lpmi)^.szDevice := UTF16ToUTF8(LocalInfo.szDevice);
  16.     end
  17.     else begin
  18.       PMonitorInfoEx(lpmi)^.szDevice := AnsiToUtf8(PMonitorInfoEx(lpmi)^.szDevice);
  19.       Result := True;
  20.     end;
  21.   end
  22.   else
  23.     Result := MultiMon.GetMonitorInfo(hMonitor, LPMonitorInfo(lpmi));
  24. end;

It misses a call to MultiMon.GetMonitorInfo as marked bellow:
Code: Pascal  [Select][+][-]
  1. function TWin32WidgetSet.GetMonitorInfo(hMonitor: HMONITOR; lpmi: LCLType.PMonitorInfo): Boolean;
  2. var
  3.   LocalInfo: TMonitorInfoExW;
  4. begin
  5.   if (lpmi <> nil) and (lpmi^.cbSize >= SizeOf(TMonitorInfoEx)) then
  6.   begin
  7.     if UnicodeEnabledOS then
  8.     begin
  9.       LocalInfo.cbSize := SizeOf(TMonitorInfoExW);
  10.       Result := MultiMon.GetMonitorInfo(hMonitor, @LocalInfo);
  11.       lpmi^.rcMonitor := LocalInfo.rcMonitor;
  12.       lpmi^.rcWork := LocalInfo.rcWork;
  13.       lpmi^.dwFlags := LocalInfo.dwFlags;
  14.       PMonitorInfoEx(lpmi)^.szDevice := UTF16ToUTF8(LocalInfo.szDevice);
  15.     end
  16.     else begin
  17.       Result := MultiMon.GetMonitorInfo(hMonitor, PMonitorInfo(lpmi));
  18.       PMonitorInfoEx(lpmi)^.szDevice := AnsiToUTF8(PMonitorInfoExA(lpmi)^.szDevice);
  19.       Result := True;
  20.     end;
  21.   end
  22.   else
  23.     Result := MultiMon.GetMonitorInfo(hMonitor, LPMonitorInfo(lpmi));
  24. end;

I don't know about Linux.

regs

  • Jr. Member
  • **
  • Posts: 53
Re: Getting monitor names
« Reply #2 on: July 24, 2016, 06:47:54 pm »
NT is Unicode. So shouldn't affect. 9x is not officially supported anymore.
It does stop in Unicode section.

Same unreadable mess on Linux as well.
« Last Edit: July 24, 2016, 07:00:58 pm by regs »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Getting monitor names
« Reply #3 on: July 25, 2016, 12:10:28 am »
Yes, you are right. But it calls ANSI version of GetMonitorInfo. Check InitMultipleMonitorStubs:
Code: Pascal  [Select][+][-]
  1. //\fpc\3.0.0\source\packages\winunits-base\src\multimon.pp
  2. function InitMultipleMonitorStubs: Boolean;
  3. var
  4.   hUser32: HMODULE;
  5. begin
  6.   if g_fMultiMonInitDone then
  7.     Exit(@g_pfnGetMonitorInfo <> nil);
  8.  
  9.   hUser32 := GetModuleHandle('USER32');
  10.   if hUser32 <> 0 then
  11.   begin
  12.     Pointer(g_pfnGetSystemMetrics)    := GetProcAddress(hUser32, 'GetSystemMetrics');
  13.     Pointer(g_pfnMonitorFromWindow)   := GetProcAddress(hUser32, 'MonitorFromWindow');
  14.     Pointer(g_pfnMonitorFromRect)     := GetProcAddress(hUser32, 'MonitorFromRect');
  15.     Pointer(g_pfnMonitorFromPoint)    := GetProcAddress(hUser32, 'MonitorFromPoint');
  16.     Pointer(g_pfnEnumDisplayMonitors) := GetProcAddress(hUser32, 'EnumDisplayMonitors');
  17. {$ifdef UNICODE}
  18.     Pointer(g_pfnEnumDisplayDevices)  := GetProcAddress(hUser32, 'EnumDisplayDevicesW');
  19.     if IsPlatformNT then
  20.       Pointer(g_pfnGetMonitorInfo)    := GetProcAddress(hUser32, 'GetMonitorInfoW')
  21.     else
  22.       Pointer(g_pfnGetMonitorInfo)    := GetProcAddress(hUser32, 'GetMonitorInfoA');
  23. {$else}
  24.     Pointer(g_pfnGetMonitorInfo)      := GetProcAddress(hUser32, 'GetMonitorInfoA');
  25.     Pointer(g_pfnEnumDisplayDevices)  := GetProcAddress(hUser32, 'EnumDisplayDevicesA');
  26. {$endif}
  27.     g_fMultiMonInitDone := True;
  28.     Result := True;
  29.   end
  30.   else
  31.   begin
  32.     Pointer(g_pfnGetSystemMetrics)    := nil;
  33.     Pointer(g_pfnMonitorFromWindow)   := nil;
  34.     Pointer(g_pfnMonitorFromRect)     := nil;
  35.     Pointer(g_pfnMonitorFromPoint)    := nil;
  36.     Pointer(g_pfnEnumDisplayMonitors) := nil;
  37.     Pointer(g_pfnGetMonitorInfo)      := nil;
  38.     Pointer(g_pfnEnumDisplayDevices)  := nil;
  39.  
  40.     g_fMultiMonInitDone := True;
  41.     Result := False;
  42.   end;
  43. end;

regs

  • Jr. Member
  • **
  • Posts: 53
Re: Getting monitor names
« Reply #4 on: July 25, 2016, 02:12:29 am »
doesn't seem so
Code: Pascal  [Select][+][-]
  1. {$ifdef UNICODE}
  2.     Pointer(g_pfnEnumDisplayDevices)  := GetProcAddress(hUser32, 'EnumDisplayDevicesW');
  3.     if IsPlatformNT then
  4.       Pointer(g_pfnGetMonitorInfo)    := GetProcAddress(hUser32, 'GetMonitorInfoW')

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Getting monitor names
« Reply #5 on: July 25, 2016, 06:02:47 am »
According to my quick test UNICODE is not defined. For instance try:
Code: Pascal  [Select][+][-]
  1. var
  2.   MonitorInfoA: TMonitorInfoExA;
  3. begin
  4.    MonitorInfoA.cbSize := SizeOf(MonitorInfoA);
  5.    MultiMon.GetMonitorInfo(Screen.Monitors[0].Handle, PMonitorInfo(@MonitorInfoA));
  6.    MonitorInfoA.szDevice := AnsiToUTF8(MonitorInfoA.szDevice);

Notice that it uses AnsiToUTF8.

 

TinyPortal © 2005-2018