Exemple #1
0
        /// <summary>
        /// 转换文本使其长度能够在指定控件的宽度范围内显示,使用省略号替换剪辑掉的部分。
        /// </summary>
        /// <param name="text">将要被转换的文本。</param>
        /// <param name="ctrl">剪辑后的文本即将在此控件内显示。</param>
        /// <param name="options">指示如何处理文本。</param>
        /// <returns>当参数“text”为 null 或 string.Empty 返回 text 的值,否则返回转换后的内容。</returns>
        public static string Compact(string text, Control ctrl, EllipsisFormat options)
        {
            if (ctrl == null)
            {
                throw new ArgumentNullException("ctrl");
            }

            using (Graphics dc = ctrl.CreateGraphics())
            {
                return(Compact(dc, text, ctrl.Width, ctrl.Font, options));
            }
        }
        uint isChecked(EllipsisFormat fmt)
        {
            EllipsisFormat mask = fmt;

            switch (fmt)
            {
            case EllipsisFormat.None:
            case EllipsisFormat.Start:
            case EllipsisFormat.End:
                mask = EllipsisFormat.Middle;
                break;
            }
            return(((AutoEllipsis & mask) == fmt) ? MF_CHECKED : MF_UNCHECKED);
        }
Exemple #3
0
        public Aircraft()
        {
            InitializeComponent();
            updateVersion();
            this.usingUTC = true;

            EllipsisFormat fmt = EllipsisFormat.None;

            fmt |= EllipsisFormat.Middle;
            fmt |= EllipsisFormat.Word;

            this.imagePath.AutoEllipsis = fmt;
            this.workingDirectory       = null;
            this.fileCount                    = 0;
            this.imagePath.Text               = "";
            this.trackLogFile.Text            = "";
            this.trackLog                     = null;
            this.trackLogLocation.Enabled     = false;
            this.currentFile.Text             = "";
            this.readingFile.Text             = "0000 of 0000";
            this.fileFailures.Text            = String.Format("{0,4:0000}", 0);;
            this.convertImageFiles.Enabled    = false;
            this.direction.Text               = String.Format("{0:000}", getOffsetHeading());
            this.photographerPosition.Enabled = false;
            this.trackLogFile.Text            = "";
            this.cameraTime.Enabled           = false;
            this.deltaSeconds.Text            = "";
            this.doReverseGeocode.Checked     = isNetworkOn() ? true : false;
            setGeocodingOption(false);

            this.heading315Lbl.Visible = false;
            this.direction315.Enabled  = false;
            this.direction315.Visible  = false;

            if (Directory.Exists(IMAGE_ROOT))
            {
                this.imageFolderBrowserDialog.SelectedPath = IMAGE_ROOT;
            }
            else
            {
                this.imageFolderBrowserDialog.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            }
        }
