MASM32编程获取Windows当前桌面主题名

  在网上没有找到现成的代码,只能DIY了。

 

  方法和步骤如下:

 

  1、检查注册表中HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Themes/LastTheme下DisplayName of Modified的值,若其值非空,则为当前主题名;若其值为空,则往下做2。

 

  2、若其值为空,则检查HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/ThemeManager下的ThemeActive项,若其值为字符串"0",则当前使用的是“windows经典”风格;若其值为字符串"1",则需要往下做3。

 

  3、有两种方法可以获得当前主题对应的文件:

 

  一种方法是继续访问注册表HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Themes/LastTheme下的ThemeFile项的值,其值为当前使用的主题文件名(如:%SystemRoot%/resources/Themes/luna/luna.msstyles);


  若ThemeFile值为空, 则使用HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/ThemeManager下DllName项的值作为当前使用的主题文件名。


  另一种方法是使用uxtheme.dll中的API函数GetCurrentThemeName()来获取当前主题文件名。

 

  4、主题文件(如%SystemRoot%/resources/Themes/luna/luna.msstyles)对应的具体主题名称一般存放在同名的*.theme文件(如:%SystemRoot%/Resources/Themes/Luna.theme)中。


  *.theme文件结构与.INI文件类似,其
[Theme]节中的DisplayName项就是具体主题名称。

 

  如果DisplayName项的值为:“@themeui.dll,-2016”这样的格式,我们可以从HKEY_CURRENT_USER/Software/Microsoft/Windows/ShellNoRoam/MUICache获取该值对应的具体名称,如,"@themeui.dll,-2016"对应的值为"Windows 经典"。

 

  具体代码如下:

 

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 文 件 名:SysTheme.asm
; 功   能:显示当前系统主题名

; 作   者:PurpleEndurer,2009-10-29,第1版
; 开发环境:Win XP PRO SP3 + MASM32 v8

;

; 源代码和EXE下载地址:
; 1、
http://download.csdn.net/source/1780209

; 2、http://purpleendurer.ys168.com/

;

; log
; -----------------------------------------
; 2009-10-29 修改 GetSysThemeName1() & GetSysThemeName2()
; 2009-09-27 创建!
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

.386
.model flatstdcall
option casemap:none

; 2、http://purpleendurer.ys168.com/

;


include /masm32/include/windows.inc



include /masm32/include/kernel32.inc
includelib /masm32/lib/kernel32.lib



include /masm32/include/user32.inc
includelib /masm32/lib/user32.lib



include /masm32/include/advapi32.inc
includelib /masm32/lib/advapi32.lib




GetSysThemeName1                 proto :LPSTR
GetSysThemeName2                 proto :LPSTR, :DWORD
TranMsstylesFile2ThemeFileSpec  proto :LPSTR
ExpandEnvironmentFileSpec        proto :LPSTR
GetThemeDispName                 proto :LPSTR
TranDllNum2Name                  proto :LPSTR
IsWinClassStyle                  proto :LPSTR
IsModifiedTheme                  proto :LPSTR
IsUnknownTheme                   proto :LPSTR

 



; sssssssssssssssssssssssssssssssssssssssssssss
.data
; sssssssssssssssssssssssssssssssssssssssssssss
g_szAppName db "当前主题",0
g_szWinClassStyle db "windows 经典", 0
;g_szWinXP db "Windows XP", 0

g_szRegThemeManager_Path db "Software/Microsoft/Windows/CurrentVersion/ThemeManager", 0

g_szFailOpenRegKey db "未能打开注册键!", 0
g_szThemeActive db "ThemeActive", 0
g_szREG_SZ db "REG_SZ", 0
g_szREG_EXPAND_SZ db "REG_EXPAND_SZ", 0
;g_szFailGetThemeActiveValue db "未能获取ThemeActive值", 0
g_szDllName db "DllName", 0

g_szRegLastTheme_Path db "Software/Microsoft/Windows/CurrentVersion/Themes/Last"
g_szTheme db "Theme", 0

