Browse Source

* file not added in earlier commit, and was forgotten.

git-svn-id: trunk@13233 -
marco 16 years ago
parent
commit
9a9b05b683
2 changed files with 465 additions and 0 deletions
  1. 1 0
      .gitattributes
  2. 464 0
      packages/winunits-base/src/multimon.pp

+ 1 - 0
.gitattributes

@@ -5033,6 +5033,7 @@ packages/winunits-base/src/dwmapi.pp svneol=native#text/plain
 packages/winunits-base/src/flatsb.pp svneol=native#text/plain
 packages/winunits-base/src/flatsb.pp svneol=native#text/plain
 packages/winunits-base/src/imagehlp.pp svneol=native#text/plain
 packages/winunits-base/src/imagehlp.pp svneol=native#text/plain
 packages/winunits-base/src/mmsystem.pp svneol=native#text/plain
 packages/winunits-base/src/mmsystem.pp svneol=native#text/plain
+packages/winunits-base/src/multimon.pp svneol=native#text/plain
 packages/winunits-base/src/ole2.pp svneol=native#text/plain
 packages/winunits-base/src/ole2.pp svneol=native#text/plain
 packages/winunits-base/src/oleserver.pp svneol=native#text/plain
 packages/winunits-base/src/oleserver.pp svneol=native#text/plain
 packages/winunits-base/src/richedit.pp svneol=native#text/plain
 packages/winunits-base/src/richedit.pp svneol=native#text/plain

+ 464 - 0
packages/winunits-base/src/multimon.pp

