Blog

posts tagged with visual studio

Balloon Windows for .NET

0 Comments
By Fons Sonnemans, 07-aug-2002

I have found a class that allows for balloon shaped forms in .NET.

Have a look at CodeProject.

READ MORE

WinForm SplashScreen

0 Comments
By Fons Sonnemans, 01-aug-2002

Download SplashScreen.zip

Introduction

Most commercial WinForm applications have a SplashScreen. This article explains how you can implement one using the Microsoft .NET Framework.


Example: Visual Studio.NET SplashScreen


SplashApplicationContext

The SplashApplicationContext is used to show a splash Form before the main Form is shown. It's base class is ApplicationContext.

The constructor accepts 3 arguments

  • mainForm: The main Form of the application to use for context
  • splashForm: The splash Form of the application to use for context
  • interval: The time (in milliseconds) the splash Form is visible. Specify 0 to disable the timeout.

Usage

The Application.Run(context) method creates a standard application message loop on the current thread, with an ApplicationContext.

The following code creates a SplashApplicationContext using a new Form1 as the MainForm and a new SplashForm as the SplashForm. The interval is set to 2000 which will show the SplashForm for 2 seconds. This is done in the static Main() method.

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
staticvoid Main()
{
    SplashApplicationContext myContext=
        new SplashApplicationContext(new Form1(),new SplashForm(), 2000);

    Application.Run(myContext);
}
Code: Form1.cs

You can use the time that the SplashForm is shown usefully. You can use it to connect to databases or do some other intializations. The following code simulates some activity. The status is displayed using a Label control.

private void SplashForm_Load(object sender, System.EventArgs e)
{
    // Show Form
    this.Show();
    Application.DoEvents();// Finish Paint
    Cursor.Current = Cursors.WaitCursor;

    // Simulate some activity (e.g. connect to database, caching data, retrieving defaults)
    this.labelStatus.Text ="Step 1";
    this.labelStatus.Refresh();
    System.Threading.Thread.Sleep(1000);

    // Simulate some activity
    this.labelStatus.Text ="Step 2";
    this.labelStatus.Refresh();
    System.Threading.Thread.Sleep(1000);

    // Simulate some activity
    this.labelStatus.Text ="Step 3";
    this.labelStatus.Refresh();
    System.Threading.Thread.Sleep(1000);

    // Close Form
    this.Close();
}

Code: SplashForm.cs

You must set the interval to 0 to disable the timer.

[STAThread]
staticvoid Main()
{
    SplashApplicationContext myContext=
        new SplashApplicationContext(new Form1(),new SplashForm(), 0);

    Application.Run(myContext);
}

Code: Form1.cs

Conclusion

The SplashApplicationContext class is easy solution to show a SplashScreen. It demonstrates the power of the .NET Framework.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

C# XML Documentation and NDoc

0 Comments
By Fons Sonnemans, 30-jul-2002

I have found the opensource project/tool NDoc which compiles the C# Xml Documentation to MSDN like help file.

It works great!

READ MORE

Free OutlookBar WinForm control

0 Comments
By Fons Sonnemans, 25-jul-2002

READ MORE

Distributed Transactions without COM+ (EnterpriceServices)

0 Comments
By Fons Sonnemans, 24-jul-2002

I don't like COM+. I have never liked it but I had to use it when I needed Distributed Transactions. At the Teched 2002 in Barcelona I learned how you can use Distributed Transactions without COM+.

My problem with COM+ is the fact that you only can choose one transactiontype for a class. You can not differentiate it per method.

Download the following Zip file and have a look at Ron Jacobs example project and slides.

Be carefull, this only works on Windows XP. It uses some lowlevel COM+ 1.5 features.

READ MORE

Simple .NET ReportLibrary

0 Comments
By Fons Sonnemans, 01-jun-2002

Download ReportLibrary.zip

Introduction

Printing in .NET is greatly improved when compared with Visual Basic 6.0. In my projects I almost never use external reporting tools like Crystal Reports. They are too large and complex for my needs. In this article I demonstrate the use of the ReportLibrary which I developed. It can be used to create simple reports which can be printed and previewed.


ReportLibrary