g_szThemeFile db "ThemeFile", 0
g_szFailGetThemeFileValue db "未能获取ThemeFile值", 0
g_szUnknown db "未知", 0
g_szDisplayName_of_Modified db "DisplayName of Modified", 0

g_szFailLoadUxtheme_dll db "未能装载"
g_szUxtheme_dll db "uxtheme.dll", 0

g_szFailGetCurrentThemeNameAdress db "获取地址失败:"
g_szGetCurrentThemeName db "GetCurrentThemeName", 0

g_szFailRunGetCurrentThemeName db "运行GetCurrentThemeName失败", 0

g_szDot_theme db ".theme", 0
g_szFailTranToThemeFile db "未能转换为theme文件", 0
g_szMUICache_Path db "Software/Microsoft/Windows/ShellNoRoam/MUICache", 0

g_szDisplayName db "DisplayName", 0
g_szQuestion db "?", 0
g_szSysThemeName db MAX_PATH dup(?)

 



; sssssssssssssssssssssssssssssssssssssssssssss
.code
; sssssssssssssssssssssssssssssssssssssssssssss
start:
    mov dword ptr g_szSysThemeName, NULL
    invoke GetSysThemeName1, addr g_szSysThemeName
    invoke MessageBox, NULL, addr g_szSysThemeName, addr g_szAppName, MB_OK

    mov dword ptr g_szSysThemeName, NULL
    invoke GetSysThemeName2, addr g_szSysThemeName, sizeof g_szSysThemeName
    invoke MessageBox, NULL, addr g_szSysThemeName, addr g_szAppName, MB_OK
    invoke ExitProcess,NULL

 




; ///////////////////////////////////////////////////
;获取当前系统主题名
; ///////////////////////////////////////////////////
GetSysThemeName1 proc lpszSysThemeName: LPSTR
    local bModified[MAX_PATH]: byte
    local hKey1: HKEY
    local bDllNameValue[MAX_PATH]: byte
    local dwDllNameValueLen: dword
    local bThemeFileValue[MAX_PATH]: byte
    local dwThemeFileValueLen: dword




    ;invoke IsWinClassStyle, lpszSysThemeName
    ;mov eax, lpszSysThemeName
    ;cmp dword ptr [eax], NULL
    ;jne @GetSysThemeName1Ret

    invoke IsModifiedTheme, lpszSysThemeName
    test eaxeax
    jz @GetSysThemeName1Ret

    invoke lstrcpy, addr bModified, lpszSysThemeName

    mov hKey1, 0

    ;--- 打开注册表值DllName所在键ThemeManager
    invoke RegOpenKey, HKEY_CURRENT_USER, addr g_szRegThemeManager_Path, addr hKey1
    .IF eax == ERROR_SUCCESS
        ;--- 取“DllName”值备用
        mov dwDllNameValueLen, sizeof bDllNameValue
        invoke RegQueryValueEx, hKey1, addr g_szDllName, NULL, addr g_szREG_EXPAND_SZ/
            , addr bDllNameValue, addr dwDllNameValueLen

        .if eax != ERROR_SUCCESS
            mov byte ptr bDllNameValue, NULL
        .endif

        invoke RegCloseKey, hKey1

        ;--- 打开注册表值“ThemeFile”所在键LastTheme
        invoke RegOpenKey, HKEY_CURRENT_USER, addr g_szRegLastTheme_Path, addr hKey1
        .if eax != ERROR_SUCCESS
            invoke lstrcpy, lpszSysThemeName, addr g_szFailOpenRegKey
        .else
            ;--- 取“ThemeFile”值
            mov dwThemeFileValueLen, sizeof bThemeFileValue
            invoke RegQueryValueEx, hKey1, addr g_szThemeFile, NULL, addr g_szREG_EXPAND_SZ/
                , addr bThemeFileValue, addr dwThemeFileValueLen
            .IF eax != ERROR_SUCCESS
                invoke lstrcpy, lpszSysThemeName, addr g_szFailGetThemeFileValue
            .ELSE
                invoke lstrcpy, lpszSysThemeName, addr bThemeFileValue

                ;--- “ThemeFile”值为空吗?
                    ;invoke lstrlen, lpszSysThemeName
                    ;test eax, eax
                    ;.if ZERO?  
                mov eax, lpszSysThemeName
                .if byte ptr [eax] == NULL
                    ;--- 若ThemeFile值为空, 则使用DllName值
                    .IF byte ptr bDllNameValue != NULL
                        invoke lstrcpy, lpszSysThemeName, addr bDllNameValue
                        invoke ExpandEnvironmentFileSpec, lpszSysThemeName
                        invoke TranMsstylesFile2ThemeFileSpec, lpszSysThemeName
                        test eaxeax
                        jz @F
                    .ENDIF
                .else       ;否则获取主题文件中DisplayName值
