AddFontResourceW after create new Font object - c#

i have got some problems with adding custom fonts, after creating a font object.
Here is some demo code:
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, uint wMsg, int wParam, int lParam);
[DllImport("gdi32.dll", EntryPoint = "AddFontResourceW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int AddFontResource([In][MarshalAs(UnmanagedType.LPWStr)]
public void Demo()
{
var font = new Font("Roboto", 8); //Create roboto font. Not installed yet, then use Times New Roman. Ok!
var result = AddFontResource(#"C:\Roboto.ttf"); //Install roboto font until system reboots (Sample filename). result == 1. Ok!
var test = SendMessage(0xffff, 0x001D, 0, 0);
font = new Font("Roboto", 8); //Font should be roboto, but still Times New Roman.
}
Then following demo works:
public void Demo()
{
var result = AddFontResource(#"C:\Roboto.ttf"); //Install roboto font until system reboots (Sample filename). result == 1. Ok!
var test = SendMessage(0xffff, 0x001D, 0, 0);
var font = new Font("Roboto", 8); //Font is roboto. OK!
}
Could somebody tell me why AddFontResourceW only works, if no font object was created earlier? Or how can i get the first example to run properly?

Related

Form Font Embedding

It's a while that I'm trying to figure out what's happening in this piece of code.
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont,
uint cbFont, IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts);
public static PrivateFontCollection myFontCollection = new PrivateFontCollection();
public static FontFamily RobotoBold = null;
public static FontFamily RobotoThin = null;
public enum Fonts
{
Roboto_Bold = 0,
Roboto_Thin = 1
}
public static void loadFonts()
{
Array fonts = Enum.GetValues(typeof(Fonts));
foreach (Fonts font in fonts)
{
byte[] fontData = (byte[])Resources.ResourceManager.GetObject(font.ToString());
IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length);
System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
uint dummy = 0;
myFontCollection.AddMemoryFont(fontPtr, fontData.Length);
AddFontMemResourceEx(fontPtr, (uint)fontData.Length, IntPtr.Zero, ref dummy);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr);
}
RobotoBold = Program.myFontCollection.Families[(int)Program.Fonts.Roboto_Bold];
RobotoThin = Program.myFontCollection.Families[(int)Program.Fonts.Roboto_Thin];
}
Actually it reads the .ttf I've embedded as resources, but if I debug, inside the FontFamilys I read this message:
{Name = The name 'name' does not exist in the current context}
I've already tried to figure out what's happening, but can't find my error.
The resource is being read correctly using the ResourceManager, but I think something's wrong while adding the font.

Resize system icon in C#

I want to use SystemIcons.Warning but it is too big for my need. I want to resize it.
I have tried :
Icon sizedIcon = new Icon(SystemIcons.Warning, new Size(10,10));
But it does not work, icon remains the same.
Any suggestions?
The .NET Icon class is pretty crippled, it is stuck in the previous decade due to once-relevant support for Windows 98 and Windows 2000. On top of this, Windows does not support loading the system icons in any size other than the system's default icon size. Usually 32x32. Resizing it is going to inevitably look bad.
Do keep in mind that no icon is ever going to look good at 10x10. It is but a fleck on a modern monitor. You do get ahead a bit by starting with an icon size that's close to the desired final size, the less drastic the required resize, the higher the odds that it still looks reasonable. When you can, do favor sizes that are likely to be present in the icon. Like 16x16, 32x32, 48x48.
Anyhoo, this is fixable. Do keep in mind that this takes considerable hack-o-rama since Windows doesn't directly support this. What's required is reading the icon directly from the system DLL resources. And using a more modern winapi, LoadImage() instead of the one that .NET uses, LoadIcon(). Works on XP and up.
Add a new class to your project and paste this code:
using System;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
public class IconEx : IDisposable {
public enum SystemIcons {
Application = 100,
Asterisk = 104,
Error = 103,
Exclamation = 101,
Hand = 103,
Information = 104,
Question = 102,
Shield = 106,
Warning = 101,
WinLogo = 100
}
public IconEx(string path, Size size) {
IntPtr hIcon = LoadImage(IntPtr.Zero, path, IMAGE_ICON, size.Width, size.Height, LR_LOADFROMFILE);
if (hIcon == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
attach(hIcon);
}
public IconEx(SystemIcons sysicon, Size size) {
IntPtr hUser = GetModuleHandle("user32");
IntPtr hIcon = LoadImage(hUser, (IntPtr)sysicon, IMAGE_ICON, size.Width, size.Height, 0);
if (hIcon == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
attach(hIcon);
}
public Icon Icon {
get { return this.icon; }
}
public void Dispose() {
if (icon != null) icon.Dispose();
}
private Icon icon;
private void attach(IntPtr hIcon) {
// Invoke the private constructor so we can get the Icon object to own the handle
var ci = typeof(Icon).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
null, new Type[] { typeof(IntPtr), typeof(bool) }, null);
this.icon = (Icon)ci.Invoke(new object[] { hIcon, true});
}
private const int IMAGE_ICON = 1;
private const int LR_LOADFROMFILE = 0x10;
private const int LR_SHARED = 0x8000;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetModuleHandle(string name);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadImage(IntPtr hinst, string lpszName, int uType,
int cxDesired, int cyDesired, int fuLoad);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadImage(IntPtr hinst, IntPtr resId, int uType,
int cxDesired, int cyDesired, int fuLoad);
}
Sample usage:
using (var icon = new IconEx(IconEx.SystemIcons.Warning, new Size(10, 10))) {
e.Graphics.DrawIcon(icon.Icon, 0, 0);
}
It does look better than SystemIcons.Warning. It's squeaky clean when you use 16x16.

How to set font size in DateTimePicker

I want to increase font size in DateTimePicker in Window Form C#. I want to set minimum 14 to 16 font size in DateTime picker.
I have tried below code but it's not working.
dateTimePicker1.CalendarFont = new Font("Courier New", 8.25F, FontStyle.Italic, GraphicsUnit.Point, ((Byte)(0)));
If you wish to retain visual styles for the other controls in your application, but disable for the date picker's drop down only, you can use the following code:
public class MyDateTimePicker : DateTimePicker
{
[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
static extern Int32 SetWindowTheme(IntPtr hWnd, String textSubAppName, String textSubIdList);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
protected override void OnDropDown(EventArgs eventargs)
{
if (Application.RenderWithVisualStyles)
{
const int DTM_GETMONTHCAL = 0x1008;
//Get handle of calendar control - disable theming
IntPtr hCalendar = SendMessage(this.Handle, DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
if (hCalendar != IntPtr.Zero)
{
SetWindowTheme(hCalendar, "", "");
//Get handle of parent popup - resize appropriately
IntPtr hParent = GetParent(hCalendar);
if (hParent != IntPtr.Zero)
{
//The size you specify here will depend on the CalendarFont size chosen
MoveWindow(hParent, 0, 0, 400, 300, true);
}
}
}
base.OnDropDown(eventargs);
}
}
In main program delete / comment line Application.EnableVisualStyles();
and add new line of code after yours:
dateTimePicker1.Font = new Font("Courier New", 8.25F, FontStyle.Italic, GraphicsUnit.Point, ((Byte)(0)));
In iOS u have to make a renderer:
private void SetFont(CustomPicker view)
{
UIFont uiFont;
Control.Font = UIFont.SystemFontOfSize(11f); //the size which u want
}
In android you have to set the font for the renderer:
private void SetFont(CustomDatePicker view)
{
if (view.Font != Font.Default)
{
Control.TextSize = view.Font.ToScaledPixel();
Typeface font = Typeface.CreateFromAsset(Forms.Context.Assets,"Roboto-Bold.ttf");
Control.Typeface = font;
Control.Typeface = view.Font.ToTypeface();
}
}

How to read another windows from a different program

I tried it with findwindow and process but it didn't work, how can I find a specific button ?
For example I have the button class AfxWnd90u and the instance 21. I want to check if this button is visible. I tried it with this code, but I couldn't find the button. I think I made a mistake with the instance.
Between I didn't use findwindow here because I experimented a little bit.
//////IMPORTANT/////////////
System.Diagnostics.Process[] move = System.Diagnostics.Process.GetProcessesByName("PartyGaming");
ArrayList save = new ArrayList();
RECT rct = new RECT();
listBox1.Items.Add(move.Length);
List<System.Diagnostics.Process> process = new List<System.Diagnostics.Process>();
// use only the process with the button AfxWnd90u21
for (int i = 0; i < move.Length;++i )
{
IntPtr hCheck = FindWindowEx(move[i].MainWindowHandle, IntPtr.Zero, "AfxWnd90u21", null);
//if button is visible
if (hCheck != IntPtr.Zero)
process.Add(move[i]);
//////IMPORTANT/////////////
}
I believe a combination of FindWindow and SendMessage Windows API functions will give you want you want. The tricky part will be discovering the window class names, but something like WinSpy++ could help you there.
Here's a sample of how to use the API. Open Notepad.exe a few times, type in some text and then run this sample.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<WinText> windows = new List<WinText>();
//find the "first" window
IntPtr hWnd = FindWindow("notepad", null);
while (hWnd != IntPtr.Zero)
{
//find the control window that has the text
IntPtr hEdit = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);
//initialize the buffer. using a StringBuilder here
System.Text.StringBuilder sb = new System.Text.StringBuilder(255); // or length from call with GETTEXTLENGTH
//get the text from the child control
int RetVal = SendMessage(hEdit, WM_GETTEXT, sb.Capacity, sb);
windows.Add(new WinText() { hWnd = hWnd, Text = sb.ToString() });
//find the next window
hWnd = FindWindowEx(IntPtr.Zero, hWnd, "notepad", null);
}
//do something clever
windows.OrderBy(x => x.Text).ToList().ForEach(y => Console.Write("{0} = {1}\n", y.hWnd, y.Text));
Console.Write("\n\nFound {0} window(s).", windows.Count);
Console.ReadKey();
}
private struct WinText
{
public IntPtr hWnd;
public string Text;
}
const int WM_GETTEXT = 0x0D;
const int WM_GETTEXTLENGTH = 0x0E;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int msg, int Param, System.Text.StringBuilder text);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
}
}
Autoit provides a great way to interact with Windows.
Install the nuget package called AutoItX.Dotnet
using AutoIt;
class Program
{
static void Main(string[] args)
{
var buttonVisible = AutoItX.ControlCommand("Untitled - Notepad", "", "[CLASSNN:Edit1]", "IsVisible", "");
//in your case it would be:
//var buttonVisible = AutoItX.ControlCommand("Put the application title here", "", "[CLASSNN:AfxWnd90u21]", "IsVisible", "");
if (buttonVisible == "1")
{
Console.WriteLine("Visible");
} else
{
Console.WriteLine("Not visible");
}
}
}

