Günther's profileGünther Foidl (gfoidl)PhotosBlogGuestbookMore Tools Help

Blog


    June 25

    Drag a control at runtime

    How to drag a control at runtime is shown in the example. I’ve used a picturebox for demonstration.

       1: using System.Drawing;
       2: using System.Windows.Forms;
       3:  
       4: namespace DragControlAtRuntime
       5: {
       6:     public partial class Form1 : Form
       7:     {
       8:         private bool _dragging = false;
       9:         private Point _dragOffset;
      10:         //---------------------------------------------------------------------
      11:         public Form1()
      12:         {
      13:             InitializeComponent();
      14:         }
      15:         //---------------------------------------------------------------------
      16:         private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
      17:         {
      18:             if (!_dragging && (e.Button & MouseButtons.Left) == MouseButtons.Left)
      19:             {
      20:                 // Make the control capture the mouse so we receive MouseMove
      21:                 // event if the user moves the mouse fast and it gets out of
      22:                 // the control area:
      23:                 pictureBox1.Capture = true;
      24:  
      25:                 _dragging = true;
      26:  
      27:                 // Remember where the control was clicked:
      28:                 _dragOffset = new Point(-e.X, -e.Y);
      29:             }
      30:         }
      31:         //---------------------------------------------------------------------
      32:         private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
      33:         {
      34:             if (_dragging)
      35:             {
      36:                 // The mouse location is relative to the control's top left
      37:                 // corner but the location property must be relative to the
      38:                 // parent's (i.e. form) top left corner:
      39:                 Point location = new Point(e.X, e.Y);
      40:  
      41:                 // The mouse location is relative to the top left corner
      42:                 // of the control, make it relative to the top left corner
      43:                 // of the screen:
      44:                 location = pictureBox1.PointToScreen(location);
      45:  
      46:                 // Make the location relative to the top left corner of the
      47:                 // form:
      48:                 location = this.PointToClient(location);
      49:  
      50:                 // This is needed because the control is not necessarilly 
      51:                 // dragged from its top left corner:
      52:                 location.Offset(_dragOffset);
      53:  
      54:                 // Set the new location:
      55:                 pictureBox1.Location = location;
      56:             }
      57:         }
      58:         //---------------------------------------------------------------------
      59:         private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
      60:         {
      61:             if (_dragging)
      62:             {
      63:                 _dragging = false;
      64:                 pictureBox1.Capture = false;
      65:             }
      66:         }
      67:     }
      68: }


    June 23

    Thread nach Timeout beenden

    Das Beispiel zeigt wie eine Methode bzw. ein Thread welche die Methode ausführt nach einem bestimmten Timeout beendet falls die Methode noch nicht fertig ist.

       1: #define LONG
       2: //-----------------------------------------------------------------------------
       3: using System;
       4: using System.Threading;
       5:  
       6: namespace ConsoleApplication1
       7: {
       8:     class Program
       9:     {
      10:         static void Main(string[] args)
      11:         {
      12:             // Wird zur Threadbenachrichtigung benötigt:
      13:             AutoResetEvent signal = new AutoResetEvent(false);
      14:  
      15:             // Wird benötigt da ThreadPool verwendet wird:
      16:             Thread workerThread = null;
      17:  
      18:             // Durch diese Variante gibt es den Vorteil dass 
      19:             // die Worker-Methode nicht geändert werden muss.
      20:             ThreadPool.QueueUserWorkItem((o) =>
      21:             {
      22:                 // Auf ThreadPool-Threads kann normalerweise nicht 
      23:                 // zugegriffen werden. Mit diesem "Trick" gehts.
      24:                 workerThread = Thread.CurrentThread;
      25:  
      26:                 // Worker starten:
      27:                 Worker();
      28:  
      29:                 // Benachrichtigen dass Worker fertig ist:
      30:                 signal.Set();
      31:             });
      32:  
      33:             // Timer starten der 5 Sekunden wartet und dann das Signal
      34:             // setzt.
      35:             new Timer((o) => { signal.Set(); }, null, 5000, Timeout.Infinite);
      36:  
      37:             // Warten bis das Signal gesetz ist:
      38:             signal.WaitOne();
      39:  
      40:             // Prüfen ob der WorkerThread noch arbeitet. Falls ja den Thread
      41:             // abbrechen. Würde im Worker eine Schleife ausgeführt werden
      42:             // könnte diese eleganter beendet werden in dem Worker in eine
      43:             // Klasse gepackt wird und diese Klasse eine Methode 
      44:             // RequestStop implementiert welche ein volatile-bool-Feld
      45:             // setzt welches in jedem Schleifendurchgang abgefragt wird.
      46:             // Ist dieses bool-Feld gesetz so beende die Arbeit.
      47:             if (workerThread != null && workerThread.IsAlive)
      48:                 workerThread.Abort(); 
      49:  
      50:             Console.WriteLine("Fertig.");
      51:             Console.ReadKey();
      52:         }
      53:         //---------------------------------------------------------------------
      54:         /// <summary>
      55:         /// Arbeits-Methode.
      56:         /// </summary>
      57:         static void Worker()
      58:         {
      59:             Console.WriteLine("In Worker");
      60:  
      61:             // Lange Arbeit simulieren:
      62: #if LONG
      63:             Thread.Sleep(200000);
      64: #else
      65:             Thread.Sleep(1000);
      66: #endif
      67:             Console.WriteLine("Worker fertig.");
      68:         }
      69:     }
      70: }

    Happy coding ;)


    Comparison with Enumerable<T>.Distinct()

    See also Get unique elements from an IEnumerable<T>

    So when we use .net 3.5 why don’t we use list.Distinct().ToList() to get the same result?
    The reason is for performance. I don’t know exactly how Microsoft implemented Distinct because it’s very hard to go throught the code when yield gets compiled (yield is C#-specific and therefore the compiler generates code for that).

    The proof that the above implementation is faster is given in the following chart:

     

    The code used for testing is given below. Note that the Garbage is collected prior to measuring so that the result aren’t influenced by the garbage collection during the measurement.

       1: using System;
       2: using System.Collections.Generic;
       3: using System.Diagnostics;
       4: using System.IO;
       5: using System.Linq;
       6: using gfoidl.Extensions;
       7:  
       8: namespace Duplikate_entfernen
       9: {
      10:     class Program
      11:     {
      12:         static void Main(string[] args)
      13:         {
      14:             const int N = 1000000;
      15:             Stopwatch sw = new Stopwatch();
      16:             File.Delete("result.csv");
      17:  
      18:             for (int i = 0; i <= N; i += 10000)
      19:             {
      20:                 List<string> list = CreateTestList(i);
      21:  
      22:                 GC.Collect();
      23:                 GC.WaitForPendingFinalizers();
      24:                 sw.Reset();
      25:                 sw.Start();
      26:                 list.GetDistinct(false);
      27:                 sw.Stop();
      28:                 double ticks1 = sw.ElapsedTicks / (double)i;
      29:  
      30:                 GC.Collect();
      31:                 GC.WaitForPendingFinalizers();
      32:                 sw.Reset();
      33:                 sw.Start();
      34:                 list.GetDistinctEnumerable().ToList();
      35:                 sw.Stop();
      36:                 double ticks2 = sw.ElapsedTicks / (double)i;
      37:  
      38:                 GC.Collect();
      39:                 GC.WaitForPendingFinalizers();
      40:                 sw.Reset();
      41:                 sw.Start();
      42:                 list.Distinct().ToList();
      43:                 sw.Stop();
      44:                 double ticks3 = sw.ElapsedTicks / (double)i;
      45:  
      46:                 string result = string.Format(
      47:                     "{0};{1};{2};{3}\n", 
      48:                     i, ticks1, ticks2, ticks3);
      49:                 File.AppendAllText("result.csv", result);
      50:                 Console.Write(result);
      51:             }
      52:  
      53: #if !DEBUG
      54:             Process.Start("result.csv");
      55: #else
      56:             Console.ReadKey();
      57: #endif
      58:         }
      59:         //---------------------------------------------------------------------
      60:         private static List<string> CreateTestList(int n)
      61:         {
      62:             string ident = Guid.NewGuid().ToString();
      63:             List<string> list = new List<string>(n);
      64:  
      65:             for (int i = 0; i < n; i++)
      66:                 if (i % 2 == 0)
      67:                     list.Add(ident);
      68:                 else
      69:                     list.Add(Guid.NewGuid().ToString());
      70:  
      71:             return list;
      72:         }
      73:     }
      74: }

     

    Happy coding ;)






    Get unique elements from an IEnumerable

    See also: Comparison with Enumerable<T>.Distinct()

    With the HashSet<T> implemented in .net 3.5 there is an efficient way for retrieving unique elements from an IEnumerable<T> (“remove duplicates”).

    Here’s the extension methods for that purpose (please apologize the German comments in the code ;).

       1: namespace gfoidl.Extensions
       2: {
       3:     using System.Collections.Generic;
       4:     using System.Linq;
       5:     //-------------------------------------------------------------------------
       6:     /// <summary>
       7:     /// Erweiterungsmethoden für <see cref="IEnumerable&lt;T>"/>
       8:     /// </summary>
       9:     public static class MyIEnumerableExtensions
      10:     {
      11:         //---------------------------------------------------------------------
      12:         /// <summary>
      13:         /// Gibt eine <see cref="List&lt;T>"/> mit eindeutigen Werten
      14:         /// zurück.
      15:         /// </summary>
      16:         /// <typeparam name="T">
      17:         /// Der Typ der aufzulistenden Objekte.
      18:         /// </typeparam>
      19:         /// <param name="collection">
      20:         /// Die Auflistung.
      21:         /// </param>
      22:         /// <returns>
      23:         /// Auflistung ohne Duplikate.
      24:         /// </returns>
      25:         public static List<T> GetDistinct<T>(
      26:             this IEnumerable<T> collection)
      27:         {
      28:             return collection.GetDistinct(false);
      29:         }
      30:         //---------------------------------------------------------------------
      31:         /// <summary>
      32:         /// Gibt eine <see cref="List&lt;T>"/> mit eindeutigen Werten
      33:         /// zurück.
      34:         /// </summary>
      35:         /// <typeparam name="T">
      36:         /// Der Typ der aufzulistenden Objekte.
      37:         /// </typeparam>
      38:         /// <param name="collection">
      39:         /// Die Auflistung.
      40:         /// </param>
      41:         /// <param name="keepOrder">
      42:         /// Gitb an ob die Reihenfolge der Elemente beibehalten werden soll.
      43:         /// </param>
      44:         /// <returns>
      45:         /// Auflistung ohne Duplikate.
      46:         /// </returns>
      47:         public static List<T> GetDistinct<T>(
      48:             this IEnumerable<T> collection,
      49:             bool keepOrder)
      50:         {
      51:             if (keepOrder)
      52:             {
      53:                 HashSet<T> hashSet = new HashSet<T>();
      54:  
      55:                 // Eine Kapazität wird nicht angegeben da es sich gezeigt
      56:                 // dass die Wahl dieser Größe sehr schwierig ist. Wird die
      57:                 // Länge per Count ermittelt so wird über die ganze Enumeration
      58:                 // iteriert und das ist die gleiche Aufwandsklasse wie das
      59:                 // umkopieren der Elemente wenn keine Kapazität angegeben wird
      60:                 // (beide sind O(n)).
      61:                 List<T> result = new List<T>();
      62:  
      63:                 foreach (T item in collection)
      64:                     if (hashSet.Add(item))
      65:                         result.Add(item);
      66:  
      67:                 return result;
      68:             }
      69:             else
      70:                 return new HashSet<T>(collection).ToList();
      71:         }
      72:         //---------------------------------------------------------------------
      73:         /// <summary>
      74:         /// Gibt ein <see cref="IEnumerable&lt;T>"/> mit eindeutigen Werten
      75:         /// zurück.
      76:         /// </summary>
      77:         /// <typeparam name="T">
      78:         /// Der Typ der aufzulistenden Objekte.
      79:         /// </typeparam>
      80:         /// <param name="collection">
      81:         /// Die Auflistung.
      82:         /// </param>
      83:         /// <returns>
      84:         /// Auflistung ohne Duplikate.
      85:         /// </returns>
      86:         public static IEnumerable<T> GetDistinctEnumerable<T>(
      87:             this IEnumerable<T> collection)
      88:         {
      89:             HashSet<T> hashSet = new HashSet<T>();
      90:             foreach (T item in collection)
      91:                 if (hashSet.Add(item))
      92:                     yield return item;
      93:         }
      94:         //---------------------------------------------------------------------
      95:         /// <summary>
      96:         /// Gibt eine <see cref="List&lt;T>"/> mit eindeutigen Werten
      97:         /// zurück.
      98:         /// </summary>
      99:         /// <typeparam name="T">
     100:         /// Der Typ der aufzulistenden Objekte.
     101:         /// </typeparam>
     102:         /// <param name="collection">
     103:         /// Die Auflistung.
     104:         /// </param>
     105:         /// <param name="keepOrder">
     106:         /// Gitb an ob die Reihenfolge der Elemente beibehalten werden soll.
     107:         /// </param>
     108:         /// <param name="comparer">
     109:         /// Die <see cref="IEqualityComparer&lt;T>"/>-Implementierung, die 
     110:         /// zum Vergleichen von Schlüsseln verwendet werden soll, oder null, 
     111:         /// wenn der Standard-<see cref="EqualityComparer&lt;T>"/> für diesen 
     112:         /// Schlüsseltyp verwendet werden soll.
     113:         /// </param>
     114:         /// <returns>
     115:         /// Auflistung ohne Duplikate.
     116:         /// </returns>
     117:         public static List<T> GetDistinct<T>(
     118:             this IEnumerable<T> collection,
     119:             bool keepOrder,
     120:             IEqualityComparer<T> comparer)
     121:         {
     122:             if (keepOrder)
     123:             {
     124:                 HashSet<T> hashSet = new HashSet<T>(comparer);
     125:                 List<T> result = new List<T>();
     126:  
     127:                 foreach (T item in collection)
     128:                     if (hashSet.Add(item))
     129:                         result.Add(item);
     130:  
     131:                 return result;
     132:             }
     133:             else
     134:                 return new HashSet<T>(collection, comparer).ToList();
     135:         }
     136:     }
     137: }




    June 08

    Neuer Artikel auf Codeproject.com

    Ich habe einen neuen Artikel auf Codeproject.com eingestellt.

    Thema: DataGridView that saves column order, width and visibility to user.config

    Weitere Artikel von mir auf Codeproject zeigt die Artikelübersicht.



    LINQ Compiled Query

    Mein Artikel darüber kann hier gelesen werden.



    June 06

    Hallo Welt!

    Für einen Programmierer wie mich sicher der Beste erste Blogeintrag.

    Bis demnächst,
    Günther