Search code examples
c#.netpinvokeaero

How to call DrawThemeTextEx in .NET


I need to write a text with glow in a Vista/seven glass window, and I'm, trying to call the API to write some text there. I have checked out a great sample in CodeProject, but the problem is that I'm using .NET 1 (please, don't ask :-)

I need to translate the following .NET 2 code to PInvoke, .NET 1 code.

// using System.Windows.Forms.VisualStyles
VisualStyleRenderer renderer = new VisualStyleRenderer(
                               VisualStyleElement.Window.Caption.Active);

// call to UxTheme.dll
DrawThemeTextEx(renderer.Handle, 
                memoryHdc, 0, 0, text, -1, (int)flags,    
                ref textBounds, ref dttOpts);

The class VisualStyleRenderer does not exist in .NET 1, so I need to get the renderer.Handle in other way.


Solution

  • Define the OpenThemeData API and DrawThemeTextEx, as well as some required structs and constants:

        [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
        private static extern IntPtr OpenThemeData(IntPtr hwnd, string pszClassList);
    
        [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
        private extern static Int32 DrawThemeTextEx(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, string pszText, int iCharCount, uint flags, ref RECT rect, ref DTTOPTS poptions);
    
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct DTTOPTS
        {
          public int dwSize;
          public int dwFlags;
          public int crText;
          public int crBorder;
          public int crShadow;
          public int iTextShadowType;
          public int ptShadowOffsetX;
          public int ptShadowOffsetY;
          public int iBorderSize;
          public int iFontPropId;
          public int iColorPropId;
          public int iStateId;
          public bool fApplyOverlay;
          public int iGlowSize;
          public IntPtr pfnDrawTextCallback;
          public IntPtr lParam;
        }
    
        // taken from vsstyle.h
        private const int WP_CAPTION = 1;
        private const int CS_ACTIVE = 1;
    

    And then, call it like this:

    IntPtr handle = OpenThemeData(IntPtr.Zero, "WINDOW");
    DrawThemeTextExt(handle, hdc, WS_CAPTION, CS_ACTIVE, ...)
    

    The WS_CAPTION and CS_ACTIVE values match .NET 2's Caption and Active respectively. Values are described here officially: Parts and States