Search This Blog

Thursday, July 23, 2015

WPF Busy Indicator

After reading Better WPF Circular Progress Bar I knew I could do this in XAML with no code behind.  So I stole the design for the oracular progress bar and reworked the animation.

 <UserControl Name="BusyIndicator" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">    
   <Viewbox Width="{Binding Width, ElementName=BusyIndicator}" Height="{Binding Height, ElementName=BusyIndicator}"      
        HorizontalAlignment="Center" VerticalAlignment="Center">  
     <Grid Background="Transparent" ToolTip="Searching...." HorizontalAlignment="Center" VerticalAlignment="Center">  
       <Canvas Name="Canvas1"  
         RenderTransformOrigin="0.5,0.5"  
         HorizontalAlignment="Center"         
         VerticalAlignment="Center" Width="120" Height="120">  
         <Canvas.RenderTransform>  
           <RotateTransform Angle="0" />  
         </Canvas.RenderTransform>  
         <Canvas.Style>  
           <Style TargetType="Canvas">  
             <Style.Triggers>  
               <Trigger Property="IsVisible" Value="True">  
                 <Trigger.EnterActions>  
                   <BeginStoryboard Name="Storyboard_Rotate">  
                     <Storyboard RepeatBehavior="Forever">  
                       <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"   
                          From="0" To="360" Duration="0:0:2"/>  
                     </Storyboard>  
                   </BeginStoryboard>  
                 </Trigger.EnterActions>  
                 <Trigger.ExitActions>  
                   <StopStoryboard BeginStoryboardName="Storyboard_Rotate" />  
                 </Trigger.ExitActions>  
               </Trigger>  
             </Style.Triggers>  
           </Style>  
         </Canvas.Style>  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="1.0" Canvas.Left="50" Canvas.Top="0" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.9" Canvas.Left="20.6107373853764" Canvas.Top="9.54915028125262" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.8" Canvas.Left="2.44717418524233" Canvas.Top="34.5491502812526" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.7" Canvas.Left="2.44717418524232" Canvas.Top="65.4508497187474" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.6" Canvas.Left="20.6107373853763" Canvas.Top="90.4508497187474" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.5" Canvas.Left="50" Canvas.Top="100" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.4" Canvas.Left="79.3892626146236" Canvas.Top="90.4508497187474" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.3" Canvas.Left="97.5528258147577" Canvas.Top="65.4508497187474" />  
         <Ellipse Width="20" Height="20" Stretch="Fill" Fill="Black" Opacity="0.2" Canvas.Left="97.5528258147577" Canvas.Top="34.5491502812526" />  
       </Canvas>  
     </Grid>  
   </Viewbox>  
 </UserControl>  

License
I got the idea from the Code Project article linked above.  They use the The Code Project Open License (CPOL) and I derived my work from that and make no claim of ownership at all.

Friday, March 20, 2015

Hardcodet Taskbar RoutedUICommand workaround.

I have found a way to use Taskbar command using bubbled routed UI commands.

Here is the object.


/// <summary>
/// Taskbar routed UI command.
/// </summary>
public class TaskbarRoutedUICommand : DependencyObject, ICommand
{
   #region Private
   /// <summary>
   /// Window to send command.
   /// </summary>
   private Window window = null;
   #endregion

   #region Parameters
   /// <summary>
   /// Command DependencyProperty
   /// </summary>
   public static readonly DependencyProperty CommandProperty =
       DependencyProperty.Register("Command", typeof(RoutedUICommand), typeof(TaskbarRoutedUICommand), new PropertyMetadata(null));

   /// <summary>
   /// Command
   /// </summary>
   public RoutedUICommand Command
   {
       get { return (RoutedUICommand)GetValue(CommandProperty); }
       set { SetValue(CommandProperty, value); }
   }

