Blue Theme Orange Theme Green Theme Red Theme
 
Nevron Chart
Home | Forums | Videos | Advertise | Certifications | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
DevExpress UI Controls
Search :       Advanced Search »
Home » Printing in C# » Printing Windows Form in C#

Printing Windows Form in C#

This article shows how to print a Windows Forms in C# at run-time.

Page Views : 128376
Downloads : 5804
Rating :
 Rate it
Level : Intermediate
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
PrintSample.zip
 
 
Team Foundation Server Hosting
Become a Sponsor
 Tag Cloud
 Latest Jobs
More ... 
 Latest Interview Questions
More ... 


Introduction

Vb.net has a PrintForm method but C# does not have inbuilt method for printing a Windows Form. 

The following procedure enables us to print a windows form at runtime in C#.net. The base concept involves the capture of  the screen image of a Form in jpeg format during runtime and printing the same on a event like Print button click.

Let's get started.

Create a new Windows Forms project in Visual Studio.

Add some simple controls such as a Label, TextBox, and Button control to the Form.

Now add a PrintDialog and a PrintDocument components in the Form by dragging and dropping them from Toolbox.

1.gif

In the code behind

Printing functionality is defined in the System.Drawing.Printing namespace. 

Include the following namespaces to your class: 

using System.Drawing.Imaging;
using System.Drawing.Printing;

and import the following .dll for the necessary GDI functions

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]

The following code is placed in the declaration section of the form. The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.

private System.IO.Stream streamToPrint;

string streamType;

private static extern bool BitBlt

(

    IntPtr hdcDest, // handle to destination DC

    int nXDest, // x-coord of destination upper-left corner

    int nYDest, // y-coord of destination upper-left corner

    int nWidth, // width of destination rectangle

    int nHeight, // height of destination rectangle

    IntPtr hdcSrc, // handle to source DC

    int nXSrc, // x-coordinate of source upper-left corner

    int nYSrc, // y-coordinate of source upper-left corner

    System.Int32 dwRop // raster operation code

);

Select the PrintPage event of the PrintDocument component and include the following code in the event


private void printDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

{

    System.Drawing.Image image = System.Drawing.Image.FromStream
    this.streamToPrint;

    int x = e.MarginBounds.X;

    int y = e.MarginBounds.Y;

    int width = image.Width;

    int height = image.Height;

    if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))

    {

        width = e.MarginBounds.Width;

        height = image.Height * e.MarginBounds.Width / image.Width;

    }

    else

    {

        height = e.MarginBounds.Height;

        width = image.Width * e.MarginBounds.Height / image.Height;

    }

    System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(x, y, width, height);

    e.Graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);
}

Include the following code in the Print Click event handler


private void btnPrint_Click(object sender, EventArgs e)

{

    Graphics g1 = this.CreateGraphics();

    Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);

    Graphics g2 = Graphics.FromImage(MyImage);

    IntPtr dc1 = g1.GetHdc();

    IntPtr dc2 = g2.GetHdc();

    BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);

    g1.ReleaseHdc(dc1);

    g2.ReleaseHdc(dc2);

    MyImage.Save(@"c:\PrintPage.jpg", ImageFormat.Jpeg);

    FileStream fileStream = new FileStream(@"c:\PrintPage.jpg", FileMode.Open, FileAccess.Read);

    StartPrint(fileStream, "Image");

    fileStream.Close();

    if (System.IO.File.Exists(@"c:\PrintPage.jpg"))

    {

        System.IO.File.Delete(@"c:\PrintPage.jpg");

    }
}

And the StatrtPrint method to customize the PrintDialog and print the stored image

public void StartPrint(Stream streamToPrint, string streamType)

{

    this.printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);

    this.streamToPrint = streamToPrint;

    this.streamType = streamType;

    System.Windows.Forms.PrintDialog PrintDialog1 = new PrintDialog();

    PrintDialog1.AllowSomePages = true;

    PrintDialog1.ShowHelp = true;

    PrintDialog1.Document = printDoc;

    DialogResult result = PrintDialog1.ShowDialog();

    if (result == DialogResult.OK)

    {

        printDoc.Print();

        //docToPrint.Print();

    }
}

