WindowsEditBox.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 / UIAutomation / Win32Providers / MS / Internal / AutomationProxies / WindowsEditBox.cs / 1 / WindowsEditBox.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: HWND-based Edit Box proxy 
//
// History: 
//  01/10/03 : a-jeanp - created
//  08/12/03:  alexsn - bug fixes
//  03/02/04:  a-davidj - added text pattern
// 
//---------------------------------------------------------------------------
 
using System; 
using System.Collections;
using System.Diagnostics; 
using System.Globalization;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel; 
using System.Windows;
using System.Windows.Automation; 
using System.Windows.Automation.Provider; 
using System.Windows.Automation.Text;
using MS.Win32; 

namespace MS.Internal.AutomationProxies
{
    // TERMINOLOGY: Win32 Edit controls use the term "index" to mean a character position. 
    // For example the EM_LINEINDEX message converts a line number to it's starting character position.
    // Perhaps not the best choice but we use it to be consistent. 
 
    class WindowsEditBox : ProxyHwnd, IValueProvider, ITextProvider
    { 
        // -----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
        #region Constructors 

        // This is the default contructor that calls the base class constructor. 
        // This function determines the type of the edit control and then calls the default constructor.
        internal WindowsEditBox (IntPtr hwnd, ProxyFragment parent, int item)
            : base( hwnd, parent, item)
        { 
            _type = GetEditboxtype (hwnd);
            if (IsMultiline) 
            { 
                _cControlType = ControlType.Document;
            } 
            else
            {
                _cControlType = ControlType.Edit;
            } 

            // When embedded inside of the combobox, hide the edit portion in the content element tree 
            _fIsContent = !IsInsideOfCombo(); 
            _fIsKeyboardFocusable = true;
 
            if (IsInsideOfListView(hwnd))
            {
                _sAutomationId = "edit";
            } 

            // support for events 
            _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); 
        }
 
        #endregion

        #region Proxy Create
 
        // Static Create method called by UIAutomation to create this proxy.
        // = 6)
            { 
                cEvent = 1;
                return new WinEventTracker.EvtIdProperty[] { 
                    new WinEventTracker.EvtIdProperty (NativeMethods.EventObjectTextSelectionChanged, idEvent) 
                };
            } 
            */

