在公共场合的电脑上进行 PPT 演示时,这些电脑的字体安装情况往往和我们个人的有所出入,部分字体的缺失最终导致演示效果与我们所设想的情况不符,因此,有必要在开始 PPT 演示前就准备好字体并且安装,而传统字体的安装实在太过繁琐。基于 Python 语言的学习成果,我编写了一款程序,利用 Windows 的管理员授权,可以在其目录下安装所有需要的字体,从而保证演示效果。在使用时,建议提前打包为可执行文件。
源码如下:
import os
import sys
import shutil
import ctypes
import glob
import winreg
def is_admin():
"""检查当前是否拥有管理员权限"""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def install_font(src_path):
"""安装单个字体"""
font_dir = os.path.join(os.environ['WINDIR'], 'Fonts')
font_filename = os.path.basename(src_path)
dst_path = os.path.join(font_dir, font_filename)
# 1. 复制文件到字体目录
# 如果文件已存在,为了安全起见跳过复制,但仍会尝试注册
if not os.path.exists(dst_path):
try:
shutil.copy(src_path, dst_path)
print(f"[复制成功] {font_filename}")
except Exception as e:
print(f"[复制失败] {font_filename} - {e}")
return False
else:
print(f"[已存在] {font_filename} (跳过复制)")
# 2. 注册字体到注册表 (永久生效)
# 注意:标准做法是解析字体内部名称,但直接用文件名作为 Key 在大多数情况下也是兼容的
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", 0, winreg.KEY_SET_VALUE)
# 值名为 "文件名 (TrueType)" 的格式通常最稳妥,或者直接用文件名
winreg.SetValueEx(key, f"{font_filename} (TrueType)", 0, winreg.REG_SZ, font_filename)
winreg.CloseKey(key)
except Exception as e:
print(f"[注册表写入失败] {e}")
# 3. 调用 Windows API 加载字体 (当前会话立即生效)
# AddFontResourceW 返回安装的字体数量,0 表示失败
result = ctypes.windll.gdi32.AddFontResourceW(dst_path)
if result > 0:
print(f"[加载成功] {font_filename}")
return True
else:
print(f"[加载失败] 可能文件已损坏或非字体文件")
return False
def main():
# 强制以管理员身份运行
if not is_admin():
print("正在请求管理员权限...")
# 重新运行当前程序,参数为 runas (管理员模式)
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
return
# 获取当前程序所在目录 (兼容 Pyinstaller 打包后的路径)
if getattr(sys, 'frozen', False):
base_path = os.path.dirname(sys.executable)
else:
base_path = os.path.dirname(os.path.abspath(__file__))
print(f"正在扫描目录: {base_path} ...")
# 扫描常见字体格式
extensions = ['*.ttf', '*.otf', '*.ttc']
fonts = []
for ext in extensions:
fonts.extend(glob.glob(os.path.join(base_path, ext)))
if not fonts:
print("未找到任何字体文件 (.ttf, .otf, .ttc)。")
input("按回车键退出...")
return
success_count = 0
for font in fonts:
if install_font(font):
success_count += 1
# 4. 广播字体变更消息
# 这一步至关重要,它告诉 PPT 等程序“有新字体了,快刷新一下缓存”
HWND_BROADCAST = 0xFFFF
WM_FONTCHANGE = 0x001D
ctypes.windll.user32.SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0)
print(f"\n操作完成!共处理 {len(fonts)} 个文件,成功加载 {success_count} 个。")
print("建议:如果 PPT 仍然显示不正常,请完全关闭 PPT 后重新打开。")
input("按回车键退出...")
if __name__ == "__main__":
main()
