DocumentGridPage.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / MS / Internal / documents / DocumentGridPage.cs / 1 / DocumentGridPage.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: DocumentGridPage.cs 
//
// Description: DocumentGridPage displays a graphical representation of an 
//              DocumentPaginator page including drop-shadow 
//              and is used by DocumentGrid.
// 
// History:
//  10/29/2004 : jdersch - created
//
//--------------------------------------------------------------------------- 

 
using MS.Internal.Annotations.Anchoring; 
using MS.Win32;
using System.Threading; 
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Annotations.Storage;
using System.Windows.Automation; 
using System.Windows.Automation.Provider;
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Documents;
using System.Windows.Shapes; 

using System.Windows.Input;
using System.Windows.Media;
using System; 
using System.Collections;
using System.Diagnostics; 
 
namespace MS.Internal.Documents
{ 
    /// 
    ///
    /// 
    internal class DocumentGridPage : FrameworkElement, IDisposable 
    {
        //------------------------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-------------------------------------------------------------------

        #region Constructors
 
        /// 
        /// Standard constructor. 
        ///  
        public DocumentGridPage(DocumentPaginator paginator) : base()
        { 
            _paginator = paginator;

            //Attach the GetPageCompleted event handler to the paginator so we can
            //use it to keep track of whether our page has been loaded yet. 
            _paginator.GetPageCompleted += new GetPageCompletedEventHandler(OnGetPageCompleted);
 
            //Set up the static elements of our Visual Tree. 
            Init();
        } 

        #endregion

        //-------------------------------------------------------------------- 
        //
        //  Public Properties 
        // 
        //-------------------------------------------------------------------
 
        #region Public Properties

        /// 
        /// The DocumentPage for the displayed page. 
        /// 
        public DocumentPage DocumentPage 
        { 
            get
            { 
                CheckDisposed();
                return _documentPageView.DocumentPage;
            }
        } 

        ///  
        /// The page number displayed. 
        /// 
        public int PageNumber 
        {
            get
            {
                CheckDisposed(); 
                return _documentPageView.PageNumber;
            } 
            set 
            {
                CheckDisposed(); 
                if (_documentPageView.PageNumber != value)
                {
                    _documentPageView.PageNumber = value;
                } 
            }
        } 
 
        /// 
        /// The DocumentPageView displayed by this DocumentGridPage 
        /// 
        public DocumentPageView DocumentPageView
        {
            get 
            {
                CheckDisposed(); 
                return _documentPageView; 
            }
        } 

        /// 
        /// Whether to show the border and drop shadow around the page.
        ///  
        /// 
        public bool ShowPageBorders 
        { 
            get
            { 
                CheckDisposed();
                return _showPageBorders;
            }
 
            set
            { 
                CheckDisposed(); 
                if (_showPageBorders != value)
                { 
                    _showPageBorders = value;
                    InvalidateMeasure();
                }
            } 
        }
 
        ///  
        /// Whether the requested page is loaded.
        ///  
        public bool IsPageLoaded
        {
            get
            { 
                CheckDisposed();
                return _loaded; 
            } 
        }
 
        //--------------------------------------------------------------------
        //
        //  Public Events
        // 
        //--------------------------------------------------------------------
 
        #region Public Events 
        /// 
        /// Fired when the document is finished paginating. 
        /// 
        public event EventHandler PageLoaded;
        #endregion Public Events
 
        #endregion Public Properties
 
        //------------------------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //--------------------------------------------------------------------

        #region Protected Methods 
        /// 
        ///   Derived class must implement to support Visual children. The method must return 
        ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1. 
        ///
        ///    By default a Visual does not have any children. 
        ///
        ///  Remark:
        ///       During this virtual call it is not valid to modify the Visual tree.
        ///  
        protected override Visual GetVisualChild(int index)
        { 
            CheckDisposed(); 

            // count is either 0 or 3 
            if(VisualChildrenCount != 0)
            {
                switch(index)
                { 
                    case 0:
                        return _dropShadowRight; 
                    case 1: 
                        return _dropShadowBottom;
                    case 2: 
                        return _pageBorder;
                    default:
                        throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                } 
            }
 
            throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); 
        }
 