The captured image is saved in jpeg format in the defined location.When the print functionality is used throughout an application and the image is not required to be stored, the existing image file is deleted and the new one created is streamed to print.If the image is required to be stored, the filename can be specified at runtime and stored in the given path.

On running the application,the form is displayed as in the image below

2.gif

On click of  the Print button, the Print dialog is displayed.

3.gif


Summary


In this article, I demonstrated how to print a Windows Forms in C# using GDI+.


Comment Request!
Thank you for reading this post. Please post your feedback, question, or comments about this post Here.
Login to add your contents and source code to this article
 [Top] Rate this article
 
 About the author
 
Rajalakshmi
4 years experience as a developer in c#.net,sqlserver 2000/2005,Hold Master's degree in Engineering from Anna University,India.Completed diploma certifications in Unix,C,VB and Oracle.Exposure to Embedded C and related software viz. Keil etc.,Interests include R&D activities in .net web/windows applications and experimenting new GUI tools.
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Discover the top 5 tips for understanding .NET
Ricky Leeks presents the top 5 tips for understanding .NET Interoperability. Learn more.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
ASP.NET 4 Hosting
Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites – Click Here!
 
 Post a Feedback, Comment, or Question about this article
Subject:
Comment:
Discover the top 5 tips for understanding .NET Interop
Become a Sponsor
 Comments