            return base.EventToWinEvent(idEvent, out cEvent);
        } 

        #endregion 
 
        #region Value Pattern
 
        // Sets the text of the edit.
        void IValueProvider.SetValue (string str)
        {
            // Ensure that the edit box and all its parents are enabled. 
            Misc.CheckEnabled(_hwnd);
 
            int styles = WindowStyle; 

            if (Misc.IsBitSet(styles, NativeMethods.ES_READONLY)) 
            {
                throw new InvalidOperationException(SR.Get(SRID.ValueReadonly));
            }
 
            // check if control only accepts numbers
            if (Misc.IsBitSet(styles, NativeMethods.ES_NUMBER)) 
            { 
                // check if string contains any non-numeric characters.
                foreach (char ch in str) 
                {
                    if (char.IsLetter (ch))
                    {
                        throw new ArgumentException(SR.Get(SRID.NotAValidValue, str), "val"); 
                    }
                } 
            } 

            // bug# 11147, Text/edit box should not enter more characters than what is allowed through keyboard. 
            // Determine the max number of chars this editbox accepts

            int result = Misc.ProxySendMessageInt(_hwnd, NativeMethods.EM_GETLIMITTEXT, IntPtr.Zero, IntPtr.Zero);
            // A result of -1 means that no limit is set. 
            if (result != -1 && result < str.Length)
            { 
                throw new InvalidOperationException (SR.Get(SRID.OperationCannotBePerformed)); 
            }
 
            // Send the message...
            result = Misc.ProxySendMessageInt(_hwnd, NativeMethods.WM_SETTEXT, IntPtr.Zero, new StringBuilder(str));
            if (result != 1)
            { 
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            } 
        } 

        // Request to get the value that this UI element is representing as a string 
        string IValueProvider.Value
        {
            get
            { 
                return GetValue();
            } 
        } 

        bool IValueProvider.IsReadOnly 
        {
            get
            {
                return IsReadOnly(); 
            }
        } 
 
        #endregion
 
        #region Text Pattern Methods

        ITextRangeProvider [] ITextProvider.GetSelection()
        { 
            int start, end;
            GetSel(out start, out end); 
            return new ITextRangeProvider[] { new WindowsEditBoxRange(this, start, end) }; 
        }
 
        ITextRangeProvider [] ITextProvider.GetVisibleRanges()
        {
            int start, end;
            GetVisibleRangePoints(out start, out end); 

            return new ITextRangeProvider[] { new WindowsEditBoxRange(this, start, end) }; 
        } 

        ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElement) 
        {
            // we don't have any children so this call must be in error.
            throw new InvalidOperationException(SR.Get(SRID.EditControlsHaveNoChildren,GetType().FullName));
        } 

        ITextRangeProvider ITextProvider.RangeFromPoint(Point screenLocation) 
        { 
            // convert screen to client coordinates.
            // (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.) 
            NativeMethods.Win32Point clientLocation = (NativeMethods.Win32Point)screenLocation;
            if (!Misc.MapWindowPoints(IntPtr.Zero, WindowHandle, ref clientLocation, 1))
            {
                return null; 
            }
 
            // we have to deal with the possibility that the coordinate is inside the window rect 
            // but outside the client rect. in that case we just scoot it over so it is at the nearest
            // point in the client rect. 
            NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect();
            if (!Misc.GetClientRect(WindowHandle, ref clientRect))
            {
                return null; 
            }
            clientLocation.x = Math.Max(clientLocation.x, clientRect.left); 
            clientLocation.x = Math.Min(clientLocation.x, clientRect.right); 
            clientLocation.y = Math.Max(clientLocation.y, clientRect.top);
            clientLocation.y = Math.Min(clientLocation.y, clientRect.bottom); 

            // get the character at those client coordinates
            int start = CharFromPosEx(clientLocation);
            return new WindowsEditBoxRange(this, start, start); 
        }
 
        #endregion TextPattern Methods 

        #region TextPattern Properties 

        ITextRangeProvider ITextProvider.DocumentRange
        {
            get 
            {
                return new WindowsEditBoxRange(this, 0, GetTextLength()); 
            } 
        }
 
        // THESE PROPERTIES ARE REMOVED IN 8.2 BREAKING CHANGE.
        //

 

 
 

 



 

 
 

 



 

 
 

        SupportedTextSelection ITextProvider.SupportedTextSelection 
        {
            get
            {
                return SupportedTextSelection.Single; 
            }
        } 
 
        #endregion Text Properties
 
        //------------------------------------------------------
        //
        //  Internal Properties
        // 
        //------------------------------------------------------
 
        #region Internal Properties 

        internal bool IsMultiline 
        {
            get
            {
                return _type == EditboxType.Multiline; 
            }
        } 
 
        internal bool IsScrollable
        { 
            get
            {
                return _type == EditboxType.Scrollable;
            } 
        }
 
        #endregion Internal Properties 

        //----------------------------------------------------- 
        //
        //  Internal Methods
        //
        //------------------------------------------------------ 

        #region Internal Methods 
 
        // send an EM_CHARPOS message with an (x,y) coordinate in lParam and
        // report the returned character index and line number. 
        // IMPORTANT: the character index and line number are each 16-bit (half of the lResult).
        // the high-order word is zero.
        internal void CharFromPos(NativeMethods.Win32Point point, out ushort indexLowWord, out ushort lineLowWord)
        { 
            Debug.Assert(point.x >= 0 && point.x < 65536, "WindowsEditBox.CharFromPos() x coordinate out of range.");
            Debug.Assert(point.y >= 0 && point.y < 65536, "WindowsEditBox.CharFromPos() y coordinate out of range."); 
 
            // ask edit control for line number and character offset at client coordinates.
            // low order word of return value is the character position. 
            // high order word is the zero-based line index.
            IntPtr lParam = NativeMethods.Util.MAKELPARAM(point.x, point.y);
            int result = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_CHARFROMPOS, IntPtr.Zero, lParam);
            indexLowWord = unchecked((ushort)(NativeMethods.Util.LOWORD(result))); 
            lineLowWord = unchecked((ushort)(NativeMethods.Util.HIWORD(result)));
        } 
 
        // an improvement on EM_CHARFROMPOS that handles edit controls with content greater than 65535 characters.
        internal int CharFromPosEx(NativeMethods.Win32Point point) 
        {
            // get the low words of the character position and line number at the coordinate.
            ushort indexLowWord, lineLowWord;
            CharFromPos(point, out indexLowWord, out lineLowWord); 

            // we handle multi-line edit controls differently than single line edit controls. 
            int index; 
            if (IsMultiline)
            { 
                // note: an optimization would be to call GetTextLength and do the following only if the length is
                // greater than 65535.

                // to make the line number accurate in the case there are more than 65535 lines we get a 32-bit line number 
                // for the first visible line then use it to figure out the high-order word of our line number.
                // this assumes that there aren't more than 65535 visible lines in the window, which is a 
                // pretty safe assumption. 
                int line = IntFromLowWord(lineLowWord, GetFirstVisibleLine());
 
                // to make the character position accurate in case there are more than 65535 characters we use our line number to
                // get the character position of the beginning of that line and use it to figure out the high-order word
                // of our character position.
                // this assumes that there aren't more than 65535 characters on the line before our target character, 
                // which is a pretty safe assumption.
                index = IntFromLowWord(indexLowWord, LineIndex(line)); 
            } 
            else
            { 
                // single-line edit control

                // to make the character position accurate in case there are more than 65535 characters we get a 32-bit
                // character position from the first visible character, then use it to figure out the high-order word 
                // of our character position.
                // this assumes that there aren't more than 65535 visible characters in the window, 
                // which is a pretty safe assumption. 
                index = IntFromLowWord(indexLowWord, GetFirstVisibleChar());
            } 
            return index;
        }

        // Retrive edit box type 
        internal static EditboxType GetEditboxtype (IntPtr hwnd)
        { 
            int style = Misc.GetWindowStyle(hwnd); 
            EditboxType type = EditboxType.Editbox;
 
            if (Misc.IsBitSet(style, NativeMethods.ES_PASSWORD))
            {
                type = EditboxType.Password;
            } 
            else if (Misc.IsBitSet(style, NativeMethods.ES_MULTILINE))
            { 
                type = EditboxType.Multiline; 
            }
            else if (Misc.IsBitSet(style, NativeMethods.ES_AUTOHSCROLL)) 
            {
                type = EditboxType.Scrollable;
            }
 
            return type;
        } 
 
        // send an EM_GETFIRSTVISIBLELINE message to a single-line edit box to get the first visible character.
        internal int GetFirstVisibleChar() 
        {
            Debug.Assert(!IsMultiline);
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETFIRSTVISIBLELINE, IntPtr.Zero, IntPtr.Zero);
        } 

        // send an EM_GETFIRSTVISIBLELINE message to a multi-line edit box to get the first visible line. 
        internal int GetFirstVisibleLine() 
        {
            Debug.Assert(IsMultiline); 
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETFIRSTVISIBLELINE, IntPtr.Zero, IntPtr.Zero);
        }

        // send a WM_GETFONT message to find out what font the edit control is using. 
        internal IntPtr GetFont()
        { 
            IntPtr result = Misc.ProxySendMessage(WindowHandle, NativeMethods.WM_GETFONT, IntPtr.Zero, IntPtr.Zero); 

            // 
            // A null result is within normal bounds, as per the WM_GETFONT documentation:
            // The return value is a handle to the font used by the control, or NULL if the control is using the system font.
            //
            if (result == IntPtr.Zero) 
            {
                result = UnsafeNativeMethods.GetStockObject(NativeMethods.SYSTEM_FONT); 
            } 

            return result; 
        }

        // send an EM_GETLINECOUNT message to find out how many lines are in the edit box.
        internal int GetLineCount() 
        {
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETLINECOUNT, IntPtr.Zero, IntPtr.Zero); 
        } 

        internal NativeMethods.LOGFONT GetLogfont() 
        {
            IntPtr hfont = GetFont();
            Debug.Assert(hfont != IntPtr.Zero, "WindowsEditBox.GetLogfont got null HFONT");
            NativeMethods.LOGFONT logfont = new NativeMethods.LOGFONT(); 
            int cb = Marshal.SizeOf(typeof(NativeMethods.LOGFONT));
            if (Misc.GetObjectW(hfont, cb, ref logfont) != cb) 
            { 
                Debug.Assert(false, "WindowsEditBox.GetObject unexpected return value");
            } 
            return logfont;
        }

        // send an EM_GETRECT message to find out the bounding rectangle 
        internal Rect GetRect()
        { 
            NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_GETRECT, IntPtr.Zero, ref rect);
            return new Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 
        }

        // send an EM_GETSEL message to get the starting and ending
        // character positions of the selection. 
        internal void GetSel(out int start, out int end)
        { 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_GETSEL, out start, out end); 
        }
 
        // send a WM_GETTEXT message to get the text of the edit box.
        internal string GetText()
        {
            return Misc.ProxyGetText(_hwnd, GetTextLength()); 
        }
 
        // send a WM_GETTEXTLENGTH to find out how long the text is in the edit box. 
        internal int GetTextLength()
        { 
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
        }

        internal void GetVisibleRangePoints(out int start, out int end) 
        {
            start = 0; 
            end = 0; 

            NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 

            if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty)
            {
                NativeMethods.SIZE size; 
                string s = new string('E', 1);
                GetTextExtentPoint32(s, out size); 
 
                NativeMethods.Win32Point ptStart = new NativeMethods.Win32Point((int)(rect.left + size.cx / 4), (int)(rect.top + size.cy / 4));
                NativeMethods.Win32Point ptEnd = new NativeMethods.Win32Point((int)(rect.right - size.cx / 8), (int)(rect.bottom - size.cy / 4)); 

                start = CharFromPosEx(ptStart);
                end = CharFromPosEx(ptEnd);
 
                if (start > 0)
                { 
                    Point pt = PosFromChar(start); 
                    if (pt.X < rect.left)
                    { 
                        start++;
                    }
                }
            } 
            else
            { 
                // multi-line edit controls are handled differently than single-line edit controls. 

                if (IsMultiline) 
                {
                    // get the line number of the first visible line and start the range at
                    // the beginning of that line.
                    int firstLine = GetFirstVisibleLine(); 
                    start = LineIndex(firstLine);
 
                    // calculate the line number of the first line scrolled off the bottom and 
                    // end the range at the beginning of that line.
                    end = LineIndex(firstLine + LinesPerPage()); 
                }
                else
                {
                    // single-line edit control 

                    // the problem is that using a variable-width font the number of characters visible 
                    // depends on the text that is in the edit control.  so we can't just divide the 
                    // width of the edit control by the width of a character.
 
                    // so instead we do a binary search of the characters from the first visible character
                    // to the end of the text to find the visibility boundary.
                    Rect r = GetRect();
                    int limit = GetTextLength(); 
                    start = GetFirstVisibleChar();
 
                    int lo = start; // known visible 
                    int hi = limit; // known non-visible
                    while (lo + 1 < hi) 
                    {
                        int mid = (lo + hi) / 2;

                        Point pt = PosFromChar(mid); 
                        if (pt.X >= r.Left && pt.X < r.Right)
                        { 
                            lo = mid; 
                        }
                        else 
                        {
                            hi = mid;
                        }
                    } 

                    // trim off one character unless the range is empty or reaches the end. 
                    end = hi > start && hi < limit ? hi - 1 : hi; 
                }
            } 
        }

        // return true iff the user can modify the text in the edit control.
        internal bool IsReadOnly() 
        {
            return (!SafeNativeMethods.IsWindowEnabled(WindowHandle) || Misc.IsBitSet(WindowStyle, NativeMethods.ES_READONLY)); 
        } 

        // send an EM_LINEFROMCHAR message to find out what line contains a character position. 
        internal int LineFromChar(int index)
        {
            Debug.Assert(index >= 0, "WindowsEditBox.LineFromChar negative index.");
            Debug.Assert(index <= GetTextLength(), "WindowsEditBox.LineFromChar index out of range."); 
            // The return of EM_LINEFROMCHAR is the zero-based line number of the line containing the character index.
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINEFROMCHAR, (IntPtr)index, IntPtr.Zero); 
        } 

        // send an EM_LINEINDEX message to get the character position at the start of a line. 
        internal int LineIndex(int line)
        {
            int index = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINEINDEX, (IntPtr)(line), IntPtr.Zero);
            return index >=0 ? index : GetTextLength(); 
        }
 
        // send an EM_LINESCROLL message to scroll it horizontally and/or vertically 
        internal bool LineScroll(int charactersHorizontal, int linesVertical)
        { 
            return 0 != Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINESCROLL, (IntPtr)charactersHorizontal, (IntPtr)linesVertical);
        }

        // determine the number of lines that are visible in the Edit control. 
        // if there is no scrollbar then this is the actual number of lines displayed.
        internal int LinesPerPage() 
        { 
            int linePerPage = 0;
            if (Misc.IsBitSet(WindowStyle, NativeMethods.WS_VSCROLL)) 
            {
                // we call GetScrollInfo and return the size of the "page"
                NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo();
                si.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(NativeMethods.ScrollInfo)); 
                si.fMask = NativeMethods.SIF_ALL;
                bool ok = Misc.GetScrollInfo(WindowHandle, NativeMethods.SB_VERT, ref si); 
                linePerPage = ok ? si.nPage : 0; 
                if (IsMultiline && linePerPage <= 0)
                { 
                    linePerPage = 1;
                }
            }
            else 
            {
                NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 
 
                if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty)
                { 
                    NativeMethods.SIZE size;
                    string s = new string('E', 1);
                    GetTextExtentPoint32(s, out size);
 
                    if (size.cy != 0)
                    { 
                        linePerPage = (rect.bottom - rect.top) / size.cy; 
                    }
                } 
            }
            return linePerPage;
        }
 
        // send an EM_POSFROMCHAR message to find out the (x,y) position of a character.
        // note: this assumes that the x and y coordinates will not be greater than 65535. 
        internal Point PosFromChar(int index) 
        {
            Debug.Assert(index >= 0, "WindowsEditBox.PosFromChar negative index."); 
            Debug.Assert(index < GetTextLength(), "WindowsEditBox.PosFromChar index out of range.");

            int result = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_POSFROMCHAR, (IntPtr)index, IntPtr.Zero);
            Debug.Assert(result!=-1, "WindowsEditBox.PosFromChar index out of bounds."); 

            // A returned coordinate can be a negative value if the specified character is not displayed in the 
            // edit control's client area.  So do not loose the sign. 
            int x = (int)((short)NativeMethods.Util.LOWORD(result));
            int y = (int)((short)NativeMethods.Util.HIWORD(result)); 
            return new Point(x, y);
        }

        // a variation on EM_POSFROMCHAR that returns the upper-right corner instead of upper-left. 
        internal Point PosFromCharUR(int index, string text)
        { 
            // get the upper-left of the character 
            Point pt;
            char ch = text[index]; 
            switch(ch)
            {
                case '\n':
                case '\r': 
                    // get the UL corner of the character and return it since these characters have no width.
                    pt = PosFromChar(index); 
                    break; 

                case '\t': 
                    {
                        // for tabs the calculated width of the character is no help so we use the
                        // UL corner of the following character if it is on the same line.
                        bool useNext = index= 0, "WindowsEditBox.SetSel negative start.");
            Debug.Assert(start <= GetTextLength(), "WindowsEditBox.SetSel start out of range."); 
            Debug.Assert(end >= 0, "WindowsEditBox.SetSel negative end."); 
            Debug.Assert(end <= GetTextLength(), "WindowsEditBox.SetSel end out of range.");
 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_SETSEL, (IntPtr)start, (IntPtr)end);
        }

        // Retrieves text associated with EditBox control. 
        // this differs from GetText(), above, in that it limits the text to 2000 characters.
        // it is used by the Value pattern methods, not the Text pattern methods. 
        internal static string Text(IntPtr hwnd) 
        {
            return Misc.ProxyGetText(hwnd); 
        }

        #endregion
 
        //-----------------------------------------------------
        // 
        //  Internal Fields 
        //
        //----------------------------------------------------- 

        #region Internal Fields

        // Different styles of edit boxes. 
        internal enum EditboxType
        { 
            Editbox, 
            Multiline,
            Password, 
            Readonly,
            Scrollable
        };
 
        #endregion
 
        // ----------------------------------------------------- 
        //
        // Private Methods 
        //
        // ------------------------------------------------------

        #region Private methods 

        private int GetTextExtentPoint32(string text, out NativeMethods.SIZE size) 
        { 
            size.cx = 0;
            size.cy = 0; 

            // add the width of the character at that position.
            // note: if any of these can throw an exception then we should use a finally clause
            // to ensure the DC is released. 
            IntPtr hdc = Misc.GetDC(_hwnd);
            if (hdc == IntPtr.Zero) 
            { 
                return 0;
            } 

            IntPtr oldFont = IntPtr.Zero;
            try
            { 
                IntPtr hfont = GetFont();
                oldFont = Misc.SelectObject(hdc, hfont); 
                return Misc.GetTextExtentPoint32(hdc, text, text.Length, out size); 
            }
            finally 
            {
                if (oldFont != IntPtr.Zero)
                {
                    Misc.SelectObject(hdc, oldFont); 
                }
 
                Misc.ReleaseDC(_hwnd, hdc); 
            }
        } 

        private string GetValue()
        {
            if (_type == EditboxType.Password) 
            {
                // Trying to retrieve the text (through WM_GETTEXT) from an edit box that has 
                // the ES_PASSWORD style throws an InvalidOperationException. 
                throw new InvalidOperationException();
            } 

            return Text(_hwnd);
        }
 
        private bool IsInsideOfCombo()
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(_hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent == IntPtr.Zero) 
            {
                return false;
            }
 
            // Test for combo
            NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); 
 
            if (WindowsComboBox.GetComboInfo(hwndParent, ref cbInfo) && cbInfo.hwndItem == _hwnd)
            { 
                return true;
            }

            return false; 
        }
 
        private bool IsInsideOfSpinner() 
        {
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(_hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent != IntPtr.Zero)
            {
                // Test for spinner - Create checks if the element is a spinner 
                if (WinformsSpinner.Create(hwndParent, 0) != null)
                { 
                    return true; 
                }
            } 

            return WindowsSpinner.IsSpinnerEdit(_hwnd);
        }
 
        private static bool IsInsideOfIPAddress(IntPtr hwnd)
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent != IntPtr.Zero) 
            {
                string classname = Misc.GetClassName(hwndParent);
                if (classname.Equals("SysIPAddress32"))
                { 
                    return true;
                } 
            } 

            return false; 
        }

        private static bool IsInsideOfListView(IntPtr hwnd)
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT);
 
            if (hwndParent != IntPtr.Zero) 
            {
                string classname = Misc.GetClassName(hwndParent); 
                if (classname.Equals("SysListView32"))
                {
                    return true;
                } 
            }
 
            return false; 
        }
 
        // given the low-order word of a non-negative integer that is at most 0xffff greater than some floor integer
        // we calculate what the original integer was.
        private static int IntFromLowWord(ushort lowWord, int floor)
        { 
            // get the high-word from our floor integer
            Debug.Assert(floor >= 0); 
            short hiWord = (short)(floor >> 16); 

            // if our unknown integer has cross a 64k boundary from our floor integer 
            // then we need to increment the high-word
            ushort floorLowWord = (ushort)(floor & 0xffff);
            if (lowWord < floorLowWord)
                hiWord++; 

            // combine the adjusted floor high-word with the known low-word to get our integer 
            int i = NativeMethods.Util.MAKELONG((int)lowWord, (int)hiWord); 
            Debug.Assert(i >= floor);
 
            return i;
        }

        #endregion Private methods 

        // ----------------------------------------------------- 
        // 
        // Private Fields
        // 
        // ------------------------------------------------------

        #region Private Fields
 
        private EditboxType _type;
 
        #endregion 
    }
} 