        /// 
        ///  Derived classes override this property to enable the Visual code to enumerate
        ///  the Visual children. Derived classes need to return the number of children
        ///  from this method. 
        ///
        ///    By default a Visual does not have any children. 
        /// 
        ///  Remark: During this virtual method the Visual tree must not be modified.
        ///  
        protected override int VisualChildrenCount
        {
            get
            { 
                if(!_disposed && hasAddedChildren)
                    return 3; 
                else 
                    return 0;
            } 
        }


        ///  
        /// Content measurement.
        ///  
        /// Available size that parent can give to the child. This is soft constraint. 
        /// The DocumentGridPage's desired size.
        protected override sealed Size MeasureOverride(Size availableSize) 
        {
            CheckDisposed();

            if(!hasAddedChildren) 
            {
                //Add the drop shadow 
                this.AddVisualChild(_dropShadowRight); 
                this.AddVisualChild(_dropShadowBottom);
 
                //Add the page (inside the pageBorder)
                this.AddVisualChild(_pageBorder);

                hasAddedChildren = true; 
            }
 
            //Show / hide the border and drop shadow based on the current 
            //state of the ShowPageBorders property.
            if (ShowPageBorders) 
            {
                _pageBorder.BorderThickness = _pageBorderVisibleThickness;
                _pageBorder.Background = Brushes.White;
                _dropShadowRight.Opacity = _dropShadowOpacity; 
                _dropShadowBottom.Opacity = _dropShadowOpacity;
            } 
            else 
            {
                _pageBorder.BorderThickness = _pageBorderInvisibleThickness; 
                _pageBorder.Background = Brushes.Transparent;
                _dropShadowRight.Opacity = 0.0;
                _dropShadowBottom.Opacity = 0.0;
            } 

            //Measure our children. 
            _dropShadowRight.Measure(availableSize); 
            _dropShadowBottom.Measure(availableSize);
            _pageBorder.Measure(availableSize); 

            //Set the Page Zoom on the DocumentPageView to the ratio between our measure constraint
            //and the actual size of the page; this will cause the DPV to scale our page appropriately.
            if (DocumentPage.Size != Size.Empty && DocumentPage.Size.Width != 0.0 ) 
            {
                _documentPageView.SetPageZoom(availableSize.Width / DocumentPage.Size.Width); 
            } 

            return availableSize; 
        }

        /// 
        /// Content arrangement. 
        /// 
        /// The final size that element should use to arrange itself and its children. 
        protected override sealed Size ArrangeOverride(Size arrangeSize) 
        {
            CheckDisposed(); 

            //Arrange the page, no offset.
            _pageBorder.Arrange(new Rect(new Point(0.0,0.0), arrangeSize));
 
            //Arrange the drop shadow parts along the right
            //and bottom edges of the page. 
 
            //Right edge - as tall as the page (minus the shadow width so we don't overlap
            //with the bottom edge), 5px wide.  Offset vertically by 5px. 
            _dropShadowRight.Arrange(
                                new Rect(
                                    new Point(arrangeSize.Width, _dropShadowWidth),
                                    new Size(_dropShadowWidth, Math.Max( 0.0, arrangeSize.Height - _dropShadowWidth)) 
                                    ));
 
            //Bottom edge - 5px tall, and as wide as the page. Offset horizontally by 5px. 
            _dropShadowBottom.Arrange(
                                new Rect( 
                                    new Point(_dropShadowWidth, arrangeSize.Height),
                                    new Size(arrangeSize.Width, _dropShadowWidth)
                                    ));
 
            base.ArrangeOverride(arrangeSize);
            return arrangeSize; 
        } 

        #endregion Protected Methods 

        //-------------------------------------------------------------------
        //
        //  Private Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Private Methods
 
