mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Made display changes reliable
This commit is contained in:
parent
963b267158
commit
87f62aa322
@ -26,8 +26,8 @@ using System.Resources;
|
||||
[assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")]
|
||||
|
||||
// Version information
|
||||
[assembly: AssemblyVersion("2.2.0.252")]
|
||||
[assembly: AssemblyFileVersion("2.2.0.252")]
|
||||
[assembly: AssemblyVersion("2.2.0.280")]
|
||||
[assembly: AssemblyFileVersion("2.2.0.280")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en" )]
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
|
@ -1922,11 +1922,12 @@ namespace DisplayMagician
|
||||
// Shutdown the processes
|
||||
ProcessUtils.StopProcess(startProgramsToStop);
|
||||
|
||||
// Refresh the system tray / notification tray area to clean out any applications we stopped
|
||||
DisplayMagicianShared.Windows.TaskBarStuckRectangle.RefreshTrayArea();
|
||||
// Refresh the system tray / notification tray area to clean out any applications we stopped
|
||||
DisplayMagicianShared.Windows.WinLibrary.RefreshTrayArea();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change Audio Device back (if one specified)
|
||||
if (activeAudioDevices.Count > 0)
|
||||
{
|
||||
|
@ -289,6 +289,7 @@ namespace DisplayMagician.UIForms
|
||||
this.lbl_save_profile.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.lbl_save_profile.BackColor = System.Drawing.Color.Brown;
|
||||
this.lbl_save_profile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.lbl_save_profile.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.lbl_save_profile.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
|
||||
this.lbl_save_profile.ForeColor = System.Drawing.Color.White;
|
||||
this.lbl_save_profile.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
|
@ -518,9 +518,13 @@ namespace DisplayMagician.UIForms
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
const int WM_DISPLAYCHANGE = 0x007E;
|
||||
const int WM_SETTINGCHANGE = 0x001A;
|
||||
const int WM_DEVICECHANGE = 0x0219;
|
||||
|
||||
switch (m.Msg)
|
||||
{
|
||||
case WM_DEVICECHANGE:
|
||||
case WM_SETTINGCHANGE:
|
||||
case WM_DISPLAYCHANGE:
|
||||
btn_view_current.PerformClick();
|
||||
break;
|
||||
|
@ -160,7 +160,7 @@
|
||||
<value>248, 17</value>
|
||||
</metadata>
|
||||
<data name="lbl_save_profile.Text" xml:space="preserve">
|
||||
<value>Setup your display layout in NVIDIA Control Panel, AMD Radeon Adrenaline or Windows Display Settings, then return to DisplayMagician and click 'Save' to store this Display Profile for later. Click the Help button for step-by-step instructions.</value>
|
||||
<value>Setup your display layout in NVIDIA Control Panel, AMD Radeon Adrenaline or Windows Display Settings, then return to DisplayMagician and click 'Save' to store this Display Profile for later use. Taskbar changes will show up after a few seconds.</value>
|
||||
</data>
|
||||
<metadata name="dialog_save.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>358, 17</value>
|
||||
|
@ -9,7 +9,6 @@ using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using DisplayMagicianShared.Windows;
|
||||
|
||||
namespace DisplayMagician.UIForms
|
||||
{
|
||||
@ -117,7 +116,7 @@ namespace DisplayMagician.UIForms
|
||||
|
||||
if (tbsr.MainScreen)
|
||||
{
|
||||
TaskBarStuckRectangle.RepositionMainTaskBar(taskbarForcedEdge);
|
||||
WinLibrary.RepositionMainTaskBar(taskbarForcedEdge);
|
||||
}
|
||||
|
||||
}
|
||||
@ -132,7 +131,7 @@ namespace DisplayMagician.UIForms
|
||||
{
|
||||
SharedLogger.logger.Trace($"ProfileToolsForm/btn_apply_Click: No taskbar layout in display profile so skipping setting it!");
|
||||
}
|
||||
TaskBarStuckRectangle.RepositionSecondaryTaskBars();
|
||||
WinLibrary.RepositionSecondaryTaskBars();
|
||||
|
||||
// Now set the option to completed.
|
||||
DialogResult = DialogResult.OK;
|
||||
|
@ -318,6 +318,7 @@ namespace DisplayMagicianShared.AMD
|
||||
// so that we won't break json.net when we save a default config
|
||||
|
||||
myDefaultConfig.AdapterConfigs = new List<AMD_ADAPTER_CONFIG>();
|
||||
myDefaultConfig.SlsConfig.IsSlsEnabled = false;
|
||||
myDefaultConfig.SlsConfig.SLSMapConfigs = new List<AMD_SLSMAP_CONFIG>();
|
||||
myDefaultConfig.SlsConfig.SLSEnabledDisplayTargets = new List<ADL_MODE>();
|
||||
myDefaultConfig.DisplayMaps = new List<ADL_DISPLAY_MAP>();
|
||||
@ -353,13 +354,7 @@ namespace DisplayMagicianShared.AMD
|
||||
|
||||
private AMD_DISPLAY_CONFIG GetAMDDisplayConfig(bool allDisplays = false)
|
||||
{
|
||||
AMD_DISPLAY_CONFIG myDisplayConfig = new AMD_DISPLAY_CONFIG();
|
||||
myDisplayConfig.AdapterConfigs = new List<AMD_ADAPTER_CONFIG>();
|
||||
|
||||
// We set up the default for this display config as SLS disabled
|
||||
// (We will change this later if it turns out we're using SLS)
|
||||
myDisplayConfig.SlsConfig.IsSlsEnabled = false;
|
||||
myDisplayConfig.SlsConfig.SLSEnabledDisplayTargets = new List<ADL_MODE>();
|
||||
AMD_DISPLAY_CONFIG myDisplayConfig = CreateDefaultConfig();
|
||||
|
||||
if (_initialised)
|
||||
{
|
||||
|
@ -59,8 +59,9 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public override bool Equals(object obj) => obj is NVIDIA_HDR_CONFIG other && this.Equals(other);
|
||||
public bool Equals(NVIDIA_HDR_CONFIG other)
|
||||
=> HdrCapabilities.SequenceEqual(other.HdrCapabilities) &&
|
||||
HdrColorData.SequenceEqual(other.HdrColorData) &&
|
||||
IsNvHdrEnabled == other.IsNvHdrEnabled;
|
||||
HdrColorData.SequenceEqual(other.HdrColorData) &&
|
||||
IsNvHdrEnabled == other.IsNvHdrEnabled;
|
||||
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
@ -124,12 +125,13 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public override bool Equals(object obj) => obj is NVIDIA_DISPLAY_CONFIG other && this.Equals(other);
|
||||
|
||||
public bool Equals(NVIDIA_DISPLAY_CONFIG other)
|
||||
=> MosaicConfig.Equals(other.MosaicConfig) &&
|
||||
HdrConfig.Equals(other.HdrConfig) &&
|
||||
=> HdrConfig.Equals(other.HdrConfig) &&
|
||||
MosaicConfig.Equals(other.MosaicConfig) &&
|
||||
ColorConfig.Equals(other.ColorConfig) &&
|
||||
CustomDisplays.SequenceEqual(other.CustomDisplays) &&
|
||||
DisplayConfigs.SequenceEqual(other.DisplayConfigs) &&
|
||||
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
|
||||
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
@ -282,6 +284,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
// Fill in the minimal amount we need to avoid null references
|
||||
// so that we won't break json.net when we save a default config
|
||||
|
||||
myDefaultConfig.MosaicConfig.IsMosaicEnabled = false;
|
||||
myDefaultConfig.MosaicConfig.MosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V2[0];
|
||||
myDefaultConfig.MosaicConfig.MosaicViewports = new List<NV_RECT[]>();
|
||||
myDefaultConfig.HdrConfig.HdrCapabilities = new Dictionary<string, NV_HDR_CAPABILITIES_V2>();
|
||||
@ -320,7 +323,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
private NVIDIA_DISPLAY_CONFIG GetNVIDIADisplayConfig(bool allDisplays = false)
|
||||
{
|
||||
NVIDIA_DISPLAY_CONFIG myDisplayConfig = new NVIDIA_DISPLAY_CONFIG();
|
||||
NVIDIA_DISPLAY_CONFIG myDisplayConfig = CreateDefaultConfig();
|
||||
|
||||
if (_initialised)
|
||||
{
|
||||
|
@ -350,12 +350,19 @@ namespace DisplayMagicianShared
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_profileShortcutBitmap != null)
|
||||
return _profileShortcutBitmap;
|
||||
if (ProfileRepository.ProfilesLoaded)
|
||||
{
|
||||
if (_profileShortcutBitmap != null)
|
||||
return _profileShortcutBitmap;
|
||||
else
|
||||
{
|
||||
_profileShortcutBitmap = this.ProfileIcon.ToTightestBitmap();
|
||||
return _profileShortcutBitmap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_profileShortcutBitmap = this.ProfileIcon.ToTightestBitmap();
|
||||
return _profileShortcutBitmap;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
set
|
||||
@ -1280,18 +1287,7 @@ namespace DisplayMagicianShared
|
||||
screen.IsSpanned = false;
|
||||
screen.Colour = normalScreenColor; // this is the default unless overridden by the primary screen
|
||||
screen.IsClone = false;
|
||||
screen.ClonedCopies = 0;
|
||||
try
|
||||
{
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tbr => tbr.DevicePath.Contains($"UID{targetId}")).Edge;
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Position of the taskbar on display {targetId} is on the {screen.TaskBarEdge } of the screen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Guess that it is at the bottom (90% correct)
|
||||
SharedLogger.logger.Error(ex, $"ProfileItem/GetNVIDIAScreenPositions: Exception trying to get the position of the taskbar on display {targetId}");
|
||||
screen.TaskBarEdge = TaskBarStuckRectangle.TaskBarEdge.Bottom;
|
||||
}
|
||||
screen.ClonedCopies = 0;
|
||||
foreach (var displaySource in _windowsDisplayConfig.DisplaySources)
|
||||
{
|
||||
if (displaySource.Value.Contains(sourceId))
|
||||
@ -1357,6 +1353,39 @@ namespace DisplayMagicianShared
|
||||
}
|
||||
}
|
||||
|
||||
// Now we try to set the taskbar positions
|
||||
if (screen.IsPrimary)
|
||||
{
|
||||
// If the screen is the primary screen, then we check if we need to use the StuckRect 'Settings' reg keys
|
||||
// rather than the MMStuckRect reg keys
|
||||
try
|
||||
{
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tb => tb.DevicePath.Contains("Settings")).Edge;
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Position of the taskbar on the primary display {targetId} is on the {screen.TaskBarEdge } of the screen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Guess that it is at the bottom (90% correct)
|
||||
SharedLogger.logger.Error(ex, $"ProfileItem/GetNVIDIAScreenPositions: Exception trying to get the position of the taskbar on primary display {targetId}");
|
||||
screen.TaskBarEdge = TaskBarStuckRectangle.TaskBarEdge.Bottom;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tbr => tbr.DevicePath.Contains($"UID{targetId}")).Edge;
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Position of the taskbar on display {targetId} is on the {screen.TaskBarEdge } of the screen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Guess that it is at the bottom (90% correct)
|
||||
SharedLogger.logger.Error(ex, $"ProfileItem/GetNVIDIAScreenPositions: Exception trying to get the position of the taskbar on display {targetId}");
|
||||
screen.TaskBarEdge = TaskBarStuckRectangle.TaskBarEdge.Bottom;
|
||||
}
|
||||
}
|
||||
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetWindowsScreenPositions: Added a new Screen {screen.Name} ({screen.ScreenWidth}x{screen.ScreenHeight}) at position {screen.ScreenX},{screen.ScreenY}.");
|
||||
|
||||
_screens.Add(screen);
|
||||
|
@ -639,6 +639,10 @@ namespace DisplayMagicianShared
|
||||
SharedLogger.logger.Trace($"ProfileRepository/UpdateActiveProfile: Paused updating display settings for {totalDelay} milliseconds.");
|
||||
}
|
||||
|
||||
// Force explorer to update the TaskBar settings just in case they were moved
|
||||
//ShellHelper.TellShellToWriteSettings();
|
||||
//WinLibrary.RefreshTaskBars();
|
||||
|
||||
profile.CreateProfileFromCurrentDisplaySettings();
|
||||
|
||||
if (_profilesLoaded && _allProfiles.Count > 0)
|
||||
|
@ -42,7 +42,7 @@ namespace DisplayMagicianShared
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task IntrigueShellToWriteSettings()
|
||||
public static async Task TellShellToWriteSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -349,7 +349,12 @@ namespace DisplayMagicianShared
|
||||
public const int WM_SETTINGCHANGE = 0x001a;
|
||||
public const int WM_MOUSEMOVE = 0x0200;
|
||||
public const int SPI_SETWORKAREA = 0x002F;
|
||||
public const int SHELLHOOK = 0xC028;
|
||||
public const int WM_USER_REFRESHTASKBAR = 0x05CA;
|
||||
public const int WM_USER_440 = 0x05B8;
|
||||
public const int WM_USER_92 = 0x045C;
|
||||
public const int WM_USER_1 = 0x0401;
|
||||
public const int WM_USER_100 = 0x0464;
|
||||
public const int wParam_SHELLTRAY = 0x00000006;
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,9 @@ namespace DisplayMagicianShared.Windows
|
||||
PopulateFieldsFromBinary();
|
||||
|
||||
SharedLogger.logger.Trace($"TaskBarStuckRectangle/TaskBarStuckRectangle: The taskbar for {DevicePath} is against the {Edge} edge, is positioned at ({Location.X},{Location.Y}) and is {Location.Width}x{Location.Height} in size.");
|
||||
|
||||
// If we get here then we're done and don't need to continue with the rest of the code.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -119,6 +122,14 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"TaskBarStuckRectangle/TaskBarStuckRectangle: A MMStuckRect entry was found, but the version of the field is wrong.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"TaskBarStuckRectangle/TaskBarStuckRectangle: A MMStuckRect entry was NOT found. We will try to find the object in the StuckRect registry key instead");
|
||||
}
|
||||
|
||||
if (!foundDevicePath)
|
||||
@ -180,6 +191,23 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"TaskBarStuckRectangle/TaskBarStuckRectangle: A StuckRect entry was found, but the version of the field is wrong.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"TaskBarStuckRectangle/TaskBarStuckRectangle: A StuckRect entry was NOT found. This means we're unable to get the taskbar location, an unable to return a sensible TaskBarStuckRectangle object.");
|
||||
throw new TaskBarStuckRectangleException("A StuckRect entry was NOT found. This means we're unable to get the taskbar location, an unable to return a sensible TaskBarStuckRectangle object.");
|
||||
//SharedLogger.logger.Error($"TaskBarStuckRectangle/TaskBarStuckRectangle: A StuckRect entry was NOT found. This means we're unable to get the taskbar location, so we'll return a default object instead.");
|
||||
/*Version = 3;
|
||||
DPI = 0;
|
||||
Edge = TaskBarEdge.Bottom;
|
||||
Location = Rectangle.Empty;
|
||||
MinSize = new Size(48,48);
|
||||
Options = 0;
|
||||
Rows = 1;*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -470,79 +498,7 @@ namespace DisplayMagicianShared.Windows
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool RepositionMainTaskBar(TaskBarEdge edge)
|
||||
{
|
||||
// Tell Windows to refresh the Main Screen Windows Taskbar
|
||||
// Find the "Shell_TrayWnd" window
|
||||
IntPtr mainToolBarHWnd = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
// Send the "Shell_TrayWnd" window a WM_USER_REFRESHTASKBAR with a wParameter of 0006 and a lParamater of the position (e.g. 0000 for left, 0001 for top, 0002 for right and 0003 for bottom)
|
||||
IntPtr taskBarPositionBuffer = new IntPtr((Int32)edge);
|
||||
Utils.SendMessage(mainToolBarHWnd, Utils.WM_USER_REFRESHTASKBAR, (IntPtr)Utils.wParam_SHELLTRAY, taskBarPositionBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool RepositionSecondaryTaskBars()
|
||||
{
|
||||
// Tell Windows to refresh the Other Windows Taskbars if needed
|
||||
IntPtr lastTaskBarWindowHwnd = (IntPtr)Utils.NULL;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// Find the next "Shell_SecondaryTrayWnd" window
|
||||
IntPtr nextTaskBarWindowHwnd = Utils.FindWindowEx((IntPtr)Utils.NULL, lastTaskBarWindowHwnd, "Shell_SecondaryTrayWnd", null);
|
||||
if (nextTaskBarWindowHwnd == (IntPtr)Utils.NULL)
|
||||
{
|
||||
// No more windows taskbars to notify
|
||||
break;
|
||||
}
|
||||
// Send the "Shell_TrayWnd" window a WM_SETTINGCHANGE with a wParameter of SPI_SETWORKAREA
|
||||
Utils.SendMessage(lastTaskBarWindowHwnd, Utils.WM_SETTINGCHANGE, (IntPtr)Utils.SPI_SETWORKAREA, (IntPtr)Utils.NULL);
|
||||
lastTaskBarWindowHwnd = nextTaskBarWindowHwnd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void RefreshTrayArea()
|
||||
{
|
||||
// Finds the Shell_TrayWnd -> TrayNotifyWnd -> SysPager -> "Notification Area" containing the visible notification area icons (windows 7 version)
|
||||
IntPtr systemTrayContainerHandle = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
IntPtr systemTrayHandle = Utils.FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
|
||||
IntPtr sysPagerHandle = Utils.FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
|
||||
IntPtr notificationAreaHandle = Utils.FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
|
||||
// If the visible notification area icons (Windows 7 aren't found, then we're on a later version of windows, and we need to look for different window names
|
||||
if (notificationAreaHandle == IntPtr.Zero)
|
||||
{
|
||||
// Finds the Shell_TrayWnd -> TrayNotifyWnd -> SysPager -> "User Promoted Notification Area" containing the visible notification area icons (windows 10+ version)
|
||||
notificationAreaHandle = Utils.FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
|
||||
// Also attempt to find the NotifyIconOverflowWindow -> "Overflow Notification Area' window which is the hidden windoww that notification icons live when they are
|
||||
// too numberous or are hidden by the user.
|
||||
IntPtr notifyIconOverflowWindowHandle = Utils.FindWindow("NotifyIconOverflowWindow", null);
|
||||
IntPtr overflowNotificationAreaHandle = Utils.FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
|
||||
// Fool the "Overflow Notification Area' window into thinking the mouse is moving over it
|
||||
// which will force windows to refresh the "Overflow Notification Area' window and remove old icons.
|
||||
RefreshTrayArea(overflowNotificationAreaHandle);
|
||||
notifyIconOverflowWindowHandle = IntPtr.Zero;
|
||||
overflowNotificationAreaHandle = IntPtr.Zero;
|
||||
}
|
||||
// Fool the "Notification Area" or "User Promoted Notification Area" window (depends on the version of windows) into thinking the mouse is moving over it
|
||||
// which will force windows to refresh the "Notification Area" or "User Promoted Notification Area" window and remove old icons.
|
||||
RefreshTrayArea(notificationAreaHandle);
|
||||
systemTrayContainerHandle = IntPtr.Zero;
|
||||
systemTrayHandle = IntPtr.Zero;
|
||||
sysPagerHandle = IntPtr.Zero;
|
||||
notificationAreaHandle = IntPtr.Zero;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void RefreshTrayArea(IntPtr windowHandle)
|
||||
{
|
||||
// Moves the mouse around within the window area of the supplied window
|
||||
Utils.RECT rect;
|
||||
Utils.GetClientRect(windowHandle, out rect);
|
||||
for (var x = 0; x < rect.right; x += 5)
|
||||
for (var y = 0; y < rect.bottom; y += 5)
|
||||
Utils.SendMessage(windowHandle, Utils.WM_MOUSEMOVE, 0, (y << 16) + x);
|
||||
}
|
||||
|
||||
|
||||
/*public void DoMouseLeftClick(IntPtr handle, Point x)
|
||||
{
|
||||
@ -558,4 +514,15 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
[global::System.Serializable]
|
||||
public class TaskBarStuckRectangleException : Exception
|
||||
{
|
||||
public TaskBarStuckRectangleException() { }
|
||||
public TaskBarStuckRectangleException(string message) : base(message) { }
|
||||
public TaskBarStuckRectangleException(string message, Exception inner) : base(message, inner) { }
|
||||
protected TaskBarStuckRectangleException(
|
||||
System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ using System.IO;
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Win32;
|
||||
using System.Threading.Tasks;
|
||||
using static DisplayMagicianShared.Windows.TaskBarStuckRectangle;
|
||||
|
||||
namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
@ -320,6 +321,10 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
private WINDOWS_DISPLAY_CONFIG GetWindowsDisplayConfig(QDC selector = QDC.QDC_ONLY_ACTIVE_PATHS | QDC.QDC_INCLUDE_HMD)
|
||||
{
|
||||
|
||||
// Prepare the empty windows display config
|
||||
WINDOWS_DISPLAY_CONFIG windowsDisplayConfig = CreateDefaultConfig();
|
||||
|
||||
// Get the size of the largest Active Paths and Modes arrays
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the size of the largest Active Paths and Modes arrays");
|
||||
int pathCount = 0;
|
||||
@ -368,13 +373,7 @@ namespace DisplayMagicianShared.Windows
|
||||
throw new WinLibraryException($"QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays.");
|
||||
}
|
||||
|
||||
// Prepare the empty windows display config
|
||||
WINDOWS_DISPLAY_CONFIG windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG();
|
||||
windowsDisplayConfig.DisplayAdapters = new Dictionary<ulong, string>();
|
||||
windowsDisplayConfig.DisplayHDRStates = new List<ADVANCED_HDR_INFO_PER_PATH>();
|
||||
windowsDisplayConfig.DisplaySources = new Dictionary<string, List<uint>>();
|
||||
windowsDisplayConfig.IsCloned = false;
|
||||
|
||||
|
||||
// First of all generate the current displayIdentifiers
|
||||
windowsDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||
|
||||
@ -633,6 +632,7 @@ namespace DisplayMagicianShared.Windows
|
||||
if (match.Success)
|
||||
{
|
||||
string devicePath = match.Groups[1].Value;
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found devicePath {devicePath} from the display identifier {displayId}.");
|
||||
TaskBarStuckRectangle taskBarStuckRectangle = new TaskBarStuckRectangle(devicePath);
|
||||
taskBarStuckRectangles.Add(taskBarStuckRectangle);
|
||||
}
|
||||
@ -1393,7 +1393,7 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
if (tbsr.MainScreen)
|
||||
{
|
||||
TaskBarStuckRectangle.RepositionMainTaskBar(tbsr.Edge);
|
||||
RepositionMainTaskBar(tbsr.Edge);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1408,7 +1408,7 @@ namespace DisplayMagicianShared.Windows
|
||||
IntPtr lastTaskBarWindowHwnd = (IntPtr)Utils.NULL;
|
||||
if (displayConfig.TaskBarLayout.Count > 1)
|
||||
{
|
||||
TaskBarStuckRectangle.RepositionSecondaryTaskBars();
|
||||
RepositionSecondaryTaskBars();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1958,7 +1958,111 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool RepositionMainTaskBar(TaskBarEdge edge)
|
||||
{
|
||||
// Tell Windows to refresh the Main Screen Windows Taskbar
|
||||
// Find the "Shell_TrayWnd" window
|
||||
IntPtr mainToolBarHWnd = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
// Send the "Shell_TrayWnd" window a WM_USER_REFRESHTASKBAR with a wParameter of 0006 and a lParamater of the position (e.g. 0000 for left, 0001 for top, 0002 for right and 0003 for bottom)
|
||||
IntPtr taskBarPositionBuffer = new IntPtr((Int32)edge);
|
||||
Utils.SendMessage(mainToolBarHWnd, Utils.WM_USER_REFRESHTASKBAR, (IntPtr)Utils.wParam_SHELLTRAY, taskBarPositionBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool RepositionSecondaryTaskBars()
|
||||
{
|
||||
// Tell Windows to refresh the Other Windows Taskbars if needed
|
||||
IntPtr lastTaskBarWindowHwnd = (IntPtr)Utils.NULL;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// Find the next "Shell_SecondaryTrayWnd" window
|
||||
IntPtr nextTaskBarWindowHwnd = Utils.FindWindowEx((IntPtr)Utils.NULL, lastTaskBarWindowHwnd, "Shell_SecondaryTrayWnd", null);
|
||||
if (nextTaskBarWindowHwnd == (IntPtr)Utils.NULL)
|
||||
{
|
||||
// No more windows taskbars to notify
|
||||
break;
|
||||
}
|
||||
// Send the "Shell_TrayWnd" window a WM_SETTINGCHANGE with a wParameter of SPI_SETWORKAREA
|
||||
Utils.SendMessage(lastTaskBarWindowHwnd, Utils.WM_SETTINGCHANGE, (IntPtr)Utils.SPI_SETWORKAREA, (IntPtr)Utils.NULL);
|
||||
lastTaskBarWindowHwnd = nextTaskBarWindowHwnd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool RefreshTaskBars()
|
||||
{
|
||||
// Tell Windows to refresh the Main Screen Windows Taskbar registry settings by telling Explorer to update.
|
||||
// Find the "Shell_TrayWnd" window
|
||||
IntPtr mainToolBarHWnd = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
Utils.SendMessage(mainToolBarHWnd, Utils.WM_SETTINGCHANGE, (IntPtr)Utils.SPI_SETWORKAREA, (IntPtr)Utils.NULL);
|
||||
// Tell Windows to refresh the Other Windows Taskbars if needed
|
||||
IntPtr lastTaskBarWindowHwnd = (IntPtr)Utils.NULL;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// Find the next "Shell_SecondaryTrayWnd" window
|
||||
IntPtr nextTaskBarWindowHwnd = Utils.FindWindowEx((IntPtr)Utils.NULL, lastTaskBarWindowHwnd, "Shell_SecondaryTrayWnd", null);
|
||||
if (nextTaskBarWindowHwnd == (IntPtr)Utils.NULL)
|
||||
{
|
||||
// No more windows taskbars to notify
|
||||
break;
|
||||
}
|
||||
// Send the "Shell_TrayWnd" window a WM_SETTINGCHANGE with a wParameter of SPI_SETWORKAREA
|
||||
Utils.SendMessage(lastTaskBarWindowHwnd, Utils.WM_SETTINGCHANGE, (IntPtr)Utils.SPI_SETWORKAREA, (IntPtr)Utils.NULL);
|
||||
lastTaskBarWindowHwnd = nextTaskBarWindowHwnd;
|
||||
}
|
||||
|
||||
//IntPtr explorerToolBarHWnd = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
//Utils.PostMessage((IntPtr)Utils.HWND_BROADCAST, Utils.SHELLHOOK, 0x13, (int) mainToolBarHWnd);
|
||||
//Utils.PostMessage((IntPtr)Utils.HWND_BROADCAST, Utils.WM_SETTINGCHANGE, (int)Utils.SPI_SETWORKAREA, (int)Utils.NULL);
|
||||
/*IntPtr result;
|
||||
Utils.SendMessageTimeout((IntPtr)Utils.HWND_BROADCAST, Utils.WM_USER_1, (IntPtr)Utils.NULL, (IntPtr)Utils.NULL, Utils.SendMessageTimeoutFlag.SMTO_ABORTIFHUNG, 15, out result);*/
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void RefreshTrayArea()
|
||||
{
|
||||
// Finds the Shell_TrayWnd -> TrayNotifyWnd -> SysPager -> "Notification Area" containing the visible notification area icons (windows 7 version)
|
||||
IntPtr systemTrayContainerHandle = Utils.FindWindow("Shell_TrayWnd", null);
|
||||
IntPtr systemTrayHandle = Utils.FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
|
||||
IntPtr sysPagerHandle = Utils.FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
|
||||
IntPtr notificationAreaHandle = Utils.FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
|
||||
// If the visible notification area icons (Windows 7 aren't found, then we're on a later version of windows, and we need to look for different window names
|
||||
if (notificationAreaHandle == IntPtr.Zero)
|
||||
{
|
||||
// Finds the Shell_TrayWnd -> TrayNotifyWnd -> SysPager -> "User Promoted Notification Area" containing the visible notification area icons (windows 10+ version)
|
||||
notificationAreaHandle = Utils.FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
|
||||
// Also attempt to find the NotifyIconOverflowWindow -> "Overflow Notification Area' window which is the hidden windoww that notification icons live when they are
|
||||
// too numberous or are hidden by the user.
|
||||
IntPtr notifyIconOverflowWindowHandle = Utils.FindWindow("NotifyIconOverflowWindow", null);
|
||||
IntPtr overflowNotificationAreaHandle = Utils.FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
|
||||
// Fool the "Overflow Notification Area' window into thinking the mouse is moving over it
|
||||
// which will force windows to refresh the "Overflow Notification Area' window and remove old icons.
|
||||
RefreshTrayArea(overflowNotificationAreaHandle);
|
||||
notifyIconOverflowWindowHandle = IntPtr.Zero;
|
||||
overflowNotificationAreaHandle = IntPtr.Zero;
|
||||
}
|
||||
// Fool the "Notification Area" or "User Promoted Notification Area" window (depends on the version of windows) into thinking the mouse is moving over it
|
||||
// which will force windows to refresh the "Notification Area" or "User Promoted Notification Area" window and remove old icons.
|
||||
RefreshTrayArea(notificationAreaHandle);
|
||||
systemTrayContainerHandle = IntPtr.Zero;
|
||||
systemTrayHandle = IntPtr.Zero;
|
||||
sysPagerHandle = IntPtr.Zero;
|
||||
notificationAreaHandle = IntPtr.Zero;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void RefreshTrayArea(IntPtr windowHandle)
|
||||
{
|
||||
// Moves the mouse around within the window area of the supplied window
|
||||
Utils.RECT rect;
|
||||
Utils.GetClientRect(windowHandle, out rect);
|
||||
for (var x = 0; x < rect.right; x += 5)
|
||||
for (var y = 0; y < rect.bottom; y += 5)
|
||||
Utils.SendMessage(windowHandle, Utils.WM_MOUSEMOVE, 0, (y << 16) + x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user