How would I change the icon that appears on the toolbox for a custom control

You can do this in different ways explained below. In all the cases the bitmap or icon should follow these rules: The bitmap or icon dimension should be 16X16 with 16 colors. The left-bottom pixel-color will be assumed to be the transparent color. Technique 1: Use a bitmap (not an icon, in the embedded resource) file implicitly without specifying the ToolboxBitmapAttribute for the type: Say, you have a custom control MyControl in the namespace MyNamespace, create a bmp file MyControl.bmp following the above rules. Add this file to your project at the top-level and make it an embedded resource. The project’s default namespace should be MyNamespace. If the control’s namespace and the project’s default namespace don’t match then move the bitmap to appropriate subfolders so that they match. If this is not possible, typically when the namespaces are not related at all then you cannot use this technique, use instead one of the techniques below using the ToolboxBitmap attribute. Create the assembly and the next time you add it to the toolbox the custom image in MyControl.bmp should be available in the toolbox. This is the easiest technique to implement as it doesn’t require you to use the ToolboxBitmapAttribute in your type definition. Technique 2: Use ToolboxBitmap attribute. Example 1: Use a bitmap (not icon) in the embedded resource with the same name as the type. Default Assembly Namespace: ‘MyAssemblyNamespace’ namespace MyAssemblyNamespace { [ToolboxBitmap(typeof(MyCustomType))] public class MyCustomType : Component {…} } In the above scenario the runtime will look for a embedded bmp file of name MyCustomType.bmp in the project’s root directory. Note that the default namespace and the type’s namespace match. Example 2: If you want your icons in sub-directories then change the attribute like this: [ToolboxAttribute(typeof(MyCustomType), ‘ToolboxIcons.MyCustomType.bmp’)] or [ToolboxAttribute(typeof(MyCustomType), ‘ToolboxIcons.MyCustomType.ico’)] where the bmp or ico file (yap, now, when you explicitly specify the resource, you can use an ico file) is in a sub-directory called ‘ToolboxIcons’. Example 3: Sometimes your type’s namespace and the default assembly namespace may be unrelated, in which case you have to use a different type that has the same namespace as the default assembly namespace to scope the embedded image file. Default namespace: ‘MyAssemblyNamespace’ namespace MyAssemblyNamespace { public class SomeType {…} } namespace DifferentNamespace { // Using SomeType which has the same namespace as the default assembly namespace to scope the embedded resource. [ToolboxBitmap(typeof(SomeType), ‘MyCustomType.ico’)] public class MyCustomType {…} } In this case the runtime will look for the above resource at the top-most directory. If your icons were in a subdirectory named ‘ToolboxIcons’ then the attribute would look like this: [ToolboxBitmap(typeof(SomeType), ‘ToolboxIcons.MyCustomType.ico’)]

How do I disassemble a .net assembly (dll/exe) into the IL format?

You can covert a dll into it’s IL using the ildasm.exe utility. This is usually installed in: C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin If you want to run this utility via command line it would help if you add the above path to your Environment Path variable. Here is a sample command line that will disassemble a dll: ildasm MyFile.exe /output:MyFile.il You can reassemble the above il after making some minor changes via the ilasm utility. This is usually done to make some minor changes to an assembly like modifying the version no. of another assembly to which it links to.

How do I intercept event subscription of a event in my base class?

In C# you could intercept what gets subscribed as follows: // In a Control derived class, for example: // Use override if the base class property was marked as virtual public new event EventHandler Click { add { // Do not let derived classes subscribe to this event, they should instead override OnClick. if (value.Target != this) base.Click += value; } remove { base.Click -= value; } }

How can I display a context menu when the user right-clicks on a node in the TreeView control?

You can display a context menu when a user right-clicks on a node by listening to the TreeView’s MouseUp event as shown below: [C#] private void treeView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { if(e.Button == MouseButtons.Right) { Point ClickPoint = new Point(e.X,e.Y); TreeNode ClickNode = treeView1.GetNodeAt(ClickPoint); if(ClickNode == null) return; // Convert from Tree coordinates to Screen coordinates Point ScreenPoint = treeView1.PointToScreen(ClickPoint); // Convert from Screen coordinates to Form coordinates Point FormPoint = this.PointToClient(ScreenPoint); // Show context menu contextmenu.MenuItems.Clear(); contextmenu.MenuItems.Add(‘Item1’); contextmenu.MenuItems.Add(‘Item2’); contextmenu.Show(this,FormPoint); } } [VB.NET] Private Sub treeView1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = MouseButtons.Right Then Dim ClickPoint As Point = New Point(e.X,e.Y) Dim ClickNode As TreeNode = treeView1.GetNodeAt(ClickPoint) If ClickNode Is Nothing Then Return End If ’ Convert from Tree coordinates to Screen coordinates Dim ScreenPoint As Point = treeView1.PointToScreen(ClickPoint) ’ Convert from Screen coordinates to Form coordinates Dim FormPoint As Point = Me.PointToClient(ScreenPoint) ’ Show context menu contextmenu.MenuItems.Clear() contextmenu.MenuItems.Add(‘Item1’) contextmenu.MenuItems.Add(‘Item2’) contextmenu.Show(this,FormPoint) End If End Sub

I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear before I want it to

Setting the Current property changes the cursor and stops the processing of mouse events. Setting the cursor back to Cursors.Default restarts the mouse event processing and displays the proper cursor for each control. If a DoEvents is called before you reset the cursor back to the default, this will also start up the mouse event processing and you will lose the particular cursor you set. So, if your WaitCursor is disappearing, one explanation might be that DoEvents is getting called. Here is some code that sets a WaitCursor. Cursor oldCursor = Cursor.Current; Cursor.Current = Cursors.WaitCursor; try { // Do your processing that takes time… // eg. let’s wait for 2 seconds… DateTime dt = DateTime.Now.AddSeconds(2); while(dt > DateTime.Now) { //do nothing } } finally { Cursor.Current = oldCursor; }