Receive Key Messages irrespective of Key Modifiers

C#, Component Development, Win Forms No Comments »

As covered in a previous article, you can overrride the IsInputKey method on a control to inform winforms that you require keyboard event notification for special keys like tabe and cursor keys which are used but the hosting form for control navigation.

When writing a control, I was trying to capture the SHIFT - Right Cursor combination.  I already had the following implementation in IsInputKey

                        switch (keyData)

            {
                case Keys.Up:
                case Keys.Down:
                case Keys.Left:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                    {
                        return true;
                    }
            }
            return base.IsInputKey(keyData);
 

However, althought control-Right and Alt-Right events came through Shift-Right wouldn’t.  These were passed to the base implementation which returned true to be handled by the control but fals for the shift right.

So to force the processing of keys irrespective of the key modifiers simply chnage the case statement to read

            switch (keyData & ~Keys.Modifiers)

 Which removes and modifier bit flags from the keydata fro the switch comparison.

How to determine if a control or one of it’s child controls has focus

C#, Component Development, Win Forms 1 Comment »

Focus returns a boolean to indicate whether or not a control has focus or not, but when trying to paint your own focus rectangle in your control and you have allowed your controls scrollbars to accept focus, then the Focus property will return false. 

Instead of using Focus, check the ContainsFocus property that returns true if the control or a child control has focus.

Notifying the Collection Editor of changes

C#, Component Development, Win Forms No Comments »

When you are building your own collections of objects it is common to use an overridden ToString implementation to display some property of your object in the collection editor instead of the full class name which is the default.

For example, when developing a Column collection, I override the ToString() to return the Columns caption.  However, when the caption property of my column is updated in the standard collection editor, the respective item in the list of items in the collection editor is not updated. 

The collection editor can be notified to refresh it’s properties and therefore the list by adding a RefreshProperties attribute to the property that causes the required change.

e.g.

    public class TreeColumn
    {
        private String _Caption;
 
        [RefreshProperties(RefreshProperties.All)]
        [Browsable(true)]
        [Description("The Caption for the column")]
        public String Caption
        {
            get { return _Caption; }
            set { _Caption = value; }
        }
 
        public override string ToString()
        {
            if (!String.IsNullOrEmpty(_Caption))
                return _Caption;
            return base.ToString();
        }
    }

Runtime Resizable Panel Control

C#, Component Development, Win Forms 1 Comment »

Below is a complete resizable panel the can be resized on the right and bottom. It uses the windows SysCommand message and some little know options to cause the window (control) to resize.

If you want to allow moving or resizing in other directions, then extend the mouse location check and call the appropriate syscommand values.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

 

namespace YourAssembly

{

    public partial class ResizablePanel : Panel

    {

        private Boolean _ResizeParent;

 

        private class NativeCalls

        {

            [DllImport("USER32.DLL", EntryPoint = "SendMessage")]

            public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam);

            [DllImport("user32")]

            public static extern int ReleaseCapture(IntPtr hwnd);

            public const int WM_SYSCOMMAND = 0×0112;

            public const int SC_DRAGMOVE = 0xF012;

            public const int SC_DRAGSIZE_N = 0xF003;

            public const int SC_DRAGSIZE_S = 0xF006;

            public const int SC_DRAGSIZE_E = 0xF002;

            public const int SC_DRAGSIZE_W = 0xF001;

            public const int SC_DRAGSIZE_NW = 0xF004;

            public const int SC_DRAGSIZE_NE = 0xF005;

            public const int SC_DRAGSIZE_SW = 0xF007;

            public const int SC_DRAGSIZE_SE = 0xF008;

        }

 

        public Boolean ResizeParent

        {

            get { return _ResizeParent; }

            set { _ResizeParent = value; }

        }

 

        public ResizablePanel()

        {

            InitializeComponent();

            MinimumSize = new Size(50, 50);

            Margin = new Padding(0, 0, 0, 0);

            Padding = new Padding(0, 0, 3, 3);

            BackColor = SystemColors.ControlLight;

        }

 

        private enum MousePos {NoWhere, Right, Bottom, BottomRight}

       

        private MousePos GetMousePos(Point location)

