/// <summary> /// Draw text without a glowing background, for use on a composition element. /// </summary> /// <param name="g">Graphics reference.</param> /// <param name="text">Text to be drawn.</param> /// <param name="font">Font to use for text.</param> /// <param name="bounds">Bounding area for the text.</param> /// <param name="state">State of the source element.</param> /// <param name="color"><see cref="Color"/> of the text.</param> /// <param name="copyBackground">Should existing background be copied into the bitmap.</param> /// <param name="sf">StringFormat of the memento.</param> public static void DrawCompositionText(Graphics g, string text, Font font, Rectangle bounds, PaletteState state, Color color, bool copyBackground, StringFormat sf) { // Get the hDC for the graphics instance and create a memory DC IntPtr gDC = g.GetHdc(); try { IntPtr mDC = PI.CreateCompatibleDC(gDC); PI.BITMAPINFO bmi = new() { biWidth = bounds.Width, biHeight = -bounds.Height, biCompression = 0, biBitCount = 32, biPlanes = 1 }; bmi.biSize = (uint)Marshal.SizeOf(bmi); // Create a device independent bitmap and select into the memory DC IntPtr hDIB = PI.CreateDIBSection(gDC, ref bmi, 0, out _, IntPtr.Zero, 0); PI.SelectObject(mDC, hDIB); if (copyBackground) { // Copy existing background into the bitmap PI.BitBlt(mDC, 0, 0, bounds.Width, bounds.Height, gDC, bounds.X, bounds.Y, 0x00CC0020); } // Select the font for use when drawing IntPtr hFont = font.ToHfont(); PI.SelectObject(mDC, hFont); // Get renderer for the correct state VisualStyleRenderer renderer = new(state == PaletteState.Normal ? VisualStyleElement.Window.Caption.Active : VisualStyleElement.Window.Caption.Inactive); // Create structures needed for theme drawing call PI.RECT textBounds = new() { left = 0, top = 0, right = bounds.Right - bounds.Left, bottom = bounds.Bottom - bounds.Top }; PI.DTTOPTS dttOpts = new() { dwSize = Marshal.SizeOf(typeof(PI.DTTOPTS)), dwFlags = PI.DTT_COMPOSITED | PI.DTT_TEXTCOLOR, crText = ColorTranslator.ToWin32(color) }; // Always draw text centered TextFormatFlags textFormat = TextFormatFlags.SingleLine | TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; ////Seb | TextFormatFlags.EndEllipsis; // Perform actual drawing //PI.DrawThemeTextEx(renderer.Handle, // mDC, 0, 0, // text, -1, (int)StringFormatToFlags(sf), // ref textBounds, ref dttOpts); PI.DrawThemeTextEx(renderer.Handle, mDC, 0, 0, text, -1, (int)textFormat, ref textBounds, ref dttOpts); // Copy to foreground PI.BitBlt(gDC, bounds.Left, bounds.Top, bounds.Width, bounds.Height, mDC, 0, 0, 0x00CC0020); // Dispose of allocated objects PI.DeleteObject(hFont); PI.DeleteObject(hDIB); PI.DeleteDC(mDC); } catch { // ignored } finally { // Must remember to release the hDC g.ReleaseHdc(gDC); } }
private void UpdateLayeredWindow(Rectangle rect) { // Cache the latest size and location _showRect = rect; // Must have a visible rectangle to render if ((rect.Width > 0) && (rect.Height > 0)) { // Draw onto a bitmap that is then used as the window display Bitmap memoryBitmap = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(memoryBitmap)) { // Perform actual painting onto the bitmap Rectangle area = new Rectangle(0, 0, rect.Width, rect.Height); using (RenderContext context = new RenderContext(null, g, area, _renderer)) { _renderer.RenderGlyph.DrawDragDropDockingGlyph(context, _dragData, _paletteDragDrop, PaletteDragFeedback.Rounded); } // Get hold of the screen DC IntPtr hDC = PI.GetDC(IntPtr.Zero); // Create a memory based DC compatible with the screen DC IntPtr memoryDC = PI.CreateCompatibleDC(hDC); // Get access to the bitmap handle contained in the Bitmap object IntPtr hBitmap = memoryBitmap.GetHbitmap(Color.FromArgb(0)); // Select this bitmap for updating the window presentation IntPtr oldBitmap = PI.SelectObject(memoryDC, hBitmap); // New window size PI.SIZE ulwsize; ulwsize.cx = rect.Width; ulwsize.cy = rect.Height; // New window position PI.POINT topPos = new PI.POINT(rect.Left, rect.Top); // Offset into memory bitmap is always zero PI.POINT pointSource = new PI.POINT(0, 0); // We want to make the entire bitmap opaque PI.BLENDFUNCTION blend = new PI.BLENDFUNCTION { BlendOp = PI.AC_SRC_OVER, BlendFlags = 0, SourceConstantAlpha = 255, AlphaFormat = PI.AC_SRC_ALPHA }; // Tell operating system to use our bitmap for painting PI.UpdateLayeredWindow(Handle, hDC, ref topPos, ref ulwsize, memoryDC, ref pointSource, 0, ref blend, PI.ULW_ALPHA); // Put back the old bitmap handle PI.SelectObject(memoryDC, oldBitmap); // Cleanup resources PI.ReleaseDC(IntPtr.Zero, hDC); PI.DeleteObject(hBitmap); PI.DeleteDC(memoryDC); } } }