Exemple #4
0
        /// <summary>
        /// Truncates a text string to fit within a given control width by replacing trimmed text with ellipses. 
        /// </summary>
        /// <param name="text">String to be trimmed.</param>
        /// <param name="ctrl">text must fit within ctrl width.
        ///	The ctrl's Font is used to measure the text string.</param>
        /// <param name="options">Format and alignment of ellipsis.</param>
        /// <returns>This function returns text trimmed to the specified witdh.</returns>
        public static string Compact(string text, Func<string, Size> measure, double givenWidth, EllipsisFormat options)
        {
            if (string.IsNullOrEmpty(text))
                return text;

            // no aligment information
            if ((EllipsisFormat.Middle & options) == 0)
                return text;

            Size s = measure(text);

            // control is large enough to display the whole text
            if (s.Width <= givenWidth)
                return text;

            string pre = "";
            string mid = text;
            string post = "";

            bool isPath = (EllipsisFormat.Path & options) != 0;

            // split path string into <drive><directory><filename>
            if (isPath)
            {
                pre = Path.GetPathRoot(text);
                mid = Path.GetDirectoryName(text).Substring(pre.Length);
                post = Path.GetFileName(text);
            }

            int len = 0;
            int seg = mid.Length;
            string fit = "";

            // find the longest string that fits into
            // the control boundaries using bisection method
            while (seg > 1)
            {
                seg -= seg / 2;

                int left = len + seg;
                int right = mid.Length;

                if (left > right)
                    continue;

                if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle)
                {
                    right -= left / 2;
                    left -= left / 2;
                }
                else if ((EllipsisFormat.Start & options) != 0)
                {
                    right -= left;
                    left = 0;
                }

                // trim at a word boundary using regular expressions
                if ((EllipsisFormat.Word & options) != 0)
                {
                    if ((EllipsisFormat.End & options) != 0)
                    {
                        left -= prevWord.Match(mid, 0, left).Length;
                    }
                    if ((EllipsisFormat.Start & options) != 0)
                    {
                        right += nextWord.Match(mid, right).Length;
                    }
                }

                // build and measure a candidate string with ellipsis
                string tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right);

                // restore path with <drive> and <filename>
                if (isPath)
                {
                    tst = Path.Combine(Path.Combine(pre, tst), post);
                }
                s = measure(tst);

                // candidate string fits into control boundaries, try a longer string
                // stop when seg <= 1
                if (s.Width <= givenWidth)
                {
                    len += seg;
                    fit = tst;
                }
            }

            if (len == 0) // string can't fit into control
            {
                // "path" mode is off, just return ellipsis characters
                if (!isPath)
                    return EllipsisChars;

                // <drive> and <directory> are empty, return <filename>
                if (pre.Length == 0 && mid.Length == 0)
                    return post;

                // measure "C:\...\filename.ext"
                fit = Path.Combine(Path.Combine(pre, EllipsisChars), post);

                s = measure(fit);

                // if still not fit then return "...\filename.ext"
                if (s.Width > givenWidth)
                    fit = Path.Combine(EllipsisChars, post);
            }
            return fit;
        }