        /// 
        /// Creates the static members of DocumentGridPage's Visual Tree.
        /// 
        private void Init() 
        {
            //Create the DocumentPageView, which will display our 
            //content. 
            _documentPageView = new DocumentPageView();
            _documentPageView.ClipToBounds = true; 
            _documentPageView.StretchDirection = StretchDirection.Both;
            _documentPageView.PageNumber = int.MaxValue;

            //Create the border that goes around the page content. 
            _pageBorder = new Border();
            _pageBorder.BorderBrush = Brushes.Black; 
            _pageBorder.Child = _documentPageView; 

            //Create the drop shadow that goes behind the page, made 
            //of two rectangles in an "L" shape.
            _dropShadowRight = new Rectangle();
            _dropShadowRight.Fill = Brushes.Black;
            _dropShadowRight.Opacity = _dropShadowOpacity; 

            _dropShadowBottom = new Rectangle(); 
            _dropShadowBottom.Fill = Brushes.Black; 
            _dropShadowBottom.Opacity = _dropShadowOpacity;
 
            _loaded = false;
        }

        ///  
        /// Handles the GetPageCompleted event raised by the DocumentPaginator.
        /// At this point, we'll set the _loaded flag to indicate the page is loaded 
        /// and fire the PageLoaded event. 
        /// 
        /// Source of the event. 
        /// Details about this event.
        private void OnGetPageCompleted(object sender, GetPageCompletedEventArgs e)
        {
            //If the GetPageCompleted action completed successfully 
            //and is our page then we'll set the flag and fire the event.
            if (!_disposed && 
                e != null && 
                !e.Cancelled &&
                e.Error == null && 
                e.PageNumber != int.MaxValue &&
                e.PageNumber == this.PageNumber &&
                e.DocumentPage != null &&
                e.DocumentPage != DocumentPage.Missing) 
            {
                _loaded = true; 
 
                if (PageLoaded != null)
                { 
                    PageLoaded(this, EventArgs.Empty);
                }
            }
        } 

        ///  
        /// Dispose the object. 
        /// 
        protected void Dispose() 
        {
            if (!_disposed)
            {
                _disposed = true; 

                //Detach the GetPageCompleted event from the content. 
                if (_paginator != null) 
                {
                    _paginator.GetPageCompleted -= new GetPageCompletedEventHandler(OnGetPageCompleted); 
                    _paginator = null;
                }

                //Dispose our DocumentPageView. 
                IDisposable dpv = _documentPageView as IDisposable;
                if (dpv != null ) 
                { 
                    dpv.Dispose();
                } 
            }
        }

        ///  
        /// Checks if the instance is already disposed, throws if so.
        ///  
        private void CheckDisposed() 
        {
            if (_disposed) 
            {
                throw new ObjectDisposedException(typeof(DocumentPageView).ToString());
            }
        } 

        #endregion Private Methods 
 
        #region IDisposable Members
 
        /// 
        /// Dispose the object.
        /// 
        void IDisposable.Dispose() 
        {
            this.Dispose(); 
        } 

        #endregion IDisposable Members 

        //-------------------------------------------------------------------
        //
        //  Private Fields 
        //
        //-------------------------------------------------------------------- 
 
        #region Private Fields
        private bool hasAddedChildren; 
        private DocumentPaginator   _paginator;
        private DocumentPageView    _documentPageView;
        private Rectangle           _dropShadowRight;
        private Rectangle           _dropShadowBottom; 
        private Border              _pageBorder;
 
        private bool                _showPageBorders; 
        private bool                _loaded;
 

        //Constants
        private const double        _dropShadowOpacity = 0.35;
        private const double        _dropShadowWidth = 5.0; 
        private readonly Thickness  _pageBorderVisibleThickness = new Thickness(1, 1, 1, 1);
        private readonly Thickness  _pageBorderInvisibleThickness = new Thickness(0, 0, 0, 0); 
 