The ReportingLibrary assembly contains a Report class. A report has a collection of items of the type IReportItem. You buildup your report by adding Items to the report. An item can be a ReportGroup, ReportText, ReportHorizontalLine or ReportPageBreak.
A report has a Title and SubTitle which are printed in the default pageheader.

ReportGroup class
A ReportGroup is used to group items together. All items within the group are normally printed on the same line (Y coordinate), you can change this behavior by setting the FixedTop property to 'false'.

ReportText class
A ReportText is used to print a string on a specific X (Left) coordinate. You can use the 'Center' or 'Right' alignment when the Width property is set to a non-zero value.

A ReportGroup and ReportText can have a BackColor and a BorderPen which only have meaning when the Height property is set to a non-zero value.

Usage

The following code creates the report which preview is shown in the top of this article.

/// <summary>
/// Preview Clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonPreview_Click ( object sender , System.EventArgs e)
{
    using (Report r = CreateReport())
    {
        r.Preview();
    }
}

/// <summary>
/// Print Clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
privatevoidbuttonPrint_Click(objectsender, System.EventArgs e)
{
    using (Report r = CreateReport())
    {
        r.Print(new PrintDialog());
    }
}

/// <summary>
/// Create Report
/// </summary>
/// <returns>Initialized Report object</returns>
private Report CreateReport()
{
    // Initialize Report
    Report r =new Report();
    r.DefaultPageSettings.Landscape = (checkBoxLandscape.Checked);
    r.Title =textBoxTitle.Text;
    r.SubTitle =textBoxSubTitle.Text;
    r.NewPage +=new NewPageHandler(ReportNewPage);

    // Add Rows (Groups)
    int rows= Convert.ToInt32(numericUpDownRows.Value);
    for(int t = 1; t <=rows; t++)
    {
        // Create Group and add it to the Report
        ReportGroup g =new ReportGroup();
        r.Items.Add(g);

        // Column1
        ReportText s =new ReportText(t.ToString(),10,70);
        s.Alignment = HorizontalAlignment.Right;
        g.Items.Add(s);

        // Column2
        s =new ReportText("Some Text", 100);
        g.Items.Add(s);
    }

    // Close report with a HorizontalLine
    r.Items.Add(new ReportHorizontalLine(0, r.Width,2));

    return r;
}

Custom Page Headers

You can use the default page header or create your own. The NewPage event is triggered each time a page is printed.

/// <summary>
/// Report NewPage event handler
/// </summary>
/// <param name="sender">Report object</param>
/// <param name="items">items collection</param>
/// <param name="page">pagenumber</param>
private void ReportNewPage(object sender, ReportItemCollection items,intpage)
{
    // Use Default PageHeader?
    if (!checkBoxPageHeader.Checked)
        items.Clear();

    // Create Group and add it to the Report
    ReportGroup g =new ReportGroup(0, ((Report)sender).Width,20);
    g.BorderPen =new Pen(Brushes.Gray, 2);
    g.BackColor = Brushes.LightGray;
    g.Margin.Top =2;
    items.Add(g);

    // Column1
    ReportText s =new ReportText("Column1",10,70);
    s.Alignment = HorizontalAlignment.Right;
    g.Items.Add(s);

    // Column1
    s = new ReportText("Column2",100);
    g.Items.Add(s);

    // Add some empty space
    items.Add(new ReportGroup(5));

}

All ReportItems added to the items collection are used in the pageheader.

Conclusion

The ReportLibrary is an easy solution when you want to reports buildup from code in .NET. You can off course extend it by creating your own classes which implement the IReportItem interface. This makes it a very powerful solution.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

Pocket PC TimeBox Control

0 Comments
By Fons Sonnemans, 27-mei-2002

Download TimeBox.zip

Introduction

I own a Pocket PC since a few months. It's a nice peace of hardware although I didn't use it much. There wasn't much practical use for it. Now I have decided to write my own Time Registration and maybe my own Car Mileage Administration application.  In both Smart Device Applications I have to enter a Time regullary. Microsoft didn't supply me with a good control for this so I decided to write one.

Writing a Smart Device Applications is made easy with the introduction of Visual Studio.NET 2003 and the .NET Compact Framework. In this article I describe how I have written a TimeBox control for the Pocket PC. It's not much different from a normal Windows Forms control.