        {

            MousePos result = MousePos.NoWhere;

 

            Rectangle TestRect;

 

            int RightSize = Padding.Right;

            int BottomSize = Padding.Bottom;

 

            // Resize right border

            TestRect = new Rectangle(Width - RightSize, 0, Width - RightSize, Height - BottomSize);

            if (TestRect.Contains(location)) result = MousePos.Right;

 

            // Resize bottom border

            TestRect = new Rectangle(0, Height - BottomSize, Width - RightSize, Height);

            if (TestRect.Contains(location)) result = MousePos.Bottom;

 

            // Resize bottom Corner

            TestRect = new Rectangle(Width - RightSize, Height -BottomSize, Width, Height);

            if (TestRect.Contains(location)) result = MousePos.BottomRight;

            return result;

        }

 

        protected override void OnMouseDown(MouseEventArgs e)

        {

            base.OnMouseDown(e);

 

            IntPtr hwnd = this.Handle;

 

            if ((ResizeParent) && (this.Parent != null) && (this.Parent.IsHandleCreated))

            {

                hwnd = Parent.Handle;

            }

 

            int nul = 0;

            MousePos mousePos = GetMousePos(e.Location);

            switch (mousePos)

            {

                case MousePos.Right:

                    {

                        NativeCalls.ReleaseCapture(hwnd);

                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_E, ref nul);

                    } break;

                case MousePos.Bottom:

                    {

                        NativeCalls.ReleaseCapture(hwnd);

                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_S, ref nul);

                    } break;

                case MousePos.BottomRight:

                    {

                        NativeCalls.ReleaseCapture(hwnd);

                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_SE, ref nul);

                    } break;

            }

 

        }

 

        protected override void OnMouseMove(MouseEventArgs e)

        {

            base.OnMouseMove(e);

 

            MousePos mousePos = GetMousePos(e.Location);

            switch (mousePos)

            {

                case MousePos.Right: Cursor = Cursors.SizeWE; break;

                case MousePos.Bottom: Cursor = Cursors.SizeNS; break;

                case MousePos.BottomRight: Cursor = Cursors.SizeNWSE; break;

                default: Cursor = Cursors.Default; break;

            }

        }

 

        protected override void OnResize(EventArgs eventargs)

        {

            base.OnResize(eventargs);

            if (this.Width < this.MinimumSize.Width) this.Width = this.MinimumSize.Width;

            if (this.Height < this.MinimumSize.Height) this.Height = this.MinimumSize.Height;

        }

 

        protected override void OnMouseLeave(EventArgs e)

        {

            base.OnMouseLeave(e);

            Cursor = Cursors.Default;

        }

    }

 

 

}

 

How to create an Expandable Object Converter that will drop down a list of Class Types

C# Language, Component Development 2 Comments »

This article provides an example of a TypeConverter which, when displayed in a Property Grid, will allow the user to select an class type from the drop down list. When an item is selected, it creates and instance of that class type. This can be used, for example, if you had a property of type Shape, and wanted to allow the user to choose a shape to assign to that property, e.g. Circle, Rectangle, etc. The property has a type of the base class Shape, but ends up with the appropriate instance of a descendant class. In the following example, I have a abstract base class of GridStyleBorder which is a property on an object.

[Category("Appearance")]
[Browsable(true)] 
[TypeConverter(typeof(GridBorderTypeConverter))] 
[RefreshProperties(RefreshProperties.All)] 
[Description("Change the Border Style")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
public GridStyleBorder Border { get {  return _border; } set { _border = value; } }

Notice the TypeConvert is set to GridBorderTypeConverter this is a new TypeConvert descended from ExpandableObjectConverter. The code is below:

 


using System;
 using System.Collections.Generic;
 using System.Text;
 using System.ComponentModel;
 using System.Collections;
 using System.Drawing;
 using System.Drawing.Drawing2D;
 using System.Reflection;
 
 namespace SomeAssemby {
    /// <summary>

    /// Provides the type converter that displays a list of types. 

    /// When the user selects an item from the list, an instance of that type is created.

    /// Note : requires customization to work with other property types. (see comments)

    /// </summary>

 
    class GridBrushTypeConverter : ExpandableObjectConverter
    {
        // set the next array to be an array of types you wish to display in the drop down

        private static readonly Type[] TypesToDisplay = new Type[] 
            { 
                typeof(SolidBrush), 
                typeof(LinearGradientBrush) 
            };
 
        // Change the modify region to If Else tests for each type you support and return appropriate instances of the types.

        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value.GetType() == typeof(string))
            {
                string fullClassName = (string)value;
                
                #region —- need to modify this section ———————
                // check the full classname and return a new instance of that class for each of the types you support

                if (fullClassName == typeof(LinearGradientBrush).FullName)
                    return new LinearGradientBrush(new Point(0,0), new Point(0,100),SystemColors.Control, SystemColors.ControlDark);
                else
                    return new SolidBrush(SystemColors.Control);
                #endregion
            }
            else
                return base.ConvertFrom(context, culture, value);
        }
 
        #region —- No need to change this code —————————————
        private ArrayList TypesToDisplayArray = new ArrayList(TypesToDisplay);
 
        public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
        {
            return true;
        }
 
        public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context)
        {
            return new StandardValuesCollection(TypesToDisplayArray);
        }
 
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;
            else
                return base.CanConvertFrom(context, sourceType);
        }
 
        #endregion
 
    }
 
 } 

