如何在遊戲中自動安裝字型

作者 狼 | 日期 2017-11-16 |
如何在遊戲中自動安裝字型

有時候開發遊戲時,會選用一些特殊的字體,玩家的系統內不一定有。此時就得想辦法將字體安裝在玩家的電腦內。最簡單的方式就是夾帶字型檔在遊戲資料夾內,在遊戲內打開字型檔,叫使用者安裝。可能會出現類似這樣子的畫面:
install font image

這個方法雖然有效,但蠻蠢的XD。缺點也很明顯,在安裝字體時玩家會被彈出遊戲。

自動安裝

另一個方法是使用程式自動安裝,要自動安裝有二件事要做:

  1. 複製字型檔到系統安裝路徑內(C:\Windows\Fonts
  2. 需要寫入資訊到註冊表,可使用 Win32Api 的 WriteProfileString 函式:
    WPS = Win32API.new('kernel32', 'WriteProfileString', 'PPP', 'L')
    WPS.call('Fonts', font_name + ' (TrueType)', font_file_name)
    

這種方法可以在啟動遊戲時,直接幫玩家裝好字體。但缺點是安裝後必須重啟遊戲。且需要管理者權限。需要玩家「以系統管理員身分執行」遊戲,否則安裝會失敗。這種方法也比較容易被防毒軟體誤判為病毒,而慘遭封鎖。

在記憶體中動態加載

另一個思路是動態加載字型,在需要使用字型時才載入,但不安裝。動態載入的方法為:

  1. 使用 AddFontResource 函式加載字體:

    AFR = Win32API.new('gdi32', 'AddFontResource', ['P'], 'L')
    p 'success' if AFR.call(font_path) > 0
    
  2. 加載後,要發送視窗消息 WM_FONTCHANGE,通知新增字體:

    WM_FONTCHANGE = 0x001D
    HWND_BROADCAST = 0xffff
    SM = Win32API.new('user32', 'SendMessage', 'LLLL', 'L')
    SM.call(HWND_BROADCAST, WM_FONTCHANGE, 0, 0)
    
  3. 遊戲結束時應刪除字體資源

    RFR = Win32API.new('gdi32', 'RemoveFontResource', ['P'], 'L')
    p 'success' if RFR.call(font_path) > 0
    

這種方法不需要系統權限,也不需要玩家重啟遊戲。但缺點是動態加載進來字體,別的程序也能看到、並使用。另一個缺點是它是暫時性的,在重新開機、或隔一段時間後資料會消失,需要花時間再次載入。也有可能一些比較古老的引擎,沒有處理字體變動的訊息,導致必須重啟才生效(例如:RPG Maker XP QQ)。

另一個類似的函式是 AddFontResourceEx,功能一模一樣,只差在可以指定參數 FR_PRIVATE,讓字型不會被其它程序所看見:

FR_PRIVATE = 0x10
AFRE = Win32API.new('gdi32', 'AddFontResourceEx', 'PLL', 'L')
p 'success' if AFRE.call(font_path, FR_PRIVATE, 0) > 0