Windows Forms: Can't get font resource to show properly

have added a TrueType font to my project resources ("MyFontResource"), and I've set the build action to "Resource." My intention is to replace the font on a Label object with this resource.
Here's my code:
PrivateFontCollection myFonts = new PrivateFontCollection();
unsafe {
fixed (byte* fontBytes = Properties.Resources.MyFontResource)
myFonts.AddMemoryFont((IntPtr)fontBytes, Properties.Resources.MyFontResource.Length);
}
myLabel.Font = new Font(myFonts.Families[0], 10f);
The font displays as expected only when I have the font installed locally. If I haven't installed the font, then I see the font originally assigned to myLabel in my C# project.
Now what?
Never mind, found the reason this doesn't work here.
Here's a solution that works (original code here):
class MyClass {
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
public MyClass() {
uint installCount = 1;
PrivateFontCollection myFonts = new PrivateFontCollection();
unsafe {
fixed (byte* pFontData = Properties.Resources.MyFont) {
myFonts.AddMemoryFont((IntPtr)pFontData, Properties.Resources.MyFont.Length);
AddFontMemResourceEx((IntPtr)pFontData, (uint)Properties.Resources.MyFont.Length, IntPtr.Zero, ref installCount);
}
}
myLabel.Font = new Font(myFonts.Families[0], 20f);
}
}

Categories