// 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.
//  
//
// 
// Description: HWND-based Edit Box proxy 
//
// History: 
//  01/10/03 : a-jeanp - created
//  08/12/03:  alexsn - bug fixes
//  03/02/04:  a-davidj - added text pattern
// 
//---------------------------------------------------------------------------
 
using System; 
using System.Collections;
using System.Diagnostics; 
using System.Globalization;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel; 
using System.Windows;
using System.Windows.Automation; 
using System.Windows.Automation.Provider; 
using System.Windows.Automation.Text;
using MS.Win32; 

namespace MS.Internal.AutomationProxies
{
    // TERMINOLOGY: Win32 Edit controls use the term "index" to mean a character position. 
    // For example the EM_LINEINDEX message converts a line number to it's starting character position.
    // Perhaps not the best choice but we use it to be consistent. 
 
    class WindowsEditBox : ProxyHwnd, IValueProvider, ITextProvider
    { 
        // -----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
        #region Constructors 

        // This is the default contructor that calls the base class constructor. 
        // This function determines the type of the edit control and then calls the default constructor.
        internal WindowsEditBox (IntPtr hwnd, ProxyFragment parent, int item)
            : base( hwnd, parent, item)
        { 
            _type = GetEditboxtype (hwnd);
            if (IsMultiline) 
            { 
                _cControlType = ControlType.Document;
            } 
            else
            {
                _cControlType = ControlType.Edit;
            } 

            // When embedded inside of the combobox, hide the edit portion in the content element tree 
            _fIsContent = !IsInsideOfCombo(); 
            _fIsKeyboardFocusable = true;
 
            if (IsInsideOfListView(hwnd))
            {
                _sAutomationId = "edit";
            } 

            // support for events 
            _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); 
        }
 