   public static bool IsDesignMode
   {
       get
       {
           return (bool)
               DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
                   typeof(FrameworkElement))
                   .Metadata.DefaultValue;
       }
   }

   /// <summary>
   /// Can Execute Change
   /// Not used
   /// </summary>
   public event EventHandler CanExecuteChanged;
   #endregion

   #region ICommand        
   public bool CanExecute(object parameter)
   {
       if (window == null)                
           window = GetTaskbarWindow(parameter);
       
       if (window == null)
           return true;
       else
           return this.Command.CanExecute(parameter, window);
   }

   public void Execute(object parameter)
   {
       if (window == null)
           window = GetTaskbarWindow(parameter);

       this.Command.Execute(parameter, window);
   }
   #endregion

   #region TryFindParent helper
   /// <summary>
   /// Resolves the window that owns the TaskbarIcon class.
   /// </summary>
   /// <param name="commandParameter"></param>
   /// <returns></returns>
   protected Window GetTaskbarWindow(object commandParameter)
   {
       if (IsDesignMode) return null;

       //get the showcase window off the TaskbarIcon
       var tb = commandParameter as TaskbarIcon;
       return tb == null ? null : TryFindParent<Window>(tb);
   }

   /// <summary>
   /// Finds a parent of a given item on the visual tree.
   /// </summary>
   /// <typeparam name="T">The type of the queried item.</typeparam>
   /// <param name="child">A direct or indirect child of the
   /// queried item.</param>
   /// <returns>The first parent item that matches the submitted
   /// type parameter. If not matching item can be found, a null
   /// reference is being returned.</returns>
   public static T TryFindParent<T>(DependencyObject child)
       where T : DependencyObject
   {
       //get parent item
       DependencyObject parentObject = GetParentObject(child);

       //we've reached the end of the tree
       if (parentObject == null) return null;

       //check if the parent matches the type we're looking for
       T parent = parentObject as T;
       if (parent != null)
       {
           return parent;
       }
       else
       {
           //use recursion to proceed with next level
           return TryFindParent<T>(parentObject);
       }
   }

   /// <summary>
   /// This method is an alternative to WPF's
   /// <see cref="VisualTreeHelper.GetParent"/> method, which also
   /// supports content elements. Keep in mind that for content element,
   /// this method falls back to the logical tree of the element!
   /// </summary>
   /// <param name="child">The item to be processed.</param>
   /// <returns>The submitted item's parent, if available. Otherwise
   /// null.</returns>
   public static DependencyObject GetParentObject(DependencyObject child)
   {
       if (child == null) return null;
       ContentElement contentElement = child as ContentElement;

       if (contentElement != null)
       {
           DependencyObject parent = ContentOperations.GetParent(contentElement);
           if (parent != null) return parent;

           FrameworkContentElement fce = contentElement as FrameworkContentElement;
           return fce != null ? fce.Parent : null;
       }

       //if it's not a ContentElement, rely on VisualTreeHelper
       return VisualTreeHelper.GetParent(child);
   }

   #endregion
}

Here is how to use it in the xaml file.
Place this in the resources section

<objects:taskbarrouteduicommand command="RoutedUICommand" x:key="ApplicationExit">
</objects:taskbarrouteduicommand><

Here is an example Taskbar be sure to pass the TaskbarIcon as the parameter.

<tb:TaskbarIcon x:Name="TaskbarIcon"
              Visibility="Visible" 
              MenuActivation="LeftOrRightClick"                                 
              DoubleClickCommand="{StaticResource ApplicationExit}"                        
              DoubleClickCommandParameter="{Binding RelativeSource={RelativeSource Self}}">            
  <tb:TaskbarIcon.ContextMenu>
      <ContextMenu>
          <MenuItem Header="Exit" Command="{StaticResource ApplicationExit}" CommandParameter="{Binding}"/>
      </ContextMenu>
  </tb:TaskbarIcon.ContextMenu>
</tb:TaskbarIcon>

Thursday, April 17, 2014

C#.Net Time delayed queue of T.

Please note that the T object must implement IEquatable!!


/// <summary>
/// Time Delay Queue.
/// Generic object must implement IEquatable. 
/// </summary>
/// <typeparam name="T">Any generic type.</typeparam>
public class TimeDelayQueue<T> : IEnumerable<TimeDelay<T>>, INotifyCollectionChanged
{
   /// <summary>
   /// Base queue object.
   /// </summary>
   private Queue<TimeDelay<T>> queue;

   /// <summary>
   /// Creates a time delayed queue.
   /// </summary>
   public TimeDelayQueue()
   {
       //Initialize queue
       queue = new Queue<TimeDelay<T>>();
   }

