diff --git a/DirectStart/App.xaml.cs b/DirectStart/App.xaml.cs index ef84bc0..a7e6520 100644 --- a/DirectStart/App.xaml.cs +++ b/DirectStart/App.xaml.cs @@ -4,6 +4,8 @@ using System.Windows; using B8TAM; using System.Diagnostics; +using System.Linq; +using System.IO.Pipes; namespace AFSM { @@ -24,89 +26,122 @@ public App() Current.Shutdown(); } } + private void HandleTriggerArgument() + { + using (var client = new NamedPipeClientStream(".", "DirectStartPipe", PipeDirection.Out)) + { + try + { + client.Connect(); + using (var writer = new StreamWriter(client)) + { + writer.WriteLine("TRIGGER"); + writer.Flush(); + } + } + catch (IOException ex) + { + // Log or handle the error as needed + Debug.WriteLine("Named pipe error: " + ex.Message); + } + } + } protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); - // Read the text file from %HOMEPATH% - string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "DirectStart", "Tiles", "config.txt"); - try + string debug = "false"; + + // Check if the trigger argument is passed + if (e.Args.Contains("/trigger") || debug == "true") + { + // Handle the trigger functionality + HandleTriggerArgument(); + // Shutdown the application if it was started just to trigger + Environment.Exit(0); + } + else { - if (File.Exists(filePath)) + // Read the text file from %HOMEPATH% + string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "DirectStart", "Tiles", "config.txt"); + try { - // Read the content of the text file - string[] lines = File.ReadAllLines(filePath); + if (File.Exists(filePath)) + { + // Read the content of the text file + string[] lines = File.ReadAllLines(filePath); - // Initialize variables to hold configuration values - string theme = null; - string profilePictureShape = null; - string forceFillStartButton = null; - string retrobarfix = null; + // Initialize variables to hold configuration values + string theme = null; + string profilePictureShape = null; + string forceFillStartButton = null; + string retrobarfix = null; - // Parse each line of the config file - foreach (string line in lines) - { - string[] parts = line.Split('='); - if (parts.Length == 2) + // Parse each line of the config file + foreach (string line in lines) { - string key = parts[0].Trim(); - string value = parts[1].Trim(); - - // Apply configuration based on the key - switch (key.ToLower()) + string[] parts = line.Split('='); + if (parts.Length == 2) { - case "theme": - theme = value; - break; - case "profilepictureshape": - profilePictureShape = value; - break; - case "forcefillstartbutton": - forceFillStartButton = value; - break; - case "RetroBarFix": - retrobarfix = value; - break; - default: - // Handle unknown keys if necessary - break; + string key = parts[0].Trim(); + string value = parts[1].Trim(); + + // Apply configuration based on the key + switch (key.ToLower()) + { + case "theme": + theme = value; + break; + case "profilepictureshape": + profilePictureShape = value; + break; + case "forcefillstartbutton": + forceFillStartButton = value; + break; + case "RetroBarFix": + retrobarfix = value; + break; + default: + // Handle unknown keys if necessary + break; + } } } - } - // Apply the theme - if (!string.IsNullOrEmpty(theme)) - { - string resourceDictionaryPath = GetResourceDictionaryPath(theme); - if (!string.IsNullOrEmpty(resourceDictionaryPath)) - { - // Set the ResourceDictionary for the theme - ResourceDictionary skinDictionary = new ResourceDictionary(); - skinDictionary.Source = new Uri(resourceDictionaryPath, UriKind.RelativeOrAbsolute); - Resources.MergedDictionaries.Add(skinDictionary); - } - else + // Apply the theme + if (!string.IsNullOrEmpty(theme)) { - MessageBox.Show("Invalid theme specified in the config file."); + string resourceDictionaryPath = GetResourceDictionaryPath(theme); + if (!string.IsNullOrEmpty(resourceDictionaryPath)) + { + // Set the ResourceDictionary for the theme + ResourceDictionary skinDictionary = new ResourceDictionary(); + skinDictionary.Source = new Uri(resourceDictionaryPath, UriKind.RelativeOrAbsolute); + Resources.MergedDictionaries.Add(skinDictionary); + } + else + { + MessageBox.Show("Invalid theme specified in the config file."); + } } - } - // Store profilePictureShape and forceFillStartButton in application-level resources - this.Resources["ProfilePictureShape"] = profilePictureShape; - this.Resources["ForceFillStartButton"] = forceFillStartButton; - this.Resources["RetroBarFix"] = retrobarfix; + // Store profilePictureShape and forceFillStartButton in application-level resources + this.Resources["ProfilePictureShape"] = profilePictureShape; + this.Resources["ForceFillStartButton"] = forceFillStartButton; + this.Resources["RetroBarFix"] = retrobarfix; + } + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString(), "B8taMenu had an issue loading the config file or its values."); + Debug.WriteLine(ex.ToString(), "B8taMenu had an issue loading the config file or its values."); } - } - catch (Exception ex) - { - MessageBox.Show(ex.ToString(), "B8taMenu had an issue loading the config file or its values."); - Debug.WriteLine(ex.ToString(), "B8taMenu had an issue loading the config file or its values."); - } - // Initialize your main window or any other startup logic - StartMenu mainWindow = new StartMenu(); - mainWindow.Show(); + // Initialize your main window or any other startup logic + StartMenu mainWindow = new StartMenu(); + mainWindow.Show(); + } } private string GetResourceDictionaryPath(string themeName) diff --git a/DirectStart/Skins/Metro.xaml b/DirectStart/Skins/Metro.xaml index be2e541..ab87e24 100644 --- a/DirectStart/Skins/Metro.xaml +++ b/DirectStart/Skins/Metro.xaml @@ -21,7 +21,7 @@ diff --git a/DirectStart/StartMenu.xaml b/DirectStart/StartMenu.xaml index 1968b5b..58c42ed 100644 --- a/DirectStart/StartMenu.xaml +++ b/DirectStart/StartMenu.xaml @@ -342,7 +342,7 @@ Visibility="{Binding Text.IsEmpty, Converter={StaticResource BoolToVis}, Element - + new RunCommand(RunCommand); - private static Color GetColor(IntPtr pElementName) + private void StartPipeServer() + { + Task.Run(() => + { + while (true) + { + using (var server = new NamedPipeServerStream("DirectStartPipe", PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances)) + { + try + { + server.WaitForConnection(); + using (var reader = new StreamReader(server)) + { + var message = reader.ReadLine(); + if (message != null && message.Contains("TRIGGER")) + { + Dispatcher.Invoke(() => OnStartTriggeredNoArgs()); + } + else + { + Console.WriteLine("Received unknown message: " + message); + } + } + } + catch (IOException ex) + { + // Log or handle the error as needed + Console.WriteLine("Named pipe error: " + ex.Message); + } + catch (Exception ex) + { + // Catch other potential exceptions + Console.WriteLine("Error: " + ex.Message); + } + } + } + }); + } + + + private static Color GetColor(IntPtr pElementName) { var colourset = DUIColorHelper.GetImmersiveUserColorSetPreference(false, false); uint type = DUIColorHelper.GetImmersiveColorTypeFromName(pElementName); @@ -75,9 +117,10 @@ public StartMenu() GetPrograms(programs); programs = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs"); GetPrograms(programs); + StartPipeServer(); - this.sourceTypes = new List() + this.sourceTypes = new List() { new SourceType("Program", @"Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count"), new SourceType("Shortcut", @"Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\Count") @@ -449,15 +492,18 @@ private string GetDisplayNameFromExePath(string exePath) { string displayName = string.Empty; - try - { - var fileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(exePath); - displayName = fileVersionInfo.FileDescription; + try + { + var fileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(exePath); + displayName = fileVersionInfo.FileDescription; - // If display name is longer than 17 characters, get the path without extension - if (displayName.Length > 25) - { - displayName = Path.GetFileNameWithoutExtension(exePath); + // If display name is longer than 17 characters, get the path without extension + if (displayName != null) + { + if (displayName.Length > 25) + { + displayName = Path.GetFileNameWithoutExtension(exePath); + } } } catch (Exception ex) @@ -582,16 +628,31 @@ public void LoadTiles() TilesHost.ItemsSource = Tiles; } - void OnStartTriggered(object sender, EventArgs e) - { - Visibility = Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible; - if (Visibility == Visibility.Visible) - { - Show(); - WindowActivator.ActivateWindow(new System.Windows.Interop.WindowInteropHelper(Menu).Handle); - SearchText.Focus(); - } - } + void OnStartTriggered(object sender, EventArgs e) + { + ToggleStartMenu(); + } + + private void OnStartTriggeredNoArgs() + { + ToggleStartMenu(); + } + + private void ToggleStartMenu() + { + Visibility = Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible; + if (Visibility == Visibility.Visible) + { + Show(); + WindowActivator.ActivateWindow(new System.Windows.Interop.WindowInteropHelper(Menu).Handle); + SearchText.Focus(); + } + else + { + Hide(); + } + } + private void Window_Activated(object sender, EventArgs e) { @@ -940,7 +1001,54 @@ private void ResizeTileLarge_Click(object sender, RoutedEventArgs e) { } + + private void SearchText_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + { + // Check if any alphanumeric key is pressed + if (char.IsLetterOrDigit((char)e.Key)) + { + string rundll32Path = Environment.ExpandEnvironmentVariables(@"%windir%\system32\rundll32.exe"); + string command = @"-sta {C90FB8CA-3295-4462-A721-2935E83694BA}"; + + ProcessStartInfo startInfo = new ProcessStartInfo(rundll32Path, command) + { + CreateNoWindow = true, + UseShellExecute = false + }; + + try + { + Process.Start(startInfo); + } + catch (Exception ex) + { + Debug.WriteLine("An error occurred: " + ex.Message); + } + } + } + + private void SearchText_TextChanged(object sender, TextChangedEventArgs e) + { + string rundll32Path = Environment.ExpandEnvironmentVariables(@"%windir%\system32\rundll32.exe"); + string command = @"-sta {C90FB8CA-3295-4462-A721-2935E83694BA}"; + + ProcessStartInfo startInfo = new ProcessStartInfo(rundll32Path, command) + { + CreateNoWindow = true, + UseShellExecute = false + }; + + try + { + Process.Start(startInfo); + } + catch (Exception ex) + { + Debug.WriteLine("An error occurred: " + ex.Message); + } + } } + public class RunCommand : ICommand { public delegate void ExecuteMethod(); diff --git a/DirectStart/StartMenuListener.cs b/DirectStart/StartMenuListener.cs index 162d21d..8fe04bf 100644 --- a/DirectStart/StartMenuListener.cs +++ b/DirectStart/StartMenuListener.cs @@ -65,41 +65,41 @@ int KeyEvents(int code, IntPtr wParam, IntPtr lParam) { KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); - if (wParam == (IntPtr)0x0100) // Key down - { - pressedKeys.Add(objKeyInfo.key); // Add the key to the set of pressed keys - stopwatch.Restart(); // Restart the stopwatch - } - else if (wParam == (IntPtr)0x0101) // Key up - { - stopwatch.Stop(); // Stop the stopwatch - - if (pressedKeys.Count == 1 && (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin)) - { - // Introduce a small delay (e.g., 100 milliseconds) to ensure the key is held for a minimum time - if (stopwatch.ElapsedMilliseconds <= 100) - { - bool anyKeyPressed = false; - - foreach (Key key in Enum.GetValues(typeof(Key))) - { - if (key != Key.None && key != Key.LWin && key != Key.RWin && Keyboard.IsKeyDown(key)) - { - anyKeyPressed = true; - break; - } - } - // Only execute the actions if no other keys are pressed - if (!anyKeyPressed) - { - StartTriggered?.Invoke(this, EventArgs.Empty); - return 1; - } - } - } - - pressedKeys.Clear(); - } + //if (wParam == (IntPtr)0x0100) // Key down + //{ + // pressedKeys.Add(objKeyInfo.key); // Add the key to the set of pressed keys + // stopwatch.Restart(); // Restart the stopwatch + //} + //else if (wParam == (IntPtr)0x0101) // Key up + //{ + // stopwatch.Stop(); // Stop the stopwatch + + // if (pressedKeys.Count == 1 && (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin)) + // { + // // Introduce a small delay (e.g., 100 milliseconds) to ensure the key is held for a minimum time + // if (stopwatch.ElapsedMilliseconds <= 100) + // { + // bool anyKeyPressed = false; + + // foreach (Key key in Enum.GetValues(typeof(Key))) + // { + // if (key != Key.None && key != Key.LWin && key != Key.RWin && Keyboard.IsKeyDown(key)) + // { + // anyKeyPressed = true; + // break; + // } + // } + // // Only execute the actions if no other keys are pressed + // if (!anyKeyPressed) + // { + // StartTriggered?.Invoke(this, EventArgs.Empty); + // return 1; + // } + // } + // } + + // pressedKeys.Clear(); + //} } diff --git a/DirectStart/TileColorCalculator.cs b/DirectStart/TileColorCalculator.cs index d8c6e0e..52a2bbb 100644 --- a/DirectStart/TileColorCalculator.cs +++ b/DirectStart/TileColorCalculator.cs @@ -186,6 +186,8 @@ private static DefaultTileColors FindClosestColor(System.Drawing.Color averageCo return DefaultTileColors.Gray; case "black": return DefaultTileColors.Black; + case "red": + return DefaultTileColors.Red; case "pumpkin": return DefaultTileColors.Pumpkin; case "palegreen": diff --git a/Triggerer/Thumbs.db b/Triggerer/Thumbs.db new file mode 100644 index 0000000..732a6e0 Binary files /dev/null and b/Triggerer/Thumbs.db differ diff --git a/Triggerer/TriggerStartMenuExternally.ahk b/Triggerer/TriggerStartMenuExternally.ahk new file mode 100644 index 0000000..9d017dd --- /dev/null +++ b/Triggerer/TriggerStartMenuExternally.ahk @@ -0,0 +1,40 @@ +#Persistent +#NoEnv +#SingleInstance Force +SetBatchLines, -1 + +PipeName := "\\.\pipe\DirectStartPipe" + +SendPipeMessage("TRIGGER") + +SendPipeMessage(Message) +{ + global PipeName + + hPipe := DllCall("CreateFile", "Str", PipeName, "UInt", 0x40000000, "UInt", 0, "UInt", 0, "UInt", 3, "UInt", 0, "UInt", 0) + + if (hPipe == -1) + { + ErrorLevel := DllCall("GetLastError") + MsgBox, 16, Error, Could not open pipe. Check if DirectStart is running. Error: %ErrorLevel% + return + } + + VarSetCapacity(Buffer, StrLen(Message) + 1, 0) + StrPut(Message, &Buffer, "UTF-8") + BytesWritten := 0 + + Result := DllCall("WriteFile", "UInt", hPipe, "Ptr", &Buffer, "UInt", StrLen(Message) * 2, "UIntP", BytesWritten, "UInt", 0) ; * 2 because UTF-8 encoding might require up to 2 bytes per character + + if (!Result) + { + ErrorLevel := DllCall("GetLastError") + MsgBox, 16, Error, Could not write to pipe. Check if DirectStart is running. Error: %ErrorLevel% + } + else + { + + } + + DllCall("CloseHandle", "UInt", hPipe) +} diff --git a/Triggerer/trigger.ico b/Triggerer/trigger.ico new file mode 100644 index 0000000..09d3a95 Binary files /dev/null and b/Triggerer/trigger.ico differ