        #endregion

        #region Proxy Create
 
        // Static Create method called by UIAutomation to create this proxy.
        // = 6)
            { 
                cEvent = 1;
                return new WinEventTracker.EvtIdProperty[] { 
                    new WinEventTracker.EvtIdProperty (NativeMethods.EventObjectTextSelectionChanged, idEvent) 
                };
            } 
            */

            return base.EventToWinEvent(idEvent, out cEvent);
        } 

        #endregion 
 
        #region Value Pattern
 
        // Sets the text of the edit.
        void IValueProvider.SetValue (string str)
        {
            // Ensure that the edit box and all its parents are enabled. 
            Misc.CheckEnabled(_hwnd);
 
            int styles = WindowStyle; 

            if (Misc.IsBitSet(styles, NativeMethods.ES_READONLY)) 
            {
                throw new InvalidOperationException(SR.Get(SRID.ValueReadonly));
            }
 
            // check if control only accepts numbers
            if (Misc.IsBitSet(styles, NativeMethods.ES_NUMBER)) 
            { 
                // check if string contains any non-numeric characters.
                foreach (char ch in str) 
                {
                    if (char.IsLetter (ch))
                    {
                        throw new ArgumentException(SR.Get(SRID.NotAValidValue, str), "val"); 
                    }
                } 
            } 

            // bug# 11147, Text/edit box should not enter more characters than what is allowed through keyboard. 
            // Determine the max number of chars this editbox accepts

            int result = Misc.ProxySendMessageInt(_hwnd, NativeMethods.EM_GETLIMITTEXT, IntPtr.Zero, IntPtr.Zero);
            // A result of -1 means that no limit is set. 
            if (result != -1 && result < str.Length)
            { 
                throw new InvalidOperationException (SR.Get(SRID.OperationCannotBePerformed)); 
            }
 
            // Send the message...
            result = Misc.ProxySendMessageInt(_hwnd, NativeMethods.WM_SETTEXT, IntPtr.Zero, new StringBuilder(str));
            if (result != 1)
            { 
                throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed));
            } 
        } 

        // Request to get the value that this UI element is representing as a string 
        string IValueProvider.Value
        {
            get
            { 
                return GetValue();
            } 
        } 

        bool IValueProvider.IsReadOnly 
        {
            get
            {
                return IsReadOnly(); 
            }
        } 
 
        #endregion
 
        #region Text Pattern Methods

        ITextRangeProvider [] ITextProvider.GetSelection()
        { 
            int start, end;
            GetSel(out start, out end); 
            return new ITextRangeProvider[] { new WindowsEditBoxRange(this, start, end) }; 
        }
 
        ITextRangeProvider [] ITextProvider.GetVisibleRanges()
        {
            int start, end;
            GetVisibleRangePoints(out start, out end); 

            return new ITextRangeProvider[] { new WindowsEditBoxRange(this, start, end) }; 
        } 

        ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElement) 
        {
            // we don't have any children so this call must be in error.
            throw new InvalidOperationException(SR.Get(SRID.EditControlsHaveNoChildren,GetType().FullName));
        } 

        ITextRangeProvider ITextProvider.RangeFromPoint(Point screenLocation) 
        { 
            // convert screen to client coordinates.
            // (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.) 
            NativeMethods.Win32Point clientLocation = (NativeMethods.Win32Point)screenLocation;
            if (!Misc.MapWindowPoints(IntPtr.Zero, WindowHandle, ref clientLocation, 1))
            {
                return null; 
            }
 
            // we have to deal with the possibility that the coordinate is inside the window rect 
            // but outside the client rect. in that case we just scoot it over so it is at the nearest
            // point in the client rect. 
            NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect();
            if (!Misc.GetClientRect(WindowHandle, ref clientRect))
            {
                return null; 
            }
            clientLocation.x = Math.Max(clientLocation.x, clientRect.left); 
            clientLocation.x = Math.Min(clientLocation.x, clientRect.right); 
            clientLocation.y = Math.Max(clientLocation.y, clientRect.top);
            clientLocation.y = Math.Min(clientLocation.y, clientRect.bottom); 

            // get the character at those client coordinates
            int start = CharFromPosEx(clientLocation);
            return new WindowsEditBoxRange(this, start, start); 
        }
 
        #endregion TextPattern Methods 

        #region TextPattern Properties 

        ITextRangeProvider ITextProvider.DocumentRange
        {
            get 
            {
                return new WindowsEditBoxRange(this, 0, GetTextLength()); 
            } 
        }
 
        // THESE PROPERTIES ARE REMOVED IN 8.2 BREAKING CHANGE.
        //

 

 
 

 



 

 
 

 



 

 
 

        SupportedTextSelection ITextProvider.SupportedTextSelection 
        {
            get
            {
                return SupportedTextSelection.Single; 
            }
        } 
 
        #endregion Text Properties
 
        //------------------------------------------------------
        //
        //  Internal Properties
        // 
        //------------------------------------------------------
 
        #region Internal Properties 

        internal bool IsMultiline 
        {
            get
            {
                return _type == EditboxType.Multiline; 
            }
        } 
 
        internal bool IsScrollable
        { 
            get
            {
                return _type == EditboxType.Scrollable;
            } 
        }
 
        #endregion Internal Properties 

        //----------------------------------------------------- 
        //
        //  Internal Methods
        //
        //------------------------------------------------------ 

        #region Internal Methods 
 
        // send an EM_CHARPOS message with an (x,y) coordinate in lParam and
        // report the returned character index and line number. 
        // IMPORTANT: the character index and line number are each 16-bit (half of the lResult).
        // the high-order word is zero.
        internal void CharFromPos(NativeMethods.Win32Point point, out ushort indexLowWord, out ushort lineLowWord)
        { 
            Debug.Assert(point.x >= 0 && point.x < 65536, "WindowsEditBox.CharFromPos() x coordinate out of range.");
            Debug.Assert(point.y >= 0 && point.y < 65536, "WindowsEditBox.CharFromPos() y coordinate out of range."); 
 
            // ask edit control for line number and character offset at client coordinates.
            // low order word of return value is the character position. 
            // high order word is the zero-based line index.
            IntPtr lParam = NativeMethods.Util.MAKELPARAM(point.x, point.y);
            int result = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_CHARFROMPOS, IntPtr.Zero, lParam);
            indexLowWord = unchecked((ushort)(NativeMethods.Util.LOWORD(result))); 
            lineLowWord = unchecked((ushort)(NativeMethods.Util.HIWORD(result)));
        } 
 
        // an improvement on EM_CHARFROMPOS that handles edit controls with content greater than 65535 characters.
        internal int CharFromPosEx(NativeMethods.Win32Point point) 
        {
            // get the low words of the character position and line number at the coordinate.
            ushort indexLowWord, lineLowWord;
            CharFromPos(point, out indexLowWord, out lineLowWord); 

            // we handle multi-line edit controls differently than single line edit controls. 
            int index; 
            if (IsMultiline)
            { 
                // note: an optimization would be to call GetTextLength and do the following only if the length is
                // greater than 65535.

                // to make the line number accurate in the case there are more than 65535 lines we get a 32-bit line number 
                // for the first visible line then use it to figure out the high-order word of our line number.
                // this assumes that there aren't more than 65535 visible lines in the window, which is a 
                // pretty safe assumption. 
                int line = IntFromLowWord(lineLowWord, GetFirstVisibleLine());
 
                // to make the character position accurate in case there are more than 65535 characters we use our line number to
                // get the character position of the beginning of that line and use it to figure out the high-order word
                // of our character position.
                // this assumes that there aren't more than 65535 characters on the line before our target character, 
                // which is a pretty safe assumption.
                index = IntFromLowWord(indexLowWord, LineIndex(line)); 
            } 
            else
            { 
                // single-line edit control

                // to make the character position accurate in case there are more than 65535 characters we get a 32-bit
                // character position from the first visible character, then use it to figure out the high-order word 
                // of our character position.
                // this assumes that there aren't more than 65535 visible characters in the window, 
                // which is a pretty safe assumption. 
                index = IntFromLowWord(indexLowWord, GetFirstVisibleChar());
            } 
            return index;
        }

        // Retrive edit box type 
        internal static EditboxType GetEditboxtype (IntPtr hwnd)
        { 
            int style = Misc.GetWindowStyle(hwnd); 
            EditboxType type = EditboxType.Editbox;
 
            if (Misc.IsBitSet(style, NativeMethods.ES_PASSWORD))
            {
                type = EditboxType.Password;
            } 
            else if (Misc.IsBitSet(style, NativeMethods.ES_MULTILINE))
            { 
                type = EditboxType.Multiline; 
            }
            else if (Misc.IsBitSet(style, NativeMethods.ES_AUTOHSCROLL)) 
            {
                type = EditboxType.Scrollable;
            }
 
            return type;
        } 
 
        // send an EM_GETFIRSTVISIBLELINE message to a single-line edit box to get the first visible character.
        internal int GetFirstVisibleChar() 
        {
            Debug.Assert(!IsMultiline);
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETFIRSTVISIBLELINE, IntPtr.Zero, IntPtr.Zero);
        } 

        // send an EM_GETFIRSTVISIBLELINE message to a multi-line edit box to get the first visible line. 
        internal int GetFirstVisibleLine() 
        {
            Debug.Assert(IsMultiline); 
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETFIRSTVISIBLELINE, IntPtr.Zero, IntPtr.Zero);
        }

        // send a WM_GETFONT message to find out what font the edit control is using. 
        internal IntPtr GetFont()
        { 
            IntPtr result = Misc.ProxySendMessage(WindowHandle, NativeMethods.WM_GETFONT, IntPtr.Zero, IntPtr.Zero); 

            // 
            // A null result is within normal bounds, as per the WM_GETFONT documentation:
            // The return value is a handle to the font used by the control, or NULL if the control is using the system font.
            //
            if (result == IntPtr.Zero) 
            {
                result = UnsafeNativeMethods.GetStockObject(NativeMethods.SYSTEM_FONT); 
            } 

            return result; 
        }

        // send an EM_GETLINECOUNT message to find out how many lines are in the edit box.
        internal int GetLineCount() 
        {
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_GETLINECOUNT, IntPtr.Zero, IntPtr.Zero); 
        } 

        internal NativeMethods.LOGFONT GetLogfont() 
        {
            IntPtr hfont = GetFont();
            Debug.Assert(hfont != IntPtr.Zero, "WindowsEditBox.GetLogfont got null HFONT");
            NativeMethods.LOGFONT logfont = new NativeMethods.LOGFONT(); 
            int cb = Marshal.SizeOf(typeof(NativeMethods.LOGFONT));
            if (Misc.GetObjectW(hfont, cb, ref logfont) != cb) 
            { 
                Debug.Assert(false, "WindowsEditBox.GetObject unexpected return value");
            } 
            return logfont;
        }

        // send an EM_GETRECT message to find out the bounding rectangle 
        internal Rect GetRect()
        { 
            NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_GETRECT, IntPtr.Zero, ref rect);
            return new Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 
        }

        // send an EM_GETSEL message to get the starting and ending
        // character positions of the selection. 
        internal void GetSel(out int start, out int end)
        { 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_GETSEL, out start, out end); 
        }
 
        // send a WM_GETTEXT message to get the text of the edit box.
        internal string GetText()
        {
            return Misc.ProxyGetText(_hwnd, GetTextLength()); 
        }
 
        // send a WM_GETTEXTLENGTH to find out how long the text is in the edit box. 
        internal int GetTextLength()
        { 
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
        }

        internal void GetVisibleRangePoints(out int start, out int end) 
        {
            start = 0; 
            end = 0; 

            NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 

            if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty)
            {
                NativeMethods.SIZE size; 
                string s = new string('E', 1);
                GetTextExtentPoint32(s, out size); 
 
                NativeMethods.Win32Point ptStart = new NativeMethods.Win32Point((int)(rect.left + size.cx / 4), (int)(rect.top + size.cy / 4));
                NativeMethods.Win32Point ptEnd = new NativeMethods.Win32Point((int)(rect.right - size.cx / 8), (int)(rect.bottom - size.cy / 4)); 

                start = CharFromPosEx(ptStart);
                end = CharFromPosEx(ptEnd);
 
                if (start > 0)
                { 
                    Point pt = PosFromChar(start); 
                    if (pt.X < rect.left)
                    { 
                        start++;
                    }
                }
            } 
            else
            { 
                // multi-line edit controls are handled differently than single-line edit controls. 

                if (IsMultiline) 
                {
                    // get the line number of the first visible line and start the range at
                    // the beginning of that line.
                    int firstLine = GetFirstVisibleLine(); 
                    start = LineIndex(firstLine);
 
                    // calculate the line number of the first line scrolled off the bottom and 
                    // end the range at the beginning of that line.
                    end = LineIndex(firstLine + LinesPerPage()); 
                }
                else
                {
                    // single-line edit control 

                    // the problem is that using a variable-width font the number of characters visible 
                    // depends on the text that is in the edit control.  so we can't just divide the 
                    // width of the edit control by the width of a character.
 
                    // so instead we do a binary search of the characters from the first visible character
                    // to the end of the text to find the visibility boundary.
                    Rect r = GetRect();
                    int limit = GetTextLength(); 
                    start = GetFirstVisibleChar();
 
                    int lo = start; // known visible 
                    int hi = limit; // known non-visible
                    while (lo + 1 < hi) 
                    {
                        int mid = (lo + hi) / 2;

                        Point pt = PosFromChar(mid); 
                        if (pt.X >= r.Left && pt.X < r.Right)
                        { 
                            lo = mid; 
                        }
                        else 
                        {
                            hi = mid;
                        }
                    } 

                    // trim off one character unless the range is empty or reaches the end. 
                    end = hi > start && hi < limit ? hi - 1 : hi; 
                }
            } 
        }

        // return true iff the user can modify the text in the edit control.
        internal bool IsReadOnly() 
        {
            return (!SafeNativeMethods.IsWindowEnabled(WindowHandle) || Misc.IsBitSet(WindowStyle, NativeMethods.ES_READONLY)); 
        } 

        // send an EM_LINEFROMCHAR message to find out what line contains a character position. 
        internal int LineFromChar(int index)
        {
            Debug.Assert(index >= 0, "WindowsEditBox.LineFromChar negative index.");
            Debug.Assert(index <= GetTextLength(), "WindowsEditBox.LineFromChar index out of range."); 
            // The return of EM_LINEFROMCHAR is the zero-based line number of the line containing the character index.
            return Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINEFROMCHAR, (IntPtr)index, IntPtr.Zero); 
        } 

        // send an EM_LINEINDEX message to get the character position at the start of a line. 
        internal int LineIndex(int line)
        {
            int index = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINEINDEX, (IntPtr)(line), IntPtr.Zero);
            return index >=0 ? index : GetTextLength(); 
        }
 
        // send an EM_LINESCROLL message to scroll it horizontally and/or vertically 
        internal bool LineScroll(int charactersHorizontal, int linesVertical)
        { 
            return 0 != Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_LINESCROLL, (IntPtr)charactersHorizontal, (IntPtr)linesVertical);
        }

        // determine the number of lines that are visible in the Edit control. 
        // if there is no scrollbar then this is the actual number of lines displayed.
        internal int LinesPerPage() 
        { 
            int linePerPage = 0;
            if (Misc.IsBitSet(WindowStyle, NativeMethods.WS_VSCROLL)) 
            {
                // we call GetScrollInfo and return the size of the "page"
                NativeMethods.ScrollInfo si = new NativeMethods.ScrollInfo();
                si.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(NativeMethods.ScrollInfo)); 
                si.fMask = NativeMethods.SIF_ALL;
                bool ok = Misc.GetScrollInfo(WindowHandle, NativeMethods.SB_VERT, ref si); 
                linePerPage = ok ? si.nPage : 0; 
                if (IsMultiline && linePerPage <= 0)
                { 
                    linePerPage = 1;
                }
            }
            else 
            {
                NativeMethods.Win32Rect rect = new NativeMethods.Win32Rect(); 
 
                if (Misc.GetClientRect(_hwnd, ref rect) && !rect.IsEmpty)
                { 
                    NativeMethods.SIZE size;
                    string s = new string('E', 1);
                    GetTextExtentPoint32(s, out size);
 
                    if (size.cy != 0)
                    { 
                        linePerPage = (rect.bottom - rect.top) / size.cy; 
                    }
                } 
            }
            return linePerPage;
        }
 
        // send an EM_POSFROMCHAR message to find out the (x,y) position of a character.
        // note: this assumes that the x and y coordinates will not be greater than 65535. 
        internal Point PosFromChar(int index) 
        {
            Debug.Assert(index >= 0, "WindowsEditBox.PosFromChar negative index."); 
            Debug.Assert(index < GetTextLength(), "WindowsEditBox.PosFromChar index out of range.");

            int result = Misc.ProxySendMessageInt(WindowHandle, NativeMethods.EM_POSFROMCHAR, (IntPtr)index, IntPtr.Zero);
            Debug.Assert(result!=-1, "WindowsEditBox.PosFromChar index out of bounds."); 

            // A returned coordinate can be a negative value if the specified character is not displayed in the 
            // edit control's client area.  So do not loose the sign. 
            int x = (int)((short)NativeMethods.Util.LOWORD(result));
            int y = (int)((short)NativeMethods.Util.HIWORD(result)); 
            return new Point(x, y);
        }

        // a variation on EM_POSFROMCHAR that returns the upper-right corner instead of upper-left. 
        internal Point PosFromCharUR(int index, string text)
        { 
            // get the upper-left of the character 
            Point pt;
            char ch = text[index]; 
            switch(ch)
            {
                case '\n':
                case '\r': 
                    // get the UL corner of the character and return it since these characters have no width.
                    pt = PosFromChar(index); 
                    break; 

                case '\t': 
                    {
                        // for tabs the calculated width of the character is no help so we use the
                        // UL corner of the following character if it is on the same line.
                        bool useNext = index= 0, "WindowsEditBox.SetSel negative start.");
            Debug.Assert(start <= GetTextLength(), "WindowsEditBox.SetSel start out of range."); 
            Debug.Assert(end >= 0, "WindowsEditBox.SetSel negative end."); 
            Debug.Assert(end <= GetTextLength(), "WindowsEditBox.SetSel end out of range.");
 
            Misc.ProxySendMessage(WindowHandle, NativeMethods.EM_SETSEL, (IntPtr)start, (IntPtr)end);
        }

        // Retrieves text associated with EditBox control. 
        // this differs from GetText(), above, in that it limits the text to 2000 characters.
        // it is used by the Value pattern methods, not the Text pattern methods. 
        internal static string Text(IntPtr hwnd) 
        {
            return Misc.ProxyGetText(hwnd); 
        }

        #endregion
 
        //-----------------------------------------------------
        // 
        //  Internal Fields 
        //
        //----------------------------------------------------- 

        #region Internal Fields

        // Different styles of edit boxes. 
        internal enum EditboxType
        { 
            Editbox, 
            Multiline,
            Password, 
            Readonly,
            Scrollable
        };
 
        #endregion
 
        // ----------------------------------------------------- 
        //
        // Private Methods 
        //
        // ------------------------------------------------------

        #region Private methods 

        private int GetTextExtentPoint32(string text, out NativeMethods.SIZE size) 
        { 
            size.cx = 0;
            size.cy = 0; 

            // add the width of the character at that position.
            // note: if any of these can throw an exception then we should use a finally clause
            // to ensure the DC is released. 
            IntPtr hdc = Misc.GetDC(_hwnd);
            if (hdc == IntPtr.Zero) 
            { 
                return 0;
            } 

            IntPtr oldFont = IntPtr.Zero;
            try
            { 
                IntPtr hfont = GetFont();
                oldFont = Misc.SelectObject(hdc, hfont); 
                return Misc.GetTextExtentPoint32(hdc, text, text.Length, out size); 
            }
            finally 
            {
                if (oldFont != IntPtr.Zero)
                {
                    Misc.SelectObject(hdc, oldFont); 
                }
 
                Misc.ReleaseDC(_hwnd, hdc); 
            }
        } 

        private string GetValue()
        {
            if (_type == EditboxType.Password) 
            {
                // Trying to retrieve the text (through WM_GETTEXT) from an edit box that has 
                // the ES_PASSWORD style throws an InvalidOperationException. 
                throw new InvalidOperationException();
            } 

            return Text(_hwnd);
        }
 
        private bool IsInsideOfCombo()
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(_hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent == IntPtr.Zero) 
            {
                return false;
            }
 
            // Test for combo
            NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); 
 
            if (WindowsComboBox.GetComboInfo(hwndParent, ref cbInfo) && cbInfo.hwndItem == _hwnd)
            { 
                return true;
            }

            return false; 
        }
 
        private bool IsInsideOfSpinner() 
        {
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(_hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent != IntPtr.Zero)
            {
                // Test for spinner - Create checks if the element is a spinner 
                if (WinformsSpinner.Create(hwndParent, 0) != null)
                { 
                    return true; 
                }
            } 

            return WindowsSpinner.IsSpinnerEdit(_hwnd);
        }
 
        private static bool IsInsideOfIPAddress(IntPtr hwnd)
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 

            if (hwndParent != IntPtr.Zero) 
            {
                string classname = Misc.GetClassName(hwndParent);
                if (classname.Equals("SysIPAddress32"))
                { 
                    return true;
                } 
            } 

            return false; 
        }

        private static bool IsInsideOfListView(IntPtr hwnd)
        { 
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT);
 
            if (hwndParent != IntPtr.Zero) 
            {
                string classname = Misc.GetClassName(hwndParent); 
                if (classname.Equals("SysListView32"))
                {
                    return true;
                } 
            }
 
            return false; 
        }
 
        // given the low-order word of a non-negative integer that is at most 0xffff greater than some floor integer
        // we calculate what the original integer was.
        private static int IntFromLowWord(ushort lowWord, int floor)
        { 
            // get the high-word from our floor integer
            Debug.Assert(floor >= 0); 
            short hiWord = (short)(floor >> 16); 

            // if our unknown integer has cross a 64k boundary from our floor integer 
            // then we need to increment the high-word
            ushort floorLowWord = (ushort)(floor & 0xffff);
            if (lowWord < floorLowWord)
                hiWord++; 

            // combine the adjusted floor high-word with the known low-word to get our integer 
            int i = NativeMethods.Util.MAKELONG((int)lowWord, (int)hiWord); 
            Debug.Assert(i >= floor);
 
            return i;
        }

        #endregion Private methods 

        // ----------------------------------------------------- 
        // 
        // Private Fields
        // 
        // ------------------------------------------------------

        #region Private Fields
 
        private EditboxType _type;
 
        #endregion 
    }
} 

// 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