Windows Forms Listview Control Columns Header not Shown

When you use Windows Form Listview control, you will see a strange problem: you added columns, but the columns can not showing up in the designer panel in Visual Studio.

This is from Microsoft design: they set default Listview control view property to LargeIcon, maybe they think ListView control is not like regular DataGridView control, the view should be use Icon showing style?

Continue reading “Windows Forms Listview Control Columns Header not Shown”

Windows Form Application: Stopped Working Due to Problem Event Name CLR20r3

There was a windows form application based on .NET 4.0 and Visual Studio 2010, it was working well on a PC which we developed it. when we move its debug folder which including generated executable files, it crashed (We use Windows 7):

CLR20r3Error0

We expanded “Show problem details” button and saw the following information:

Description:
  Stopped working

Problem signature:
  Problem Event Name:    CLR20r3
  Problem Signature 01:    cnserver.exe
  Problem Signature 02:    1.0.0.0
  Problem Signature 03:    4f16e189
  Problem Signature 04:    CnServer
  Problem Signature 05:    1.0.0.0
  Problem Signature 06:    4f16e189
  Problem Signature 07:    225
  Problem Signature 08:    6
  Problem Signature 09:    System.IO.FileNotFoundException
  OS Version:    6.1.7600.2.0.0.256.48
  Locale ID:    1033

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt

Due to above information, sees our application missed some files which should be included in output folder. but what the files are ?

Obviously we have some unhandled exceptions in our program due to the error message and the crash, we can not see apparent reason, so we should add the missed exceptions handler.

For example:  AppDomain.CurrentDomain.UnhandledExceptio

Then we add the handlercode into the application startup process, In our case, we add the code in Program.cs file, see the following code, you will see what code you should add into your Program.cs:

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);


            Application.Run(new Form1());
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show(((Exception)e.ExceptionObject).Message, "Unhandled UI Exception");

        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");

        }
    }

After we added above code, we ran our application again, and got a popup window like the following:

CLR20r3Error1

So then we know the missed the file is about “Microsoft.VisualBasic.PowerPacks.Vs”, it is a library file. it missed on the new PC, so we just “include” the dll file to output folder in Visual Studio 2010, then our application can work on other PCs.

Custom Microsoft Chart Control Zoom Reset Button

After you zoom in the Microsoft Chart control. you will see X scroll bar and Y scroll bar which you can scroll the view. Also, you can see two small icons beside the scroll arrow button on scroll bars, the one is on X scroll bar, another one is on Y scroll bar. They are zoom reset buttons.

By default, the zoom reset button only reset one Axis zoom and reset the zoom level to previous scale. When you try to click them, you can see the zoom level reset step by step.

msChartReset00

In some cases, you do not want to the zoom reset works like its default way, but you want the zoom reset just “click one time” and reset the zoom rate to its original level. and also, you might just want one zoom reset button in your UI.

About how to hidden one of the tow zoom reset buttons is simple. it is only one line of code:

msChartReset01

 chartAreaTrending.AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;

The SmallScroll Style indicate there is no ResetZoom button displayed.

The custom the zoom reset button event:

private void chartTrending_AxisScrollBarClicked(object sender, ScrollBarEventArgs e)
{
   if (e.ButtonType == ScrollBarButtonType.ZoomReset)
   {
       e.IsHandled = true;
       this.chartAreaTrending.AxisX.ScaleView.ZoomReset(0);
       this.chartAreaTrending.AxisY.ScaleView.ZoomReset(0);

       this.chartAreaTrending.CursorX.SelectionStart = double.NaN;
       this.chartAreaTrending.CursorY.SelectionEnd = double.NaN;
    }
}

Force Windows Form Application to Run As Administrator on Windows 7

If you are using Windows 7 or Windows Vista, or Windows Server 2008, you should know the UAC (User Account Control), this is one of significant differences between Windows XP and the newer Windows System.

