How to programmatically install a font - c#

I would like to install a specific font on my program load and use that font in rendering text of the program. How can I programmatically install a font from .NET CF on WinCE 6.

This blog entry shows how to enumerate and add Fonts in Windows CE using native code. For managed code, this will work:
internal class FontHelper
{
private delegate int EnumFontFamProc(IntPtr lpelf, IntPtr lpntm, uint FontType, IntPtr lParam);
private List<string> m_fonts = new List<string>();
public FontHelper()
{
RefreshFontList();
}
public void RefreshFontList()
{
m_fonts.Clear();
var dc = GetDC(IntPtr.Zero);
var d = new EnumFontFamProc(EnumFontCallback);
var ptr = Marshal.GetFunctionPointerForDelegate(d);
EnumFontFamilies(dc, null, ptr, IntPtr.Zero);
}
public string[] SupportedFonts
{
get { return m_fonts.ToArray(); }
}
private const int SIZEOF_LOGFONT = 92;
private const int LOGFONT = 28;
private const int LF_FACESIZE = 32;
private const int LF_FULLFACESIZE = 64;
[DllImport("coredll", SetLastError = true)]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("coredll", SetLastError = true)]
private static extern int EnumFontFamilies(IntPtr hdc, string lpszFamily, IntPtr lpEnumFontFamProc, IntPtr lParam);
private int EnumFontCallback(IntPtr lpelf, IntPtr lpntm, uint FontType, IntPtr lParam)
{
var data = new byte[SIZEOF_LOGFONT + LF_FACESIZE + LF_FULLFACESIZE];
Marshal.Copy(lpelf, data, 0, data.Length);
var fontName = Encoding.Unicode.GetString(data, SIZEOF_LOGFONT, LF_FULLFACESIZE).TrimEnd('\0');
Debug.WriteLine(fontName);
m_fonts.Add(fontName);
return 1;
}
}

Copy font *.ttf file to Windows\Fonts folder, it may requires restarting your device.

Actually, this helps better.
http://social.msdn.microsoft.com/Forums/en/netfxcompact/thread/ee9a6947-0799-4a76-a7cd-c0bec4b7a2ab

Related