@@:
                    invoke GetThemeDispName, lpszSysThemeName
                .endif
                invoke lstrcat, lpszSysThemeName, addr bModified
            .ENDIF
        .endif
    .ENDIF

    .if (hKey1 != 0)
        invoke RegCloseKey, hKey1
    .endif

    invoke IsUnknownTheme, lpszSysThemeName

@GetSysThemeName1Ret:
    ret
GetSysThemeName1 endp




GetCurrentThemeName typedef proto :LPWSTR, :DWORD, :LPWSTR, :DWORD, :LPWSTR, :DWORD
_GetCurrentThemeName typedef ptr GetCurrentThemeName
GetSysThemeName2 proc lpszSysThemeName: LPSTR, dwSysThemeNameLen: DWORD
    local bModified[MAX_PATH]: byte
    local bThemeFile[MAX_PATH*2]: byte
    local lpfnGetCurrentThemeName: _GetCurrentThemeName

    invoke IsWinClassStyle, lpszSysThemeName
    mov eax, lpszSysThemeName
    cmp dword ptr [eax], NULL
    jne @GetSysThemeName2Ret

    invoke IsModifiedTheme, lpszSysThemeName
    test eaxeax
    jz @GetSysThemeName2Ret

    invoke lstrcpy, addr bModified, lpszSysThemeName

    invoke LoadLibrary, addr g_szUxtheme_dll
    .IF eax==NULL
        invoke lstrcpy, lpszSysThemeName, addr g_szFailLoadUxtheme_dll
    .ELSE
        push eax    ;push for FreeLibrary

        invoke GetProcAddress, eaxaddr g_szGetCurrentThemeName
        .if eax==NULL
            invoke lstrcpy, lpszSysThemeName, addr g_szFailGetCurrentThemeNameAdress
        .else
            mov lpfnGetCurrentThemeName, eax

; HRESULT GetCurrentThemeName(
 ;     LPWSTR pszThemeFileName,//[out] Pointer to a string that receives the theme path and file name.
 ;     int dwMaxNameChars,     //[in] Value of typeintthat contains the maximum number of characters allowed in the theme file name.
 ;     LPWSTR pszColorBuff,    //[out] Pointer to a string that receives the color scheme name. This parameter may be set to NULL.
 ;     int cchMaxColorChars,   //[in] Value of typeintthat contains the maximum number of characters allowed in the color scheme name.
 ;     LPWSTR pszSizeBuff,     //[out] Pointer to a string that receives the size name. This parameter may be set to NULL.
 ;     int cchMaxSizeChars     //[in] Value of typeintthat contains the maximum number of characters allowed in the size name.
 ; );
 ; Retrieves the name of the current visual style, and optionally retrieves the color scheme name and size name.
 ; The result maybe read from HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/ThemeManager/ThemeActive,DllName
 ; eg.C:/WINDOWS/Resources/Themes/Luna/luna.msstyles,  
 ;
 ; Returns S_OK if successful, otherwise an error code.

           invoke lpfnGetCurrentThemeName, addr bThemeFile, (sizeof bThemeFile)/2, NULL, NULL, NULL, NULL
            .IF eax != S_OK
                invoke lstrcpy, lpszSysThemeName, addr g_szFailRunGetCurrentThemeName
                ;invoke lstrcpy, lpszSysThemeName, addr g_szWinClassStyle    ;当前主题为"Windows 经典"
            .ELSE
                ;invoke MessageBox, NULL, addr bThemeFile, addr g_szAppName, MB_OK
                invoke WideCharToMultiByte, CP_ACP, WC_COMPOSITECHECK, addr bThemeFile, -1/
                    ,lpszSysThemeName, dwSysThemeNameLen, NULL, NULL

                ;invoke MessageBox, NULL, lpszSysThemeName, addr g_szAppName, MB_OK

                invoke TranMsstylesFile2ThemeFileSpec,  lpszSysThemeName
                test eaxeax
                .if ZERO?
                    invoke GetThemeDispName, lpszSysThemeName
                .endif
            .ENDIF
            invoke lstrcat, lpszSysThemeName, addr bModified
        .endif

        call FreeLibrary
    .ENDIF

    invoke IsUnknownTheme, lpszSysThemeName

