Wednesday, May 30, 2012

Restore MDIform full screen except task bar

ถ้าไม่ต้องการให้ restore MDIform เป็น  FormWindowState.Normal ขนาดหน้าจอตอนออกแบบ แต่ต้องการให้เป็นขนาด maximize ตลอดเวลาเมื่อกดปุ่ม restore
เพิ่ม code ดังนี้


        private void MDIMain_Resize(object sender, EventArgs e)
        {
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.Width = Screen.PrimaryScreen.Bounds.Width;
            this.Height = Screen.PrimaryScreen.WorkingArea.Height;
        }

Tuesday, May 29, 2012

Your Friend the C# Using Statement

Overview

The full value of the C# using statement is often underrated. This article will describe what this statement does and why you should use it often. Note that this article is discussing the usingstatement in the context of defining object scope and disposal, not of namespace inclusion (i.e. not "using System.Data;").

The Common Problem

Although a managed language like C# typically handles managing memory and other resources on your behalf there are still certain objects you need to be careful with. One of these that almost any web programmer is aware of is a database connection object. Since these objects are often pooled and therefore not immediately destroyed if you're not careful to clean up the resources they reference you'll have problems. Forget to call the Close method after calling the Open method and you're just asking for trouble.
This is where the using statement comes in. In this article I'm going to make the bold suggestion that you never call the Close method of a database connection method. Suicidal? We'll see...

Typical Safety

Before I back up my suggestion let's first take a look at how we usually ensure that our resource critical objects are properly cleaned up. It's normal practice to first write code that achieves it's primary purpose. For instance if we were coding a data fetch we'd probably code something like:
  1. SqlConnection connection = new SqlConnection(connectionString);  
  2. SqlCommand command = connection.CreateCommand();  
  3.   
  4. command.CommandText = "mysp_GetValue";  
  5. command.CommandType = CommandType.StoredProcedure;  
  6.   
  7. connection.Open();  
  8. object ret = command.ExecuteScalar();  
  9. connection.Close();  
In this case we've correctly released the connection when we're done with it. However what if something goes wrong while executing the query? A big fat exception will be thrown and the Closemethod will never be called. If this code is in a web page every time someone hits the page we're going to open another connection to the database. If you've never had the joy of this happen to you on a busy production server you're really missing out my friend.
Due to the plethora of database connection code samples out there almost everyone knows the "proper" way to do this:
  1. SqlConnection connection = new SqlConnection(connectionString);  
  2. SqlCommand command = connection.CreateCommand();  
  3.   
  4. command.CommandText = "mysp_GetValue";  
  5. command.CommandType = CommandType.StoredProcedure;  
  6.   
  7. object ret = null;  
  8.   
  9. try  
  10. {  
  11.     connection.Open();  
  12.     ret = command.ExecuteScalar();  
  13. }  
  14. finally  
  15. {  
  16.     if (connection != null)  
  17.         connection.Close();  
  18. }  
There, we've now done our duty and the code is now safe. Regardless of any pesky exceptions the SqlConnection will get closed after it's been opened. We couldn't do any better, right?
Well, I'm afraid I only give the above code a "B" grade. One of the reasons for this is because it's not fool-proof. A good coder codes defensively, not only for how the code currently runs but also for what could happen when the code is later adjusted (the code is always adjusted). Suppose some clever coder comes along and does this:
  1. SqlConnection connection = new SqlConnection(connectionString);  
  2. SqlCommand command = connection.CreateCommand();  
  3.   
  4. command.CommandText = "mysp_GetValue";  
  5. command.CommandType = CommandType.StoredProcedure;  
  6.   
  7. object ret = null;  
  8.   
  9. try  
  10. {  
  11.     connection.Open();  
  12.     ret = command.ExecuteScalar();  
  13. }  
  14. finally  
  15. {  
  16.     EmailerClass.EmailMe("ret = " + ret.ToString() + "!!!");  
  17.   
  18.     if (connection != null)  
  19.         connection.Close();  
  20. }  
The poor coder has done his best to add some functionality he told his boss would be very easy to do - "it will only take 5 seconds". However what happens when ret is null or something goes wrong in the EmailerClass.EmailMe method which of course doesn't handle it's own exceptions? An exception is thrown that prevents the connection from being closed.

Using Using