TimeBox Sample running in the Pocket PC Emulator


I plan to use this TimeBox in my application so I have placed it in an separate project. Due to the low memory footprint you also have to create a designer able version of it. This version will have extra design-time only code (methods and attributes).

Controls Project

The ReflectionIT.Windows.Forms project consists of 3 controls: UpDownButton, SpinButton and TimeBox. The UpDownButton is used by the SpinButton control to draw a Up and a Down button. The SpinButton is used by the TimeBox to spin the hours and minutes.

Once you have compiled your control you need to copy it to specific locations so that Microsoft Visual Studio.NET and the .NET Compact Framework can find it. The runtime version of your control should be copied to the C:\Program Files\Microsoft Visual Studio .NET\CompactFrameworkSDK\v1.0.5000\Windows CE\ directory if you have done the default install.

I have created a special batch file (copytowince 2003.cmd) which compiles the controls project and the designer project and copies the DLL's to the correct folders.

Time class

The Time class is used to store the Hours and Minutes in. It supports arithmetic, comparison and conversion operator overloading.

Time t1=new Time(10,45);
Time t2=new Time(0,15);
Time t3=t1+ t2;     // 11:00

if(t3 < (12 *60)){
    Console.WriteLine(String.Format("Good morning, it is {0}", t3));
}

The Time class has a TypeConverter which is used to support designer serialization.

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, objectvalue, Type destinationType){
    if(destinationType==typeof(InstanceDescriptor)) {
        // This will make a Time a serialiable property in the IntializeComponent method
        ConstructorInfo ci=typeof(Time).GetConstructor(new Type[]{typeof(int),typeof(int)});
        Time t =(Time)value;
        returnnew InstanceDescriptor(ci,newobject[]{t.Hours, t.Minutes});
    }

    if(destinationType.Equals(typeof(String))){
        returnvalue.ToString();
    }else{
        returnbase.ConvertTo (context,culture, value,destinationType);
    }
}

Designer Project

The designer version of the control project has a special Conditional Compilation Constant named 'NETCFDESIGNTIME'. This constant is used to add extra code for design-time support. Attributes are added to methods. Extra classes and methods are included for resizing, serialization and type conversion. The output of this project should be copied to the C:\program files\microsoft visual studio .net 2003\compactframeworksdk\v1.0.5000\Windows CE\Designer folder.

#if NETCFDESIGNTIME
[
Category("Appearance"),
Description("The current time of the timebox."),
]
#endif
public ReflectionIT.Time Time {
    get {
        return(this._time);
    }
    set {
        boolchanged=(_time !=value);
        this._time =value;

        if(changed){
            Invalidate();
            OnTimeChanged();
        }
    }
}

#if NETCFDESIGNTIME
publicvoid ResetTime() {
    this.Time =new Time(0);
}

publicbool ShouldSerializeTime() {
    returnthis.Time !=new Time(0);
}
#endif

Sample Client Project

The TimeBox Sample client project has two TimeBox controls and a disabled TextBox control. The difference between the two times is displayed in the TextBox using the TimeChanged event of the TimeBoxes.

private void timeBox_TimeChanged ( object sender , System.EventArgs e) {
    if(timeBoxStop.Time >=timeBoxStart.Time) {
        textBoxDuration.Text = (timeBoxStop.Time -timeBoxStart.Time).ToString();
    }else{
        textBoxDuration.Text = new ReflectionIT.Time().ToString();
    }
}

Links:

I have used the following articles to create this control and to write this article:

Conclusion

Writing this TimeBox control was realy a challenge. The documentation of the .NetCF is very limited. I hope that this article and sample code will help you write your own controls for the Pocket PC.

I hope I can port these applications to a Smartphone solution as soon as Microsoft will produce a .NET Compact Framework for it. A Pocket PC is just to big to carry around the whole day. Hopefully it works!

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

WinForm WizardHeader Control

0 Comments
By Fons Sonnemans, 01-mei-2002

By Fons Sonnemans (May 2002)

Download Wizard.zip

Introduction

In Windows XP all wizard dialogs have a nice looking header. This WizardHeader control can be used to add these headers to your wizard forms.

Usage

The following steps explain how you can use the WizardHeader control in your WinForm projects.