   /// <summary>
   /// Removes and returns the object at the beginning of the System.Collections.Generic.Queue of T.
   /// </summary>
   /// <returns>Generic T</returns>
   public T Dequeue()
   {
       //Output holder
       T output = default(T);

       //List of items that need to be requeued.
       List<TimeDelay<T>> requeueList = new List<TimeDelay<T>>();

       //While there is still item in the queue loop
       while (queue.Count > 0)
       {
           //Get the item
           TimeDelay<T> item = queue.Dequeue();

           //Check for no release
           if (item.Release == null)
           {
               output = item.Item;
               break;
           }
           else
           {
               //Check to see if release date has passed
               if (item.Release <= DateTime.Now)
               {
                   output = item.Item;
                   break;
               }
               else
               {
                   //Add to requeue list
                   requeueList.Add(item);
               }
           }
       }

       //Re-queue all items skipped for release date
       foreach (TimeDelay<T> item in requeueList)
       {
           queue.Enqueue(item);
       }

       //If output has value then notify collection changed
       if (output != null)
           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List<TimeDelay<T>>() { { new TimeDelay<T>(output, null) } }));

       return output;
   }

   /// <summary>
   /// Adds an object to the end of the System.Collections.Generic.Queue of T. 
   /// </summary>
   /// <param name="item">Generic T</param>
   public void Enqueue(T item)
   {

       TimeDelay<T> output = new TimeDelay<T>(item, null);

       queue.Enqueue(output);

       if (CollectionChanged != null)
           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List<TimeDelay<T>>() { output }));
   }

   /// <summary>
   /// Adds an object to the end of the System.Collections.Generic.Queue of T. 
   /// </summary>
   /// <param name="item">Generic T</param>
   /// <param name="release">DateTime of release.</param>
   public void Enqueue(T item, DateTime? release)
   {
       TimeDelay<T> output = new TimeDelay<T>(item, release);

       queue.Enqueue(output);

       if (CollectionChanged != null)
           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List<TimeDelay<T>>() { output }));
   }

   /// <summary>
   /// Adds an object to the end of the System.Collections.Generic.Queue of T. 
   /// </summary>
   /// <param name="item">Generic T</param>
   /// <param name="waitMinutes">Minutes to wait before dequeue.</param>
   public void Enqueue(T item, int waitMinutes)
   {
       TimeDelay<T> output = new TimeDelay<T>(item, DateTime.Now.AddMinutes(waitMinutes));

       queue.Enqueue(output);

       if (CollectionChanged != null)
           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List<TimeDelay<T>>() { output }));
   }

   /// <summary>
   /// Creates a System.Collections.Generic.Queue of T from an System.Collections.Generic.IEnumereable of T
   /// </summary>
   /// <returns>List o TimeDelay of T objects.</returns>
   public List<TimeDelay<T>> ToList()
   {
       return queue.ToList<TimeDelay<T>>();
   }
   
   /// <summary>
   /// Removes all objects from System.Collections.Generic.Queue of T.
   /// </summary>
   public void Clear()
   {
       queue.Clear();

       if (CollectionChanged != null)
           CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
   }

   /// <summary>
   /// Determines whether an element is in System.Collections.Generic.Queue of T.
   /// </summary>
   /// <param name="item">Generic T</param>
   /// <returns>Flag indicating presence of item.</returns>
   public bool Contains(TimeDelay<T> item)
   {
       return queue.Contains(item);
   }

   /// <summary>
   /// Determines whether an element is in System.Collections.Generic.Queue of T.
   /// </summary>
   /// <param name="item">Generic T</param>
   /// <returns>Flag indicating presence of item.</returns>
   public bool Contains(T item)
   {
       return queue.Contains(new TimeDelay<T>(item, null));
   }

   /// <summary>
   /// Gets the number of elements contained in the System.Collections.Generic.Queue of T.
   /// </summary>
   public int Count
   {
       get { return queue.Count; }
   }

   /// <summary>
   /// Returns an enumerator that iterates through the System.Collections.Generic.Queue of T.
   /// </summary>
   /// <returns></returns>
   public IEnumerator<TimeDelay<T>> GetEnumerator()
   {
       return queue.GetEnumerator();
   }

   /// <summary>
   /// Returns an enumerator that iterates through the System.Collections.Generic.Queue of T.
   /// </summary>
   /// <returns></returns>
   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
   {
       return queue.GetEnumerator();
   }

   /// <summary>
   /// Returns an enumerator that iterates through the System.Collections.Generic.Queue of T.
   /// </summary>
   /// <returns></returns>
   IEnumerator<TimeDelay<T>> IEnumerable<TimeDelay<T>>.GetEnumerator()
   {
       return queue.GetEnumerator();
   }

   /// <summary>
   /// CollectionChanged event.
   /// </summary>
   public event NotifyCollectionChangedEventHandler CollectionChanged;
}


/// <summary>
/// Time Delay.
/// </summary>
/// <typeparam name="T">Any generic type.</typeparam>
public class TimeDelay<T> : IEquatable<TimeDelay<T>>
{
   /// <summary>
   /// DateTime of release from queue.
   /// </summary>
   public DateTime? Release { get; protected set; }

   /// <summary>
   /// Generic item in the queue.
   /// </summary>
   public T Item { get; set; }

   /// <summary>
   /// Holder for
   /// </summary>
   /// <param name="item">Generic T</param>
   /// <param name="release">DateTime of release.</param>
   public TimeDelay(T item, DateTime? release)
   {
       //Store data
       this.Item = item;
       this.Release = release;
   }

