Skip to content

Commit

Permalink
- Moved the worker thread sleep out of the taskbar foreach. Taskbar u…
Browse files Browse the repository at this point in the history
…pdates will now be faster and smoother.

- Removed the thread that would constantly check Windows Accent Colour and now using a hook that catches the event from Windows. (Thanks, qwerty12!)
- Can now detect when Explorer is restarted. (Thanks again, qwerty12!)
- Replaced the Windows Accent Alpha UpDown with a slider.
  • Loading branch information
Elestriel committed Jan 11, 2017
1 parent d4893a6 commit 9c5476a
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 51 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -192,4 +192,5 @@ $RECYCLE.BIN/

#####
# End of core ignore list, below put you custom 'per project' settings (patterns or path)
#####
#####
/TaskbarTool/ProcessWatcher
11 changes: 6 additions & 5 deletions TaskbarTool/MainWindow.xaml
Expand Up @@ -71,11 +71,12 @@
IsChecked="{Binding Source={x:Static properties:Settings.Default}, Path=UseWindowsAccentColor}"
Checked="WindowsAccentColorCheckBox_Changed"
Unchecked="WindowsAccentColorCheckBox_Changed"/>
<xctk:IntegerUpDown x:Name="WindowsAccentAlpha" Grid.Column="1"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="2,89,0,0" Width="60"
Value="{Binding Source={x:Static properties:Settings.Default}, Path=WindowsAccentAlpha}"
Maximum="255" Minimum="0"/>
<Slider x:Name="WindowsAccentAlphaSlider" Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Margin="10,92,10,0" Minimum="0" Maximum="255" Value="{Binding Source={x:Static properties:Settings.Default}, Path=WindowsAccentAlpha}"
Thumb.DragCompleted="WindowsAccentAlphaSlider_DragCompleted"
Thumb.DragStarted="WindowsAccentAlphaSlider_DragStarted"
ValueChanged="WindowsAccentAlphaSlider_ValueChanged"/>
</Grid>
<Grid x:Name="OptionsGrid" Grid.Row="1">
</Grid>
Expand Down
135 changes: 92 additions & 43 deletions TaskbarTool/MainWindow.xaml.cs
Expand Up @@ -7,6 +7,7 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;

namespace TaskbarTool
Expand All @@ -25,6 +26,9 @@ public partial class MainWindow : Window

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);

