Распаковка шрифта из ресурсов проекта VS

262
26 марта 2018, 22:35

Не могу никак разобраться, в чем проблема. Почему не работает?

Файл со шрифтом находится в проекте как внедренный ресурс. Пытался сначала сделать через FileCopy, но после распаковки в папку Temp для копирования файла, говорит, что файл уже занят и ничем помочь не может.

Второй вариант - это пытаюсь распаковать файл шрифта (ttf) напрямую в папку C:\Windows\Fonts - но и это не работает. На рабочий стол (проверил), шрифт кидает и распаковывает, а в папку Fonts - нет.

Помогите разобраться, как сделать так, чтобы внедренный файл (ttf) в проект VS 2017 можно было напрямую установить в папку Windows\Fonts?

Мой код:

void ExtractResource(string resource, string path)
{
    Stream stream = GetType().Assembly.GetManifestResourceStream(resource);
    byte[] bytes = new byte[(int)stream.Length];
    stream.Read(bytes, 0, bytes.Length);
    File.WriteAllBytes(path, bytes);
}
private void FontCopy()
{
    string fontsfolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts);
    string exePath = fontsfolder + @"\a_Futurica_ExtraBold.ttf";
    ExtractResource("RustCheatCheck.a_Futurica_ExtraBold.ttf", exePath);
    /*if (!File.Exists(exePath))
    {
        ExtractResource("RustCheatCheck.a_Futurica_ExtraBold.ttf", exePath);
    }*/
}
Answer 1

Ваш код для распаковки ресурсов правильный.

Но Windows, как уважающая себя операционная система, не даёт приложениям, запущенным с правами юзера, модифицировать системный каталог (а то любая программа сможет внести хаос в систему). Чтобы писать в системный каталог, программе нужны права администратора.

Кроме того, копирование шрифта в каталог Fonts недостаточно для того, чтобы шрифт начал работать, его нужно ещё зарегистрировать в системе. Но это не лучшая опция — если пользователь снесёт ваше приложение, удалите ли вы за собой ненужные шрифты?

Если вы пишете на WPF, вы можете просто использовать шрифты не распаковывая их, прямо из ресурсов. Для этого включите шрифт в проект как Resource (не Embedded Resource!), и ссылайтесь на него по внутреннему пути:

<TextBlock FontFamily="fonts/#Имя Вашего Шрифта"/>

Документация: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/packaging-fonts-with-applications

Если вы пользуетесь Winforms, оставайтесь на Embedded Resource, и используйте PrivateFontCollection:

static void AddFontFromResource(PrivateFontCollection collection, string resouce)
{
    Stream stream = GetType().Assembly.GetManifestResourceStream(resource);
    byte[] bytes = new byte[(int)stream.Length];
    stream.Read(bytes, 0, bytes.Length);
    var memory = Marshal.AllocCoTaskMem(fontBytes.Length);
    Marshal.Copy(bytes, 0, memory, bytes.Length);
    collection.AddMemoryFont(memory, bytes.Length);
    Marshal.FreeCoTaskMem(fontData);
}

Источник: https://stackoverflow.com/a/23658552/276994

У Windows, судя по всему, нету документированного способа добавлять системные шрифты программным путём. В сети есть различные обходные пути, которые могут перестать работать в следующей версии. Поэтому использование локального шрифта кажется правильным подходом. В частности, AddFontResource добавляет шрифт только на текущую сессию, до перезагрузки.

Возможно, вам нужен инсталлятор, как описано здесь.

READ ALSO
Работа на Гексагональной сеткой

Работа на Гексагональной сеткой

Здравствуйте, я столкнулся с проблемой создание гексагональной сети в WPF и одно интересно решение в вопросе Гексагональная сеткаЯ начинающий...

248
Проблема с обращением к Скрипту Button

Проблема с обращением к Скрипту Button

Здравствуйте , есть лист объектов, содержащий весь список уровней, который присутствует к игреЯ прохожу по этому списку и включаю картинки...

201
VkNet, c# Как авторизваться без приложения?

VkNet, c# Как авторизваться без приложения?

К примеру на питоне с помощью библиотеки vk_api, можно авторизваться зная только login и пароль

234