   /// <summary>
   /// Determines whether the specified TimeDelay object is equal to the current TimeDelay object.
   /// </summary>
   /// <param name="other"></param>
   /// <returns></returns>
   public bool Equals(TimeDelay<T> other)
   {            
       return this.Item.Equals(other.Item);            
   }
}

Friday, February 21, 2014

Notepad++ command line wild card expander

Here is a C# command line expander for notepad++.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;


namespace Notepad___CommandLIneTool
{
    class Program
    {
        static void Main(string[] args)
        {
            string currentPath;
            string filePath;
            string fileName;

            //Get the current path
            currentPath = Directory.GetCurrentDirectory();

            //Loop through the arguments
            foreach (string arg in args)
            {
                //Get file path and name
                filePath = Path.GetDirectoryName(arg);
                fileName = Path.GetFileName(arg);

                //Overly blank paths with current path
                if (filePath == string.Empty)
                    filePath = currentPath;

                //Detect wild card
                if (arg.IndexOf("*") != -1)
                {
                    //Get a list of all files matching the file name in the path
                    DirectoryInfo di = new DirectoryInfo(filePath);
                    foreach (FileInfo fi in di.GetFiles(fileName))
                    {
                        //Open the file
                        OpenFile(filePath + "\\" + fi.Name);
                    }
                }
                else
                {
                    //Open the file
                    OpenFile(filePath + "\\" + fileName);
                }
            }

        }

        static void OpenFile(string fileName)
        {
            //Setup notepad command
            ProcessStartInfo psi = new ProcessStartInfo();
            psi.FileName = "Notepad++.exe";
            psi.Arguments = fileName;
            psi.WorkingDirectory = @"C:\Program Files (x86)\Notepad++";

            //Execute the process
            Process.Start(psi);
        }
    }
}

Wednesday, April 24, 2013

VBScript Internet Explorer UI made simple.

I needed a user interface for a deployment script I was writing in visual basic script.  There were many examples on how to make an IE UI with VBS but, I could not find one that was event driven.

So I have came up with a simple way to do a UI for VBS.  I hope this helps you.
The trick is using the TitleChange event in IE to get user input.


Option Explicit

Dim oIE
Dim oShell

'Setup IE options
SetupIE()

'Main sleep loop
Do 
    'Sleep    
    WScript.Sleep 10000
Loop

Sub SetupIE()
    Dim html

    'Initalzie IE and setup attributes    
    Set oIE = WScript.CreateObject("InternetExplorer.Application", "oIE_")
    With oIE    
        .ToolBar   = False 
        .RegisterAsDropTarget = False
        .StatusBar = False 
        .width = 600
        .height = 600
        .top = 1
        .left = 1
    End With
    
    'Clear the screen
    oIE.Navigate("about:blank")
    
    'Wait until not buisy
    Do While oIE.Busy 
        WScript.Sleep 100 
    Loop
    
    html = "<html>" & vbCrLf _
        &"<header><title>My Title</title></header>" & vbCrLf _
        &"<body scroll=""no"">" & vbCrLf _
        &"<script>" & vbCrLf _
        &"command=""""" & vbCrLf _
        &"function RunCommand(cmd) {" & vbCrLf _        
        &"command = cmd;" & vbCrLf _
        &"document.title = document.title;" & vbCrLf _
        &"}" & vbCrLf _
        &"</script>" & vbCrLf _
        &"<input id=""inputTest"">" & vbCrLf _ 
        &"<button onclick='RunCommand(""go"")'>GO</button>" & vbCrLf _
        &"<div id=""output""></div>" & vbCrLf _
        &"</body>" & vbCrLf
            
    'Draw html on window        
    oIE.document.WriteLn(html)    
    
    'Wait until not buisy
    Do While oIE.Busy 
        WScript.Sleep 100 
    Loop    
    
    'Show the window
    oIE.Visible = true    
    
    'Create the shell object
    Set oShell = CreateObject("WScript.Shell")
    
    'Force to front
    oShell.AppActivate oIE    
End Sub

' Execute code when IE closes
Sub oIE_onQuit       
    'Close the script
    WScript.Quit
End Sub

Sub oIE_TitleChange(text)    
    'Check for program page loaded
    If text <> "about:blank" and text <> "http:///" Then            
        'Show the command
        oIE.document.ParentWindow.output.innerHTML = oIE.document.ParentWindow.command & "<br>" & oIE.document.ParentWindow.inputTest.Value
        
        'Clear the command - optional
        oIE.document.ParentWindow.command = ""        
    End If
End Sub