A way of writing a line in a specific font [C# Console]

Alright I basically want to write a specific line in a different font, example:
Console.WriteLine("Line with regular font");
Console.WriteLine("Line with a special font");
Console.WriteLine("Line with regular font");
Console.WriteLine("Line with regular font");
Hope you get what I'm saying, and of course on a console app.
I already know this method: Console.OutputEncoding =
But that would change the whole console font, and I need a specific line
Console.OutputEncoding has nothing to do with fonts. It's encoding, like ASCII or UTF-8. You cannot do that because a console doesn't deal with fonts. It's just a stream of characters.
If you want to be change the font on a line by line basis you need to make your own GUI application to display the lines of text in the window.
Only by using kernel api, don't forget to enable unsafe code in Project Properties>Build>Allow Unsafe Code
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct CONSOLE_FONT_INFO_EX
{
internal uint cbSize;
internal uint nFont;
internal COORD dwFontSize;
internal int FontFamily;
internal int FontWeight;
internal fixed char FaceName[LF_FACESIZE];
}
[StructLayout(LayoutKind.Sequential)]
internal struct COORD
{
internal short X;
internal short Y;
internal COORD(short x, short y)
{
X = x;
Y = y;
}
}
private const int STD_OUTPUT_HANDLE = -11;
private const int TMPF_TRUETYPE = 4;
private const int LF_FACESIZE = 32;
private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetCurrentConsoleFontEx(
IntPtr consoleOutput,
bool maximumWindow,
ref CONSOLE_FONT_INFO_EX consoleCurrentFontEx);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int dwType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int SetConsoleFont(
IntPtr hOut,
uint dwFontNum
);
static void Main(string[] args)
{
SetConsoleFont();
int value = 977788899;
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("Price: " + value.ToString("C", CultureInfo.CreateSpecificCulture("fr-FR")));
Console.ReadLine();
}
public static void SetConsoleFont(string fontName = "Lucida Console")
{
unsafe
{
IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
if (hnd != INVALID_HANDLE_VALUE)
{
CONSOLE_FONT_INFO_EX info = new CONSOLE_FONT_INFO_EX();
info.cbSize = (uint)Marshal.SizeOf(info);
CONSOLE_FONT_INFO_EX newInfo = new CONSOLE_FONT_INFO_EX();
newInfo.cbSize = (uint)Marshal.SizeOf(newInfo);
newInfo.FontFamily = TMPF_TRUETYPE;
IntPtr ptr = new IntPtr(newInfo.FaceName);
Marshal.Copy(fontName.ToCharArray(), 0, ptr, fontName.Length);
newInfo.dwFontSize = new COORD(info.dwFontSize.X, info.dwFontSize.Y);
newInfo.FontWeight = info.FontWeight;
SetCurrentConsoleFontEx(hnd, false, ref newInfo);
}
}
}

How to fix memory leak in Word Add-In

I have a MS Word Application Add-in written with VSTO. It contains a button used to create new Letter documents. When pressed a document is instantiated, a WPF dialog is displayed to capture information and then the information is inserted into the document.
On one of my test machines I get the following exception when approximately 40 letters are created in a single Word session:
The disk is full. Free some space on this drive, or save the document
on another disk.
Try one or more of the following:
Close any unneeded documents, programs or windows.
Save the document to another disk.
So I monitored the Winword.exe process using Task Manager:
Memory starts at 97,000k
Memory steadily increases with each letter document until the error is seen at approximately 1,000,000k
If I then close all the documents the memory only drops down to 500,000k
Any tips on how I can troubleshoot the memory leak?
I've gone through my code and ensured that event handlers are unregistered and that i'm disposing objects that need disposing.
Any reference articles that I should be reading?
-- Edit --
Malick, I use unmanaged code to make the WPF window look like an Office dialog. Is there a better way of doing this? I'll try removing it. (edit, there wasn't a change. I'll try the memory monitoring tools)
public class OfficeDialog : Window
{
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
const int GWL_EXSTYLE = -20;
const int WS_EX_DLGMODALFRAME = 0x0001;
const int SWP_NOSIZE = 0x0001;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOZORDER = 0x0004;
const int SWP_FRAMECHANGED = 0x0020;
const uint WM_SETICON = 0x0080;
const int ICON_SMALL = 0;
const int ICON_BIG = 1;
public OfficeDialog()
{
this.ShowInTaskbar = false;
//this.Topmost = true;
}
public new void ShowDialog()
{
try
{
var helper = new WindowInteropHelper(this);
using (Process currentProcess = Process.GetCurrentProcess())
helper.Owner = currentProcess.MainWindowHandle;
base.ShowDialog();
}
catch (System.ComponentModel.Win32Exception ex)
{
Message.LogWarning(ex);
//this.Topmost = true;
var helper = new WindowInteropHelper(this);
using (Process currentProcess = Process.GetCurrentProcess())
helper.Owner = currentProcess.MainWindowHandle;
base.ShowDialog();
}
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
RemoveIcon(this);
HideMinimizeAndMaximizeButtons(this);
//using (Process currentProcess = Process.GetCurrentProcess())
// SetCentering(this, currentProcess.MainWindowHandle);
}
public static void HideMinimizeAndMaximizeButtons(Window window)
{
const int GWL_STYLE = -16;
IntPtr hwnd = new WindowInteropHelper(window).Handle;
long value = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (int)(value & -131073 & -65537));
}
public static void RemoveIcon(Window w)
{
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(w).Handle;
// Change the extended window style to not show a window icon
int extendedStyle = OfficeDialog.GetWindowLong(hwnd, GWL_EXSTYLE);
OfficeDialog.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
// reset the icon, both calls important
OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
// Update the window's non-client area to reflect the changes
OfficeDialog.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
static void SetCentering(Window win, IntPtr ownerHandle)
{
bool isWindow = IsWindow(ownerHandle);
if (!isWindow) //Don't try and centre the window if the ownerHandle is invalid. To resolve issue with invalid window handle error
{
//Message.LogInfo(string.Format("ownerHandle IsWindow: {0}", isWindow));
return;
}
//Show in center of owner if win form.
if (ownerHandle.ToInt32() != 0)
{
var helper = new WindowInteropHelper(win);
helper.Owner = ownerHandle;
win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
else
win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindow(IntPtr hWnd);
}

How can I get a URL entered into WinForms OpenFileDialog?

If a user enters a URL into a Windows Forms OpenFileDialog then the dialog box (on more modern versions) of Windows will download the file and open it from a temporary directory. Is there any way to get at the entered URL? Could the new-fangled IFileDialog help?
Please note that I am not looking for the file:// equivalent of a local file. This is for when the user enters the location of something on the Internet into the file dialog. e.g. http://example.com/path.
This asks essentially the same question, but didn't get a useful answer, perhaps because he asks that the result appear in the FileName property.
It's possible to set a windows hook to listen for text changes. This code currently picks up value changes from all fields, so you will need to figure out how to only detect the ComboBox filename field.
public class MyForm3 : Form {
public MyForm3() {
Button btn = new Button { Text = "Button" };
Controls.Add(btn);
btn.Click += btn_Click;
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private const int WINEVENT_OUTOFCONTEXT = 0;
private const uint EVENT_OBJECT_VALUECHANGE = 0x800E;
void btn_Click(object sender, EventArgs e) {
uint pid = 0;
uint tid = 0;
using (var p = Process.GetCurrentProcess())
GetWindowThreadProcessId(p.MainWindowHandle, out pid);
var hHook = SetWinEventHook(EVENT_OBJECT_VALUECHANGE, EVENT_OBJECT_VALUECHANGE, IntPtr.Zero, CallWinEventProc, pid, tid, WINEVENT_OUTOFCONTEXT);
OpenFileDialog d = new OpenFileDialog();
d.ShowDialog();
d.Dispose();
UnhookWinEvent(hHook);
MessageBox.Show("Original filename: " + OpenFilenameText);
}
private static String OpenFilenameText = "";
private static WinEventProc CallWinEventProc = new WinEventProc(EventCallback);
private delegate void WinEventProc(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime);
private static void EventCallback(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime) {
StringBuilder sb1 = new StringBuilder(256);
GetClassName(hWnd, sb1, sb1.Capacity);
if (sb1.ToString() == "Edit") {
StringBuilder sb = new StringBuilder(512);
GetWindowText(hWnd, sb, sb.Capacity);
OpenFilenameText = sb.ToString();
}
}
}
If you only want to get URL (not download file), set CheckFileExists flag to false.
Example code below
string urlName = null;
using (var dlg = new OpenFileDialog())
{
dlg.CheckFileExists = false;
dlg.ShowDialog();
urlName = dlg.FileName;
urlName = Path.GetFileName(urlName);
}

How can I load a program icon in C#

I have a path of some program (for example explorer), how can I get program icon, convert it to png/jpeg and then display in PictureBox?
I have something like this:
string filePath = "C:\\myfile.exe";
Icon TheIcon = IconFromFilePath(filePath);
if (TheIcon != null) {
// But then I don't know what to do...
}
public Icon IconFromFilePath(string filePath){
Icon programicon = null;
try {
programicon = Icon.ExtractAssociatedIcon(filePath);
}
catch { }
return programicon;
}
I found something similar here. Here is the icon. How I can create 32-bit icon?
The code is surprisingly simple if you know where to look. Start with the Icon class, since that's fundamentally what you're after here.
If you browse its methods, you'll come across a very interesting looking ExtractAssociatedIcon. That accepts a single string parameter that specifies the path to a file containing an icon, such as an executable file.
So that gives you an Icon object, now you just need to display it in a PictureBox. You don't have to convert it to a PNG or JPEG, a bitmap works fine. And there's a built-in member function for that: ToBitmap.
Assigning the new bitmap to the PictureBox.Image property is all you need to do to display it.
This question might be old but here's my answer.
Here's a full code snippet I used in extracting full 256 x 256 icons from any exe file.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
namespace IconUtils
{
internal static class ExtractIcon
{
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private readonly static IntPtr RT_ICON = (IntPtr)3;
private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;
public static Icon ExtractIconFromExecutable(string path)
{
IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
var tmpData = new List<byte[]>();
ENUMRESNAMEPROC callback = (h, t, name, l) =>
{
var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);
// Calculate the size of an entire .icon file.
int count = BitConverter.ToUInt16(dir, 4); // GRPICONDIR.idCount
int len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes
using (var dst = new BinaryWriter(new MemoryStream(len)))
{
// Copy GRPICONDIR to ICONDIR.
dst.Write(dir, 0, 6);
int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
{
// Load the picture.
ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);
// Copy GRPICONDIRENTRY to ICONDIRENTRY.
dst.Seek(6 + 16 * i, 0);
dst.Write(dir, 6 + 14 * i, 8); // First 8bytes are identical.
dst.Write(pic.Length); // ICONDIRENTRY.dwBytesInRes
dst.Write(picOffset); // ICONDIRENTRY.dwImageOffset
// Copy a picture.
dst.Seek(picOffset, 0);
dst.Write(pic, 0, pic.Length);
picOffset += pic.Length;
}
tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
}
return true;
};
EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
byte[][] iconData = tmpData.ToArray();
using (var ms = new MemoryStream(iconData[0]))
{
return new Icon(ms);
}
}
private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
{
// Load the binary data from the specified resource.
IntPtr hResInfo = FindResource(hModule, name, type);
IntPtr hResData = LoadResource(hModule, hResInfo);
IntPtr pResData = LockResource(hResData);
uint size = SizeofResource(hModule, hResInfo);
byte[] buf = new byte[size];
Marshal.Copy(pResData, buf, 0, buf.Length);
return buf;
}
}
}
Usage:
Icon ExeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(#"C:\Windows\explorer.exe");
Source: https://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files

Dial-up using wininet.dll Windows API issue (C#)

I'm calling the following function on wininet.dll in order to get online (C# pinvoke):
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int InternetDial(IntPtr hWndParent, string pszEntryName,
int dwFlags, ref int lpdwConnection,
int ReservedValue);
public static bool GetOnline()
{
int connectionID = 0;
InternetDial(IntPtr.Zero, "DefaultDialUp", INTERNET_AUTODIAL_FORCE_UNATTENDED, ref connectionID, 0);
return (connectionID != 0);
}
The problem is when error occurs in the dial up process, such as hardware failure,
Windows shows a blocking dialog that ask the user how to procceed,
And my function is stuck until the user causes the dialog to be closed:
This code should be deployed on automatic systems so this is a major issue for me...
I'm looking for a way to suppress the error dialogs on the windows API level..
Thanks in advance,
Eitan.
Iv'e managed to find a workaruond for the issue, but it's pretty nasty,
better solutions still welcome...
const int WM_CLOSE = 0x10;
const int INTERNET_AUTODIAL_FORCE_UNATTENDED = 0x2;
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int InternetDial(IntPtr hWndParent, string pszEntryName, int dwFlags, ref int lpdwConnection, int ReservedValue);
public static bool GetOnline()
{
connectionID = 0;
Form f = null;
var t = new Thread((ParameterizedThreadStart)delegate
{
f = new Form();
InternetDial(f.Handle, "DefaultDialUp", INTERNET_AUTODIAL_FORCE_UNATTENDED, ref connectionID, 0);
});
t.Start();
t.Join(23000); //wait 23 seconds before closing the window
f.Invoke((EventHandler)delegate {
PostMessage(f.Handle.ToInt32(), WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
});
t.Join();
return (connectionID != 0);
}

Categories

Resources