        private bool                _disposed;
 
        #endregion Private Fields
    }
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: DocumentGridPage.cs 
//
// Description: DocumentGridPage displays a graphical representation of an 
//              DocumentPaginator page including drop-shadow 
//              and is used by DocumentGrid.
// 
// History:
//  10/29/2004 : jdersch - created
//
//--------------------------------------------------------------------------- 

 
using MS.Internal.Annotations.Anchoring; 
using MS.Win32;
using System.Threading; 
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Annotations.Storage;
using System.Windows.Automation; 
using System.Windows.Automation.Provider;
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Documents;
using System.Windows.Shapes; 

using System.Windows.Input;
using System.Windows.Media;
using System; 
using System.Collections;
using System.Diagnostics; 
 
namespace MS.Internal.Documents
{ 
    /// 
    ///
    /// 
    internal class DocumentGridPage : FrameworkElement, IDisposable 
    {
        //------------------------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-------------------------------------------------------------------

        #region Constructors
 
        /// 
        /// Standard constructor. 
        ///  
        public DocumentGridPage(DocumentPaginator paginator) : base()
        { 
            _paginator = paginator;

            //Attach the GetPageCompleted event handler to the paginator so we can
            //use it to keep track of whether our page has been loaded yet. 
            _paginator.GetPageCompleted += new GetPageCompletedEventHandler(OnGetPageCompleted);
 
            //Set up the static elements of our Visual Tree. 
            Init();
        } 

        #endregion

        //-------------------------------------------------------------------- 
        //
        //  Public Properties 
        // 
        //-------------------------------------------------------------------
 
        #region Public Properties

        /// 
        /// The DocumentPage for the displayed page. 
        /// 
        public DocumentPage DocumentPage 
        { 
            get
            { 
                CheckDisposed();
                return _documentPageView.DocumentPage;
            }
        } 

        ///  
        /// The page number displayed. 
        /// 
        public int PageNumber 
        {
            get
            {
                CheckDisposed(); 
                return _documentPageView.PageNumber;
            } 
            set 
            {
                CheckDisposed(); 
                if (_documentPageView.PageNumber != value)
                {
                    _documentPageView.PageNumber = value;
                } 
            }
        } 
 
        /// 
        /// The DocumentPageView displayed by this DocumentGridPage 
        /// 
        public DocumentPageView DocumentPageView
        {
            get 
            {
                CheckDisposed(); 
                return _documentPageView; 
            }
        } 

        /// 
        /// Whether to show the border and drop shadow around the page.
        ///  
        /// 
        public bool ShowPageBorders 
        { 
            get
            { 
                CheckDisposed();
                return _showPageBorders;
            }
 
            set
            { 
                CheckDisposed(); 
                if (_showPageBorders != value)
                { 
                    _showPageBorders = value;
                    InvalidateMeasure();
                }
            } 
        }
 
        ///  
        /// Whether the requested page is loaded.
        ///  
        public bool IsPageLoaded
        {
            get
            { 
                CheckDisposed();
                return _loaded; 
            } 
        }
 
        //--------------------------------------------------------------------
        //
        //  Public Events
        // 
        //--------------------------------------------------------------------
 
        #region Public Events 
        /// 
        /// Fired when the document is finished paginating. 
        /// 
        public event EventHandler PageLoaded;
        #endregion Public Events
 
        #endregion Public Properties
 
        //------------------------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //--------------------------------------------------------------------

        #region Protected Methods 
        /// 
        ///   Derived class must implement to support Visual children. The method must return 
        ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1. 
        ///
        ///    By default a Visual does not have any children. 
        ///
        ///  Remark:
        ///       During this virtual call it is not valid to modify the Visual tree.
        ///  
        protected override Visual GetVisualChild(int index)
        { 
            CheckDisposed(); 

            // count is either 0 or 3 
            if(VisualChildrenCount != 0)
            {
                switch(index)
                { 
                    case 0:
                        return _dropShadowRight; 
                    case 1: 
                        return _dropShadowBottom;
                    case 2: 
                        return _pageBorder;
                    default:
                        throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                } 
            }
 
            throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); 
        }
 
