/// <summary> /// /// </summary> /// <param name="hdc"></param> /// <param name="fontDescription"></param> /// <param name="orientation"></param> /// <param name="text"></param> /// <param name="rectangle"></param> /// <param name="contentAlignment"></param> /// <param name="rect"></param> internal static void PrintRotatedText(IntPtr hdc, FontDescription fontDescription, int orientation, string text, Rectangle rectangle, ContentAlignment contentAlignment, NativeWindowCommon.RECT rect, bool rightToLeft) { IntPtr hFont; Point point; // get the original font and its LOGFONT NativeWindowCommon.LOGFONT logfont = fontDescription.LogFont; // Set the rotation angle logfont.lfEscapement = logfont.lfOrientation = orientation; // create the new, rotated font hFont = NativeWindowCommon.CreateFontIndirect(logfont); NativeWindowCommon.SelectObject(hdc, hFont); point = CalculateStartCoordinates(hdc, rectangle, orientation, text, contentAlignment); uint fuOptions = NativeWindowCommon.ETO_CLIPPED; if (rightToLeft) { fuOptions = NativeWindowCommon.ETO_RTLREADING; } NativeWindowCommon.ExtTextOut(hdc, point.X, point.Y, fuOptions, ref rect, text, (uint)text.Length, null); NativeWindowCommon.DeleteObject(hFont); }
/// <summary> /// Get font text metrics points. /// </summary> /// <param name="g"></param> /// <param name="hFont"></param> /// <param name="fontName"></param> /// <param name="fontSize"></param> /// <param name="retPoint"></param> public static void GetTextMetrics(Graphics g, IntPtr hFont, string fontName, int fontSize, out PointF retPoint) { retPoint = new PointF(); int dpiX = (int)g.DpiX; // create the handle of DC IntPtr hdc = g.GetHdc(); IntPtr hFontOld = (IntPtr)NativeWindowCommon.SelectObject(hdc, hFont); NativeWindowCommon.TEXTMETRIC tm; NativeWindowCommon.GetTextMetrics(hdc, out tm); retPoint.X = tm.tmAveCharWidth; retPoint.Y = tm.tmHeight; if (SpecialTextSizeFactoring && dpiX == 120) //defect 117706 { //please, create an infrastructure for this if you need to add another font ... if (fontName == "Microsoft Sans Serif" && fontSize == 8 && retPoint.X == 6) { //For 100% resolution we got tm.tmAveCharWidth = 5 (average char width) //For 125% resolution we got tm.tmAveCharWidth = 6 and in prepareUOMConversion we use this data as factor for calculating all magic sizes for all controls and form. //So, the difference between 125% resolution and 100% resolution is 6/5 = 1.2, i.e 120% which is not enough //Here we manually set factor retPoint.X = 5 * 1.275F; } } NativeWindowCommon.SelectObject(hdc, hFontOld); // release the resources g.ReleaseHdc(hdc); }
/// <summary> /// Draw the text. /// </summary> /// <param name="hdc"></param> /// <param name="color"></param> /// <param name="rect"></param> /// <param name="topOffset"></param> /// <param name="orientation"></param> /// <param name="fontDescription"></param> /// <param name="text"></param> /// <param name="contentAlignment"></param> /// <param name="flags"></param> public static void DrawText(IntPtr hdc, Color color, Rectangle rect, int topOffset, int orientation, FontDescription fontDescription, String text, ContentAlignment contentAlignment, int flags, bool rightToLeft) { NativeWindowCommon.SetBkMode(hdc, NativeWindowCommon.TRANSPARENT); NativeWindowCommon.SetTextColor(hdc, ColorTranslator.ToWin32(color)); #if !PocketPC // QCR #439182 & 430913: the font is used for a control before even being initialized. // TODO: We need a better fix that avoids calling get_Font() for logical controls that are not initialized properly. if (fontDescription == null) { fontDescription = new FontDescription(Control.DefaultFont); } #endif NativeWindowCommon.RECT rc = new NativeWindowCommon.RECT(); rc.left = rect.Left; rc.right = rect.Right; rc.top = rect.Top + topOffset; rc.bottom = rect.Bottom; #if !PocketPC if (orientation != 0) { PrintRotatedText(hdc, fontDescription, orientation, text, rect, contentAlignment, rc, rightToLeft); } else #endif { IntPtr hFont = fontDescription.FontHandle; NativeWindowCommon.SelectObject(hdc, hFont); NativeWindowCommon.DrawText(hdc, text, text.Length, ref rc, flags); } }
/// <summary>return the size of the string according to the font</summary> /// <param name="font"></param> /// <param name="str"></param> /// <param name="control"></param> /// <returns></returns> public static Size GetTextExt(Font font, String str, Control control) { Size size = new Size(); if (control != null && str != null) { #if PocketPC Form form = (Form)((control is Form)? control : control.TopLevelControl); using (Graphics g = form.CreateGraphics()) { // Mobile does not support GetTextExtentPoint32 or similar functions SizeF sizef = g.MeasureString(str, font); size.Width = (int)Math.Ceiling(sizef.Width); size.Height = (int)Math.Ceiling(sizef.Height); } #else using (Graphics g = control.CreateGraphics()) { IntPtr hdc = g.GetHdc(); IntPtr hFont = FontHandlesCache.GetInstance().Get(font).FontHandle; IntPtr hFontOld = (IntPtr)NativeWindowCommon.SelectObject(hdc, hFont); NativeWindowCommon.SIZE nativeSize = new NativeWindowCommon.SIZE(); NativeWindowCommon.GetTextExtentPoint32(hdc, str, str.Length, out nativeSize); size.Width = nativeSize.cx; //(int)Math.Ceiling(size.cx); size.Height = nativeSize.cy; //(int)Math.Ceiling(size.cy); NativeWindowCommon.SelectObject(hdc, hFontOld); g.ReleaseHdc(hdc); } #endif } return(size); }
/// <summary> /// Draw Header section filter /// </summary> /// <param name="hdc"></param> /// <param name="rct"></param> /// <param name="g"></param> public void DrawFilter(IntPtr hdc, NativeWindowCommon.RECT rct) { //Filter line drawing int x = rct.right - FILTER_WIDTH; int bottomY = 0; Header.HeaderRenderer.DrawLine(hdc, new Point(x, bottomY), new Point(x, Header.FilterHeight)); //Filter highlight drawing NativeWindowCommon.RECT rectHighlight = new NativeWindowCommon.RECT() { bottom = Header.FilterHeight, top = 0, left = rct.right - FILTER_WIDTH + 1, right = rct.right + 1 }; if ((FilterColor != Color.Empty) && !Header.OnSectionResize) { if (Header.TitleColor != Color.Empty) { Header.HighlightBrush = NativeWindowCommon.CreateSolidBrush(ColorTranslator.ToWin32(FilterColor)); } else { Header.HighlightBrush = NativeWindowCommon.CreateSolidBrush(ColorTranslator.ToWin32(Color.FromArgb(255, 149, 202, 255))); } NativeWindowCommon.FillRect(hdc, ref rectHighlight, Header.HighlightBrush); NativeWindowCommon.DeleteObject(Header.HighlightBrush); } int filterWidthIcon = FILTER_WIDTH / 3; //Filter arrow drawing NativeWindowCommon.POINT[] points = new NativeWindowCommon.POINT[3]; //right points[0].x = rct.right - filterWidthIcon; points[0].y = rct.top + (rct.bottom - rct.top) / 2 - 2; // center point points[1].x = rct.right - FILTER_WIDTH / 2; points[1].y = points[0].y + filterWidthIcon / 2; // left point points[2].x = points[0].x - filterWidthIcon; points[2].y = points[0].y; NativeWindowCommon.SelectObject(hdc, Header.FilterBrush); NativeWindowCommon.SelectObject(hdc, Header.FilterPen); NativeWindowCommon.Polygon(hdc, points, 3); }
/// <summary> /// Get font text metrics points. /// </summary> /// <param name="hFont"></param> /// <param name="str"></param> /// <param name="control"></param> /// <returns></returns> public static Size GetTextExt(IntPtr hFont, string str, Control control) { Size size = new Size(); using (Graphics g = control.CreateGraphics()) { IntPtr hdc = g.GetHdc(); IntPtr hFontOld = (IntPtr)NativeWindowCommon.SelectObject(hdc, hFont); NativeWindowCommon.SIZE nativeSize = new NativeWindowCommon.SIZE(); NativeWindowCommon.GetTextExtentPoint32(hdc, str, str.Length, out nativeSize); size.Width = nativeSize.cx; size.Height = nativeSize.cy; NativeWindowCommon.SelectObject(hdc, hFontOld); g.ReleaseHdc(hdc); } return(size); }
/// <summary> /// calc text rect /// use ContentAlignment.MiddleRight for the calculation because if we use ContentAlignment.MiddleCenter /// then GuiUtils.CalcTextRect() returns wrong results. The problem is that the height returned by GuiUtils.CalcTextRect() /// will be of a single line always. /// /// </summary> /// <param name="g"></param> /// <param name="rect"></param> /// <param name="font"></param> /// <param name="text"></param> /// <param name="flags"></param> /// <param name="retCalcTextRect"></param> public static void CalcTextRect(Graphics g, Rectangle rect, FontDescription font, String text, int flags, out NativeWindowCommon.RECT retCalcTextRect) { IntPtr hdc1; IntPtr hFont1; hdc1 = g.GetHdc(); hFont1 = font.FontHandle; NativeWindowCommon.SelectObject(hdc1, hFont1); retCalcTextRect = new NativeWindowCommon.RECT(); retCalcTextRect.left = rect.Left; retCalcTextRect.right = rect.Right; retCalcTextRect.top = rect.Top; retCalcTextRect.bottom = rect.Bottom; int calcRectFlags = (int)(TextFormatFlags)flags | 0x400; // TextFormatFlags.CalcRect == 0x400 == DT_CALCRECT NativeWindowCommon.DrawText(hdc1, text, text.Length, ref retCalcTextRect, calcRectFlags); g.ReleaseHdc(hdc1); }
/// <summary> /// draw line /// </summary> /// <param name="hdc"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="pen"></param> public void DrawLine(IntPtr hdc, Point start, Point end, IntPtr pen) { NativeWindowCommon.MoveToEx(hdc, start.X, start.Y, IntPtr.Zero); NativeWindowCommon.SelectObject(hdc, pen); NativeWindowCommon.LineTo(hdc, end.X, end.Y); }
/// <summary> /// draw header section title /// </summary> /// <param name="hdc"></param> /// <param name="rc"></param> internal void DrawTitle(IntPtr hdc, NativeWindowCommon.RECT rc, int index, bool supportsMultilineText, bool addEndEllipsesFlag, bool rightToLeftLayout) { Header.HeaderRenderer.GetTitleTextRect(index, ref rc); using (Graphics gr = Graphics.FromHdc(hdc)) { //draw sort icon if (SortMark != HeaderSectionSortMarks.Non && !HasFilter) { int iconWindth = SortIconWidth(); DrawSortMark(hdc, rc, gr); rc.right -= iconWindth + Header.SORT_ICON_LEFT_RIGHT_MARGIN; } if (HasFilter) { rc.right -= HeaderSection.FILTER_WIDTH + Header.SORT_ICON_LEFT_RIGHT_MARGIN; } //draw ... in the end of text if width is too short int width = rc.right - rc.left; int format = NativeWindowCommon.DT_EDITCONTROL | NativeWindowCommon.DT_EXTERNALLEADING; if (supportsMultilineText) { format |= NativeWindowCommon.DT_WORDBREAK; } StringBuilder stringBuilder = new StringBuilder(Text); if (addEndEllipsesFlag) { //for windows CE && orientated fonts DT_END_ELLIPSIS style is not supported //http://support.microsoft.com/kb/249678 format |= NativeWindowCommon.DT_END_ELLIPSIS; } if (Environment.OSVersion.Platform == PlatformID.WinCE) { if (Text.IndexOf("\n") != -1) { SizeF size = gr.MeasureString(text, Font); int cur, len = cur = text.Length; while (size.Width > width && cur > 1) { cur = --len; stringBuilder.Length = len; while (cur > 1 && len - cur < 3) { stringBuilder[--cur] = '.'; } size = gr.MeasureString(stringBuilder.ToString(), Font); } } } NativeWindowCommon.SetBkMode(hdc, NativeWindowCommon.TRANSPARENT); NativeWindowCommon.SetTextColor(hdc, ColorTranslator.ToWin32(Color)); #if !PocketPC if (FontOrientation != 0) { Rectangle rectangle = new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); ControlRenderer.PrintRotatedText(hdc, FontDescription, FontOrientation, stringBuilder.ToString(), rectangle, ContentAlignment, rc, rightToLeftLayout); } else #endif { //text flags are exactly the same as DrawText DT_*** flags format |= (int)Utils.ContentAlignment2TextFlags(ContentAlignment); if (isSingleLine()) { format |= NativeWindowCommon.DT_SINGLELINE; } IntPtr hFont = FontDescription.FontHandle; NativeWindowCommon.SelectObject(hdc, hFont); NativeWindowCommon.DrawText(hdc, stringBuilder.ToString(), stringBuilder.Length, ref rc, format); } #if !PocketPC //Set the rectangle back if (HasFilter) { rc.right += HeaderSection.FILTER_WIDTH + Header.SORT_ICON_LEFT_RIGHT_MARGIN; DrawFilter(hdc, rc); } #endif } }
/// <summary> /// drow sort marking on the column /// </summary> /// <param name="hdc"></param> /// <param name="rc"></param> /// <param name="gr"></param> void DrawSortMark(IntPtr hdc, NativeWindowCommon.RECT rc, Graphics gr) { int iconWidth = SortIconWidth(); int topBottomMargin = (this.Header.Height - iconWidth) / 2; int iconHeight = SortIconHeight(); NativeWindowCommon.POINT[] points = new NativeWindowCommon.POINT[3]; if (SortMark == HeaderSectionSortMarks.Up) { points[0].x = rc.right - Header.SORT_ICON_LEFT_RIGHT_MARGIN; points[0].y = (rc.bottom + iconHeight) / 2; // center point points[1].x = points[0].x - iconWidth / 2; points[1].y = points[0].y - iconHeight; // left point points[2].x = points[0].x - iconWidth; points[2].y = points[0].y; } else if (SortMark == HeaderSectionSortMarks.Down) { //right points[0].x = rc.right - Header.SORT_ICON_LEFT_RIGHT_MARGIN; points[0].y = (rc.bottom - iconHeight) / 2; // center point points[1].x = points[0].x - iconWidth / 2; points[1].y = points[0].y + iconHeight; // left point points[2].x = points[0].x - iconWidth; points[2].y = points[0].y; } #if !PocketPC if (Application.RenderWithVisualStyles) { //draw XP style sort triangle NativeWindowCommon.SelectObject(hdc, Header.SortBrush); NativeWindowCommon.SelectObject(hdc, Header.SortPen); NativeWindowCommon.Polygon(hdc, points, 3); } else #endif { //draw windows 2000 style sort triangle Point[] points1 = new Point[3] { new Point(points[0].x, points[0].y), new Point(points[1].x, points[1].y), new Point(points[2].x, points[2].y) }; NativeWindowCommon.MoveToEx(hdc, points1[0].X, points1[0].Y, IntPtr.Zero); NativeWindowCommon.SelectObject(hdc, Header.WhitePen); NativeWindowCommon.LineTo(hdc, points1[1].X, points1[1].Y); NativeWindowCommon.SelectObject(hdc, Header.ButtonShadowPen); NativeWindowCommon.LineTo(hdc, points1[2].X, points1[2].Y); if (SortMark == HeaderSectionSortMarks.Up) { NativeWindowCommon.SelectObject(hdc, Header.WhitePen); } else { NativeWindowCommon.SelectObject(hdc, Header.ButtonShadowPen); } NativeWindowCommon.LineTo(hdc, points1[0].X, points1[0].Y); } }