@GetSysThemeName2Ret:
    ret
GetSysThemeName2 endp




IsWinClassStyle proc lpszSysThemeName: LPSTR
    local hKey1: HKEY
    local bThemeActiveValue[2]: byte
    local dwThemeActiveValueLen: dword

    mov eax, lpszSysThemeName
    mov dword ptr [eax], NULL

    ;--- 打开注册表值ThemeActive所在键ThemeManager
    invoke RegOpenKey, HKEY_CURRENT_USER, addr g_szRegThemeManager_Path, addr hKey1
    .IF eax == ERROR_SUCCESS
        ;--- 取ThemeActive值
        mov dwThemeActiveValueLen, sizeof bThemeActiveValue
        invoke RegQueryValueEx, hKey1, addr g_szThemeActive, NULL, addr g_szREG_SZ/
                , addr bThemeActiveValue, addr dwThemeActiveValueLen
   
        .if eax == ERROR_SUCCESS && (byte ptr bThemeActiveValue=='0')   ;值为'0',当前主题为"Windows 经典"
            invoke lstrcpy, lpszSysThemeName, addr g_szWinClassStyle
        .endif

        invoke RegCloseKey, hKey1
    .ENDIF
        
    ret
IsWinClassStyle endp




;/////////////////////////////////////////////
; 取 "@xxx.dll,-nnn" 的对应值
; 如. "@themeui.dll,-2016"="Windows 经典"
;/////////////////////////////////////////////
TranDllNum2Name proc lpszDllNum: LPSTR
    local hKey1: HKEY
    local bValue[MAX_PATH]: byte
    local dwValueLen: dword

    ;--- 打开注册表键MUICache
    invoke RegOpenKey, HKEY_CURRENT_USER, addr g_szMUICache_Path, addr hKey1
    .IF eax == ERROR_SUCCESS
        ;--- 取lpszDllNum对应值
        mov dwValueLen, sizeof bValue
        invoke RegQueryValueEx, hKey1, lpszDllNum, NULL, addr g_szREG_SZ/
                , addr bValue, addr dwValueLen
   
        .if eax == ERROR_SUCCESS
            invoke lstrcpy, lpszDllNum, addr bValue
        .endif
        invoke RegCloseKey, hKey1
;    .ELSE
;        invoke lstrcpy, lpszDllNum, addr g_szFailOpenRegKey
    .ENDIF

    ret
TranDllNum2Name endp




; //////////////////////////////////////////////////////////////////////////////////////
;将文件说明符中包含环境变量转化具体值
; 如将:%SystemRoot%/resources/Themes/Aquanox/Aquanox.msstyles
; 转为:c:/windows/resources/Themes/Aquanox/Aquanox.msstyles
; //////////////////////////////////////////////////////////////////////////////////////

ExpandEnvironmentFileSpec proc lpszFileSpec: LPSTR
    local bFileSpec[MAX_PATH]: byte

    invoke ExpandEnvironmentStrings, lpszFileSpec, addr bFileSpec, sizeof bFileSpec
    invoke lstrcpy, lpszFileSpec, addr bFileSpec

    ret
ExpandEnvironmentFileSpec endp