Exemple #5
0
            /// <summary>
            /// Truncates a text string to fit within a given width by replacing trimmed text with ellipses.
            /// </summary>
            /// <param name="text">String to be trimmed.</param>
            /// <param name="font">Font to be used to measure the text.</param>
            /// <param name="proposedWidth">The target width to accomodate the text.</param>
            /// <param name="options">Format and alignment of ellipsis.</param>
            /// <returns>This function returns text trimmed to the specified witdh.</returns>
            public static string Compact(string text, Font font, int proposedWidth, EllipsisFormat options)
            {
                if (string.IsNullOrEmpty(text))
                {
                    return(text);
                }

                // no aligment information
                if (((EllipsisFormat.Path | EllipsisFormat.Start | EllipsisFormat.End | EllipsisFormat.Middle) & options) == 0)
                {
                    return(text);
                }

                if (font == null)
                {
                    throw new ArgumentNullException("font");
                }

                Size s = TextRenderer.MeasureText(text, font);

                // control is large enough to display the whole text
                if (s.Width <= proposedWidth)
                {
                    return(text);
                }

                string pre  = "";
                string mid  = text;
                string post = "";

                bool isPath = (EllipsisFormat.Path & options) != 0;

                // split path string into <drive><directory><filename>
                if (isPath)
                {
                    pre  = Path.GetPathRoot(text);
                    mid  = Path.GetDirectoryName(text).Substring(pre.Length);
                    post = Path.GetFileName(text);
                }

                int    len = 0;
                int    seg = mid.Length;
                string fit = "";

                // find the longest string that fits into
                // the control boundaries using bisection method
                while (seg > 1)
                {
                    seg -= seg / 2;

                    int left  = len + seg;
                    int right = mid.Length;

                    if (left > right)
                    {
                        continue;
                    }

                    if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle)
                    {
                        right -= left / 2;
                        left  -= left / 2;
                    }
                    else if ((EllipsisFormat.Start & options) != 0)
                    {
                        right -= left;
                        left   = 0;
                    }

                    // trim at a word boundary using regular expressions
                    if ((EllipsisFormat.Word & options) != 0)
                    {
                        if ((EllipsisFormat.End & options) != 0)
                        {
                            left -= prevWord.Match(mid, 0, left).Length;
                        }
                        if ((EllipsisFormat.Start & options) != 0)
                        {
                            right += nextWord.Match(mid, right).Length;
                        }
                    }

                    // build and measure a candidate string with ellipsis
                    string tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right);

                    // restore path with <drive> and <filename>
                    if (isPath)
                    {
                        tst = Path.Combine(Path.Combine(pre, tst), post);
                    }
                    s = TextRenderer.MeasureText(tst, font);

                    // candidate string fits into control boundaries, try a longer string
                    // stop when seg <= 1
                    if (s.Width <= proposedWidth)
                    {
                        len += seg;
                        fit  = tst;
                    }
                }

                if (len == 0) // string can't fit into control
                {
                    // "path" mode is off, just return ellipsis characters
                    if (!isPath)
                    {
                        return(EllipsisChars);
                    }

                    // <directory> is empty
                    if (mid.Length == 0)
                    {
                        // <drive> is empty, return compacted <filename>
                        if (pre.Length == 0)
                        {
                            return(Compact(text, font, proposedWidth, options & ~EllipsisFormat.Path));
                        }

                        // we compare ellipsis and <drive> to get the shorter
                        string testEllipsis = Path.Combine(EllipsisChars, ".");
                        testEllipsis = testEllipsis.Substring(0, testEllipsis.Length - 1);
                        if (TextRenderer.MeasureText(testEllipsis, font).Width < TextRenderer.MeasureText(pre, font).Width)
                        {
                            pre = EllipsisChars;
                        }
                    }
                    else
                    {
                        // "C:\...\filename.ext" No need to check for drive, but generates extra check
                        if (pre.Length > 0)
                        {
                            fit = Path.Combine(Path.Combine(pre, EllipsisChars), post);

                            s = TextRenderer.MeasureText(fit, font);

                            if (s.Width <= proposedWidth)
                            {
                                return(fit);
                            }
                        }

                        pre = EllipsisChars;
                    }

                    // Try "...\filename.ext" or "c:\filename.ext"
                    fit = Path.Combine(pre, post);

                    s = TextRenderer.MeasureText(fit, font);

                    // if still not fit then return "...\f...e.ext"
                    if (s.Width > proposedWidth)
                    {
                        fit = Path.Combine(pre, Compact(post, font, proposedWidth - TextRenderer.MeasureText(fit.Substring(0, fit.Length - post.Length), font).Width, options & ~EllipsisFormat.Path));
                    }
                }
                return(fit);
            }
        /// <summary>
        /// Truncates a text string to fit within a given control width by replacing trimmed text with ellipses.
        /// </summary>
        /// <param name="text">String to be trimmed.</param>
        /// <param name="control">text must fit within control width.
        ///	The control's Font is used to measure the text string.</param>
        /// <param name="options">Format and alignment of ellipsis.</param>
        /// <returns>This function returns text trimmed to the specified width.</returns>
        public static string Compact(string text, Control control, EllipsisFormat options)
        {
            if (string.IsNullOrEmpty(text))
            {
                return(text);
            }

            // no alignment information
            if (!options.FastHasFlag(EllipsisFormat.Start) && !options.FastHasFlag(EllipsisFormat.Middle) && !options.FastHasFlag(EllipsisFormat.End))
            {
                return(text);
            }

            if (control == null)
            {
                throw new ArgumentNullException(nameof(control));
            }

            using (Graphics dc = control.CreateGraphics())
            {
                Size s = TextRenderer.MeasureText(dc, text, control.Font);

                // control is large enough to display the whole text
                if (s.Width <= control.Width)
                {
                    return(text);
                }

                string pre  = string.Empty;
                string mid  = text;
                string post = string.Empty;

                bool isWord   = options.FastHasFlag(EllipsisFormat.Word);
                bool isPath   = options.FastHasFlag(EllipsisFormat.Path);
                bool isStart  = options.FastHasFlag(EllipsisFormat.Start);
                bool isMiddle = options.FastHasFlag(EllipsisFormat.Middle);
                bool isEnd    = options.FastHasFlag(EllipsisFormat.End);

                // split path string into <drive><directory><filename>
                if (isPath)
                {
                    pre  = Path.GetPathRoot(text);
                    mid  = Path.GetDirectoryName(text)?.Substring(pre.Length) ?? string.Empty;
                    post = Path.GetFileName(text);
                }

                int    len = 0;
                int    seg = mid.Length;
                string fit = string.Empty;

                // find the longest string that fits into
                // the control boundaries using bisection method
                while (seg > 1)
                {
                    seg -= seg / 2;

                    int left  = len + seg;
                    int right = mid.Length;

                    if (left > right)
                    {
                        continue;
                    }

                    if (isMiddle)
                    {
                        right -= left / 2;
                        left  -= left / 2;
                    }
                    else if (isStart)
                    {
                        right -= left;
                        left   = 0;
                    }

                    // trim at a word boundary using regular expressions
                    if (isWord)
                    {
                        if (isEnd)
                        {
                            left -= __prevWord.Match(mid, 0, left).Length;
                        }
                        if (isStart)
                        {
                            right += __nextWord.Match(mid, right).Length;
                        }
                    }

                    // build and measure a candidate string with ellipsis
                    string tst = mid.Substring(0, left) + ELLIPSIS_CHARS + mid.Substring(right);

                    // restore path with <drive> and <filename>
                    if (isPath)
                    {
                        tst = Path.Combine(Path.Combine(pre, tst), post);
                    }
                    s = TextRenderer.MeasureText(dc, tst, control.Font);

                    if (s.Width > control.Width)
                    {
                        continue;
                    }

                    // candidate string fits into control boundaries, try a longer string
                    // stop when seg <= 1
                    len += seg;
                    fit  = tst;
                }

                if (len != 0)
                {
                    return(fit);
                }

                // string can't fit into control

                // "path" mode is off, just return ellipsis characters
                if (!isPath)
                {
                    return(ELLIPSIS_CHARS);
                }

                // <drive> and <directory> are empty, return <filename>
                if (pre.Length == 0 && mid.Length == 0)
                {
                    return(post);
                }

                // measure "C:\...\filename.ext"
                fit = Path.Combine(Path.Combine(pre, ELLIPSIS_CHARS), post);
                s   = TextRenderer.MeasureText(dc, fit, control.Font);

                // if still not fit then return "...\filename.ext"
                if (s.Width > control.Width)
                {
                    fit = Path.Combine(ELLIPSIS_CHARS, post);
                }
                return(fit);
            }
        }