[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern uint RegisterWindowMessage(string msgString);
#endregion Invokes

#region Enums
Expand Down Expand Up @@ -78,13 +82,20 @@ public WinCompatTrData(WindowCompositionAttribute attribute, IntPtr data, int si
#endregion Structs

#region Declarations
static Task WindowsAccentColorTask;
static bool RunAccentTask = false;
// Worker thread
static Task ApplyTask;
static bool RunApplyTask = false;
static AccentPolicy accentPolicy = new AccentPolicy();
public static bool FindTaskbarHandles = true;

static System.Windows.Forms.NotifyIcon SysTrayIcon;
ContextMenu SysTrayContextMenu;

private static bool alphaDragStarted = false;

static AccentPolicy accentPolicy = new AccentPolicy();

private static readonly uint WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
private const uint WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;
#endregion Declarations

#region Initializations
Expand Down Expand Up @@ -162,6 +173,7 @@ private void Window_ContentRendered(object sender, EventArgs e)
if (Properties.Settings.Default.StartMinimized) { this.WindowState = WindowState.Minimized; }
if (Properties.Settings.Default.StartWhenLaunched) { StartStopButton_Click(null, null); }

//ProcessWatcher.Process.Start();
}
#endregion Initializations

Expand All @@ -170,7 +182,6 @@ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs
{
SysTrayIcon.Dispose();
SaveSettings();
RunAccentTask = false;
RunApplyTask = false;
}

Expand All @@ -184,33 +195,38 @@ private void CloseMainWindow(object sender, RoutedEventArgs e)
private void ApplyToAllTaskbars()
{
List<IntPtr> hWndList = new List<IntPtr>();

while (RunApplyTask)
{
if (FindTaskbarHandles || ProcessWatcher.Process.NewExplorerStarted)
{
hWndList.Add(FindWindow("Shell_TrayWnd", null));
IntPtr otherBars = IntPtr.Zero;

hWndList.Add(FindWindow("Shell_TrayWnd", null));
IntPtr otherBars = IntPtr.Zero;
//IntPtr cortana = FindWindowEx(hWndList[0], IntPtr.Zero, "TrayDummySearchControl", null);
//hWndList.Add(cortana);

//IntPtr cortana = FindWindowEx(hWndList[0], IntPtr.Zero, "TrayDummySearchControl", null);
//hWndList.Add(cortana);
while (true)
{
otherBars = FindWindowEx(IntPtr.Zero, otherBars, "Shell_SecondaryTrayWnd", "");
if (otherBars == IntPtr.Zero) { break; }
else { hWndList.Add(otherBars); }
}

while (true)
{
otherBars = FindWindowEx(IntPtr.Zero, otherBars, "Shell_SecondaryTrayWnd", "");
if (otherBars == IntPtr.Zero) { break; }
else { hWndList.Add(otherBars); }
}
FindTaskbarHandles = false;
ProcessWatcher.Process.NewExplorerStarted = false;
}

while (RunApplyTask)
{
foreach (IntPtr hWnd in hWndList)
{
SetWindowBlur(hWnd);
Thread.Sleep(10);
SetTaskbarStyle(hWnd);
}
Thread.Sleep(10);
}
}

private void SetWindowBlur(IntPtr hWnd)
private void SetTaskbarStyle(IntPtr hWnd)
{

int sizeOfPolicy = Marshal.SizeOf(accentPolicy);
IntPtr policyPtr = Marshal.AllocHGlobal(sizeOfPolicy);
Marshal.StructureToPtr(accentPolicy, policyPtr, false);
Expand All @@ -222,12 +238,34 @@ private void SetWindowBlur(IntPtr hWnd)
Marshal.FreeHGlobal(policyPtr);
}

private void GetWindowsAccentColorLoop()
protected override void OnSourceInitialized(EventArgs e)
{
while (RunAccentTask) {
accentPolicy.GradientColor = WindowsAccentColor.GetColorAsInt();
Thread.Sleep(900);
base.OnSourceInitialized(e);

IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
mainWindowSrc.AddHook(WndProc);
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_TASKBARCREATED)
{
FindTaskbarHandles = true;
handled = true;
} else if (msg == WM_DWMCOLORIZATIONCOLORCHANGED) {
accentPolicy.GradientColor = WindowsAccentColor.GetColorAsInt(); // TODO: use colour from wParam
handled = true;
}

return IntPtr.Zero;
}

private void ApplyAlphaToWindowsAccent(byte alpha)
{
byte[] bytes = BitConverter.GetBytes(accentPolicy.GradientColor);
int colorInt = BitConverter.ToInt32(new byte[] { bytes[0], bytes[1], bytes[2], alpha }, 0);
accentPolicy.GradientColor = colorInt;
}

#endregion Functions
Expand All @@ -244,6 +282,8 @@ private void StartStopButton_Click(object sender, RoutedEventArgs e)
{
StartStopButton.Content = "Stop";
RunApplyTask = true;
if (WindowsAccentColorCheckBox.IsChecked == true) { accentPolicy.GradientColor = WindowsAccentColor.GetColorAsInt(); }

ApplyTask = new Task(() => ApplyToAllTaskbars());
ApplyTask.Start();
}
Expand Down Expand Up @@ -281,42 +321,52 @@ private void WindowsAccentColorCheckBox_Changed(object sender, RoutedEventArgs e
{
if (WindowsAccentColorCheckBox.IsChecked == true)
{
accentPolicy.GradientColor = WindowsAccentColor.GetColorAsInt();
GradientColorPicker.IsEnabled = false;
RunAccentTask = true;
WindowsAccentColorTask = new Task(() => GetWindowsAccentColorLoop());
WindowsAccentColorTask.Start();
}
else
{
RunAccentTask = false;
Color gradientColor = GradientColorPicker.SelectedColor ?? Color.FromArgb(255, 255, 255, 255);
accentPolicy.GradientColor = BitConverter.ToInt32(new byte[] { gradientColor.R, gradientColor.G, gradientColor.B, gradientColor.A }, 0);
GradientColorPicker.IsEnabled = true;
}
}

private void WindowsAccentAlphaSlider_DragCompleted(object sender, RoutedEventArgs e)
{
alphaDragStarted = false;
if (Properties.Settings.Default.UseWindowsAccentColor)
{
ApplyAlphaToWindowsAccent((byte)WindowsAccentAlphaSlider.Value);
}
}

private void WindowsAccentAlphaSlider_DragStarted(object sender, RoutedEventArgs e)
{
alphaDragStarted = true;
}

private void WindowsAccentAlphaSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!alphaDragStarted && Properties.Settings.Default.UseWindowsAccentColor)
{
ApplyAlphaToWindowsAccent((byte)WindowsAccentAlphaSlider.Value);
}
}

#endregion Control Handles
}