        /// 
        ///  Derived classes override this property to enable the Visual code to enumerate
        ///  the Visual children. Derived classes need to return the number of children
        ///  from this method. 
        ///
        ///    By default a Visual does not have any children. 
        /// 
        ///  Remark: During this virtual method the Visual tree must not be modified.
        ///  
        protected override int VisualChildrenCount
        {
            get
            { 
                if(!_disposed && hasAddedChildren)
                    return 3; 
                else 
                    return 0;
            } 
        }


        ///  
        /// Content measurement.
        ///  
        /// Available size that parent can give to the child. This is soft constraint. 
        /// The DocumentGridPage's desired size.
        protected override sealed Size MeasureOverride(Size availableSize) 
        {
            CheckDisposed();

            if(!hasAddedChildren) 
            {
                //Add the drop shadow 
                this.AddVisualChild(_dropShadowRight); 
                this.AddVisualChild(_dropShadowBottom);
 
                //Add the page (inside the pageBorder)
                this.AddVisualChild(_pageBorder);

                hasAddedChildren = true; 
            }
 
            //Show / hide the border and drop shadow based on the current 
            //state of the ShowPageBorders property.
            if (ShowPageBorders) 
            {
                _pageBorder.BorderThickness = _pageBorderVisibleThickness;
                _pageBorder.Background = Brushes.White;
                _dropShadowRight.Opacity = _dropShadowOpacity; 
                _dropShadowBottom.Opacity = _dropShadowOpacity;
            } 
            else 
            {
                _pageBorder.BorderThickness = _pageBorderInvisibleThickness; 
                _pageBorder.Background = Brushes.Transparent;
                _dropShadowRight.Opacity = 0.0;
                _dropShadowBottom.Opacity = 0.0;
            } 

            //Measure our children. 
            _dropShadowRight.Measure(availableSize); 
            _dropShadowBottom.Measure(availableSize);
            _pageBorder.Measure(availableSize); 

            //Set the Page Zoom on the DocumentPageView to the ratio between our measure constraint
            //and the actual size of the page; this will cause the DPV to scale our page appropriately.
            if (DocumentPage.Size != Size.Empty && DocumentPage.Size.Width != 0.0 ) 
            {
                _documentPageView.SetPageZoom(availableSize.Width / DocumentPage.Size.Width); 
            } 

            return availableSize; 
        }

        /// 
        /// Content arrangement. 
        /// 
        /// The final size that element should use to arrange itself and its children. 
        protected override sealed Size ArrangeOverride(Size arrangeSize) 
        {
            CheckDisposed(); 

            //Arrange the page, no offset.
            _pageBorder.Arrange(new Rect(new Point(0.0,0.0), arrangeSize));
 
            //Arrange the drop shadow parts along the right
            //and bottom edges of the page. 
 
            //Right edge - as tall as the page (minus the shadow width so we don't overlap
            //with the bottom edge), 5px wide.  Offset vertically by 5px. 
            _dropShadowRight.Arrange(
                                new Rect(
                                    new Point(arrangeSize.Width, _dropShadowWidth),
                                    new Size(_dropShadowWidth, Math.Max( 0.0, arrangeSize.Height - _dropShadowWidth)) 
                                    ));
 
            //Bottom edge - 5px tall, and as wide as the page. Offset horizontally by 5px. 
            _dropShadowBottom.Arrange(
                                new Rect( 
                                    new Point(_dropShadowWidth, arrangeSize.Height),
                                    new Size(arrangeSize.Width, _dropShadowWidth)
                                    ));
 
            base.ArrangeOverride(arrangeSize);
            return arrangeSize; 
        } 

        #endregion Protected Methods 

        //-------------------------------------------------------------------
        //
        //  Private Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Private Methods
 