“User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. When you attempt to perform a task that requires administrative privileges, you can dynamically elevate your role by using the Consent dialog box. The code that executes the IsInRole method does not display the Consent dialog box. The code returns false if you are in the standard user role or in the Built-in Administrators group. You can elevate your privileges before you execute the code by right-clicking the application icon and indicating that you want to run as an administrator.” – From MSDN.

When you build a Windows Form application using C#, your application will not run as administrator by default. Then if your application need more permissions just like an Administrator, you might get problem since your application can not access enough resources;

The simplest solution is disabling the UAC on your Windows system. About how to disable UAC, we will discuss in another time, this time we do not want to talk about more about this since disabling UAC for a windows system is not recommended.

The normal and the best solution is using manifest file.

Open your application in Visual Studio 2010, Right click the project and add a new item, choose “Application Manifest File”:

manifest00

Now you can see a new file named “app.manifest” is added under Properties folder:

manifest01

When you open app.manifest file, you can see there are some sample settings have been already there, for example:

      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the 
            requestedExecutionLevel node with one of the following.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            Specifying requestedExecutionLevel node will disable file and registry virtualization.
            If you want to utilize File and Registry Virtualization for backward 
            compatibility then delete the requestedExecutionLevel node.
        -->

      </requestedPrivileges>

What we should do is just remove comment for this line:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

manifest02

When you done above steps, rebuild your windows form application, then every time when you try to restart your application, you will be asked whether you need to run as administrator.

 manifest03

Form.DialogResult Does Not Call Close Method Automatically

When we use Form.DialogResult in our Windows Form project, we should know it just return a DialogResult, it does NOT call a Close method to close the form automatically. Even you click the Close icon in the top-right corner of the form to close the form.

When a form is displayed as a modal dialog box, setting DialogResult enumeration value as the result for the form, it will hide the modal dialog box, and returns control to the calling form. But the form is just hidden, it is still there. The Close method is not called automatically. If you click the Close icon in the top-right corner of the form, it just causes the form to be hidden too. If you want to close the form, you have to load Dispose method in your code.

Here is a sample:

private void CfgToolStripMenuItem_Click(object sender, EventArgs e)
{
    ConfigForm cfgForm = new ConfigForm();
    //cfgForm.Show(this);

    if (cfgForm.ShowDialog() == DialogResult.OK)
    {
        if (this.imgBrs != null)
        {
            this.imgBrs.ReLoadCfg();
            this.imgBrs.InitImageBrowser();
        }
    }

    cfgForm.Dispose();

}

Note (from MSDN):

If a Form is displayed as a modeless window, the value returned by the DialogResult property might not return a value assigned to the form because the form’s resources are automatically released when the form is closed.

Custom Renderer for ToolStrip Control

“You can achieve completely custom appearance and behavior by setting either the ToolStrip.Renderer property or the ToolStripManager.Renderer property to a custom renderer.” – From Microsoft.

Create a custom renderer

public class RedTextRenderer : _
    System.Windows.Forms.ToolStripRenderer
{
    protected override void _
        OnRenderItemText(ToolStripItemTextRenderEventArgs e)
    {
        e.TextColor = Color.Red;
        e.TextFont = new Font("Helvetica", 7, FontStyle.Bold);
       base.OnRenderItemText(e);
    }
}

Set the custom renderer to be the current renderer

To set the custom renderer for one ToolStrip:

toolStrip1.Renderer = new RedTextRenderer();

Above code from MSDN, please read more information from there.

Handle Keyboard Input at the Form Level and Control Level

When you handle keyboard input in Windows Form, you have to control them in at least two level: Form level and Control level.

At Form level, you MUST set the KeyPreview property of the form to true so that keyboard messages are received by the form before they reach any controls on the form when Handle the KeyPress or KeyDown event of the form.

Firstly I show you our sample for the hotkey F4:

(Do not use KeyPress event because KeyPress event can not use e.KeyCode == Keys.F4 kinds of code)

        #region Hot Keys
        private void Main_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F4)
            {
                StateView pointMonitorView = new StateView();
                pointMonitorView.ShowDialog(this);
            }
        }
        #endregion

The following sample from Microsoft:

The application includes a TextBox along with several other controls that allow you to move focus from the TextBox. The KeyPress event of the main Form consumes ‘1’, ‘4’, and ‘7’, and the KeyPress event of the TextBox consumes ‘2’, ‘5’, and ‘8’ while displaying the remaining keys. Compare the MessageBox output when you press a number key while the TextBox has focus with the MessageBox output when you press a number key while focus is on one of the other controls.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace KeyboardInputForm
{
    class Form1 : Form
    {
        TextBox TextBox1 = new TextBox();

        [STAThread]
        public static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new Form1());
        }

        public Form1()
        {
            this.AutoSize = true;

            FlowLayoutPanel panel = new FlowLayoutPanel();
            panel.AutoSize = true;
            panel.FlowDirection = FlowDirection.TopDown;
            panel.Controls.Add(TextBox1);
            this.Controls.Add(panel);

            this.KeyPreview = true;
            this.KeyPress +=
                new KeyPressEventHandler(Form1_KeyPress);
            TextBox1.KeyPress +=
                new KeyPressEventHandler(TextBox1_KeyPress);
        }

        // Detect all numeric characters at the form level and consume 1,
        // 4, and 7. Note that Form.KeyPreview must be set to true for this
        // event handler to be called.
        void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar >= 48 && e.KeyChar <= 57)
            {
                MessageBox.Show(“Form.KeyPress: ‘” +
                    e.KeyChar.ToString() + “‘ pressed.”);

                switch (e.KeyChar)
                {
                    case (char)49:
                    case (char)52:
                    case (char)55:
                        MessageBox.Show(“Form.KeyPress: ‘” +
                            e.KeyChar.ToString() + “‘ consumed.”);
                        e.Handled = true;
                        break;
                }
            }
        }

        // Detect all numeric characters at the TextBox level and consume 
        // 2, 5, and 8.
        void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar >= 48 && e.KeyChar <= 57)
            {
                MessageBox.Show(“Control.KeyPress: ‘” +
                    e.KeyChar.ToString() + “‘ pressed.”);

                switch (e.KeyChar)
                {
                    case (char)50:
                    case (char)53:
                    case (char)56:
                        MessageBox.Show(“Control.KeyPress: ‘” +
                            e.KeyChar.ToString() + “‘ consumed.”);
                        e.Handled = true;
                        break;
                }
            }
        }
    }
}

How to align controls in TableLayoutPanel ?

There is no direct alignment property for TableLayoutPanel.  So lots
of programmer have similar question: How to align the controls in
TableLayoutPanel ?

Finally I found several FAQs about Windows Form TableLayoutPanel control (Content from Microsoft site):

Q: How to stretch and align elements within a TableLayoutPanel ?
A: Use the anchor property of the control to align to a particular side (e.g. Left will stick it to the Left side).  Using opposing anchors, the control can be stretched.  E.g. Anchor=Left|Right will stretch to fill the width.  The Dock property works in a similar manner.

Q: How to absolutely position elements within a TableLayoutPanel ?
A: The margin property of control can be used to adjust the distance from the edge of the cell.  If you change the anchor to be Top|Left and change the Margin to be (20,3,0,0) the control will be 20 pixels from the left edge and 3 pixels from the top.

Additionally the tableLayoutPanel provides several methods to change the position of controls that are already added to the table:
tableLayoutPanel.SetCellPosition(new TableLayoutPanelCellPosition(4,2))
NOTE: Via extender provider on the control itself the SetRow and SetColumn methods can be used.

To determine where a control was place programmatically use the following:
public TableLayoutPanelCellPosition GetPositionFromControl(Control control);