How do I access DWriteCore from a C# managed application?

Kenny Brown 51 Reputation points
2021-10-02T06:36:10.877+00:00

How do I access DWriteCore from a C# managed application?

I'm using .Net5 WindowsAppSDK Desktop.

I need to get a SYSTEM and CUSTOM FONT COLLECTION LIST using DWriteCore, but I need to do so from a C# App using WindowsAppSDK, which says it includes DWriteCore, but I could only find a C++ sample. All nuget packages have been installed.

Thank you, in advance, for any assistance.

Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
794 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,649 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,005 questions
.NET Runtime
.NET Runtime
.NET: Microsoft Technologies based on the .NET software framework.Runtime: An environment required to run apps that aren't compiled to machine language.
1,166 questions
{count} votes

Accepted answer
  1. Castorix31 85,796 Reputation points
    2021-10-05T23:25:53.287+00:00

    From comments in the other thread, a DWriteCore test in C#/WindowsAppSDK with GetSystemFontCollection from IDWriteFactory7 :

    137869-windowsappsdk-fonts2.jpg

    At beginning :

    using DWrite;  
    using System.Text;  
    using System.ComponentModel;  
    using System.Collections.ObjectModel;  
      
    

    Download DWrite.cs and add it to the project

    Declarations :

     // As I could not get DWriteCore.dll from Microsoft.WindowAppSDK.DWrite package when I tested,  
        // I got it from https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/TextRendering  
        // then it must be copied in executable directory  
        [DllImport("DWriteCore.dll", SetLastError = true, CharSet = CharSet.Auto)]  
        public static extern HRESULT DWriteCoreCreateFactory(DWRITE_FACTORY_TYPE factoryType, ref Guid iid, out IntPtr factory);  
    
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]  
        public static extern int GetUserDefaultLocaleName(StringBuilder lpLocaleName, int cchLocaleName);  
    
        public const int LOCALE_NAME_MAX_LENGTH = 85;  
          
      
    

    Test IDWriteFactory7.GetSystemFontCollection in a button click :

        IDWriteFactory m_pDWriteFactory = null;  
        IDWriteFactory7 m_pDWriteFactory7 = null;  
        public System.Collections.ObjectModel.ObservableCollection<string> fonts = new System.Collections.ObjectModel.ObservableCollection<string>();  
          
        private void myButton_Click(object sender, RoutedEventArgs e)  
        {  
            fonts.Clear();  
    
            Guid CLSID_DWriteFactory = new Guid("B859EE5A-D838-4B5B-A2E8-1ADC7D93DB48");  
            Guid CLSID_DWriteFactory7 = new Guid("35D0E0B3-9076-4D2E-A016-A91B568A06B4");  
              
            IntPtr pDWriteFactoryPtr = IntPtr.Zero;  
            // HRESULT hr = DWriteCoreCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED, ref CLSID_DWriteFactory, out pDWriteFactoryPtr);  
            HRESULT hr = DWriteCoreCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED, ref CLSID_DWriteFactory7, out pDWriteFactoryPtr);  
            if (hr == HRESULT.S_OK)  
            {  
                // m_pDWriteFactory = Marshal.GetObjectForIUnknown(pDWriteFactoryPtr) as IDWriteFactory;  
                m_pDWriteFactory7 = Marshal.GetObjectForIUnknown(pDWriteFactoryPtr) as IDWriteFactory7;  
                //IDWriteFontCollection pFontCollection;  
                //hr = m_pDWriteFactory.GetSystemFontCollection(out pFontCollection);  
                IDWriteFontCollection3 pFontCollection;  
                hr = m_pDWriteFactory7.GetSystemFontCollection7(false, DWRITE_FONT_FAMILY_MODEL.DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, out pFontCollection);                 
                if (hr == HRESULT.S_OK)  
                {  
                    uint nFamilyCount = pFontCollection.GetFontFamilyCount();  
                    for (uint i = 0; i < nFamilyCount; i++)  
                    {  
                        IDWriteFontFamily pFontFamily;  
                        hr = pFontCollection.GetFontFamily(i, out pFontFamily);  
                        IDWriteLocalizedStrings pFamilyNames;  
                        pFontFamily.GetFamilyNames(out pFamilyNames);  
    
                        // https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritelocalizedstrings-findlocalename  
                        uint nIndex = 0;  
                        bool bExists = false;  
                        StringBuilder sbLocaleName = new StringBuilder(LOCALE_NAME_MAX_LENGTH);  
                        int nDefaultLocaleSuccess = GetUserDefaultLocaleName(sbLocaleName, LOCALE_NAME_MAX_LENGTH);  
                        if (nDefaultLocaleSuccess > 0)  
                        {  
                            hr = pFamilyNames.FindLocaleName(sbLocaleName.ToString(), out nIndex, out bExists);  
                        }  
                        if (hr == HRESULT.S_OK && !bExists)  
                        {  
                            hr = pFamilyNames.FindLocaleName("en-us", out nIndex, out bExists);  
                        }  
                        if (!bExists)  
                            nIndex = 0;  
                        hr = pFamilyNames.GetString(nIndex, sbLocaleName, LOCALE_NAME_MAX_LENGTH);  
                        string sName = sbLocaleName.ToString();  
                        //Console.WriteLine("Font : {0}", sName);  
                        //System.Diagnostics.Debug.WriteLine("Font : " + sName);  
    
                        fonts.Add(sName);  
    
                        Marshal.ReleaseComObject(pFamilyNames);  
                        Marshal.ReleaseComObject(pFontFamily);  
                    }  
                    Marshal.ReleaseComObject(pFontCollection);  
                }  
                //Marshal.ReleaseComObject(m_pDWriteFactory);  
                Marshal.ReleaseComObject(m_pDWriteFactory7);  
            }  
        }  
       
       
    

    Button + Listbox in XAML

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">  
        <Button x:Name="myButton" Click="myButton_Click" Margin="100,100,0,0" >Click Me</Button>        
        <ListBox x:Name="FontsList" Height="200" Width="250" Margin="150,100,0,0" HorizontalContentAlignment="Stretch"  
         ItemsSource="{x:Bind fonts}"><!--DisplayMemberPath="Source">-->  
            <ListBox.ItemTemplate>  
            <DataTemplate x:DataType="x:String">  
                <TextBlock FontFamily="{x:Bind}"  
                           Text="{x:Bind}" />  
            </DataTemplate>  
        </ListBox.ItemTemplate>  
        </ListBox>        
    </StackPanel>  
      
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.