Установите шрифт типа 1 в проекте установки VS 2010 - PullRequest
1 голос
/ 27 сентября 2011

Я пытаюсь использовать проект установки Visual Studio 2010, чтобы упаковать набор шрифтов типа 1 в файл MSI для простой установки.

Я настроил свой проект установки для размещения всех PFM и PFBфайлы в папке «Шрифты», установите для всех файлов PFM значение vsdrfFont и исправьте проблему именования, упомянутую здесь:

http://cjwdev.wordpress.com/2011/03/14/installing-non-truetype-fonts-with-visual-studio-installer/

Однако это не работает для шрифтов типа 1.

Файлы шрифтов типа 1 установлены, но шрифт по-прежнему не распознается и не отображается в окне Fonts.

При установке вручную шрифты типа 1 регистрируются в HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Type 1 Installer\Type 1 Fonts и работают нормально.

Как можно добиться того же результата с помощью проекта установки?

Ответы [ 2 ]

2 голосов
/ 08 ноября 2011

Для установки шрифтов типа 1 необходимо выполнить следующие действия:

  1. Зарегистрировать заголовок шрифта в разделе «Шрифты Type 1»
  2. Скопировать как PFM, так и PFB в окнакаталог шрифтов
  3. вызов метода AddFontResource

Зарегистрируйте заголовок шрифта в разделе «Тип 1 шрифтов»

SOFTWARE\Microsoft\Windows NT\CurrentVersion\Type 1 Installer\Type 1 Fonts

Требуется заголовок шрифта. Вместо того, чтобы предоставлять его установщику, следующий фрагмент кода позволит вам прочитать заголовок шрифта из PFM.Он основан на информации, полученной из следующего источника:

http://partners.adobe.com/public/developer/en/font/5178.PFM.pdf

    private static string GetType1FontName(string filename)
    {
        StringBuilder postscriptName = new StringBuilder();

        FileInfo fontFile = new FileInfo(filename);
        using (FileStream fs = fontFile.OpenRead())
        {
            using (StreamReader sr = new StreamReader(fs))
            {
                using (BinaryReader inStream = new BinaryReader(fs))
                {
                    // PFM Header is 117 bytes
                    inStream.ReadBytes(117); // skip 117
                    short size = inStream.ReadInt16();
                    int extMetricsOffset = inStream.ReadInt32();
                    int extentTableOffset = inStream.ReadInt32();

                    inStream.ReadBytes(4); // skip 4
                    int kernPairOffset = inStream.ReadInt32();
                    int kernTrackOffset = inStream.ReadInt32();
                    int driverInfoOffset = inStream.ReadInt32();

                    fs.Position = driverInfoOffset;
                    while (inStream.PeekChar() != 0)
                    {
                        postscriptName.Append(inStream.ReadChar());
                    }
                }
            }
        }

        return postscriptName.ToString();
    }

Скопируйте PFM и PFB в каталог шрифтов Windows

Согласно этому блогу http://www.atalasoft.com/cs/blogs/stevehawley/archive/2008/08/25/getting-the-fonts-folder.aspx правильный способ получить папку шрифтов Windows выглядит следующим образом:

    [DllImport("shell32.dll")]
    private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken,
               uint dwFlags, [Out] StringBuilder pszPath);

    public static string GetFontFolderPath()
    {
        StringBuilder sb = new StringBuilder();
        SHGetFolderPath(IntPtr.Zero, 0x0014, IntPtr.Zero, 0x0000, sb);

        return sb.ToString();
    }

Вызовите метод AddFontResource

Наконец, должен быть вызван метод AddFontResource, параметр lpFilename должен состоять из файлов pfm и pfb, разделенных символом канала '|'.В моем случае я поставил полный путь к папке шрифтов Windows, которая, кажется, работает.После вызова AddFontResource вам нужно вызвать PostMessage с параметром WM.FONTCHANGE (0x001D), чтобы сообщить другим окнам об изменении.

    [DllImport("gdi32.dll")]
    static extern int AddFontResource(string lpFilename);

    // build the name for the api "<pfm>|<pfb>"
    string apiValue = string.Format("{0}|{1}", PfmFileDestination, PfbFileDestination);

    // Call the api to register the font
    int retVal = AddFontResource(apiValue);

    // Inform other windows of change
    PostMessage(HWND_BROADCAST, WM.FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
1 голос
/ 05 октября 2011

Вот решение, которое включает в себя пользовательское действие MSI. Я написал с использованием C #, но любой другой язык, способный вызывать DLL, может быть пользовательским. Вот учебная ссылка для C #: Пошаговое руководство. Создание настраиваемого действия

using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Runtime.InteropServices;

namespace InstallType1Font
{
    [RunInstaller(true)]
    public partial class Installer1 : Installer
    {
        public Installer1()
        {
            InitializeComponent();
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);

            // here, you'll have to determine the proper path
            string path = @"c:\Windows\Fonts\MyFont.pfm";
            if (File.Exists(path))
            {
                InstallFontFile(IntPtr.Zero, path, 0);
            }
        }

        [DllImport("fontext.dll", CharSet = CharSet.Auto)]
        private static extern void InstallFontFile(IntPtr hwnd, string filePath, int flags);

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
        }
    }
}

Насколько я знаю, InstallFontFile не документирован, но позволяет постоянно устанавливать шрифт. Используйте это на свой страх и риск.

Примечание: вам все еще нужно изменить .MSI, чтобы обеспечить наличие в шрифте файла FonTitle шрифта, как описано в приведенной вами ссылке.

...