Exemple #7
0
            /// <summary>
            /// Truncates a text string to fit within a given width by replacing trimmed text with ellipses. 
            /// </summary>
            /// <param name="text">String to be trimmed.</param>
            /// <param name="font">Font to be used to measure the text.</param>
            /// <param name="proposedWidth">The target width to accomodate the text.</param>
            /// <param name="options">Format and alignment of ellipsis.</param>
            /// <returns>This function returns text trimmed to the specified witdh.</returns>
            public static string Compact(string text, Font font, int proposedWidth, EllipsisFormat options)
            {
                if (string.IsNullOrEmpty(text))
                    return text;

                // no aligment information
                if (((EllipsisFormat.Path | EllipsisFormat.Start | EllipsisFormat.End | EllipsisFormat.Middle) & options) == 0)
                    return text;

                if (font == null)
                    throw new ArgumentNullException("font");

                Size s = TextRenderer.MeasureText(text, font);

                // control is large enough to display the whole text
                if (s.Width <= proposedWidth)
                    return text;

                string pre = "";
                string mid = text;
                string post = "";

                bool isPath = (EllipsisFormat.Path & options) != 0;

                // split path string into <drive><directory><filename>
                if (isPath)
                {
                    pre = Path.GetPathRoot(text);
                    mid = Path.GetDirectoryName(text).Substring(pre.Length);
                    post = Path.GetFileName(text);
                }

                int len = 0;
                int seg = mid.Length;
                string fit = "";

                // find the longest string that fits into
                // the control boundaries using bisection method
                while (seg > 1)
                {
                    seg -= seg / 2;

                    int left = len + seg;
                    int right = mid.Length;

                    if (left > right)
                        continue;

                    if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle)
                    {
                        right -= left / 2;
                        left -= left / 2;
                    }
                    else if ((EllipsisFormat.Start & options) != 0)
                    {
                        right -= left;
                        left = 0;
                    }

                    // trim at a word boundary using regular expressions
                    if ((EllipsisFormat.Word & options) != 0)
                    {
                        if ((EllipsisFormat.End & options) != 0)
                        {
                            left -= prevWord.Match(mid, 0, left).Length;
                        }
                        if ((EllipsisFormat.Start & options) != 0)
                        {
                            right += nextWord.Match(mid, right).Length;
                        }
                    }

                    // build and measure a candidate string with ellipsis
                    string tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right);

                    // restore path with <drive> and <filename>
                    if (isPath)
                    {
                        tst = Path.Combine(Path.Combine(pre, tst), post);
                    }
                    s = TextRenderer.MeasureText(tst, font);

                    // candidate string fits into control boundaries, try a longer string
                    // stop when seg <= 1
                    if (s.Width <= proposedWidth)
                    {
                        len += seg;
                        fit = tst;
                    }
                }

                if (len == 0) // string can't fit into control
                {
                    // "path" mode is off, just return ellipsis characters
                    if (!isPath)
                        return EllipsisChars;

                    // <directory> is empty
                    if (mid.Length == 0)
                    {
                        // <drive> is empty, return compacted <filename>
                        if (pre.Length == 0)
                            return Compact(text, font, proposedWidth, options & ~EllipsisFormat.Path);

                        // we compare ellipsis and <drive> to get the shorter
                        string testEllipsis = Path.Combine(EllipsisChars, ".");
                        testEllipsis = testEllipsis.Substring(0, testEllipsis.Length - 1);
                        if (TextRenderer.MeasureText(testEllipsis, font).Width < TextRenderer.MeasureText(pre, font).Width)
                            pre = EllipsisChars;
                    }
                    else
                    {
                        // "C:\...\filename.ext" No need to check for drive, but generates extra check
                        if (pre.Length > 0)
                        {
                            fit = Path.Combine(Path.Combine(pre, EllipsisChars), post);

                            s = TextRenderer.MeasureText(fit, font);

                            if (s.Width <= proposedWidth) return fit;
                        }

                        pre = EllipsisChars;
                    }

                    // Try "...\filename.ext" or "c:\filename.ext"
                    fit = Path.Combine(pre, post);

                    s = TextRenderer.MeasureText(fit, font);

                    // if still not fit then return "...\f...e.ext"
                    if (s.Width > proposedWidth)
                    {
                        fit = Path.Combine(pre, Compact(post, font, proposedWidth - TextRenderer.MeasureText(fit.Substring(0, fit.Length - post.Length), font).Width, options & ~EllipsisFormat.Path));
                    }
                }
                return fit;
            }