Print sample giving error pls help me and give me reply. by sreenivas On February 1, 2008
Hi Rajalakshmi my id: vsreenivasulu@ssdi.sharp.co.in. Please help me. i am not able to Run your code(print windows form sample). the following code giving compile errors that code is regarding print windows form(whatever u have wrote code that code only). using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; using System.Drawing.Printing; namespace Print { public partial class Form1 : Form { public System.IO.Stream streamToPrint; string streamType; private static extern bool BitBlt ( IntPtr hdcDest, // handle to destination DC int nXDest, // x-coord of destination upper-left corner int nYDest, // y-coord of destination upper-left corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle IntPtr hdcSrc, // handle to source DC int nXSrc, // x-coordinate of source upper-left corner int nYSrc, // y-coordinate of source upper-left corner System.Int32 dwRop // raster operation code ); private void printDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { System.Drawing.Image image = System.Drawing.Image.FromStream; this.streamToPrint; int x = e.MarginBounds.X; int y = e.MarginBounds.Y; int width = image.Width; int height = image.Height; if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height)) { width = e.MarginBounds.Width; height = image.Height * e.MarginBounds.Width / image.Width; } else { height = e.MarginBounds.Height; width = image.Width * e.MarginBounds.Height / image.Height; } System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(x, y, width, height); e.Graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel); } [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")] public void StartPrint(Stream streamToPrint, string streamType) { this.printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); this.streamToPrint = streamToPrint; this.streamType = streamType; System.Windows.Forms.PrintDialog PrintDialog1 = new PrintDialog(); PrintDialog1.AllowSomePages = true; PrintDialog1.ShowHelp = true; PrintDialog1.Document = printDoc; DialogResult result = PrintDialog1.ShowDialog(); if (result == DialogResult.OK) { printDoc.Print(); //docToPrint.Print(); } } public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { Graphics g1 = this.CreateGraphics(); Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1); Graphics g2 = Graphics.FromImage(MyImage); IntPtr dc1 = g1.GetHdc(); IntPtr dc2 = g2.GetHdc(); BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376); g1.ReleaseHdc(dc1); g2.ReleaseHdc(dc2); MyImage.Save(@"c:\PrintPage.jpg", ImageFormat.Jpeg); FileStream fileStream = new FileStream(@"c:\PrintPage.jpg", FileMode.Open, FileAccess.Read); StartPrint(fileStream, "Image"); fileStream.Close(); if (System.IO.File.Exists(@"c:\PrintPage.jpg")) { System.IO.File.Delete(@"c:\PrintPage.jpg"); } } } } i am waiting for u r code. thanks and regards Sreenivas
Reply | Email | Modify 
Re: Print sample giving error pls help me and give me reply. by Rajalakshmi On February 29, 2008

hi,

sorry for the late response.can u give me the details of the error?

My code as such does'nt give me error.which version of Visual studio do u use?

Regards,

Rajalakshmi

Reply | Email | Modify 
Why a FileStream ? by dNetGuru On February 26, 2008
In btnPrint_Click() we can't assume that C: is writable by the current user and actually we don't *really* need any temp file, u could simple use a MemoryStream as follows : private void btnPrint_Click(object sender, EventArgs e) { // .... Some Code Omitted ... MemoryStream ms = new MemoryStream(); MyImage.Save(ms, ImageFormat.Jpeg); StartPrint(ms, "Image"); ms.Close(); }
Reply | Email | Modify 
error in inporting Gdi32.dll by salman On December 11, 2008
hi i m salman and i have used ur code for printing but unable to import the Gdi32.dll file in my code, i have downloaded the gdi32.dll from internet. In visual studio when i add reference to it, it do not allow me to add the reference and generates an error. The error z "A reference to 'C:\documents and settings\abc\my documents\Visual Studio 2005\projects\print\print\Gdi32.dll' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component". so plz guide me how to import this Dll to my project.
Reply | Email | Modify 
Re: error in inporting Gdi32.dll by shilpa On December 28, 2009
try this code



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using System.Drawing.Printing;
using System.Runtime.InteropServices;

namespace fro
{
    public partial class print : Form
    {
        private System.IO.Stream streamToPrint;
        string streamType;
        [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
        private static extern bool BitBlt
        (
        IntPtr hdcDest,
        int nXDest,
        int nYDest,
        int nWidth,
        int nHeights,
        IntPtr hdcSrc,
        int nXSrc,
        int nYSrc,
        System.Int32 dwRop
        );

        public print()
        {
            InitializeComponent();
            printDocument1.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
        }



     



        private void printDocument1_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            System.Drawing.Image image = System.Drawing.Image.FromStream(this.streamToPrint);
            int x = e.MarginBounds.X;
            int y = e.MarginBounds.Y;
            int width = image.Width;
            int height = image.Height;
            if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))
            {
                width = e.MarginBounds.Width;
                height = image.Height * e.MarginBounds.Width / image.Width;
            }
            else
            {
                height = e.MarginBounds.Height;
                width = image.Width * e.MarginBounds.Height / image.Height;
            }
            System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(x, y, width, height);
            e.Graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);
        }


        public void StartPrint(Stream streamToPrint, string streamType)
        {
            this.printDocument1.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
            this.streamToPrint = streamToPrint;
            this.streamType = streamType;
            System.Windows.Forms.PrintDialog printDialog1 = new PrintDialog();
            printDialog1.AllowSomePages = true;
            printDialog1.ShowHelp = true;
            printDialog1.Document = printDocument1;
            DialogResult result = printDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                printDocument1.Print();

            }

        }

        private void print_Load(object sender, EventArgs e)
        {
            this.Load += new System.EventHandler(this.print_Load);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("errr");
            Graphics g1 = this.CreateGraphics();
            Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);
            Graphics g2 = Graphics.FromImage(MyImage);
            IntPtr dc1 = g1.GetHdc();
            IntPtr dc2 = g2.GetHdc();
            BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);
            g1.ReleaseHdc(dc1);
            g2.ReleaseHdc(dc2);
            MyImage.Save(@"C:\PrintPage.jpg", ImageFormat.Jpeg);
            FileStream filestream = new FileStream(@"C:\PrintPage.jpg", FileMode.Open, FileAccess.Read);
            StartPrint(filestream, "Image");
            if (System.IO.File.Exists(@"c:\PrintPage.jpg"))
            {
                System.IO.File.Delete(@"C:\PrintPage.jpg");
            }
            else
                MessageBox.Show("errr");
        }

        private void InitializeComponent()
        {
            this.printDocument1 = new System.Drawing.Printing.PrintDocument();
           this.SuspendLayout();
        //    //
        //    // Form1
        //    //
           this.ClientSize = new System.Drawing.Size(292, 266);
           this.Name = "print";
           this.Load += new System.EventHandler(this.print_Load);
           this.ResumeLayout(false);

       }


    }


}

Reply | Email | Modify 
Non active mdi Child Images by Tharindu On March 24, 2009
Hi, Article is great. Just one more thin. I want to know if i have several Mdi Child forms how to get the images of then if they are overlapping each other. When forms are over lapped you get the part of form that is on top of that form. Is there a way to do this. I am trying to create a window with all the images of currently opened windows. But using your code its bit hard to do. Thanks Pats
Reply | Email | Modify 
print largest form by djelloul On May 6, 2009