#region Helper Classes
public static class WindowsAccentColor
{
private static Color accentColor = Color.FromArgb(255, 0, 0, 0);
private static DateTime lastUpdateTime;
private static TimeSpan timeSinceLastUpdate;

public static Color GetColor()
{
timeSinceLastUpdate = DateTime.Now - lastUpdateTime;
if (timeSinceLastUpdate.TotalSeconds > 1)
{ UpdateColor(); }

return accentColor;
}

public static int GetColorAsInt()
{
Color color = GetColor();
UpdateColor();

return BitConverter.ToInt32(new byte[] { color.R, color.G, color.B, Properties.Settings.Default.WindowsAccentAlpha }, 0);
return BitConverter.ToInt32(new byte[] { accentColor.R, accentColor.G, accentColor.B, Properties.Settings.Default.WindowsAccentAlpha }, 0);
}

private static void UpdateColor()
Expand All @@ -325,8 +375,7 @@ private static void UpdateColor()
int keyColor = (int)Microsoft.Win32.Registry.GetValue(keyName, "StartColorMenu", 00000000);

byte[] bytes = BitConverter.GetBytes(keyColor);

lastUpdateTime = DateTime.Now;

accentColor = Color.FromArgb(bytes[3], bytes[0], bytes[1], bytes[2]);
}
}
Expand Down
4 changes: 2 additions & 2 deletions TaskbarTool/Properties/AssemblyInfo.cs
Expand Up @@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5")]
[assembly: AssemblyFileVersion("1.0.5")]
[assembly: AssemblyVersion("1.0.6")]
[assembly: AssemblyFileVersion("1.0.6")]
6 changes: 6 additions & 0 deletions TaskbarTool/TaskbarTool.csproj
Expand Up @@ -41,10 +41,14 @@
<PropertyGroup>
<ApplicationIcon>Resources\Mushroom1UP.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
Expand Down Expand Up @@ -82,6 +86,7 @@
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="ProcessWatcher\ProcessWatcher.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
Expand All @@ -99,6 +104,7 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.manifest" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
Expand Down
76 changes: 76 additions & 0 deletions TaskbarTool/app.manifest
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->

<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->

<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->

<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->

<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->

<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->

</application>
</compatibility>

<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
-->

<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->

</assembly>

2 comments on commit 9c5476a

@Aemony
Copy link

@Aemony Aemony commented on 9c5476a Jan 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's up with excluding /TaskbarTool/ProcessWatcher in .gitignore? I'd assume that's a mistake as it makes the code uncompilable without that file.

@Elestriel
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up not needing it. I thought I'd removed all references to it, but I guess not. I'll remove it properly next time I check in.

Please sign in to comment.