Exemple #8
0
		/// <summary>
		/// Truncates a text string to fit within a given control width by replacing trimmed text with ellipses. 
		/// </summary>
		/// <param name="text">String to be trimmed.</param>
		/// <param name="ctrl">text must fit within ctrl width.
		///	The ctrl's Font is used to measure the text string.</param>
		/// <param name="options">Format and alignment of ellipsis.</param>
		/// <returns>This function returns text trimmed to the specified witdh.</returns>
		public static string Compact(string text, Control ctrl, EllipsisFormat options)
		{
			if (string.IsNullOrEmpty(text))
				return text;

			// no aligment information
			if ((EllipsisFormat.Middle & options) == 0)
				return text;

			if (ctrl == null)
				throw new ArgumentNullException("ctrl");

			using (Graphics dc = ctrl.CreateGraphics())
			{
				Size s = TextRenderer.MeasureText(dc, text, ctrl.Font);

				// control is large enough to display the whole text
				if (s.Width <= ctrl.Width)
					return text;

				string pre = "";
				string mid = text;
				string post = "";

				bool isPath = (EllipsisFormat.Path & options) != 0;

				// split path string into <drive><directory><filename>
				if (isPath)
				{
					pre = Path.GetPathRoot(text);
					mid = Path.GetDirectoryName(text).Substring(pre.Length);
					post = Path.GetFileName(text);
				}

				int len = 0;
				int seg = mid.Length;
				string fit = "";

				// find the longest string that fits into 
				// the control boundaries using bisection method
				while (seg > 1)
				{
					seg -= seg / 2;

					int left = len + seg;
					int right = mid.Length;

					if (left > right)
						continue;

					if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle)
					{
						right -= left / 2;
						left -= left / 2;
					}
					else if ((EllipsisFormat.Start & options) != 0)
					{
						right -= left;
						left = 0;
					}

					// trim at a word boundary using regular expressions
					if ((EllipsisFormat.Word & options) != 0)
					{
						if ((EllipsisFormat.End & options) != 0)
						{
							left -= prevWord.Match(mid, 0, left).Length;
						}
						if ((EllipsisFormat.Start & options) != 0)
						{
							right += nextWord.Match(mid, right).Length;
						}
					}

					// build and measure a candidate string with ellipsis
					string tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right);
					
					// restore path with <drive> and <filename>
					if (isPath)
					{
						tst = Path.Combine(Path.Combine(pre, tst), post);
					}
					s = TextRenderer.MeasureText(dc, tst, ctrl.Font);

					// candidate string fits into control boundaries, try a longer string
					// stop when seg <= 1
					if (s.Width <= ctrl.Width)
					{
						len += seg;
						fit = tst;
					}
				}

				if (len == 0) // string can't fit into control
				{
					// "path" mode is off, just return ellipsis characters
					if (!isPath)
						return EllipsisChars;

					// <drive> and <directory> are empty, return <filename>
					if (pre.Length == 0 && mid.Length == 0)
						return post;

					// measure "C:\...\filename.ext"
					fit = Path.Combine(Path.Combine(pre, EllipsisChars), post);

					s = TextRenderer.MeasureText(dc, fit, ctrl.Font);

					// if still not fit then return "...\filename.ext"
					if (s.Width > ctrl.Width)
						fit = Path.Combine(EllipsisChars, post);
				}
				return fit;
			}
		}