hollo;

I have a prbleme for printing my form;
I have a large Form which exceeds screen size, and I would like print it in A4 format of paper;

can you help me please

best regard

Reply | Email | Modify 
Printing specific objects by Asif On December 15, 2009
Very nice article...its brilliant

I have modified it for the client area of the from...

My question is if a client area consists of different objects like circles,square,rectangle and i want to print only circles then u do u have any recommendations regarding that...
Reply | Email | Modify 
Thanks by Nidhi On May 19, 2010
Thanks a lot.

It simply works great
Reply | Email | Modify 
Not working by Kwesi On June 22, 2010
Its not working for me. i believe its not reading the gdi32.dll file. do u have an email address.
Reply | Email | Modify 
Help by hOSAIN On August 4, 2010

Hi

Thank you for your Great Article But i cannot use your code and always I get This Error:

Error    1   : Attribute 'System.Runtime.InteropServices.DllImport' is not valid on this declaration type. It is only valid on 'method' declarations.  

and I get blue line Under this parameter :

[System.Runtime.InteropServices.DllImport("gdi32.dll")]


Also I Add using System.Runtime.InteropServices; and add System.Runtime.InteropServices.dll too -and I cannot add gdi32.dll and I get This Error :

http://rapidshare.com/files/410920459/Error.jpg

How can i fix it?

Thank you

Reply | Email | Modify 
thankyou by hOSAIN On August 11, 2010
Hi man thank you for great article.

It solved my problem
Reply | Email | Modify 
Abend An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in system.drawing.dll by James On September 15, 2010

An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in system.drawing.dll

Additional information: A generic error occurred in GDI+
line

MyImage.Save(@"c:\PrintPage.jpg", ImageFormat.Jpeg), method btnPrint_Click

Reply | Email | Modify 
Error: The handle is invalid by shawn On September 22, 2010
When I click print, I get an unhandled exception error saying the handle is invalid
 ************** Exception Text **************
System.ComponentModel.Win32Exception: The handle is invalid
   at System.Drawing.Printing.StandardPrintController.OnStartPrint(PrintDocument document, PrintEventArgs e)
   at System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument document, PrintEventArgs e)
   at System.Drawing.Printing.PrintController.Print(PrintDocument document)
   at System.Drawing.Printing.PrintDocument.Print()
   at PrintSample.PrintForm.StartPrint(Stream streamToPrint, String streamType) in C:\Documents and Settings\Shawn\Desktop\PrintSample\PrintSample\PrintSample\PrintSample\PrintForm.cs:line 75
   at PrintSample.PrintForm.btnPrint_Click(Object sender, EventArgs e) in C:\Documents and Settings\Shawn\Desktop\PrintSample\PrintSample\PrintSample\PrintSample\PrintForm.cs:line 98
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3615 (GDR.050727-3600)
    CodeBase: file:///c:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
PrintSample
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///C:/Documents%20and%20Settings/Shawn/Desktop/PrintSample/PrintSample/PrintSample/PrintSample/bin/Debug/PrintSample.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3614 (GDR.050727-3600)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3082 (QFE.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
However the image is being stored at the location specified on C:, any ideas how to remedy this so the image will actually print?
Reply | Email | Modify 
Sir, i think there is no print page event in windows form then how will i write ur code . by Boyapati On February 12, 2011
reply me fast sir
Reply | Email | Modify 
Re: Sir, i think there is no print page event in windows form then how will i write ur code . by Rajalakshmi On February 13, 2011
The printpage_print is an event for printDocument component. In toolbox, u can find this component under Priniting
Reply | Email | Modify 
print by Vicky On May 16, 2011
thanks a lot
Reply | Email | Modify 
print by Nidhi On June 13, 2011
This code is running supeb.... thank you, For the Help...............................
Reply | Email | Modify 
out of bounds by Irfan On September 22, 2011
the code you provided works well,but it out of bounds of the paper. kindly help
Reply | Email | Modify 
Discover the top 5 tips for understanding .NET Interop
 © 2012  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.