Step1 - Download the Zip file and extract it.
Download Wizard.zip  and extract it to you local harddrive. This version was compiled using the final version of Microsoft .NET Framework SDK. The C# source of the WizardHeader control is included.

Step2 - Design the Form
Create a Windows Application project.

Step3 - Add the WizardHeader control to the Toolbox
Right-click the Toolbox and select 'Customize Toolbox...'Select the '.NET Framework Components' Tab and click the 'Browse' button.


Open the 'WizardControlLibary.dll' in the Wizard\WizardControlLibrary\Bin\Release folder. The 'WizardHeader' control is checked and will be visible in the Toolbox. Click OK.

Step4 - Add a WizardHeader to the form and set its properties 

Set the properties:

  • Text
  • Description
  • Image

Step5 - Run the application


Conclusion

The WizardHeader control is an small control. Use it in your wizard forms or study it to learn more about creating .NET controls.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

Add a Splitter to a WinForm

2 Comments
By Fons Sonnemans, 01-apr-2002

Download SplitterDemo.zip

Introduction

I used to program in Visual Basic 6.0. It is a great tool but not perfect. It was lacking some crucial controls. A Splitter control was one of them. Microsoft has added it to the .NET framework (thanks) but forgot to make it easy to use. You must place it on a Form, set some properties for it and then also some (Dock) properties of the other two controls. Then you have to set the order of the controls correctly by using 'Bring to Front' or 'Send to Back'.

This article demonstrates the use of a simple AddSplitter() method which simplifies the use of splitters.

AddSplitter() method

/// <summary>
/// Add a splitter between the two given controls
/// </summary>
/// <param name="control1">Control 1</param>
/// <param name="control2">Control 2</param>
/// <param name="vertical">Vertical orientation</param>
/// <returns>The created Splitter</returns>
public static Splitter AddSplitter(Control control1, Control control2,bool vertical)
{
    Control parent =control1.Parent;

    // Validate
    if (parent!=control2.Parent)
        thrownew ArgumentException(
                "Both controls must be placed on the same Containter");

    if(parent.Controls.Count > 2)
        thrownew ArgumentException(
                "There may only be 2 controls on the Container");

     parent.SuspendLayout();

    // Move control2 before control1
    if (parent.Controls.IndexOf(control2) > parent.Controls.IndexOf(control1))
        parent.Controls.SetChildIndex(control2,0);

    // Create splitter
    Splitter splitter=new Splitter();
    splitter.Dock = System.Windows.Forms.DockStyle.Left;

    // Set controls properties
    control2.Dock = DockStyle.Fill;
    if(vertical)
    {
        control1.Dock = DockStyle.Left;
        splitter.Dock = DockStyle.Left;
        splitter.Width = 6;
    }
    else
    {
        control1.Dock = DockStyle.Top;
        splitter.Dock = DockStyle.Top;
        splitter.Height = 6;
        splitter.Cursor = Cursors.HSplit;
    }

    // Add splitter to the parent in the middle
    parent.Controls.Add(splitter);
    parent.Controls.SetChildIndex(splitter,1);
    parent.ResumeLayout();

    return splitter;
}

Usage

I will explain how you can create a Form with two Spitters as shown above. Create a Windows Form and a a ListBox and a Panel to it. Add another ListBox and TextBox and place them in the Panel.

Do not place any Spliters on the Form, they will be added using the AddSplitter() method. Modify the constructor of the Form.

public FormBoth()
{
    //
    // Required for Windows Form Designer support
    //
    InitializeComponent();

    //
    // Add Splitter
    //
    ControlUtil.AddSplitter(listBox1,panel1, true);
    ControlUtil.AddSplitter(listBox2,textBox1,false);
}

The vertical splitter is added between Listbox1 and the panel. The horizontal splitter is added between ListBox2 and TextBox1.

Conclusion

Splitters are great but not easy to use, the AddSplitter() method solves this.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

WinForm DualList Component

0 Comments
By Fons Sonnemans, 01-mrt-2002

Download DualList.zip

Introduction

This article demonstrates the use of the DualList component in a Microsoft .NET WinForm application. It doesn't explain how the component was written, you can figure that out by examining the C# source code (see download).

