{******************************************************************************} { } { Visual Styles (Themes) API interface Unit for Object Pascal } { } { Portions created by Microsoft are Copyright (C) 1995-2001 Microsoft } { Corporation. All Rights Reserved. } { } { The original file is: uxtheme.h, released June 2001. The original Pascal } { code is: UxTheme.pas, released July 2001. The initial developer of the } { Pascal code is Marcel van Brakel (brakelm@chello.nl). } { } { Portions created by Marcel van Brakel are Copyright (C) 1999-2001 } { Marcel van Brakel. All Rights Reserved. } { } { Portions created by Mike Lischke are Copyright (C) 1999-2002 } { Mike Lischke. All Rights Reserved. } { } { Obtained through: Joint Endeavour of Delphi Innovators (Project JEDI) } { } { You may retrieve the latest version of this file at the Project JEDI home } { page, located at http://delphi-jedi.org or my personal homepage located at } { http://members.chello.nl/m.vanbrakel2 } { } { The contents of this file are used with permission, subject to the Mozilla } { Public License Version 1.1 (the "License"); you may not use this file except } { in compliance with the License. You may obtain a copy of the License at } { http://www.mozilla.org/MPL/MPL-1.1.html } { } { Software distributed under the License is distributed on an "AS IS" basis, } { WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for } { the specific language governing rights and limitations under the License. } { } { Alternatively, the contents of this file may be used under the terms of the } { GNU Lesser General Public License (the "LGPL License"), in which case the } { provisions of the LGPL License are applicable instead of those above. } { If you wish to allow use of your version of this file only under the terms } { of the LGPL License and not to allow others to use your version of this file } { under the MPL, indicate your decision by deleting the provisions above and } { replace them with the notice and other provisions required by the LGPL } { License. If you do not delete the provisions above, a recipient may use } { your version of this file under either the MPL or the LGPL License. } { } { For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html } { } {******************************************************************************} { Simplified by Martijn Laan for Inno Setup Cannot be replaced by Delphi's built in Winapi.UxTheme.pas even though it has the same functions: see the comment at the bottom of this file. For this reason this unit has been renamed to NewUxTheme. Additionally this unit includes SetPreferredAppMode, FlushMenuThemes, and WM_UAHDRAWMENU(ITEM). } unit NewUxTheme; {$ALIGN ON} {$MINENUMSIZE 4} interface uses Windows; procedure FreeThemeLibrary; function InitThemeLibrary: Boolean; function UseThemes: Boolean; const WM_THEMECHANGED = $031A; type HIMAGELIST = THANDLE; // TODO TEMPORARY HTHEME = THANDLE; // handle to a section of theme data for class //---------------------------------------------------------------------------------------------------------------------- // NOTE: PartId's and StateId's used in the theme API are defined in the // hdr file using the TM_PART and TM_STATE macros. For // example, "TM_PART(BP, PUSHBUTTON)" defines the PartId "BP_PUSHBUTTON". //---------------------------------------------------------------------------------------------------------------------- // OpenThemeData() - Open the theme data for the specified HWND and // semi-colon separated list of class names. // // OpenThemeData() will try each class name, one at // a time, and use the first matching theme info // found. If a match is found, a theme handle // to the data is returned. If no match is found, // a "NULL" handle is returned. // // When the window is destroyed or a WM_THEMECHANGED // msg is received, "CloseThemeData()" should be // called to close the theme handle. // // hwnd - window handle of the control/window to be themed // // pszClassList - class name (or list of names) to match to theme data // section. if the list contains more than one name, // the names are tested one at a time for a match. // If a match is found, OpenThemeData() returns a // theme handle associated with the matching class. // This param is a list (instead of just a single // class name) to provide the class an opportunity // to get the "best" match between the class and // the current theme. For example, a button might // pass L"OkButton, Button" if its ID=ID_OK. If // the current theme has an entry for OkButton, // that will be used. Otherwise, we fall back on // the normal Button entry. //---------------------------------------------------------------------------------------------------------------------- var OpenThemeData: function(hwnd: HWND; pszClassList: LPCWSTR): HTHEME; stdcall; //---------------------------------------------------------------------------------------------------------------------- // CloseTHemeData() - closes the theme data handle. This should be done // when the window being themed is destroyed or // whenever a WM_THEMECHANGED msg is received // (followed by an attempt to create a new Theme data // handle). // // hTheme - open theme data handle (returned from prior call // to OpenThemeData() API). //---------------------------------------------------------------------------------------------------------------------- var CloseThemeData: function(hTheme: HTHEME): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // functions for basic drawing support //---------------------------------------------------------------------------------------------------------------------- // The following methods are the theme-aware drawing services. // Controls/Windows are defined in drawable "parts" by their author: a // parent part and 0 or more child parts. Each of the parts can be // described in "states" (ex: disabled, hot, pressed). //---------------------------------------------------------------------------------------------------------------------- // For the list of all themed classes and the definition of all // parts and states, see the file "tmschmea.h". //---------------------------------------------------------------------------------------------------------------------- // Each of the below methods takes a "iPartId" param to specify the // part and a "iStateId" to specify the state of the part. // "iStateId=0" refers to the root part. "iPartId" = "0" refers to // the root class. //---------------------------------------------------------------------------------------------------------------------- // Note: draw operations are always scaled to fit (and not to exceed) // the specified "Rect". //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // DrawThemeBackground() // - draws the theme-specified border and fill for // the "iPartId" and "iStateId". This could be // based on a bitmap file, a border and fill, or // other image description. // // hTheme - theme data handle // hdc - HDC to draw into // iPartId - part number to draw // iStateId - state number (of the part) to draw // pRect - defines the size/location of the part // pClipRect - optional clipping rect (don't draw outside it) //---------------------------------------------------------------------------------------------------------------------- var DrawThemeBackground: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pRect: TRect; pClipRect: PRECT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- //----- DrawThemeText() flags ---- const DTT_GRAYED = $1; // draw a grayed-out string //---------------------------------------------------------------------------------------------------------------------- // DrawThemeText() - draws the text using the theme-specified // color and font for the "iPartId" and // "iStateId". // // hTheme - theme data handle // hdc - HDC to draw into // iPartId - part number to draw // iStateId - state number (of the part) to draw // pszText - actual text to draw // dwCharCount - number of chars to draw (-1 for all) // dwTextFlags - same as DrawText() "uFormat" param // dwTextFlags2 - additional drawing options // pRect - defines the size/location of the part //---------------------------------------------------------------------------------------------------------------------- var DrawThemeText: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; pszText: LPCWSTR; iCharCount: Integer; dwTextFlags, dwTextFlags2: DWORD; const pRect: TRect): HRESULT; stdcall; type DTT_CALLBACK_PROC = function(hdc: HDC; pszText: LPWSTR; cchText: Integer; prc: PRect; dwFlags: UINT; lParam: LPARAM): Integer; stdcall; TFNDTTCallbackProc = DTT_CALLBACK_PROC; DTTOPTS = record dwSize: DWORD; // size of the struct dwFlags: DWORD; // which options have been specified crText: COLORREF; // color to use for text fill crBorder: COLORREF; // color to use for text outline crShadow: COLORREF; // color to use for text shadow iTextShadowType: Integer; // TST_SINGLE or TST_CONTINUOUS ptShadowOffset: TPoint; // where shadow is drawn (relative to text) iBorderSize: Integer; // Border radius around text iFontPropId: Integer; // Font property to use for the text instead of TMT_FONT iColorPropId: Integer; // Color property to use for the text instead of TMT_TEXTCOLOR iStateId: Integer; // Alternate state id fApplyOverlay: BOOL; // Overlay text on top of any text effect? iGlowSize: Integer; // Glow radious around text pfnDrawTextCallback: TFNDTTCallbackProc;// Callback for DrawText lParam: LPARAM; // Parameter for callback end; TDTTOpts = DTTOPTS; var DrawThemeTextEx: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; pszText: LPCWSTR; iCharCount: Integer; dwTextFlags: DWORD; pRect: PRect; var pOptions: TDTTOpts): HResult; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeBackgroundContentRect() // - gets the size of the content for the theme-defined // background. This is usually the area inside // the borders or Margins. // // hTheme - theme data handle // hdc - (optional) device content to be used for drawing // iPartId - part number to draw // iStateId - state number (of the part) to draw // pBoundingRect - the outer RECT of the part being drawn // pContentRect - RECT to receive the content area //---------------------------------------------------------------------------------------------------------------------- var GetThemeBackgroundContentRect: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pBoundingRect: TRect; pContentRect: PRECT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeBackgroundExtent() - calculates the size/location of the theme- // specified background based on the // "pContentRect". // // hTheme - theme data handle // hdc - (optional) device content to be used for drawing // iPartId - part number to draw // iStateId - state number (of the part) to draw // pContentRect - RECT that defines the content area // pBoundingRect - RECT to receive the overall size/location of part //---------------------------------------------------------------------------------------------------------------------- var GetThemeBackgroundExtent: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pContentRect: TRect; var pExtentRect: TRect): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- type THEMESIZE = ( TS_MIN, // minimum size TS_TRUE, // size without stretching TS_DRAW // size that theme mgr will use to draw part ); TThemeSize = THEMESIZE; //---------------------------------------------------------------------------------------------------------------------- // GetThemePartSize() - returns the specified size of the theme part // // hTheme - theme data handle // hdc - HDC to select font into & measure against // iPartId - part number to retrieve size for // iStateId - state number (of the part) // prc - (optional) rect for part drawing destination // eSize - the type of size to be retreived // psz - receives the specified size of the part //---------------------------------------------------------------------------------------------------------------------- var GetThemePartSize: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; prc: PRECT; eSize: THEMESIZE; var psz: TSize): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeTextExtent() - calculates the size/location of the specified // text when rendered in the Theme Font. // // hTheme - theme data handle // hdc - HDC to select font & measure into // iPartId - part number to draw // iStateId - state number (of the part) // pszText - the text to be measured // dwCharCount - number of chars to draw (-1 for all) // dwTextFlags - same as DrawText() "uFormat" param // pszBoundingRect - optional: to control layout of text // pszExtentRect - receives the RECT for text size/location //---------------------------------------------------------------------------------------------------------------------- var GetThemeTextExtent: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; pszText: LPCWSTR; iCharCount: Integer; dwTextFlags: DWORD; pBoundingRect: PRECT; var pExtentRect: TRect): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeTextMetrics() // - returns info about the theme-specified font // for the part/state passed in. // // hTheme - theme data handle // hdc - optional: HDC for screen context // iPartId - part number to draw // iStateId - state number (of the part) // ptm - receives the font info //---------------------------------------------------------------------------------------------------------------------- var GetThemeTextMetrics: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; var ptm: TTEXTMETRIC): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeBackgroundRegion() // - computes the region for a regular or partially // transparent theme-specified background that is // bound by the specified "pRect". // If the rectangle is empty, sets the HRGN to NULL // and return S_FALSE. // // hTheme - theme data handle // hdc - optional HDC to draw into (DPI scaling) // iPartId - part number to draw // iStateId - state number (of the part) // pRect - the RECT used to draw the part // pRegion - receives handle to calculated region //---------------------------------------------------------------------------------------------------------------------- var GetThemeBackgroundRegion: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pRect: TRect; var pRegion: HRGN): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- //----- HitTestThemeBackground, HitTestThemeBackgroundRegion flags ---- // Theme background segment hit test flag (default). possible return values are: // HTCLIENT: hit test succeeded in the middle background segment // HTTOP, HTLEFT, HTTOPLEFT, etc: // hit test succeeded in the the respective theme background segment. const HTTB_BACKGROUNDSEG = $0000; // Fixed border hit test option. possible return values are: // HTCLIENT: hit test succeeded in the middle background segment // HTBORDER: hit test succeeded in any other background segment HTTB_FIXEDBORDER = $0002; // Return code may be either HTCLIENT or HTBORDER. // Caption hit test option. Possible return values are: // HTCAPTION: hit test succeeded in the top, top left, or top right background segments // HTNOWHERE or another return code, depending on absence or presence of accompanying flags, resp. HTTB_CAPTION = $0004; // Resizing border hit test flags. Possible return values are: // HTCLIENT: hit test succeeded in middle background segment // HTTOP, HTTOPLEFT, HTLEFT, HTRIGHT, etc: hit test succeeded in the respective system resizing zone // HTBORDER: hit test failed in middle segment and resizing zones, but succeeded in a background border segment HTTB_RESIZINGBORDER_LEFT = $0010; // Hit test left resizing border, HTTB_RESIZINGBORDER_TOP = $0020; // Hit test top resizing border HTTB_RESIZINGBORDER_RIGHT = $0040; // Hit test right resizing border HTTB_RESIZINGBORDER_BOTTOM = $0080; // Hit test bottom resizing border HTTB_RESIZINGBORDER = (HTTB_RESIZINGBORDER_LEFT or HTTB_RESIZINGBORDER_TOP or HTTB_RESIZINGBORDER_RIGHT or HTTB_RESIZINGBORDER_BOTTOM); // Resizing border is specified as a template, not just window edges. // This option is mutually exclusive with HTTB_SYSTEMSIZINGWIDTH; HTTB_SIZINGTEMPLATE takes precedence HTTB_SIZINGTEMPLATE = $0100; // Use system resizing border width rather than theme content margins. // This option is mutually exclusive with HTTB_SIZINGTEMPLATE, which takes precedence. HTTB_SYSTEMSIZINGMARGINS = $0200; //---------------------------------------------------------------------------------------------------------------------- // HitTestThemeBackground() // - returns a HitTestCode (a subset of the values // returned by WM_NCHITTEST) for the point "ptTest" // within the theme-specified background // (bound by pRect). "pRect" and "ptTest" should // both be in the same coordinate system // (client, screen, etc). // // hTheme - theme data handle // hdc - HDC to draw into // iPartId - part number to test against // iStateId - state number (of the part) // pRect - the RECT used to draw the part // hrgn - optional region to use; must be in same coordinates as // - pRect and pTest. // ptTest - the hit point to be tested // dwOptions - HTTB_xxx constants // pwHitTestCode - receives the returned hit test code - one of: // // HTNOWHERE, HTLEFT, HTTOPLEFT, HTBOTTOMLEFT, // HTRIGHT, HTTOPRIGHT, HTBOTTOMRIGHT, // HTTOP, HTBOTTOM, HTCLIENT //---------------------------------------------------------------------------------------------------------------------- var HitTestThemeBackground: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; dwOptions: DWORD; const pRect: TRect; hrgn: HRGN; ptTest: TPoint; var pwHitTestCode: WORD): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // DrawThemeEdge() - Similar to the DrawEdge() API, but uses part colors // and is high-DPI aware // hTheme - theme data handle // hdc - HDC to draw into // iPartId - part number to draw // iStateId - state number of part // pDestRect - the RECT used to draw the line(s) // uEdge - Same as DrawEdge() API // uFlags - Same as DrawEdge() API // pContentRect - Receives the interior rect if (uFlags & BF_ADJUST) //---------------------------------------------------------------------------------------------------------------------- var DrawThemeEdge: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pDestRect: TRect; uEdge, uFlags: UINT; pContentRect: PRECT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // DrawThemeIcon() - draws an image within an imagelist based on // a (possible) theme-defined effect. // // hTheme - theme data handle // hdc - HDC to draw into // iPartId - part number to draw // iStateId - state number of part // pRect - the RECT to draw the image within // himl - handle to IMAGELIST // iImageIndex - index into IMAGELIST (which icon to draw) //---------------------------------------------------------------------------------------------------------------------- var DrawThemeIcon: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId: Integer; const pRect: TRect; himl: HIMAGELIST; iImageIndex: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // IsThemePartDefined() - returns TRUE if the theme has defined parameters // for the specified "iPartId" and "iStateId". // // hTheme - theme data handle // iPartId - part number to find definition for // iStateId - state number of part //---------------------------------------------------------------------------------------------------------------------- var IsThemePartDefined: function(hTheme: HTHEME; iPartId, iStateId: Integer): BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- // IsThemeBackgroundPartiallyTransparent() // - returns TRUE if the theme specified background for // the part/state has transparent pieces or // alpha-blended pieces. // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part //---------------------------------------------------------------------------------------------------------------------- var IsThemeBackgroundPartiallyTransparent: function(hTheme: HTHEME; iPartId, iStateId: Integer): BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- // lower-level theme information services //---------------------------------------------------------------------------------------------------------------------- // The following methods are getter routines for each of the Theme Data types. // Controls/Windows are defined in drawable "parts" by their author: a // parent part and 0 or more child parts. Each of the parts can be // described in "states" (ex: disabled, hot, pressed). //---------------------------------------------------------------------------------------------------------------------- // Each of the below methods takes a "iPartId" param to specify the // part and a "iStateId" to specify the state of the part. // "iStateId=0" refers to the root part. "iPartId" = "0" refers to // the root class. //---------------------------------------------------------------------------------------------------------------------- // Each method also take a "iPropId" param because multiple instances of // the same primitive type can be defined in the theme schema. //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // GetThemeColor() - Get the value for the specified COLOR property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pColor - receives the value of the property //---------------------------------------------------------------------------------------------------------------------- var GetThemeColor: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pColor: COLORREF): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeMetric() - Get the value for the specified metric/size // property // // hTheme - theme data handle // hdc - (optional) hdc to be drawn into (DPI scaling) // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // piVal - receives the value of the property //---------------------------------------------------------------------------------------------------------------------- var GetThemeMetric: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; var piVal: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeString() - Get the value for the specified string property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pszBuff - receives the string property value // cchMaxBuffChars - max. number of chars allowed in pszBuff //---------------------------------------------------------------------------------------------------------------------- var GetThemeString: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; pszBuff: LPWSTR; cchMaxBuffChars: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeBool() - Get the value for the specified BOOL property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pfVal - receives the value of the property //---------------------------------------------------------------------------------------------------------------------- var GetThemeBool: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pfVal: BOOL): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeInt() - Get the value for the specified int property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // piVal - receives the value of the property //---------------------------------------------------------------------------------------------------------------------- var GetThemeInt: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var piVal: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeEnumValue() - Get the value for the specified ENUM property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // piVal - receives the value of the enum (cast to int*) //---------------------------------------------------------------------------------------------------------------------- var GetThemeEnumValue: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var piVal: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemePosition() - Get the value for the specified position // property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pPoint - receives the value of the position property //---------------------------------------------------------------------------------------------------------------------- var GetThemePosition: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer;var pPoint: TPoint): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeFont() - Get the value for the specified font property // // hTheme - theme data handle // hdc - (optional) hdc to be drawn to (DPI scaling) // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pFont - receives the value of the LOGFONT property // (scaled for the current logical screen dpi) //---------------------------------------------------------------------------------------------------------------------- var GetThemeFont: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; var pFont: TLOGFONT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeRect() - Get the value for the specified RECT property // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pRect - receives the value of the RECT property //---------------------------------------------------------------------------------------------------------------------- var GetThemeRect: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pRect: TRect): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- type _MARGINS = record cxLeftWidth: Integer; // width of left border that retains its size cxRightWidth: Integer; // width of right border that retains its size cyTopHeight: Integer; // height of top border that retains its size cyBottomHeight: Integer; // height of bottom border that retains its size end; MARGINS = _MARGINS; PMARGINS = ^MARGINS; TMargins = MARGINS; //---------------------------------------------------------------------------------------------------------------------- // GetThemeMargins() - Get the value for the specified MARGINS property // // hTheme - theme data handle // hdc - (optional) hdc to be used for drawing // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // prc - RECT for area to be drawn into // pMargins - receives the value of the MARGINS property //---------------------------------------------------------------------------------------------------------------------- var GetThemeMargins: function(hTheme: HTHEME; hdc: HDC; iPartId, iStateId, iPropId: Integer; prc: PRECT; var pMargins: MARGINS): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- const MAX_INTLIST_COUNT = 10; type _INTLIST = record iValueCount: Integer; // number of values in iValues iValues: array [0..MAX_INTLIST_COUNT - 1] of Integer; end; INTLIST = _INTLIST; PINTLIST = ^INTLIST; TIntList = INTLIST; //---------------------------------------------------------------------------------------------------------------------- // GetThemeIntList() - Get the value for the specified INTLIST struct // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to get the value for // pIntList - receives the value of the INTLIST property //---------------------------------------------------------------------------------------------------------------------- var GetThemeIntList: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pIntList: INTLIST): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- type PROPERTYORIGIN = ( PO_STATE, // property was found in the state section PO_PART, // property was found in the part section PO_CLASS, // property was found in the class section PO_GLOBAL, // property was found in [globals] section PO_NOTFOUND); // property was not found TPropertyOrigin = PROPERTYORIGIN; //---------------------------------------------------------------------------------------------------------------------- // GetThemePropertyOrigin() // - searches for the specified theme property // and sets "pOrigin" to indicate where it was // found (or not found) // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to search for // pOrigin - receives the value of the property origin //---------------------------------------------------------------------------------------------------------------------- var GetThemePropertyOrigin: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; var pOrigin: PROPERTYORIGIN): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // SetWindowTheme() // - redirects an existing Window to use a different // section of the current theme information than its // class normally asks for. // // hwnd - the handle of the window (cannot be NULL) // // pszSubAppName - app (group) name to use in place of the calling // app's name. If NULL, the actual calling app // name will be used. // // pszSubIdList - semicolon separated list of class Id names to // use in place of actual list passed by the // window's class. if NULL, the id list from the // calling class is used. //---------------------------------------------------------------------------------------------------------------------- // The Theme Manager will remember the "pszSubAppName" and the // "pszSubIdList" associations thru the lifetime of the window (even // if themes are subsequently changed). The window is sent a // "WM_THEMECHANGED" msg at the end of this call, so that the new // theme can be found and applied. //---------------------------------------------------------------------------------------------------------------------- // When "pszSubAppName" or "pszSubIdList" are NULL, the Theme Manager // removes the previously remember association. To turn off theme-ing for // the specified window, you can pass an empty string (L"") so it // won't match any section entries. //---------------------------------------------------------------------------------------------------------------------- var SetWindowTheme: function(hwnd: HWND; pszSubAppName: LPCWSTR; pszSubIdList: LPCWSTR): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeFilename() - Get the value for the specified FILENAME property. // // hTheme - theme data handle // iPartId - part number // iStateId - state number of part // iPropId - the property number to search for // pszThemeFileName - output buffer to receive the filename // cchMaxBuffChars - the size of the return buffer, in chars //---------------------------------------------------------------------------------------------------------------------- var GetThemeFilename: function(hTheme: HTHEME; iPartId, iStateId, iPropId: Integer; pszThemeFileName: LPWSTR; cchMaxBuffChars: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysColor() - Get the value of the specified System color. // // hTheme - the theme data handle. if non-NULL, will return // color from [SysMetrics] section of theme. // if NULL, will return the global system color. // // iColorId - the system color index defined in winuser.h //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysColor: function(hTheme: HTHEME; iColorId: Integer): COLORREF; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysColorBrush() // - Get the brush for the specified System color. // // hTheme - the theme data handle. if non-NULL, will return // brush matching color from [SysMetrics] section of // theme. if NULL, will return the brush matching // global system color. // // iColorId - the system color index defined in winuser.h //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysColorBrush: function(hTheme: HTHEME; iColorId: Integer): HBRUSH; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysBool() - Get the boolean value of specified System metric. // // hTheme - the theme data handle. if non-NULL, will return // BOOL from [SysMetrics] section of theme. // if NULL, will return the specified system boolean. // // iBoolId - the TMT_XXX BOOL number (first BOOL // is TMT_FLATMENUS) //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysBool: function(hTheme: HTHEME; iBoolId: Integer): BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysSize() - Get the value of the specified System size metric. // (scaled for the current logical screen dpi) // // hTheme - the theme data handle. if non-NULL, will return // size from [SysMetrics] section of theme. // if NULL, will return the global system metric. // // iSizeId - the following values are supported when // hTheme is non-NULL: // // SM_CXBORDER (border width) // SM_CXVSCROLL (scrollbar width) // SM_CYHSCROLL (scrollbar height) // SM_CXSIZE (caption width) // SM_CYSIZE (caption height) // SM_CXSMSIZE (small caption width) // SM_CYSMSIZE (small caption height) // SM_CXMENUSIZE (menubar width) // SM_CYMENUSIZE (menubar height) // // when hTheme is NULL, iSizeId is passed directly // to the GetSystemMetrics() function //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysSize: function(hTheme: HTHEME; iSizeId: Integer): Integer; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysFont() - Get the LOGFONT for the specified System font. // // hTheme - the theme data handle. if non-NULL, will return // font from [SysMetrics] section of theme. // if NULL, will return the specified system font. // // iFontId - the TMT_XXX font number (first font // is TMT_CAPTIONFONT) // // plf - ptr to LOGFONT to receive the font value. // (scaled for the current logical screen dpi) //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysFont: function(hTheme: HTHEME; iFontId: Integer; var plf: TLOGFONT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysString() - Get the value of specified System string metric. // // hTheme - the theme data handle (required) // // iStringId - must be one of the following values: // // TMT_CSSNAME // TMT_XMLNAME // // pszStringBuff - the buffer to receive the string value // // cchMaxStringChars - max. number of chars that pszStringBuff can hold //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysString: function(hTheme: HTHEME; iStringId: Integer; pszStringBuff: LPWSTR; cchMaxStringChars: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeSysInt() - Get the value of specified System int. // // hTheme - the theme data handle (required) // // iIntId - must be one of the following values: // // TMT_DPIX // TMT_DPIY // TMT_MINCOLORDEPTH // // piValue - ptr to int to receive value //---------------------------------------------------------------------------------------------------------------------- var GetThemeSysInt: function(hTheme: HTHEME; iIntId: Integer; var piValue: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // IsThemeActive() - can be used to test if a system theme is active // for the current user session. // // use the API "IsAppThemed()" to test if a theme is // active for the calling process. //---------------------------------------------------------------------------------------------------------------------- var IsThemeActive: function: BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- // IsAppThemed() - returns TRUE if a theme is active and available to // the current process //---------------------------------------------------------------------------------------------------------------------- var IsAppThemed: function: BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetWindowTheme() - if window is themed, returns its most recent // HTHEME from OpenThemeData() - otherwise, returns // NULL. // // hwnd - the window to get the HTHEME of //---------------------------------------------------------------------------------------------------------------------- var GetWindowTheme: function(hwnd: HWND): HTHEME; stdcall; //---------------------------------------------------------------------------------------------------------------------- // EnableThemeDialogTexture() // // - Enables/disables dialog background theme. This method can be used to // tailor dialog compatibility with child windows and controls that // may or may not coordinate the rendering of their client area backgrounds // with that of their parent dialog in a manner that supports seamless // background texturing. // // hdlg - the window handle of the target dialog // dwFlags - ETDT_ENABLE to enable the theme-defined dialog background texturing, // ETDT_DISABLE to disable background texturing, // ETDT_ENABLETAB to enable the theme-defined background // texturing using the Tab texture //---------------------------------------------------------------------------------------------------------------------- const ETDT_DISABLE = $00000001; ETDT_ENABLE = $00000002; ETDT_USETABTEXTURE = $00000004; ETDT_ENABLETAB = (ETDT_ENABLE or ETDT_USETABTEXTURE); var EnableThemeDialogTexture: function(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // IsThemeDialogTextureEnabled() // // - Reports whether the dialog supports background texturing. // // hdlg - the window handle of the target dialog //---------------------------------------------------------------------------------------------------------------------- var IsThemeDialogTextureEnabled: function(hwnd: HWND): BOOL; stdcall; //---------------------------------------------------------------------------------------------------------------------- //---- flags to control theming within an app ---- const STAP_ALLOW_NONCLIENT = (1 shl 0); STAP_ALLOW_CONTROLS = (1 shl 1); STAP_ALLOW_WEBCONTENT = (1 shl 2); //---------------------------------------------------------------------------------------------------------------------- // GetThemeAppProperties() // - returns the app property flags that control theming //---------------------------------------------------------------------------------------------------------------------- var GetThemeAppProperties: function: DWORD; stdcall; //---------------------------------------------------------------------------------------------------------------------- // SetThemeAppProperties() // - sets the flags that control theming within the app // // dwFlags - the flag values to be set //---------------------------------------------------------------------------------------------------------------------- var SetThemeAppProperties: procedure(dwFlags: DWORD); stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetCurrentThemeName() // - Get the name of the current theme in-use. // Optionally, return the ColorScheme name and the // Size name of the theme. // // pszThemeFileName - receives the theme path & filename // cchMaxNameChars - max chars allowed in pszNameBuff // // pszColorBuff - (optional) receives the canonical color scheme name // (not the display name) // cchMaxColorChars - max chars allowed in pszColorBuff // // pszSizeBuff - (optional) receives the canonical size name // (not the display name) // cchMaxSizeChars - max chars allowed in pszSizeBuff //---------------------------------------------------------------------------------------------------------------------- var GetCurrentThemeName: function(pszThemeFileName: LPWSTR; cchMaxNameChars: Integer; pszColorBuff: LPWSTR; cchMaxColorChars: Integer; pszSizeBuff: LPWSTR; cchMaxSizeChars: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // GetThemeDocumentationProperty() // - Get the value for the specified property name from // the [documentation] section of the themes.ini file // for the specified theme. If the property has been // localized in the theme files string table, the // localized version of the property value is returned. // // pszThemeFileName - filename of the theme file to query // pszPropertyName - name of the string property to retreive a value for // pszValueBuff - receives the property string value // cchMaxValChars - max chars allowed in pszValueBuff //---------------------------------------------------------------------------------------------------------------------- const SZ_THDOCPROP_DISPLAYNAME = 'DisplayName'; SZ_THDOCPROP_CANONICALNAME = 'ThemeName'; SZ_THDOCPROP_TOOLTIP = 'ToolTip'; SZ_THDOCPROP_AUTHOR = 'author'; var GetThemeDocumentationProperty: function(pszThemeName, pszPropertyName: LPCWSTR; pszValueBuff: LPWSTR; cchMaxValChars: Integer): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // Theme API Error Handling // // All functions in the Theme API not returning an HRESULT (THEMEAPI_) // use the WIN32 function "SetLastError()" to record any call failures. // // To retreive the error code of the last failure on the // current thread for these type of API's, use the WIN32 function // "GetLastError()". // // All Theme API error codes (HRESULT's and GetLastError() values) // should be normal win32 errors which can be formatted into // strings using the Win32 API FormatMessage(). //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // DrawThemeParentBackground() // - used by partially-transparent or alpha-blended // child controls to draw the part of their parent // that they appear in front of. // // hwnd - handle of the child control // hdc - hdc of the child control // prc - (optional) rect that defines the area to be // drawn (CHILD coordinates) //---------------------------------------------------------------------------------------------------------------------- var DrawThemeParentBackground: function(hwnd: HWND; hdc: HDC; prc: PRECT): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- // EnableTheming() - enables or disables themeing for the current user // in the current and future sessions. // // fEnable - if FALSE, disable theming & turn themes off. // - if TRUE, enable themeing and, if user previously // had a theme active, make it active now. //---------------------------------------------------------------------------------------------------------------------- var EnableTheming: function(fEnable: BOOL): HRESULT; stdcall; //---------------------------------------------------------------------------------------------------------------------- type PREFERREDAPPMODE = ( PAM_DEFAULT, PAM_ALLOWDARK, PAM_FORCEDARK, PAM_FORCELIGHT, PAM_MAX ); TPreferredAppMode = PREFERREDAPPMODE; var SetPreferredAppMode: function(appMode: TPreferredAppMode): TPreferredAppMode; stdcall; FlushMenuThemes: procedure; stdcall; type UAHMENU = record hmenu: HMENU; hdc: HDC; dwFlags: DWORD; end; TUAHMenu = UAHMENU; PUAHMenu = ^TUAHMenu; UAHMENUITEM = record iPosition: Cardinal; // 0-based position of menu item in menubar //UAHMENUITEMMETRICS umim; //UAHMENUPOPUPMETRICS umpm; end; TUAHMenuItem = UAHMENUITEM; PUAHMenuItem = ^TUAHMenuItem; UAHDRAWMENUITEM = record dis: TDrawItemStruct; // itemID looks uninitialized um: TUAHMenu; umi: TUAHMenuItem; end; TUAHDrawMenuItem = UAHDRAWMENUITEM; PUAHDrawMenuItem = ^TUAHDrawMenuItem; const WM_UAHDRAWMENU = $91; WM_UAHDRAWMENUITEM = $92; implementation //---------------------------------------------------------------------------------------------------------------------- uses SysUtils, PathFunc; const themelib = 'uxtheme.dll'; var ThemeLibrary: HMODULE; ReferenceCount: Integer; // We have to keep track of several load/unload calls. procedure FreeThemeLibrary; begin if ReferenceCount > 0 then Dec(ReferenceCount); if (ThemeLibrary <> 0) and (ReferenceCount = 0) then begin FreeLibrary(ThemeLibrary); ThemeLibrary := 0; OpenThemeData := nil; CloseThemeData := nil; DrawThemeBackground := nil; DrawThemeText := nil; DrawThemeTextEx := nil; GetThemeBackgroundContentRect := nil; GetThemeBackgroundExtent := nil; GetThemePartSize := nil; GetThemeTextExtent := nil; GetThemeTextMetrics := nil; GetThemeBackgroundRegion := nil; HitTestThemeBackground := nil; DrawThemeEdge := nil; DrawThemeIcon := nil; IsThemePartDefined := nil; IsThemeBackgroundPartiallyTransparent := nil; GetThemeColor := nil; GetThemeMetric := nil; GetThemeString := nil; GetThemeBool := nil; GetThemeInt := nil; GetThemeEnumValue := nil; GetThemePosition := nil; GetThemeFont := nil; GetThemeRect := nil; GetThemeMargins := nil; GetThemeIntList := nil; GetThemePropertyOrigin := nil; SetWindowTheme := nil; GetThemeFilename := nil; GetThemeSysColor := nil; GetThemeSysColorBrush := nil; GetThemeSysBool := nil; GetThemeSysSize := nil; GetThemeSysFont := nil; GetThemeSysString := nil; GetThemeSysInt := nil; IsThemeActive := nil; IsAppThemed := nil; GetWindowTheme := nil; EnableThemeDialogTexture := nil; IsThemeDialogTextureEnabled := nil; GetThemeAppProperties := nil; SetThemeAppProperties := nil; GetCurrentThemeName := nil; GetThemeDocumentationProperty := nil; DrawThemeParentBackground := nil; EnableTheming := nil; SetPreferredAppMode := nil; FlushMenuThemes := nil; end; end; //---------------------------------------------------------------------------------------------------------------------- var WindowsVersion: Cardinal; function InitThemeLibrary: Boolean; function GetSystemDir: String; var Buf: array[0..MAX_PATH-1] of Char; begin GetSystemDirectory(Buf, SizeOf(Buf) div SizeOf(Buf[0])); Result := StrPas(Buf); end; function WindowsVersionAtLeast(const AMajor, AMinor: Byte; const ABuild: Word): Boolean; begin Result := WindowsVersion >= Cardinal((AMajor shl 24) or (AMinor shl 16) or ABuild); end; function WindowsVersionAtMost(const AMajor, AMinor: Byte; const ABuild: Word): Boolean; begin Result := WindowsVersion <= Cardinal((AMajor shl 24) or (AMinor shl 16) or ABuild); end; begin Inc(ReferenceCount); if ThemeLibrary = 0 then begin ThemeLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + themelib)); if ThemeLibrary <> 0 then begin OpenThemeData := GetProcAddress(ThemeLibrary, 'OpenThemeData'); CloseThemeData := GetProcAddress(ThemeLibrary, 'CloseThemeData'); DrawThemeBackground := GetProcAddress(ThemeLibrary, 'DrawThemeBackground'); DrawThemeText := GetProcAddress(ThemeLibrary, 'DrawThemeText'); DrawThemeTextEx := GetProcAddress(ThemeLibrary, 'DrawThemeTextEx'); GetThemeBackgroundContentRect := GetProcAddress(ThemeLibrary, 'GetThemeBackgroundContentRect'); GetThemeBackgroundExtent := GetProcAddress(ThemeLibrary, 'GetThemeBackgroundContentRect'); GetThemePartSize := GetProcAddress(ThemeLibrary, 'GetThemePartSize'); GetThemeTextExtent := GetProcAddress(ThemeLibrary, 'GetThemeTextExtent'); GetThemeTextMetrics := GetProcAddress(ThemeLibrary, 'GetThemeTextMetrics'); GetThemeBackgroundRegion := GetProcAddress(ThemeLibrary, 'GetThemeBackgroundRegion'); HitTestThemeBackground := GetProcAddress(ThemeLibrary, 'HitTestThemeBackground'); DrawThemeEdge := GetProcAddress(ThemeLibrary, 'DrawThemeEdge'); DrawThemeIcon := GetProcAddress(ThemeLibrary, 'DrawThemeIcon'); IsThemePartDefined := GetProcAddress(ThemeLibrary, 'IsThemePartDefined'); IsThemeBackgroundPartiallyTransparent := GetProcAddress(ThemeLibrary, 'IsThemeBackgroundPartiallyTransparent'); GetThemeColor := GetProcAddress(ThemeLibrary, 'GetThemeColor'); GetThemeMetric := GetProcAddress(ThemeLibrary, 'GetThemeMetric'); GetThemeString := GetProcAddress(ThemeLibrary, 'GetThemeString'); GetThemeBool := GetProcAddress(ThemeLibrary, 'GetThemeBool'); GetThemeInt := GetProcAddress(ThemeLibrary, 'GetThemeInt'); GetThemeEnumValue := GetProcAddress(ThemeLibrary, 'GetThemeEnumValue'); GetThemePosition := GetProcAddress(ThemeLibrary, 'GetThemePosition'); GetThemeFont := GetProcAddress(ThemeLibrary, 'GetThemeFont'); GetThemeRect := GetProcAddress(ThemeLibrary, 'GetThemeRect'); GetThemeMargins := GetProcAddress(ThemeLibrary, 'GetThemeMargins'); GetThemeIntList := GetProcAddress(ThemeLibrary, 'GetThemeIntList'); GetThemePropertyOrigin := GetProcAddress(ThemeLibrary, 'GetThemePropertyOrigin'); SetWindowTheme := GetProcAddress(ThemeLibrary, 'SetWindowTheme'); GetThemeFilename := GetProcAddress(ThemeLibrary, 'GetThemeFilename'); GetThemeSysColor := GetProcAddress(ThemeLibrary, 'GetThemeSysColor'); GetThemeSysColorBrush := GetProcAddress(ThemeLibrary, 'GetThemeSysColorBrush'); GetThemeSysBool := GetProcAddress(ThemeLibrary, 'GetThemeSysBool'); GetThemeSysSize := GetProcAddress(ThemeLibrary, 'GetThemeSysSize'); GetThemeSysFont := GetProcAddress(ThemeLibrary, 'GetThemeSysFont'); GetThemeSysString := GetProcAddress(ThemeLibrary, 'GetThemeSysString'); GetThemeSysInt := GetProcAddress(ThemeLibrary, 'GetThemeSysInt'); IsThemeActive := GetProcAddress(ThemeLibrary, 'IsThemeActive'); IsAppThemed := GetProcAddress(ThemeLibrary, 'IsAppThemed'); GetWindowTheme := GetProcAddress(ThemeLibrary, 'GetWindowTheme'); EnableThemeDialogTexture := GetProcAddress(ThemeLibrary, 'EnableThemeDialogTexture'); IsThemeDialogTextureEnabled := GetProcAddress(ThemeLibrary, 'IsThemeDialogTextureEnabled'); GetThemeAppProperties := GetProcAddress(ThemeLibrary, 'GetThemeAppProperties'); SetThemeAppProperties := GetProcAddress(ThemeLibrary, 'SetThemeAppProperties'); GetCurrentThemeName := GetProcAddress(ThemeLibrary, 'GetCurrentThemeName'); GetThemeDocumentationProperty := GetProcAddress(ThemeLibrary, 'GetThemeDocumentationProperty'); DrawThemeParentBackground := GetProcAddress(ThemeLibrary, 'DrawThemeParentBackground'); EnableTheming := GetProcAddress(ThemeLibrary, 'EnableTheming'); if WindowsVersionAtLeast(10, 0, 18362) and { Windows 10 Version 1903 (May 2019 Update) } WindowsVersionAtMost(10, 0, 26200) then begin { Windows 11 Version 25H2 (2025 Update) } SetPreferredAppMode := GetProcAddress(ThemeLibrary, MakeIntResource(135)); FlushMenuThemes := GetProcAddress(ThemeLibrary, MakeIntResource(136)); end else begin SetPreferredAppMode := nil; FlushMenuThemes := nil; end; end; end; Result := ThemeLibrary <> 0; end; //---------------------------------------------------------------------------------------------------------------------- function UseThemes: Boolean; begin Result := ThemeLibrary <> 0; if Result then Result := IsAppThemed and IsThemeActive; end; //---------------------------------------------------------------------------------------------------------------------- initialization var OSVersionInfo: TOSVersionInfo; OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo); GetVersionEx(OSVersionInfo); WindowsVersion := (Byte(OSVersionInfo.dwMajorVersion) shl 24) or (Byte(OSVersionInfo.dwMinorVersion) shl 16) or Word(OSVersionInfo.dwBuildNumber); { Following commented out by JR. Depending on unit deinitialization order, the FreeThemeLibrary call below could be made while other units are still using the theme library. This happens with NewCheckListBox when Application.Run isn't called; this unit gets deinitialized before WizardForm and its TNewCheckListBoxes are destroyed. This resulted in an AV before because TNewCheckListBox.Destroy calls theme functions. And there's really no point in freeing a DLL during shutdown anyway; the system will do so automatically. } (* finalization while ReferenceCount > 0 do FreeThemeLibrary; *) end.