The answer to these problems is the using statement. This statement guarantees that resources are properly cleaned up and that they're cleaned up in the most timely manner. Recoded with theusing statement our code block would look like:
  1. using (SqlConnection connection = new SqlConnection(connectionString))  
  2. {  
  3.     SqlCommand command = connection.CreateCommand();  
  4.   
  5.     command.CommandText = "mysp_GetValue";  
  6.     command.CommandType = CommandType.StoredProcedure;  
  7.   
  8.     connection.Open();  
  9.     object ret = command.ExecuteScalar();  
  10. }  
The big change here is that we're wrapping the instantiation of our resource critical object in the "resource-acquisition" part of a using statement. The curly braces after this define the scope of the object. When the object goes out of scope it is automatically cleaned up. In the case of our SqlConnection object, it's connection will be closed. This is true regardless of any exception that gets thrown. So you don't have to worry about other programmers not being careful about what code they inject and where they inject it. The code that you wrote is safe.
There you have it - a database connection object being used with no call being made to it's Closemethod. If you're interested in how this "magic" works and what the performance implications are, read on. Otherwise just start coding with using statements.

IDisposable

So how does our using statement, as coded above, know that for the particular object involved (the database connection object) the connection should be closed when the object goes out of scope? The answer is that this is done in the usual object-oriented way - via the implementation of an interface. The interface for this is called IDisposable and it is important enough to be found in the System namespace.
When a class implements the IDisposable interface it must implement a method called Dispose. It is this method that gets called when an object goes out of the scope of a using statement. In effect the above code is functionally equivalent to:
  1. IDisposable connection = null;  
  2. try  
  3. {  
  4.     connection = new SqlConnection(connectionString);  
  5.     SqlCommand command = connection.CreateCommand();  
  6.   
  7.     command.CommandText = "mysp_GetValue";  
  8.     command.CommandType = CommandType.StoredProcedure;  
  9.   
  10.     ((SqlConnection)connection).Open();  
  11.     object ret = command.ExecuteScalar();  
  12. }  
  13. finally  
  14. {  
  15.     connection.Dispose();  
  16. }  
This implies that only objects that implement IDisposable can be used in a using statement, which is important to note. It is also important to note that calling Dispose explicitly (or implicitly via a using statement) can have performance benefits. As MSDN states: "Code that is using a resource can call Dispose to indicate that the resource is no longer needed. If Dispose is not called, then automatic disposal eventually occurs as a consequence of garbage collection." Yet another reason to use using statements.
But "wait a minute" you say! "What if I need my object to be a class member and therefore can't wrap it's scope in a using statement?" Good question! The answer to is to have your class implement IDisposable and in the Dispose method call the Dispose method of your member object. Then whenever you instantiate your class, do so in a using statement.

Saturday, May 26, 2012

Problem with ShowDialog when ShowInTaskbar

ปัญหาเมื่่อ set form.ShowInTaskbar = false แล้วเวลาแสดง form จะ ไม่แสดงไว้หน้าสุด

form.ShowInTaskbar = false;

แก้ไขโดยกำหนด
public partial class Form1 : Form
{
    Form2 f2;

    public Form1()
    {
        InitializeComponent();

        f2 = new Form2();
        f2.Owner = this;  // <-- This is the important thing
        f2.Show();
    }
}
Example :

private void ShowInTaskBarEx()
{
    Form myForm = new Form();
    myForm.Text = "My Form";
    myForm.SetBounds(10,10,200,200);
    myForm.FormBorderStyle = FormBorderStyle.FixedDialog;
    myForm.MinimizeBox = false;
    myForm.MaximizeBox = false;
    // Do not allow form to be displayed in taskbar.
    myForm.ShowInTaskbar = false;
    myForm.ShowDialog();
}
ref : http://msdn.microsoft.com/en-us/library/system.windows.forms.form.showintaskbar(v=vs.80).aspx

ReportDocument.PrintToPrinter Method

Parameters

nCopies
Indicates the number of copies to print.
collated
Indicates whether to collate the pages.
startPageN
Indicates the first page to print.
endPageN
Indicates the last page to print.

Remarks

To print all pages, set the startPageN and endPageN parameters to zero.

Example

The following example sets the report's page margins, selects the printer, and prints the report.