Problem Description

In many of my applications there are dialogs in which you have two listboxes and some buttons to move (or copy) item(s) from one listbox to the other. This seems very easy to implement, but it isn't. You have to implement a lot of features:

  • Actions: Move Selected, Copy Selected, Move All, Copy All
  • DoubleClick support, inclusive (re)setting the Default button
  • Select next item
  • Enable and disable buttons
  • MultiSelect support

You don't want to program this in every form which has 2 listboxes and some move or copy buttons. This would lead to lots of (duplicate) code which is very difficult to maintain. A generic (reusable) solution is required.


Class vs. Control vs. Component

There are three possible solutions: a class, a (composite) control and a component.

Class
Within your form you create an instances of this class and initialize it with an 'action' (move or copy and selected or all), 2 listboxes and 1 button. You need an instance for each button on your form. The class handles all events of the controls (e.g. Button.Click, ListBox.DoubleClick) and executes the requested action. The solution works fine but is not user-friendly. You have to do everything from code, you can not use the designer.

Composite control
This composite control would hold the 2 listboxes and 8 buttons. One button for each action in each direction. The user (programmer) can set the properties and handle events easily using the designer. It has the disadvantage that it is not very flexible. The layout of the composite controls will need lot's of special properties which not contribute to the problem description (low cohesion).

Component
The component is a "best of both worlds" solution. You can set it's properties using the designer and doesn't need any layout properties because it doesn't contain any controls.

DualList Component

The DualList component takes care of all the features mentioned in the problem domain. You can place it on the form as a sort of "invisible control". Next you set its behavior properties: Action, Button, ListBoxFrom and ListBoxTo. Optionally you can set the DoubleClickSupport and EnableDisableSupport properties.

The DualList handles all events of the controls (e.g. Button.Click, ListBox.DoubleClick) and executes the requested action.

+DualList : Component
{Implements: IComponent, IDisposable}
 
 DualList(in container : IContainer)
 DualList()
 CopyAll() : Void
 CopySelected() : Void
 MoveAll() : Void
 MoveSelected() : Void
 Action : DualListAction
 Button : Button
 DoubleClickSupport : Boolean
 AutoDisableButton : Boolean
 ListBoxFrom : ListBox
 ListBoxTo : ListBox
 AfterAction : AfterActionHandler
 BeforeAction : BeforeActionHandler

Usage

The following steps explain how you can use the DualList component in your WinForm projects.

Step1 - Download the Zip file and extract it.
Download DualList.zip and extract it to you local harddrive. This version was compiled using the final version of Microsoft .NET Framework SDK. The C# source of the DualList component is included.

Step2 - Design the Form
Create a form, place 2 listboxes and the required buttons on the form. The example only uses an Add and Remove button. These buttons move the selected items between the listboxes. Add some items to the listboxes.

You can off course set the Sorted property of the listboxes to True.

Step3 - Add the DualList component to the Toolbox
Right-click the Toolbox and select 'Customize Toolbox...'Select the '.NET Framework Components' Tab and click the 'Browse' button.

Open the 'ReflectionITWinFormComponents.dll' in the DualList\ComponentLibrary\Bin\Debug folder. The 'DualList' is checked and will be visible in the Toolbox. Click OK.

Step4 - Add a DualList to the form and set its properties
Drag two DualList components on your form.

Set the properties for both components

Step5 - Run the application

DualList events

The DualList component has 2 events. The BeforeAction event can be used to Cancel the action or to change the moved/copied Item. The AfterAction event can be used to process your changes (e.g. write them to your database, select the moved/copied item).

private void dualListAdd_AfterAction ( object sender , DualListActionEventArgs e)
{
    listAssigned.SelectedIndex = e.Index;
}

privatevoid dualListDelete_AfterAction(objectsender, DualListActionEventArgs e)
{
    listAvailable.SelectedIndex = e.Index;
}

Conclusion

The DualList Component is an easy solution for a difficult feature. It takes care of all logic needed to move and or copy items from one ListBox to another. It demonstrates the possibilities of .NET components. A very new, powerful feature of the .NET framework.

You can off course extend the class with Drag-and-drop support. That would really complete it. I might do it myself in the near future. Check this site for updates.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

READ MORE

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.