@@ -0,0 +1,464 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2009 by the Free Pascal development team
+    member of the Free Pascal development team.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+//=============================================================================
+//
+// multimon.h -- Stub module that fakes multiple monitor apis on Win32 OSes
+//               without them.
+//
+// By using this header your code will get back default values from
+// GetSystemMetrics() for new metrics, and the new multimonitor APIs
+// will act like only one display is present on a Win32 OS without
+// multimonitor APIs.
+//
+// Exactly one source must include this with COMPILE_MULTIMON_STUBS defined.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//=============================================================================
+unit MultiMon;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Windows;
+
+//
+// If we are building with Win95/NT4 headers, we need to declare
+// the multimonitor-related metrics and APIs ourselves.
+//
+const
+  SM_XVIRTUALSCREEN    = 76;
+  SM_YVIRTUALSCREEN    = 77;
+  SM_CXVIRTUALSCREEN   = 78;
+  SM_CYVIRTUALSCREEN   = 79;
+  SM_CMONITORS         = 80;
+  SM_SAMEDISPLAYFORMAT = 81;
+
+// HMONITOR is already declared if WINVER >= 0x0500 in windef.h
+// This is for components built with an older version number.
+type
+  HMONITOR = HANDLE;
+
+const
+  MONITOR_DEFAULTTONULL    = $00000000;
+  MONITOR_DEFAULTTOPRIMARY = $00000001;
+  MONITOR_DEFAULTTONEAREST = $00000002;
+
+  MONITORINFOF_PRIMARY     = $00000001;
+
+type
+  tagMONITORINFO = record
+    cbSize: DWORD;
+    rcMonitor: TRect;
+    rcWork: TRect;
+    dwFlags: DWORD;
+  end;
+  MONITORINFO = tagMONITORINFO;
+  LPMONITORINFO = ^tagMONITORINFO;
+  TMonitorInfo = MONITORINFO;
+  PMonitorInfo = LPMONITORINFO;
+
+const
+  CCHDEVICENAME = 32;
+
+type
+  tagMONITORINFOEXA = record
+    cbSize: DWORD;
+    rcMonitor: TRect;
+    rcWork: TRect;
+    dwFlags: DWORD;
+    szDevice: array[0..CCHDEVICENAME - 1] of Char;
+  end;
+  MONITORINFOEXA = tagMONITORINFOEXA;
+  LPMONITORINFOEXA = ^tagMONITORINFOEXA;
+  TMonitorInfoExA = MONITORINFOEXA;
+  PMonitorInfoExA = LPMONITORINFOEXA;
+
+  tagMONITORINFOEXW = record
+    cbSize: DWORD;
+    rcMonitor: TRect;
+    rcWork: TRect;
+    dwFlags: DWORD;
+    szDevice: array[0..CCHDEVICENAME - 1] of WideChar;
+  end;
+  MONITORINFOEXW = tagMONITORINFOEXW;
+  LPMONITORINFOEXW = ^tagMONITORINFOEXW;
+  TMonitorInfoExW = MONITORINFOEXW;
+  PMonitorInfoExW = LPMONITORINFOEXW;
+
+{$ifdef UNICODE}
+  MONITORINFOEX = MONITORINFOEXW;
+  LPMONITORINFOEX = LPMONITORINFOEXW;
+  TMonitorInfoEx = MONITORINFOEXW;
+  PMonitorInfoEx = LPMONITORINFOEXW;
+{$else}
+  MONITORINFOEX = MONITORINFOEXA;
+  LPMONITORINFOEX = LPMONITORINFOEXA;
+  TMonitorInfoEx = MONITORINFOEXA;
+  PMonitorInfoEx = LPMONITORINFOEXA;
+{$endif}
+
+type
+  TMonitorEnumProc = function(hMonitor: HMONITOR; hdcMonitor: HDC; lprcMonitor: PRect;
+    dwData: LPARAM): BOOL; stdcall;
+
+// ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
+type
+  _DISPLAY_DEVICEA = record
+    cb: DWORD;
+    DeviceName: array[0..31] of Char;
+    DeviceString: array[0..127] of Char;
+    StateFlags: DWORD;
+    DeviceID: array[0..127] of Char;
+    DeviceKey: array[0..127] of Char;
+  end;
+  DISPLAY_DEVICEA = _DISPLAY_DEVICEA;
+  PDISPLAY_DEVICEA = ^_DISPLAY_DEVICEA;
+  LPDISPLAY_DEVICEA = ^_DISPLAY_DEVICEA;
+  TDisplayDeviceA = DISPLAY_DEVICEA;
+  PDisplayDeviceA = PDISPLAY_DEVICEA;
+
+  _DISPLAY_DEVICEW = record
+    cb: DWORD;
+    DeviceName: array[0..31] of WideChar;
+    DeviceString: array[0..127] of WideChar;
+    StateFlags: DWORD;
+    DeviceID: array[0..127] of WideChar;
+    DeviceKey: array[0..127] of WideChar;
+  end;
+  DISPLAY_DEVICEW = _DISPLAY_DEVICEW;
+  PDISPLAY_DEVICEW = ^_DISPLAY_DEVICEW;
+  LPDISPLAY_DEVICEW = ^_DISPLAY_DEVICEW;
+  TDisplayDeviceW = DISPLAY_DEVICEW;
+  PDisplayDeviceW = PDISPLAY_DEVICEW;
+
+{$ifdef UNICODE}
+  DISPLAY_DEVICE = DISPLAY_DEVICEW;
+  PDISPLAY_DEVICE = PDISPLAY_DEVICEW;
+  LPDISPLAY_DEVICE = LPDISPLAY_DEVICEW;
+  TDisplayDevice = TDisplayDeviceW;
+  PDisplayDevice = PDisplayDeviceW;
+{$else}
+  DISPLAY_DEVICE = DISPLAY_DEVICEA;
+  PDISPLAY_DEVICE = PDISPLAY_DEVICEA;
+  LPDISPLAY_DEVICE = LPDISPLAY_DEVICEA;
+  TDisplayDevice = TDisplayDeviceA;
+  PDisplayDevice = PDisplayDeviceA;
+{$endif} // UNICODE
+
+const
+  DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = $00000001;
+  DISPLAY_DEVICE_MULTI_DRIVER        = $00000002;
+  DISPLAY_DEVICE_PRIMARY_DEVICE      = $00000004;
+  DISPLAY_DEVICE_MIRRORING_DRIVER    = $00000008;
+  DISPLAY_DEVICE_VGA_COMPATIBLE      = $00000010;
+
+type
+  TGetSystemMetrics = function(nIndex: longint): longint; stdcall;
+  TMonitorFromWindow = function(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall;
+  TMonitorFromRect = function(lprcScreenCoords: PRect; dwFlags: DWord): HMONITOR; stdcall;
+  TMonitorFromPoint = function(ptScreenCoords: TPoint; dwFlags: DWord): HMONITOR; stdcall;
+  TGetMonitorInfo = function(hMonitor: HMONITOR; lpmi: PMonitorInfo): BOOL; stdcall;
+  TEnumDisplayMonitors = function(hdc: HDC; lprcClip: PRect; lpfnEnum: TMonitorEnumProc; dwData: LPARAM): BOOL; stdcall;
+  TEnumDisplayDevices = function(lpDevice: Pointer; iDevNum: DWORD; lpDisplayDevice: PDisplayDevice; dwFlags: DWORD): BOOL; stdcall;
+
+var
+  GetSystemMetrics: TGetSystemMetrics;
+  MonitorFromWindow: TMonitorFromWindow;
+  MonitorFromRect: TMonitorFromRect;
+  MonitorFromPoint: TMonitorFromPoint;
+  GetMonitorInfo: TGetMonitorInfo;
+  EnumDisplayMonitors: TEnumDisplayMonitors;
+  EnumDisplayDevices: TEnumDisplayDevices;
+
+implementation
+
+var
+  g_fMultiMonInitDone: Boolean = False;
+  g_pfnGetSystemMetrics: TGetSystemMetrics = nil;
+  g_pfnMonitorFromWindow: TMonitorFromWindow = nil;
+  g_pfnMonitorFromRect: TMonitorFromRect = nil;
+  g_pfnMonitorFromPoint: TMonitorFromPoint = nil;
+  g_pfnGetMonitorInfo: TGetMonitorInfo = nil;
+  g_pfnEnumDisplayMonitors: TEnumDisplayMonitors = nil;
+  g_pfnEnumDisplayDevices: TEnumDisplayDevices = nil;
+
+function IsPlatformNT: Boolean;
+var
+  osvi: TOSVersionInfo;
+begin
+{$HINTS OFF}
+  FillChar(osvi, SizeOf(osvi), 0);
+{$HINTS ON}
+  osvi.dwOSVersionInfoSize := sizeof(osvi);
+  GetVersionExA(@osvi);
+  Result := VER_PLATFORM_WIN32_NT = osvi.dwPlatformId;
+end;
+
+function InitMultipleMonitorStubs: Boolean;
+var
+  hUser32: HMODULE;
+begin
+  if g_fMultiMonInitDone then
+    Exit(@g_pfnGetMonitorInfo <> nil);
+
+  hUser32 := GetModuleHandle('USER32');
+  if hUser32 <> 0 then
+  begin
+    Pointer(g_pfnGetSystemMetrics)    := GetProcAddress(hUser32, 'GetSystemMetrics');
+    Pointer(g_pfnMonitorFromWindow)   := GetProcAddress(hUser32, 'MonitorFromWindow');
+    Pointer(g_pfnMonitorFromRect)     := GetProcAddress(hUser32, 'MonitorFromRect');
+    Pointer(g_pfnMonitorFromPoint)    := GetProcAddress(hUser32, 'MonitorFromPoint');
+    Pointer(g_pfnEnumDisplayMonitors) := GetProcAddress(hUser32, 'EnumDisplayMonitors');
+{$ifdef UNICODE}
+    Pointer(g_pfnEnumDisplayDevices)  := GetProcAddress(hUser32, 'EnumDisplayDevicesW');
+    if IsPlatformNT then
+      Pointer(g_pfnGetMonitorInfo)    := GetProcAddress(hUser32, 'GetMonitorInfoW')
+    else
+      Pointer(g_pfnGetMonitorInfo)    := GetProcAddress(hUser32, 'GetMonitorInfoA');
+{$else}
+    Pointer(g_pfnGetMonitorInfo)      := GetProcAddress(hUser32, 'GetMonitorInfoA');
+    Pointer(g_pfnEnumDisplayDevices)  := GetProcAddress(hUser32, 'EnumDisplayDevicesA');
+{$endif}
+    g_fMultiMonInitDone := True;
+    Result := True;
+  end
+  else
+  begin
+    Pointer(g_pfnGetSystemMetrics)    := nil;
+    Pointer(g_pfnMonitorFromWindow)   := nil;
+    Pointer(g_pfnMonitorFromRect)     := nil;
+    Pointer(g_pfnMonitorFromPoint)    := nil;
+    Pointer(g_pfnEnumDisplayMonitors) := nil;
+    Pointer(g_pfnGetMonitorInfo)      := nil;
+    Pointer(g_pfnEnumDisplayDevices)  := nil;
+
+    g_fMultiMonInitDone := True;
+    Result := False;
+  end;
+end;
+
+//-----------------------------------------------------------------------------
+//
+// fake implementations of Monitor APIs that work with the primary display
+// no special parameter validation is made since these run in client code
+//
+//-----------------------------------------------------------------------------
+
+function xGetSystemMetrics(nIndex: Integer): Integer; stdcall;
+begin
+  if (InitMultipleMonitorStubs()) then
+    Exit(g_pfnGetSystemMetrics(nIndex));
+
+  case nIndex of
+    SM_CMONITORS,
+    SM_SAMEDISPLAYFORMAT:
+      Exit(1);
+
+    SM_XVIRTUALSCREEN,
+    SM_YVIRTUALSCREEN:
+      Exit(0);
+
+    SM_CXVIRTUALSCREEN:
+      nIndex := SM_CXSCREEN;
+
+    SM_CYVIRTUALSCREEN:
+      nIndex := SM_CYSCREEN;
+  end;
+  Result := GetSystemMetrics(nIndex);
+end;
+
+const
+  xPRIMARY_MONITOR = HMONITOR($12340042);
+
+function xMonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWORD): HMONITOR; stdcall;
+begin
+  if (InitMultipleMonitorStubs()) then
+      Exit(g_pfnMonitorFromPoint(ptScreenCoords, dwFlags));
+
+  if ((dwFlags and (MONITOR_DEFAULTTOPRIMARY or MONITOR_DEFAULTTONEAREST) <> 0 ) or
+      ((ptScreenCoords.x >= 0) and
+      (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) and
+      (ptScreenCoords.y >= 0) and
+      (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN)))) then
+    Result := xPRIMARY_MONITOR
+  else
+    Result := 0;
+end;
+
+function xMonitorFromRect(lprcScreenCoords: PRect; dwFlags: DWORD): HMONITOR; stdcall;
+begin
+  if (InitMultipleMonitorStubs()) then
+    Exit(g_pfnMonitorFromRect(lprcScreenCoords, dwFlags));
+
+  if ((dwFlags and (MONITOR_DEFAULTTOPRIMARY or MONITOR_DEFAULTTONEAREST) <> 0) or
+      ((lprcScreenCoords^.right > 0) and
+      (lprcScreenCoords^.bottom > 0) and
+      (lprcScreenCoords^.left < GetSystemMetrics(SM_CXSCREEN)) and
+      (lprcScreenCoords^.top < GetSystemMetrics(SM_CYSCREEN)))) then
+    Result := xPRIMARY_MONITOR
+  else
+    Result := 0;
+end;
+
+function xMonitorFromWindow(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall;
+var
+  wp: TWindowPlacement;
+  B: Boolean;
+begin
+  if (InitMultipleMonitorStubs()) then
+    Exit(g_pfnMonitorFromWindow(hWnd, dwFlags));
+
+  if (dwFlags and (MONITOR_DEFAULTTOPRIMARY or MONITOR_DEFAULTTONEAREST) <> 0) then
+    Exit(xPRIMARY_MONITOR);
+
+  if IsIconic(hWnd) then
+    B := GetWindowPlacement(hWnd, @wp)
+  else
+    B := GetWindowRect(hWnd, @wp.rcNormalPosition);
+
+  if B then
+    Result := xMonitorFromRect(@wp.rcNormalPosition, dwFlags)
+  else
+    Result := 0;
+end;
+
+function xGetMonitorInfo(hMonitor: HMONITOR; lpMonitorInfo: PMonitorInfo): BOOL; stdcall;
+var
+  rcWork: TRect;
+  f: BOOL;
+begin
+  if (InitMultipleMonitorStubs()) then
+  begin
+    f := g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
+{$ifdef UNICODE}
+    if (f and not IsPlatformNT and (lpMonitorInfo^.cbSize >= sizeof(TMonitorInfoEx))) then
+    begin
+      MultiByteToWideChar(CP_ACP, 0,
+          LPCSTR(@PMonitorInfoEx(lpMonitorInfo)^.szDevice[0]), -1,
+          @PMonitorInfoEx(lpMonitorInfo)^.szDevice[0], CCHDEVICENAME);
+    end;
+{$endif}
+    Exit(f);
+  end;
+
+  if ((hMonitor = xPRIMARY_MONITOR) and
+      (lpMonitorInfo <> nil) and
+      (lpMonitorInfo^.cbSize >= sizeof(TMonitorInfo)) and
+      SystemParametersInfo(SPI_GETWORKAREA, 0, @rcWork, 0)) then
+  begin
+    lpMonitorInfo^.rcMonitor.left := 0;
+    lpMonitorInfo^.rcMonitor.top  := 0;
+    lpMonitorInfo^.rcMonitor.right  := GetSystemMetrics(SM_CXSCREEN);
+    lpMonitorInfo^.rcMonitor.bottom := GetSystemMetrics(SM_CYSCREEN);
+    lpMonitorInfo^.rcWork := rcWork;
+    lpMonitorInfo^.dwFlags := MONITORINFOF_PRIMARY;
+
+    if (lpMonitorInfo^.cbSize >= sizeof(TMonitorInfoEx)) then
+      PMonitorInfoEx(lpMonitorInfo)^.szDevice := 'DISPLAY';
+
+    Result := True;
+  end
+  else
+    Result := False;
+end;
+
+function xEnumDisplayMonitors(hdcOptionalForPainting: HDC; lprcEnumMonitorsThatIntersect: PRect;
+   lpfnEnumProc: TMonitorEnumProc; dwData: LPARAM): BOOL; stdcall;
+var
+  rcLimit, rcClip: TRect;
+  ptOrg: TPoint;
+  Cb: Integer;
+begin
+  if (InitMultipleMonitorStubs()) then
+    Exit(g_pfnEnumDisplayMonitors(
+           hdcOptionalForPainting,
+           lprcEnumMonitorsThatIntersect,
+           lpfnEnumProc,
+           dwData));
+
+  if (lpfnEnumProc = nil) then
+    Exit(False);
+
+  rcLimit.left   := 0;
+  rcLimit.top    := 0;
+  rcLimit.right  := GetSystemMetrics(SM_CXSCREEN);
+  rcLimit.bottom := GetSystemMetrics(SM_CYSCREEN);
+
+  if (hdcOptionalForPainting <> 0) then
+  begin
+    Cb := GetClipBox(hdcOptionalForPainting, @rcClip);
+    if not GetDCOrgEx(hdcOptionalForPainting, @ptOrg) then
+      Exit(False);
+
+    OffsetRect(rcLimit, -ptOrg.x, -ptOrg.y);
+    if (IntersectRect(rcLimit, rcLimit, rcClip) and
+       ((lprcEnumMonitorsThatIntersect = nil) or
+         IntersectRect(rcLimit, rcLimit, lprcEnumMonitorsThatIntersect^))) then
+    begin
+      if Cb =  NULLREGION then
+        Exit(True)
+      else
+      if Cb = ERROR then
+        Exit(False);
+    end
+  end
+  else
+  if ((lprcEnumMonitorsThatIntersect <> nil) and
+      not IntersectRect(rcLimit, rcLimit, lprcEnumMonitorsThatIntersect^)) then
+    Exit(True);
+
+  Result := lpfnEnumProc(
+              xPRIMARY_MONITOR,
+              hdcOptionalForPainting,
+              @rcLimit,
+              dwData);
+end;
+
+function xEnumDisplayDevices(Unused: Pointer; iDevNum: DWORD; lpDisplayDevice: PDisplayDevice;
+  dwFlags: DWORD): BOOL; stdcall;
+begin
+  if (InitMultipleMonitorStubs()) then
+    Exit(g_pfnEnumDisplayDevices(Unused, iDevNum, lpDisplayDevice, dwFlags));
+
+  if (Unused <> nil) then
+    Exit(False);
+
+  if (iDevNum <> 0) then
+    Exit(False);
+
+  if (lpDisplayDevice = nil) or (lpDisplayDevice^.cb < sizeof(TDisplayDevice)) then
+    Exit(False);
+
+  lpDisplayDevice^.DeviceName := 'DISPLAY';
+  lpDisplayDevice^.DeviceString := 'DISPLAY';
+
+  lpDisplayDevice^.StateFlags := DISPLAY_DEVICE_ATTACHED_TO_DESKTOP or DISPLAY_DEVICE_PRIMARY_DEVICE;
+
+  Result := True;
+end;
+
+
+initialization
+  Pointer(GetSystemMetrics) := @xGetSystemMetrics;
+  Pointer(MonitorFromWindow) := @xMonitorFromWindow;
+  Pointer(MonitorFromRect) := @xMonitorFromRect;
+  Pointer(MonitorFromPoint) := @xMonitorFromPoint;
+  Pointer(GetMonitorInfo) := @xGetMonitorInfo;
+  Pointer(EnumDisplayMonitors) := @xEnumDisplayMonitors;
+  Pointer(EnumDisplayDevices) := @xEnumDisplayDevices;
+end.
+