C#
private void PrintReport(string printerName)
{
   PageMargins margins;

   // Get the PageMargins structure and set the 
   // margins for the report.
   margins = Report.PrintOptions.PageMargins;
   margins.bottomMargin = 350;
   margins.leftMargin = 350;
   margins.rightMargin = 350;
   margins.topMargin = 350;
   // Apply the page margins.
   Report.PrintOptions.ApplyPageMargins(margins);

   // Select the printer.
   Report.PrintOptions.PrinterName = printerName;

   // Print the report. Set the startPageN and endPageN
   // parameters to 0 to print all pages.
   Report.PrintToPrinter(1, false,0,0);
} 

Friday, May 25, 2012

Choosing a printer when printing from Crystal Reports in C# Winform

Introduction

I use Crystal Reports 9 in my project. I once encountered an issue with printing a report. Then, I searched the Internet and found a code from this website that showed me how to send a report to the printer without previewing it, but the code did not allow me to choose the printer. In this article, I have customized the code to use a Print Dialog to choose the printer.

Using the code

I use the Print Dialog to get the printer name. Then, I assign it to the report. To print the report, I use the method:
crReportDocument.PrintToPrinter(nCopy, false, sPage, ePage);
to send the data from the report to the printer.
The code below shows how to choose the printer to print the report:
private void button2_Click(object sender, System.EventArgs e)
{
    //Open the PrintDialog
    this.printDialog1.Document = this.printDocument1;
    DialogResult dr = this.printDialog1.ShowDialog();
    if(dr == DialogResult.OK)
    {
        //Get the Copy times
        int nCopy = this.printDocument1.PrinterSettings.Copies;
        //Get the number of Start Page
        int sPage = this.printDocument1.PrinterSettings.FromPage;
        //Get the number of End Page
        int ePage = this.printDocument1.PrinterSettings.ToPage;
        //Get the printer name
        string PrinterName = this.printDocument1.PrinterSettings.PrinterName;

        crReportDocument = new ReportDocument();
        //Create an instance of a report
        crReportDocument = new Chart();
        try
        {
            //Set the printer name to print the report to. By default the sample
            //report does not have a defult printer specified. This will tell the
            //engine to use the specified printer to print the report. Print out 
            //a test page (from Printer properties) to get the correct value.

            crReportDocument.PrintOptions.PrinterName = PrinterName;


            //Start the printing process. Provide details of the print job
            //using the arguments.
            crReportDocument.PrintToPrinter(nCopy, false, sPage, ePage);

            //Let the user know that the print job is completed
            MessageBox.Show("Report finished printing!");
        }
        catch(Exception err)
        {
            MessageBox.Show(err.ToString());
        }
    }
}

Points of Interest

I think the important thing in this article is it shows how to get the names of printers in your computer or your local network.

remove the Main Tab in Crystal Report Viewer WinForm

Omid's answer is correct, but you have to make sure to do that stuff after you have set the viewer's ReportSource. The version in my function below is a little more robust, and makes what's going on a little clearer, though I'm still not sure why doing that bit of magic to the TabControl's ItemSize and SizeMode make the tab bar go away.
// This is a method of a Form with one of these:
//     CrystalDecisions.Windows.Forms.CrystalReportViewer
// This hides the tab control with the "Main Report" button.
public void hideTheTabControl()
{
    System.Diagnostics.Debug.Assert(
        crystalReportViewer1.ReportSource != null, 
        "you have to set the ReportSource first");

    foreach (Control c1 in crystalReportViewer1.Controls)
    {
        if (c1 is CrystalDecisions.Windows.Forms.PageView)
        {
            PageView pv = (PageView)c1;
            foreach (Control c2 in pv.Controls)
            {
                if (c2 is TabControl)
                {
                    TabControl tc = (TabControl)c2;
                    tc.ItemSize = new Size(0, 1);
                    tc.SizeMode = TabSizeMode.Fixed;
                }
            }
        }
    }
}

V.2 รูปแบบ ที่ 2

 foreach (Control control in crystalReportViewer1.Controls)
            {

                if (control is CrystalDecisions.Windows.Forms.PageView)
                {

                    TabControl tab = (TabControl)(CrystalDecisions.Windows.Forms.PageView)control).Controls[0];

                    tab.ItemSize = new Size(0, 1);

                    tab.SizeMode = TabSizeMode.Fixed;

                    tab.Appearance = TabAppearance.Buttons;

                }

            }
ref : http://stackoverflow.com/questions/561586/how-can-i-remove-the-main-tab-in-crystal-report-viewer