protected virtual XplatUIWin32.RECT NCCalcSize(XplatUIWin32.RECT proposed_window_rect) { int bw = ThemeEngine.Current.ManagedWindowBorderWidth(this); if (HasBorders) { proposed_window_rect.top += TitleBarHeight + bw; proposed_window_rect.bottom -= bw; proposed_window_rect.left += bw; proposed_window_rect.right -= bw; } if (XplatUI.RequiresPositiveClientAreaSize) { // This is necessary for Linux, can't handle <= 0-sized // client areas correctly. if (proposed_window_rect.right <= proposed_window_rect.left) { proposed_window_rect.right += proposed_window_rect.left - proposed_window_rect.right + 1; } if (proposed_window_rect.top >= proposed_window_rect.bottom) { proposed_window_rect.bottom += proposed_window_rect.top - proposed_window_rect.bottom + 1; } } return(proposed_window_rect); }
static extern int Win32DrawText(IntPtr hdc, string lpStr, int nCount, ref XplatUIWin32.RECT lpRect, int wFormat);
internal static Size_ MeasureTextInternal(IDeviceContext dc, string text, Font font, Size_ proposedSize, TextFormatFlags flags, bool useMeasureString) { if (!useMeasureString && !XplatUI.RunningOnUnix) { // Tell DrawText to calculate Size_ instead of draw flags |= (TextFormatFlags)1024; // DT_CALCRECT IntPtr hdc = dc.GetHdc(); XplatUIWin32.RECT r = XplatUIWin32.RECT.FromRectangle(new Rectangle_(Point_.Empty, proposedSize)); IntPtr prevobj; if (font != null) { prevobj = SelectObject(hdc, font.ToHfont()); Win32DrawText(hdc, text, text.Length, ref r, (int)flags); prevobj = SelectObject(hdc, prevobj); DeleteObject(prevobj); } else { Win32DrawText(hdc, text, text.Length, ref r, (int)flags); } dc.ReleaseHdc(); // Really, I am just making something up here, which as far as I can tell, MS // just makes something up as well. This will require lots of tweaking to match MS. :( Size_ retval = r.ToRectangle().Size; if (retval.Width > 0 && (flags & TextFormatFlags.NoPadding) == 0) { retval.Width += 6; retval.Width += (int)retval.Height / 8; } return(retval); } else { StringFormat sf = FlagsToStringFormat(flags); Size_ retval; int proposedWidth; if (proposedSize.Width == 0) { proposedWidth = Int32.MaxValue; } else { proposedWidth = proposedSize.Width; if ((flags & TextFormatFlags.NoPadding) == 0) { proposedWidth -= 9; } } if (dc is Graphics) { retval = (dc as Graphics).MeasureString(text, font, proposedWidth, sf).ToSize(); } else { retval = TextRenderer.MeasureString(text, font, proposedWidth, sf).ToSize(); } if (retval.Width > 0 && (flags & TextFormatFlags.NoPadding) == 0) { retval.Width += 9; } return(retval); } }
internal static void DrawTextInternal(IDeviceContext dc, string text, Font font, Rectangle_ bounds, Color_ foreColor, Color_ backColor, TextFormatFlags flags, bool useDrawString) { if (dc == null) { throw new ArgumentNullException("dc"); } if (text == null || text.Length == 0) { return; } // We use MS GDI API's unless told not to, or we aren't on Windows if (!useDrawString && XplatUI.RunningOnUnix) { if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter || (flags & TextFormatFlags.Bottom) == TextFormatFlags.Bottom) { flags |= TextFormatFlags.SingleLine; } // Calculate the text bounds (there is often padding added) Rectangle_ new_bounds = PadRectangle(bounds, flags); new_bounds.Offset((int)(dc as Graphics).Transform.OffsetX, (int)(dc as Graphics).Transform.OffsetY); IntPtr hdc = IntPtr.Zero; bool clear_clip_region = false; // If we need to use the graphics clipping region, add it to our hdc if ((flags & TextFormatFlags.PreserveGraphicsClipping) == TextFormatFlags.PreserveGraphicsClipping) { Graphics graphics = (Graphics)dc; Region clip_region = graphics.Clip; if (!clip_region.IsInfinite(graphics)) { IntPtr hrgn = clip_region.GetHrgn(graphics); hdc = dc.GetHdc(); SelectClipRgn(hdc, hrgn); DeleteObject(hrgn); clear_clip_region = true; } } if (hdc == IntPtr.Zero) { hdc = dc.GetHdc(); } // Set the fore color if (foreColor != Color_.Empty) { SetTextColor(hdc, ColorTranslator.ToWin32(foreColor)); } // Set the back color if (backColor != Color_.Transparent && backColor != Color_.Empty) { SetBkMode(hdc, 2); //1-Transparent, 2-Opaque SetBkColor(hdc, ColorTranslator.ToWin32(backColor)); } else { SetBkMode(hdc, 1); //1-Transparent, 2-Opaque } XplatUIWin32.RECT r = XplatUIWin32.RECT.FromRectangle(new_bounds); IntPtr prevobj; if (font != null) { prevobj = SelectObject(hdc, font.ToHfont()); Win32DrawText(hdc, text, text.Length, ref r, (int)flags); prevobj = SelectObject(hdc, prevobj); DeleteObject(prevobj); } else { Win32DrawText(hdc, text, text.Length, ref r, (int)flags); } if (clear_clip_region) { SelectClipRgn(hdc, IntPtr.Zero); } dc.ReleaseHdc(); } // Use Graphics.DrawString as a fallback method else { Graphics g; IntPtr hdc = IntPtr.Zero; if (dc is Graphics) { g = (Graphics)dc; } else { hdc = dc.GetHdc(); g = Graphics.FromHdc(hdc); } StringFormat sf = FlagsToStringFormat(flags); Rectangle_ new_bounds = PadDrawStringRectangle(bounds, flags); g.DrawString(text, font, ThemeEngine.Current.ResPool.GetSolidBrush(foreColor), new_bounds, sf); if (!(dc is Graphics)) { g.Dispose(); dc.ReleaseHdc(); } } }