; ///////////////////////////////////////////////////////////////////
;获取指定主题文件中的DisplayName值
; 如C:/WINDOWS/Resources/Themes/Aquanox.theme中
;[Theme]
;DisplayName=经典-深色Aquanox风格
; ///////////////////////////////////////////////////////////////////
GetThemeDispName proc lpszThemeFileSpec: LPSTR
    local bDispNameValue[MAX_PATH]: byte

    invoke ExpandEnvironmentFileSpec, lpszThemeFileSpec

    invoke GetPrivateProfileString, ADDR g_szTheme, ADDR g_szDisplayName/
        , ADDR g_szQuestion, ADDR bDispNameValue, SIZEOF bDispNameValue, lpszThemeFileSpec

    .if byte ptr bDispNameValue != '?'
        invoke lstrcpy, lpszThemeFileSpec, ADDR bDispNameValue        
        .IF byte ptr bDispNameValue == "@"
            invoke TranDllNum2Name, lpszThemeFileSpec
        .ENDIF
    .endif

    ret
GetThemeDispName endp




;///////////////////////////////////////////////////////////////////////////
; 生成.msstyles 文件对应的.theme文件
; 如     C:/WINDOWS/Resources/Themes/luna/luna.msstyles
; 对应: C:/WINDOWS/Resources/Themes/Luna.theme
; 输入: lpszFileSpec - 指向存储.msstyles文件说明符字符串
; 输出: 
;  若成功, eax= 0, lpszFileSpec 指向存储对应的.theme文件的文件说明符字符串
;  否则 eax=1, lpszFileSpec 指向存储出错信息的字符串
;///////////////////////////////////////////////////////////////////////////

TranMsstylesFile2ThemeFileSpec proc lpszFileSpec: LPSTR
    invoke lstrlen, lpszFileSpec

    ;--- 从串末向前定位最后一个'/'字符
    mov edi, lpszFileSpec
    add edieax
    .repeat
        dec edi
        mov albyte ptr [edi]
    .until (edi==lpszFileSpec || al=='/')

    .IF (edi==lpszFileSpec)
        invoke lstrcpy, lpszFileSpec, addr g_szFailTranToThemeFile
        xor eaxeax
        inc eax
    .ELSE
        mov byte ptr [edi], 0
        invoke lstrcat, lpszFileSpec, addr g_szDot_theme
        xor eaxeax
    .ENDIF

    ret
TranMsstylesFile2ThemeFileSpec endp




;/////////////////////////////////////////////////////////////////////////////////////////////////////////////
;取注册表HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/LastTheme
;中的“DisplayName of Modified”项值
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////
IsModifiedTheme proc lpszThemeName: LPSTR
    local hKey1: HKEY
    local bDispNameModifiedValue[30]: byte
    local dwDispNameModifiedValueLen: dword

    ;--- 打开注册表值“DisplayName of Modified”所在键LastTheme
    invoke RegOpenKey, HKEY_CURRENT_USER, addr g_szRegLastTheme_Path, addr hKey1
    .if eax == ERROR_SUCCESS
        ;--- 读取“DisplayName of Modified”值
        mov dwDispNameModifiedValueLen, sizeof bDispNameModifiedValue

        invoke RegQueryValueEx, hKey1, addr g_szDisplayName_of_Modified, NULL, addr g_szREG_SZ/
                , addr bDispNameModifiedValue, addr dwDispNameModifiedValueLen

        .IF eax == ERROR_SUCCESS
            invoke lstrcpy, lpszThemeName, addr bDispNameModifiedValue
        .ENDIF
        invoke RegCloseKey, hKey1
    .else
        
    .endif

    xor eaxeax

    ;值是否为空或为“更改的主题”。"更"的机内码为0B8FCh
    .if byte ptr bDispNameModifiedValue == NULL || word ptr bDispNameModifiedValue == 0FCB8h
        inc eax
    .endif
    ret

IsModifiedTheme endp




IsUnknownTheme proc lpszThemeName: LPSTR
    invoke lstrlen, lpszThemeName
    test eaxeax
    .if ZERO?
        invoke lstrcpy, lpszThemeName, addr g_szUnknown
    .endif

    ret
IsUnknownTheme endp

end start

 

 

你可能感兴趣的:(MASM32编程获取Windows当前桌面主题名)