Exemple #9
0
        public static string Compact(string strText, Control objControl, EllipsisFormat enuEllipsisFormat)
        {
            if (string.IsNullOrEmpty(strText))
            {
                return(strText);
            }
            if ((EllipsisFormat.Middle & enuEllipsisFormat) == 0)
            {
                return(strText);
            }
            if (objControl == null)
            {
                throw new ArgumentNullException("objControl", "A valid non-null Control is expected.");
            }

            using (Graphics objGraphics = objControl.CreateGraphics())
            {
                Size objSize = TextRenderer.MeasureText(objGraphics, strText, objControl.Font);

                if (objSize.Width <= objControl.Width)
                {
                    return(strText);
                }

                string strBegin  = string.Empty;
                string strMiddle = strText;
                string strEnd    = string.Empty;

                bool blnIsPath = (EllipsisFormat.Path & enuEllipsisFormat) != 0;
                if (blnIsPath)
                {
                    strBegin  = Path.GetPathRoot(strText);
                    strMiddle = Path.GetDirectoryName(strText).Substring(strBegin.Length);
                    strEnd    = Path.GetFileName(strText);
                }

                int    intLength  = 0;
                int    intSegment = strMiddle.Length;
                string strFit     = string.Empty;

                while (intSegment > 1)
                {
                    intSegment -= intSegment / 2;

                    int intLeft  = intLength + intSegment;
                    int intRight = strMiddle.Length;

                    if (intLeft > intRight)
                    {
                        continue;
                    }

                    if ((EllipsisFormat.Middle & enuEllipsisFormat) == EllipsisFormat.Middle)
                    {
                        intRight -= intLeft / 2;
                        intLeft  -= intLeft / 2;
                    }
                    else if ((EllipsisFormat.Start & enuEllipsisFormat) != 0)
                    {
                        intRight -= intLeft;
                        intLeft   = 0;
                    }

                    if ((EllipsisFormat.Word & enuEllipsisFormat) != 0)
                    {
                        if ((EllipsisFormat.End & enuEllipsisFormat) != 0)
                        {
                            intLeft -= objPreviousWord.Match(strMiddle, 0, intLeft).Length;
                        }
                        if ((EllipsisFormat.Start & enuEllipsisFormat) != 0)
                        {
                            intRight += objNextWord.Match(strMiddle, intRight).Length;
                        }
                    }

                    string strTest = strMiddle.Substring(0, intLeft) + EllipsisChars + strMiddle.Substring(intRight);

                    if (blnIsPath)
                    {
                        strTest = Path.Combine(Path.Combine(strBegin, strTest), strEnd);
                    }

                    objSize = TextRenderer.MeasureText(objGraphics, strTest, objControl.Font);
                    if (objSize.Width <= objControl.Width)
                    {
                        intLength += intSegment;
                        strFit     = strTest;
                    }
                }

                if (intLength == 0)
                {
                    if (blnIsPath == false)
                    {
                        return(EllipsisChars);
                    }

                    if ((strBegin.Length == 0) && (strMiddle.Length == 0))
                    {
                        return(strEnd);
                    }

                    strFit  = Path.Combine(Path.Combine(strBegin, EllipsisChars), strEnd);
                    objSize = TextRenderer.MeasureText(objGraphics, strFit, objControl.Font);

                    if (objSize.Width > objControl.Width)
                    {
                        strFit = Path.Combine(EllipsisChars, strEnd);
                    }
                }

                return(strFit);
            }
        }
        uint isChecked(EllipsisFormat fmt)
        {
            EllipsisFormat mask = fmt;

            switch (fmt)
            {
                case EllipsisFormat.None:
                case EllipsisFormat.Start:
                case EllipsisFormat.End:
                    mask = EllipsisFormat.Middle;
                    break;
            }
            return ((AutoEllipsis & mask) == fmt) ? MF_CHECKED : MF_UNCHECKED;
        }
        internal static string Ellipsis(this string text, int length, EllipsisFormat options = EllipsisFormat.Start | EllipsisFormat.None)
        {
            if (string.IsNullOrEmpty(text))
                return text;

            // no aligment information
            if ((EllipsisFormat.Middle & options) == 0)
                return text;

            if (length <= 0)
                throw new ArgumentOutOfRangeException("length");

            // control is large enough to display the whole text
            if (text.Length <= length)
                return text;

            var pre = "";
            var mid = text;
            var post = "";

            var isPath = (EllipsisFormat.Path & options) != 0;

            // split path string into <drive><directory><filename>
            if (isPath)
            {
                pre = Path.GetPathRoot(text);
                mid = Path.GetDirectoryName(text).Substring(pre.Length);
                post = Path.GetFileName(text);
            }

            var len = 0;
            var seg = mid.Length;
            var fit = "";

            // find the longest string that fits into 
            // the control boundaries using bisection method
            while (seg > 1)
            {
                seg -= seg / 2;

                int left = len + seg;
                int right = mid.Length;

                if (left > right)
                    continue;

                if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle)
                {
                    right -= left / 2;
                    left -= left / 2;
                }
                else if ((EllipsisFormat.Start & options) != 0)
                {
                    right -= left;
                    left = 0;
                }

                // trim at a word boundary using regular expressions
                if ((EllipsisFormat.Word & options) != 0)
                {
                    if ((EllipsisFormat.End & options) != 0)
                    {
                        left -= _prevWord.Match(mid, 0, left).Length;
                    }
                    if ((EllipsisFormat.Start & options) != 0)
                    {
                        right += _nextWord.Match(mid, right).Length;
                    }
                }

                // build and measure a candidate string with ellipsis
                var tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right);

                // restore path with <drive> and <filename>
                if (isPath)
                {
                    tst = Path.Combine(Path.Combine(pre, tst), post);
                }
                //s = TextRenderer.MeasureText(dc, tst, ctrl.Font);

                // candidate string fits into control boundaries, try a longer string
                // stop when seg <= 1
                if (tst.Length <= length)
                {
                    len += seg;
                    fit = tst;
                }
            }

            if (len == 0) // string can't fit into control
            {
                // "path" mode is off, just return ellipsis characters
                if (!isPath)
                    return EllipsisChars;

                // <drive> and <directory> are empty, return <filename>
                if (pre.Length == 0 && mid.Length == 0)
                    return post;

                // measure "C:\...\filename.ext"
                fit = Path.Combine(Path.Combine(pre, EllipsisChars), post);

                // if still not fit then return "...\filename.ext"
                if (fit.Length > length)
                    fit = Path.Combine(EllipsisChars, post);
            }
            return fit;
        }
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
            case WM_ENTERIDLE:
                base.WndProc(ref m);

                if (MSGF_MENU == (int)m.WParam)
                {
                    MENUBARINFO mbi = new MENUBARINFO();
                    mbi.cbSize = Marshal.SizeOf(mbi);

                    GetMenuBarInfo(m.LParam, OBJID_CLIENT, 0, ref mbi);

                    if (GetMenuState(mbi.hMenu, WM_APP + 1, MF_BYCOMMAND) == -1)
                    {
                        IntPtr hSubMenu = CreatePopupMenu();

                        if (hSubMenu != IntPtr.Zero)
                        {
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.None), WM_NONE, "None");
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.Start), WM_LEFT, "Left");
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.End), WM_RIGHT, "Right");
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.Middle), WM_CENTER, "Center");
                            AppendMenu(hSubMenu, MF_SEPARATOR, 0, null);
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.Path), WM_PATH, "Path Ellipsis");
                            AppendMenu(hSubMenu, isChecked(EllipsisFormat.Word), WM_WORD, "Word Ellipsis");

                            AppendMenu(mbi.hMenu, MF_SEPARATOR, 0, null);
                            AppendMenu(mbi.hMenu, MF_POPUP, (uint)hSubMenu, "Auto Ellipsis");
                        }
                    }
                }
                break;

            case WM_NONE:
                AutoEllipsis = EllipsisFormat.None;
                break;

            case WM_LEFT:
                AutoEllipsis = AutoEllipsis & ~EllipsisFormat.Middle | EllipsisFormat.Start;
                break;

            case WM_RIGHT:
                AutoEllipsis = AutoEllipsis & ~EllipsisFormat.Middle | EllipsisFormat.End;
                break;

            case WM_CENTER:
                AutoEllipsis |= EllipsisFormat.Middle;
                break;

            case WM_PATH:
                if ((AutoEllipsis & EllipsisFormat.Path) == 0)
                {
                    AutoEllipsis |= EllipsisFormat.Path;
                }
                else
                {
                    AutoEllipsis &= ~EllipsisFormat.Path;
                }
                break;

            case WM_WORD:
                if ((AutoEllipsis & EllipsisFormat.Word) == 0)
                {
                    AutoEllipsis |= EllipsisFormat.Word;
                }
                else
                {
                    AutoEllipsis &= ~EllipsisFormat.Word;
                }
                break;

            default:
                base.WndProc(ref m);
                break;
            }
        }