Rendering a Focus Rectangle

C#, Component Development, Graphics and Images No Comments »

Although you can use the DrawRectangle method to render a focus rectangle, you’ll have to set up the pen to render in the stadard dotted format. However, in the controlpaint static class there is already a DrawFocusRectangle method which does the job for you and makes the appropriate system call.

[csharp]

ControlPaint.DrawFocusRectangle(g, FocusRect);

[/csharp]

ControlPaint is found in System.Windows.Forms.

How to grab input keys (Tab, Cursors Keys) in a control

C#, Component Development No Comments »

As default, systems keys such as tab, return, up, down, left and right are handled by the form to move between controls. To enable theses keys to be raised as key down, up and pressed events, you need to override the IsInpuKey method and return true for the keys you wish your control to process.

e.g. to get a control to process the Tab key.

[csharp]

protected override bool IsInputKey(System.Windows.Forms.Keys keyData)
{
switch (keyData)
{
case Keys.Tab: return (true);
default:
return (base.IsInputKey(keyData));
}
}
[/csharp]

Creating a transparent UserControl

C#, Component Development, Graphics and Images 1 Comment »

If you want to create a user control that is not rectangular and shows the parent control surface then you have to make the control transparent.

This can be achieved by adding the following to the UserControl’s constructor.

[csharp]

SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);

[/csharp]

Rendering standard visual style control elements

C#, Component Development, Graphics and Images No Comments »

.Net provides a single class that can render most standard control elements such as Buttons, 3d rectangles checkboxes, etc using the current theme services.

This class is the static ControlPaint class. Some of the methods include:

DrawBorder(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style);
DrawBorder3D(Graphics graphics, Rectangle rectangle);
DrawButton(Graphics graphics, int x, int y, int width, int height, ButtonState state);
DrawCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state);
DrawRadioButton(Graphics graphics, Rectangle rectangle, ButtonState state);
DrawSizeGrip(Graphics graphics, Color backColor, Rectangle bounds);

    See the documentation for more methods.

    In addition there are specific static Renderer classes availablehat provide measuring routines and rendering routines as well, such as:

    ButtonRenderer
    CheckBoxRenderer
    TabRenderer
    TextBoxRender
    TextRenderer
    ScrollBarRenderer
    ToolStripRenderer

      For a full list type renderer into the object browser in Visual studio.

How to create a curved tab and fill with a gradiant

C#, Component Development, Graphics and Images 2 Comments »

ExampleIf you want to create a curved tab style control similar to the control on the right, then you can use the path functionallity of the graphics class to produce the rectangle with rounded corners at the top.

A linear gradiant brush finishes off the nice rendering effect.

[csharp]

Rectangle rc = new Rectangle(0, 0, this.Width, _CaptionHeight+1);
LinearGradientBrush b = new LinearGradientBrush(rc,
_CaptionLeftColor, _CaptionRightColor,
LinearGradientMode.Vertical);

// Now draw the caption areas with the rounded corners at the top
GraphicsPath path = new GraphicsPath();
path.AddLine(_CurveRadius, 0, this.Width -
(_CurveRadius * 2), 0);
path.AddArc(this.Width - (_CurveRadius * 2) - 1, 0,
(_CurveRadius * 2), (_CurveRadius * 2), 270, 90);
path.AddLine(this.Width-1, _CurveRadius,this.Width-1, _CaptionHeight);
path.AddLine(this.Width, _CaptionHeight+1, 0, _CaptionHeight+1);
path.AddLine(0, _CaptionHeight, 0, _CurveRadius);
path.AddArc(0, 0, (_CurveRadius * 2),
(_CurveRadius * 2), 180, 90);

// Remove jaggies
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

// Smooooth fill
e.Graphics.FillPath(b, path);
e.Graphics.DrawPath(new Pen(_PanelOutlineColor), path);

[/csharp]

WP Theme &Design by minus19.com & Icons
Entries RSS Comments RSS Log in