You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
618 lines
25 KiB
618 lines
25 KiB
#include "stdafx.h"
|
|
#pragma hdrstop
|
|
|
|
// 98/10/02 vtan: Multiple monitor bug fixes.
|
|
|
|
// Given an old monitor layout, a new monitor layout and a component
|
|
// this function makes sure that it is in the new layout using a
|
|
// monitor relative scheme. It tries to preserve the position
|
|
// relatively within a given monitor. If the resolution of the monitor
|
|
// changes then this needs to be accounted for also.
|
|
|
|
// Preserve the component within a given monitor if the monitor is the
|
|
// same HMONITOR but the GDI co-ordinates change.
|
|
|
|
// If the same monitor cannot be located then move the component to the
|
|
// nearest monitor and position it as best on that monitor.
|
|
|
|
// If all else fails then use the default component positioning
|
|
// algorithm. This should never happen.
|
|
|
|
// Preserve the component within a given monitor if the resolution
|
|
// changes. Preserve the size of the component by MOVING the component
|
|
// in the X and Y axis until the left or the top of the monitor is
|
|
// reached. When either axis reaches 0 then reduce the size of the
|
|
// component until it fits within the given new resolution.
|
|
|
|
static const int kNameSize = 16;
|
|
|
|
typedef struct
|
|
{
|
|
HMONITOR miHMONITOR;
|
|
RECT miDisplayAreaRect,
|
|
miWorkAreaRect;
|
|
} tMonitorInfoRec, *tMonitorInfoPtr;
|
|
|
|
typedef struct
|
|
{
|
|
int miaCount, miaIndex;
|
|
RECT miaVirtualScreen;
|
|
tMonitorInfoRec miaMonitors[1];
|
|
} tMonitorInfoArrayRec, *tMonitorInfoArrayPtr;
|
|
|
|
typedef struct
|
|
{
|
|
BOOL ciValidData, ciVisible, ciRepositioned;
|
|
TCHAR ciName[kNameSize]; // this is not excessive but limited
|
|
DWORD ciItemState;
|
|
int ciType;
|
|
COMPPOS ciPosition;
|
|
COMPSTATEINFO ciStateInfo;
|
|
} tComponentInfoRec, *tComponentInfoPtr;
|
|
|
|
static tMonitorInfoArrayPtr gOldMonitorArray = NULL;
|
|
static tMonitorInfoArrayPtr gNewMonitorArray = NULL;
|
|
|
|
// Functions located in Dutil.cpp used for co-ordinate mapping.
|
|
|
|
void SetPt (POINT& pt, LONG x, LONG y);
|
|
void OffsetPt (POINT& pt, LONG dh, LONG dv);
|
|
void CalculateVirtualScreen (RECT& virtualScreen);
|
|
|
|
// Local function prototypes.
|
|
|
|
BOOL CALLBACK MonitorCountEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data);
|
|
BOOL CALLBACK MonitorCalculateEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data);
|
|
HRESULT CalculateCurrentMonitorArray(void);
|
|
void ApplyCurrentMonitorArray (void);
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, HMONITOR hMonitor);
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, POINT& pt);
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, RECT& rc);
|
|
BOOL RepositionDesktopRect (RECT& rcComponent, tMonitorInfoArrayPtr oldMonitorArray, tMonitorInfoArrayPtr newMonitorArray);
|
|
BOOL RepositionDesktopComponent (COMPPOS& componentPosition, COMPSTATEINFO& componentStateInfo, DWORD dwItemState);
|
|
BOOL ReadAllComponents (HKEY hKeyDesktop, tComponentInfoPtr& pComponentInfo, DWORD& dwComponentCount);
|
|
void WriteAllComponents (HKEY hKeyDesktop, tComponentInfoPtr pComponentInfo, DWORD dwComponentCount);
|
|
|
|
BOOL CALLBACK MonitorCountEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data)
|
|
|
|
// Count the number of monitors attached to the system.
|
|
|
|
{
|
|
int *iCounter;
|
|
|
|
iCounter = reinterpret_cast<int*>(data);
|
|
++(*iCounter);
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL CALLBACK MonitorCalculateEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data)
|
|
|
|
// Store each monitor HMONITOR and dimensions in the array.
|
|
|
|
{
|
|
tMonitorInfoArrayPtr monitorArray;
|
|
MONITORINFO monitorInfo;
|
|
|
|
monitorArray = reinterpret_cast<tMonitorInfoArrayPtr>(data);
|
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
|
// adding monitors in the space of a few nanoseconds isnt a real attack vector, but double-check
|
|
// against the size of the array we allocated
|
|
if ((GetMonitorInfo(hMonitor, &monitorInfo) != 0) && (monitorArray->miaIndex < monitorArray->miaCount))
|
|
{
|
|
tMonitorInfoPtr pMI;
|
|
|
|
pMI = &monitorArray->miaMonitors[monitorArray->miaIndex++];
|
|
pMI->miHMONITOR = hMonitor;
|
|
TBOOL(CopyRect(&pMI->miDisplayAreaRect, &monitorInfo.rcMonitor));
|
|
TBOOL(CopyRect(&pMI->miWorkAreaRect, &monitorInfo.rcWork));
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
HRESULT CalculateCurrentMonitorArray(void)
|
|
|
|
// Allocate and fill the monitor rectangle array.
|
|
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
int iCount;
|
|
|
|
iCount = 0;
|
|
TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCountEnumProc, reinterpret_cast<LPARAM>(&iCount)));
|
|
gNewMonitorArray = reinterpret_cast<tMonitorInfoArrayPtr>(LocalAlloc(LMEM_FIXED, sizeof(tMonitorInfoArrayRec) + ((iCount - 1) * sizeof(tMonitorInfoRec))));
|
|
|
|
if (gNewMonitorArray)
|
|
{
|
|
gNewMonitorArray->miaCount = iCount;
|
|
gNewMonitorArray->miaIndex = 0;
|
|
CalculateVirtualScreen(gNewMonitorArray->miaVirtualScreen);
|
|
TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCalculateEnumProc, reinterpret_cast<LPARAM>(gNewMonitorArray)));
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void ApplyCurrentMonitorArray (void)
|
|
|
|
// Discard the old and save the new as current monitor
|
|
// rectangle array for the next time the function is called.
|
|
|
|
{
|
|
if (gOldMonitorArray != NULL)
|
|
(HLOCAL)LocalFree(gOldMonitorArray);
|
|
gOldMonitorArray = gNewMonitorArray;
|
|
gNewMonitorArray = NULL;
|
|
}
|
|
|
|
// These functions determine the index into the monitor
|
|
// rectangle array of a given HMONITOR, POINT or RECT.
|
|
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, HMONITOR hMonitor)
|
|
|
|
{
|
|
int i, iLimit, iResult;
|
|
tMonitorInfoPtr pMI;
|
|
|
|
iResult = -1;
|
|
for (i = 0, iLimit = pMIA->miaCount, pMI = pMIA->miaMonitors; i < iLimit; ++i, ++pMI)
|
|
{
|
|
if (pMI->miHMONITOR == hMonitor)
|
|
{
|
|
iResult = i;
|
|
break;
|
|
}
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
// Note that the functions that take a POINT or RECT
|
|
// require the co-ordinates to be in TRIDENT co-ordinates.
|
|
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, POINT& pt)
|
|
|
|
{
|
|
int i, iLimit, iResult;
|
|
tMonitorInfoPtr pMI;
|
|
POINT ptLocal;
|
|
|
|
ptLocal = pt;
|
|
OffsetPt(ptLocal, +pMIA->miaVirtualScreen.left, +pMIA->miaVirtualScreen.top);
|
|
iResult = -1;
|
|
for (i = 0, iLimit = pMIA->miaCount, pMI = pMIA->miaMonitors; i < iLimit; ++i, ++pMI)
|
|
{
|
|
if (PtInRect(&pMI->miDisplayAreaRect, ptLocal) != 0)
|
|
{
|
|
iResult = i;
|
|
break;
|
|
}
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, RECT& rc)
|
|
|
|
{
|
|
int iResult;
|
|
POINT pt;
|
|
|
|
// 99/05/12 #338446 vtan: Try all four corners of the rectangle
|
|
// to find a match.
|
|
|
|
pt.x = rc.left;
|
|
pt.y = rc.top;
|
|
iResult = IndexOfMonitor(pMIA, pt);
|
|
if (iResult < 0)
|
|
{
|
|
pt.x = rc.left;
|
|
pt.y = rc.bottom;
|
|
iResult = IndexOfMonitor(pMIA, pt);
|
|
if (iResult < 0)
|
|
{
|
|
pt.x = rc.right;
|
|
pt.y = rc.top;
|
|
iResult = IndexOfMonitor(pMIA, pt);
|
|
if (iResult < 0)
|
|
{
|
|
pt.x = rc.right;
|
|
pt.y = rc.bottom;
|
|
iResult = IndexOfMonitor(pMIA, pt);
|
|
}
|
|
}
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, COMPPOS& componentPosition)
|
|
|
|
{
|
|
RECT rcComponent;
|
|
|
|
TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
|
|
return(IndexOfMonitor(pMIA, rcComponent));
|
|
}
|
|
|
|
BOOL RepositionDesktopRect (RECT& rcComponent, tMonitorInfoArrayPtr oldMonitorArray, tMonitorInfoArrayPtr newMonitorArray)
|
|
|
|
// Reposition the component's RECT based on the logic at the
|
|
// top of the source file. Used for both the component's
|
|
// current position and the restored position.
|
|
|
|
{
|
|
BOOL bRepositionedComponent;
|
|
int iOldMonitorIndex, iNewMonitorIndex;
|
|
|
|
// This is for future expansion. The components are always
|
|
// deemed to be repositioned if this function is called.
|
|
|
|
bRepositionedComponent = TRUE;
|
|
|
|
// Find out if the monitor which the component was on is still
|
|
// present. To do this find the index of the component in the
|
|
// old monitor array, get the HMONITOR and find that in the new
|
|
// monitor array.
|
|
|
|
iOldMonitorIndex = IndexOfMonitor(oldMonitorArray, rcComponent);
|
|
if (iOldMonitorIndex >= 0)
|
|
{
|
|
RECT *prcOldMonitor, *prcNewMonitor;
|
|
|
|
iNewMonitorIndex = IndexOfMonitor(newMonitorArray, oldMonitorArray->miaMonitors[iOldMonitorIndex].miHMONITOR);
|
|
if (iNewMonitorIndex < 0)
|
|
{
|
|
HMONITOR hMonitor;
|
|
|
|
// The component is on a monitor that no longer exists. The only
|
|
// thing to do in this case is to find the nearest monitor based
|
|
// on the GDI co-ordinates and position it on that monitor.
|
|
|
|
hMonitor = MonitorFromRect(&rcComponent, MONITOR_DEFAULTTONEAREST);
|
|
iNewMonitorIndex = IndexOfMonitor(newMonitorArray, hMonitor);
|
|
ASSERT(iNewMonitorIndex >= 0);
|
|
}
|
|
|
|
// If iNewMonitorIndex was already positive then the monitor which
|
|
// the component was on still exists and simply mapping GDI
|
|
// co-ordinates will work. Otherwise we found the nearest monitor
|
|
// and mapping GDI co-ordinates also works!
|
|
|
|
// This maps from the component's OLD co-ordinates in trident
|
|
// co-ordinates to GDI co-ordinates. Then it maps from the GDI
|
|
// co-ordinates to an OLD monitor relative co-ordinate. Then it
|
|
// maps from the OLD monitor relative co-ordinates to the NEW
|
|
// monitor GDI co-ordinates.
|
|
|
|
prcOldMonitor = &oldMonitorArray->miaMonitors[iOldMonitorIndex].miDisplayAreaRect;
|
|
prcNewMonitor = &newMonitorArray->miaMonitors[iNewMonitorIndex].miDisplayAreaRect;
|
|
TBOOL(OffsetRect(&rcComponent, +oldMonitorArray->miaVirtualScreen.left, +oldMonitorArray->miaVirtualScreen.top));
|
|
TBOOL(OffsetRect(&rcComponent, -prcOldMonitor->left, -prcOldMonitor->top));
|
|
TBOOL(OffsetRect(&rcComponent, +prcNewMonitor->left, +prcNewMonitor->top));
|
|
}
|
|
else
|
|
{
|
|
|
|
// Component exists at an invalid location in the old monitor
|
|
// layout. It may be valid in the new layout. Try this. If that
|
|
// doesn't work then it doesn't exist in the old nor the new
|
|
// layout. It was in no-man's land. Position it using the default
|
|
// positioning system.
|
|
|
|
iNewMonitorIndex = IndexOfMonitor(newMonitorArray, rcComponent);
|
|
if (iNewMonitorIndex < 0)
|
|
{
|
|
POINT ptOrigin;
|
|
COMPPOS componentPosition;
|
|
|
|
GetNextComponentPosition(&componentPosition);
|
|
IncrementComponentsPositioned();
|
|
TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
|
|
|
|
// Get the primary monitor index in our monitor rectangle array.
|
|
|
|
SetPt(ptOrigin, 0, 0);
|
|
iNewMonitorIndex = IndexOfMonitor(newMonitorArray, MonitorFromPoint(ptOrigin, MONITOR_DEFAULTTOPRIMARY));
|
|
ASSERT(iNewMonitorIndex >= 0);
|
|
}
|
|
}
|
|
|
|
// At this stage the component position is in GDI co-ordinates.
|
|
// Convert from GDI co-ordinates back to trident co-ordinates.
|
|
|
|
TBOOL(OffsetRect(&rcComponent, -newMonitorArray->miaVirtualScreen.left, -newMonitorArray->miaVirtualScreen.top));
|
|
|
|
return(bRepositionedComponent);
|
|
}
|
|
|
|
BOOL RepositionDesktopComponent (COMPPOS& componentPosition, COMPSTATEINFO& componentStateInfo, DWORD dwItemState, int iComponentType)
|
|
|
|
{
|
|
BOOL bRepositionedComponent;
|
|
tMonitorInfoArrayPtr oldMonitorArray, newMonitorArray;
|
|
RECT rcComponent;
|
|
|
|
// Check if the monitor layout has changed. If unchanged then
|
|
// there is no need to move the components.
|
|
|
|
oldMonitorArray = gOldMonitorArray;
|
|
newMonitorArray = gNewMonitorArray;
|
|
if (oldMonitorArray == NULL)
|
|
{
|
|
oldMonitorArray = newMonitorArray;
|
|
}
|
|
|
|
TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
|
|
bRepositionedComponent = RepositionDesktopRect(rcComponent, oldMonitorArray, newMonitorArray);
|
|
componentPosition.iLeft = rcComponent.left;
|
|
componentPosition.iTop = rcComponent.top;
|
|
componentPosition.dwWidth = rcComponent.right - rcComponent.left;
|
|
componentPosition.dwHeight = rcComponent.bottom - rcComponent.top;
|
|
ValidateComponentPosition(&componentPosition, dwItemState, iComponentType, NULL, NULL);
|
|
|
|
// If the component is zoomed also reposition the restored
|
|
// COMPSTATEINFO.
|
|
|
|
if (IsZoomedState(dwItemState))
|
|
{
|
|
COMPPOS restoredCompPos;
|
|
|
|
TBOOL(SetRect(&rcComponent, componentStateInfo.iLeft, componentStateInfo.iTop, componentStateInfo.iLeft + componentStateInfo.dwWidth, componentStateInfo.iTop + componentStateInfo.dwHeight));
|
|
bRepositionedComponent = RepositionDesktopRect(rcComponent, oldMonitorArray, newMonitorArray) || bRepositionedComponent;
|
|
restoredCompPos.iLeft = componentStateInfo.iLeft = rcComponent.left;
|
|
restoredCompPos.iTop = componentStateInfo.iTop = rcComponent.top;
|
|
restoredCompPos.dwWidth = componentStateInfo.dwWidth = rcComponent.right - rcComponent.left;
|
|
restoredCompPos.dwHeight = componentStateInfo.dwHeight = rcComponent.bottom - rcComponent.top;
|
|
ZoomComponent(&componentPosition, dwItemState, FALSE);
|
|
restoredCompPos.dwSize = sizeof(restoredCompPos);
|
|
ValidateComponentPosition(&restoredCompPos, IS_NORMAL, iComponentType, NULL, NULL);
|
|
}
|
|
|
|
return(bRepositionedComponent);
|
|
}
|
|
|
|
BOOL ReadAllComponents (HKEY hKeyDesktop, tComponentInfoPtr& pComponentInfo, DWORD& dwComponentCount)
|
|
|
|
{
|
|
tComponentInfoPtr pCI;
|
|
|
|
if (RegQueryInfoKey(hKeyDesktop, NULL, NULL, NULL, &dwComponentCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
dwComponentCount = 0;
|
|
if (dwComponentCount > 0)
|
|
{
|
|
|
|
// 99/08/09 #383184: STRESS fix. Allocate the whole block of
|
|
// memory required for the components but allocate one extra
|
|
// entry. advapi32!RegEnumKeyEx will try to access the memory
|
|
// before determining that there is a failure condition. With
|
|
// pageheap on (and the block allocated at the end of the page)
|
|
// this causes an access violation. The simplest fix is to add
|
|
// an extra entry.
|
|
|
|
pComponentInfo = pCI = reinterpret_cast<tComponentInfoPtr>(LocalAlloc(LPTR, (dwComponentCount + 1) * sizeof(*pCI))); // LMEM_FIXED | LMEM_ZEROINIT
|
|
if (pCI != NULL)
|
|
{
|
|
DWORD dwIndex, dwSize;
|
|
|
|
// Enumerate all the desktop components.
|
|
|
|
dwIndex = 0;
|
|
dwSize = sizeof(pCI->ciName);
|
|
while (RegEnumKeyEx(hKeyDesktop, dwIndex, pCI->ciName, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
CRegKey regKeyComponent;
|
|
|
|
if (regKeyComponent.Open(hKeyDesktop, pCI->ciName, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwType, cbData;
|
|
|
|
// Read the Position value.
|
|
|
|
cbData = sizeof(pCI->ciPosition);
|
|
if (SHQueryValueEx(regKeyComponent, REG_VAL_COMP_POSITION, NULL, &dwType, &pCI->ciPosition, &cbData) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwFlags;
|
|
|
|
pCI->ciValidData = TRUE;
|
|
if (SHQueryValueEx(regKeyComponent, REG_VAL_COMP_FLAGS, NULL, &dwType, &dwFlags, &cbData) == ERROR_SUCCESS)
|
|
{
|
|
pCI->ciVisible = ((dwFlags & COMP_SELECTED) != 0);
|
|
pCI->ciType = (dwFlags & COMP_TYPE_MASK);
|
|
}
|
|
else
|
|
{
|
|
pCI->ciVisible = FALSE;
|
|
pCI->ciType = COMP_TYPE_WEBSITE;
|
|
}
|
|
pCI->ciItemState = IS_NORMAL; // if missing (IE4 machine) or error the assume normal
|
|
cbData = sizeof(pCI->ciItemState);
|
|
if ((SHQueryValueEx(regKeyComponent, REG_VAL_COMP_CURSTATE, NULL, &dwType, &pCI->ciItemState, &cbData) == ERROR_SUCCESS))
|
|
{
|
|
|
|
// If the component is zoomed also read in the COMPSTATEINFO.
|
|
|
|
if (IsZoomedState(pCI->ciItemState))
|
|
{
|
|
cbData = sizeof(pCI->ciStateInfo);
|
|
TW32(SHQueryValueEx(regKeyComponent, REG_VAL_COMP_RESTOREDSTATEINFO, NULL, &dwType, &pCI->ciStateInfo, &cbData));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
++pCI;
|
|
++dwIndex;
|
|
dwSize = sizeof(pCI->ciName);
|
|
}
|
|
}
|
|
}
|
|
return((dwComponentCount != 0) && (pComponentInfo != NULL));
|
|
}
|
|
|
|
int IndexOfComponent (tComponentInfoPtr pComponentInfo, DWORD dwComponentCount, LPCTSTR pcszName)
|
|
|
|
{
|
|
int iResult, i;
|
|
|
|
for (iResult = -1, i = 0; (iResult < 0) && (i < static_cast<int>(dwComponentCount)); ++i)
|
|
{
|
|
if (lstrcmp(pComponentInfo[i].ciName, pcszName) == 0)
|
|
iResult = i;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
void WriteAllComponents (HKEY hKeyDesktop, tComponentInfoPtr pComponentInfo, DWORD dwComponentCount)
|
|
|
|
{
|
|
TCHAR szSubKeyName[kNameSize];
|
|
DWORD dwSubKeyIndex, dwSubKeySize;
|
|
|
|
// Enumerate all the desktop components.
|
|
|
|
dwSubKeyIndex = 0;
|
|
dwSubKeySize = ARRAYSIZE(szSubKeyName);
|
|
while (RegEnumKeyEx(hKeyDesktop, dwSubKeyIndex, szSubKeyName, &dwSubKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
{
|
|
CRegKey regKeyComponent;
|
|
|
|
if (regKeyComponent.Open(hKeyDesktop, szSubKeyName, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
|
|
{
|
|
int i;
|
|
|
|
i = IndexOfComponent(pComponentInfo, dwComponentCount, szSubKeyName);
|
|
if ((i >= 0) && pComponentInfo[i].ciRepositioned)
|
|
{
|
|
TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_POSITION, 0, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciPosition), sizeof(pComponentInfo[i].ciPosition)));
|
|
TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_CURSTATE, NULL, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciItemState), sizeof(pComponentInfo[i].ciItemState)));
|
|
|
|
// If the component is zoomed also write out the COMPSTATEINFO.
|
|
|
|
if (IsZoomedState(pComponentInfo[i].ciItemState))
|
|
{
|
|
TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciStateInfo), sizeof(pComponentInfo[i].ciStateInfo)));
|
|
}
|
|
}
|
|
}
|
|
++dwSubKeyIndex;
|
|
dwSubKeySize = ARRAYSIZE(szSubKeyName);
|
|
}
|
|
}
|
|
|
|
BOOL AdjustDesktopComponents (LPCRECT arectNew,
|
|
int crectNew,
|
|
LPCRECT arectOldMonitors,
|
|
LPCRECT arectOld,
|
|
int crectOld)
|
|
|
|
{
|
|
static const int kMaximumMonitorCount = 16;
|
|
HRESULT hr;
|
|
BOOL bRepositionedComponent;
|
|
int zoomedComponentIndices[kMaximumMonitorCount]; // 16 monitors limitation here - make dynamic if required
|
|
int i;
|
|
tMonitorInfoArrayPtr oldMonitorArray;
|
|
CRegKey regKeyDesktop;
|
|
TCHAR szDeskcomp[MAX_PATH];
|
|
|
|
for (i = 0; i < kMaximumMonitorCount; ++i)
|
|
zoomedComponentIndices[i] = -1;
|
|
|
|
bRepositionedComponent = FALSE;
|
|
hr = CalculateCurrentMonitorArray();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
oldMonitorArray = gOldMonitorArray;
|
|
if (oldMonitorArray == NULL)
|
|
oldMonitorArray = gNewMonitorArray;
|
|
|
|
GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
|
|
|
|
if (ERROR_SUCCESS == regKeyDesktop.Open(HKEY_CURRENT_USER, szDeskcomp, KEY_READ))
|
|
{
|
|
DWORD dwComponentCount;
|
|
tComponentInfoPtr pComponentInfo;
|
|
|
|
// Enumerate all the desktop components.
|
|
|
|
if (ReadAllComponents(regKeyDesktop, pComponentInfo, dwComponentCount))
|
|
{
|
|
tComponentInfoPtr pCI;
|
|
|
|
for (pCI = pComponentInfo, i = 0; i < static_cast<int>(dwComponentCount); ++pCI, ++i)
|
|
{
|
|
int iPreviousMonitorIndexOfComponent;
|
|
|
|
// Calculate the previous monitor position BEFORE the component
|
|
// gets repositioned.
|
|
|
|
iPreviousMonitorIndexOfComponent = IndexOfMonitor(oldMonitorArray, pCI->ciPosition);
|
|
if (RepositionDesktopComponent(pCI->ciPosition, pCI->ciStateInfo, pCI->ciItemState, pCI->ciType))
|
|
{
|
|
int iCurrentMonitorIndexOfComponent;
|
|
|
|
pCI->ciRepositioned = bRepositionedComponent = TRUE;
|
|
iCurrentMonitorIndexOfComponent = IndexOfMonitor(gNewMonitorArray, pCI->ciPosition);
|
|
if (iCurrentMonitorIndexOfComponent >= 0)
|
|
{
|
|
|
|
// 99/05/12 #338446 vtan: Only use a zero or positive index into the
|
|
// monitor array. -1 is invalid and will cause an AV. This should NEVER
|
|
// happen but rather than assert this condition is handled.
|
|
|
|
if (IsZoomedState(pCI->ciItemState) && (zoomedComponentIndices[iCurrentMonitorIndexOfComponent] >= 0))
|
|
{
|
|
tComponentInfoPtr pCIToRestore;
|
|
|
|
// This component is zoomed on a monitor that already has a zoomed
|
|
// component. Compare this component and the component already on the
|
|
// monitor. The one that was there before is the one that stays. The one
|
|
// that shouldn't be there is the one that gets restored.
|
|
|
|
if ((iPreviousMonitorIndexOfComponent == iCurrentMonitorIndexOfComponent) && pCI->ciVisible)
|
|
pCIToRestore = pComponentInfo + zoomedComponentIndices[iCurrentMonitorIndexOfComponent];
|
|
else
|
|
pCIToRestore = pCI;
|
|
pCIToRestore->ciPosition.iLeft = pCIToRestore->ciStateInfo.iLeft;
|
|
pCIToRestore->ciPosition.iTop = pCIToRestore->ciStateInfo.iTop;
|
|
pCIToRestore->ciPosition.dwWidth = pCIToRestore->ciStateInfo.dwWidth;
|
|
pCIToRestore->ciPosition.dwHeight = pCIToRestore->ciStateInfo.dwHeight;
|
|
pCIToRestore->ciPosition.izIndex = COMPONENT_TOP;
|
|
pCIToRestore->ciItemState = IS_NORMAL;
|
|
}
|
|
|
|
// If the component is zoomed also write out the COMPSTATEINFO.
|
|
|
|
if (IsZoomedState(pCI->ciItemState))
|
|
{
|
|
zoomedComponentIndices[iCurrentMonitorIndexOfComponent] = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
WriteAllComponents(regKeyDesktop, pComponentInfo, dwComponentCount);
|
|
LocalFree(pComponentInfo);
|
|
}
|
|
|
|
if (bRepositionedComponent)
|
|
{
|
|
SHELLSTATE ss;
|
|
|
|
SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
|
|
SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
|
|
|
|
// Refresh only if AD is turned on.
|
|
|
|
if(ss.fDesktopHTML)
|
|
{
|
|
|
|
// 98/09/22 #182982 vtan: Use dynamic HTML by default to refresh.
|
|
// Only disallow usage when specifically told to by a flag.
|
|
|
|
PokeWebViewDesktop(AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH);
|
|
}
|
|
}
|
|
}
|
|
ApplyCurrentMonitorArray();
|
|
}
|
|
|
|
return bRepositionedComponent;
|
|
}
|