        /// 
        /// Creates the static members of DocumentGridPage's Visual Tree.
        /// 
        private void Init() 
        {
            //Create the DocumentPageView, which will display our 
            //content. 
            _documentPageView = new DocumentPageView();
            _documentPageView.ClipToBounds = true; 
            _documentPageView.StretchDirection = StretchDirection.Both;
            _documentPageView.PageNumber = int.MaxValue;

            //Create the border that goes around the page content. 
            _pageBorder = new Border();
            _pageBorder.BorderBrush = Brushes.Black; 
            _pageBorder.Child = _documentPageView; 

            //Create the drop shadow that goes behind the page, made 
            //of two rectangles in an "L" shape.
            _dropShadowRight = new Rectangle();
            _dropShadowRight.Fill = Brushes.Black;
            _dropShadowRight.Opacity = _dropShadowOpacity; 

            _dropShadowBottom = new Rectangle(); 
            _dropShadowBottom.Fill = Brushes.Black; 
            _dropShadowBottom.Opacity = _dropShadowOpacity;
 
            _loaded = false;
        }

        ///  
        /// Handles the GetPageCompleted event raised by the DocumentPaginator.
        /// At this point, we'll set the _loaded flag to indicate the page is loaded 
        /// and fire the PageLoaded event. 
        /// 
        /// Source of the event. 
        /// Details about this event.
        private void OnGetPageCompleted(object sender, GetPageCompletedEventArgs e)
        {
            //If the GetPageCompleted action completed successfully 
            //and is our page then we'll set the flag and fire the event.
            if (!_disposed && 
                e != null && 
                !e.Cancelled &&
                e.Error == null && 
                e.PageNumber != int.MaxValue &&
                e.PageNumber == this.PageNumber &&
                e.DocumentPage != null &&
                e.DocumentPage != DocumentPage.Missing) 
            {
                _loaded = true; 
 
                if (PageLoaded != null)
                { 
                    PageLoaded(this, EventArgs.Empty);
                }
            }
        } 

        ///  
        /// Dispose the object. 
        /// 
        protected void Dispose() 
        {
            if (!_disposed)
            {
                _disposed = true; 

                //Detach the GetPageCompleted event from the content. 
                if (_paginator != null) 
                {
                    _paginator.GetPageCompleted -= new GetPageCompletedEventHandler(OnGetPageCompleted); 
                    _paginator = null;
                }

                //Dispose our DocumentPageView. 
                IDisposable dpv = _documentPageView as IDisposable;
                if (dpv != null ) 
                { 
                    dpv.Dispose();
                } 
            }
        }

        ///  
        /// Checks if the instance is already disposed, throws if so.
        ///  
        private void CheckDisposed() 
        {
            if (_disposed) 
            {
                throw new ObjectDisposedException(typeof(DocumentPageView).ToString());
            }
        } 

        #endregion Private Methods 
 
        #region IDisposable Members
 
        /// 
        /// Dispose the object.
        /// 
        void IDisposable.Dispose() 
        {
            this.Dispose(); 
        } 

        #endregion IDisposable Members 

        //-------------------------------------------------------------------
        //
        //  Private Fields 
        //
        //-------------------------------------------------------------------- 
 
        #region Private Fields
        private bool hasAddedChildren; 
        private DocumentPaginator   _paginator;
        private DocumentPageView    _documentPageView;
        private Rectangle           _dropShadowRight;
        private Rectangle           _dropShadowBottom; 
        private Border              _pageBorder;
 
        private bool                _showPageBorders; 
        private bool                _loaded;
 

        //Constants
        private const double        _dropShadowOpacity = 0.35;
        private const double        _dropShadowWidth = 5.0; 
        private readonly Thickness  _pageBorderVisibleThickness = new Thickness(1, 1, 1, 1);
        private readonly Thickness  _pageBorderInvisibleThickness = new Thickness(0, 0, 0, 0); 
 
        private bool                _disposed;
 
        #endregion Private Fields
    }
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK