How can I load a program icon in C# - 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

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);
}
}
}

Extracting an icon group from a .dll file in C#

I'm trying to extract an icon from imageres.dll. Specifically the "My Computer" or "This PC" icon. The problem is that at between Win7 and Win10, the icon number changes. However, the icon group does not (109). Is there a way to get that icon group, and then let the computer figure out which icon to use of that group, in the same way it figures out which icon to use for my app?
This is the code I'm using to get the specific icon via the index:
public class GetIcon {
public static Icon Extract(string file, int number) {
IntPtr large;
IntPtr small;
ExtractIconEx(file, number, out large, out small, 1);
try {
return Icon.FromHandle(small);
}
catch {
return null;
}
}
[DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);
}
Thanks.
There are a couple of ways to do this. The most reliable, and potentially most time consuming (provided you can't find an existing library), is to parse the PE File (i.e. .exe, .dll) and extract the relevant Icon group data yourself. Here's a good resource for the format: https://msdn.microsoft.com/en-us/library/ms809762.aspx
The second way, can be done easily enough with Windows functions, however there is one caveat. It will only work on PE files that are of the same bit-type as your application. So, for example, if your application is 64-bit, it will only work on 64-bit PE files.
Here's a function I just wrote - based off this: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648051(v=vs.85).aspx#_win32_Sharing_Icon_Resources, that takes a file name, group number, and desired icon size, and returns a System.Drawing.Icon
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32.dll")]
static extern IntPtr FindResource(IntPtr hModule, int lpName, int lpType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll")]
static extern IntPtr LockResource(IntPtr hResData);
[DllImport("user32.dll")]
static extern int LookupIconIdFromDirectoryEx(byte[] presbits, bool fIcon, int cxDesired, int cyDesired, uint Flags);
[DllImport("user32.dll")]
static extern IntPtr CreateIconFromResourceEx(byte[] pbIconBits, uint cbIconBits, bool fIcon, uint dwVersion, int cxDesired, int cyDesired, uint uFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
const int RT_GROUP_ICON = 14;
const int RT_ICON = 0x00000003;
private System.Drawing.Icon GetIconFromGroup(string file, int groupId, int size)
{
IntPtr hExe = LoadLibrary(file);
if(hExe != IntPtr.Zero)
{
IntPtr hResource = FindResource(hExe, groupId, RT_GROUP_ICON);
IntPtr hMem = LoadResource(hExe, hResource);
IntPtr lpResourcePtr = LockResource(hMem);
uint sz = SizeofResource(hExe, hResource);
byte[] lpResource = new byte[sz];
Marshal.Copy(lpResourcePtr, lpResource, 0, (int)sz);
int nID = LookupIconIdFromDirectoryEx(lpResource, true, size, size, 0x0000);
hResource = FindResource(hExe, nID, RT_ICON);
hMem = LoadResource(hExe, hResource);
lpResourcePtr = LockResource(hMem);
sz = SizeofResource(hExe, hResource);
lpResource = new byte[sz];
Marshal.Copy(lpResourcePtr, lpResource, 0, (int)sz);
IntPtr hIcon = CreateIconFromResourceEx(lpResource, sz, true, 0x00030000, size, size, 0);
System.Drawing.Icon testIco = System.Drawing.Icon.FromHandle(hIcon);
return testIco;
}
return null;
}
The process basically works like this:
use LoadLibrary to load up the .exe or .dll file
Get the handle & data of the RT_GROUP_ICON resource
Pass the data, along with the desired size to LookupIconIdFromDirectoryEx, to get the icon index
From there, you can either use ExtractIconEx, or just repeat step 2 with the icon index, and RT_ICON instead, followed by using CreateIconFromResourceEx to get your icon handle.

Retrieving the parent window Handle C# (trying to maximize outlook)

I generally do run the method listed below to maximize iconized windows;
however when it comes to outlook, there are times where it will maximize a Mail (message) that i have open instead of the parent application (outlook) ; its just pulling up anything outlook that it finds and i need the parent, how can i achieve this?
I have tried using WINAPI GetAncestor, I have also tried GetParent .
public static bool EventChecking(string progr)
{
int bb = 0;
if (Process.GetProcessesByName(progr).Length > 0)
{
bb++;
}
if (bb == 0)
{
return false;
}
foreach (Process ddcd in Process.GetProcesses())
{
if (ddcd.ProcessName.Contains(progr))
{
if (ddcd.MainWindowHandle != IntPtr.Zero)
{
pointer = ddcd.MainWindowHandle;
if (IsIconic(pointer))
{
SendMessage(pointer, 0x112, 0xF120, 0);
}
SetForegroundWindow(pointer);
}
};
}
return true;
}
EDIT:
I also recently tried:
if (ddcd.MainWindowTitle.EndsWith("- Outlook"))
and it still pulls up the single email
I have also had trouble working with Outlook via C# but I have had some success with Win32 calls. Below is one way to locate the Outlook Main Window by checking the Caption.
You could also try EnumWindows but it takes more effort to implement due to Callbacks.
using System.Text;
using System.Runtime.InteropServices;
public IntPtr GetOutlookHandle()
{
string windowClass = "rctrl_renwnd32";
uint GW_HWNDNEXT = 2;
IntPtr firstHandle = new IntPtr(0);
IntPtr handle = new IntPtr(0);
// Look for a Window with the right Class
firstHandle = FindWindow(windowClass, null);
// Nothing Found
if (firstHandle.Equals(IntPtr.Zero)) return IntPtr.Zero;
// Remember where we started to avoid an infinite loop
handle = firstHandle;
do
{
// Check the Caption to find the Main Window
if (GetWindowCaption(handle).EndsWith(" - Microsoft Outlook"))
{
return handle;
}
// Get the next Window with the same Class
handle = GetWindow(handle, GW_HWNDNEXT);
} while (handle != firstHandle);
// Didn't find any matches
return IntPtr.Zero;
}
private static string GetWindowCaption(IntPtr windowHandle)
{
// Determine Length of Caption
int length = GetWindowTextLength(windowHandle);
StringBuilder sb = new StringBuilder(length + 1);
// Get Window Caption
GetWindowText(windowHandle, sb, sb.Capacity);
return sb.ToString();
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetWindowTextLength(IntPtr hWnd);

Convert C# bitmap to Windows dib handle for RIOT?

I am trying to implement an application which uses RIOT (Radical Image Optimization Tool) for batch image optimizaton. I can successfully import riot.dll into my app. But I cannot figure out how to pass a Windows DIB (Device Independent Bitmap) handle to RIOT function.
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Riot_Test
{
public partial class Form1 : Form
{
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern bool RIOT_LoadFromDIB(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName = "", [MarshalAs(UnmanagedType.LPStr)] string iniFile = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
[DllImport("RIOT.dll")]
static extern void RIOT_Show();
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern bool RIOT_LoadFromFile([MarshalAs(UnmanagedType.LPStr)] string filename, int flags = 0);
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RIOT_SaveToFile(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName, [MarshalAs(UnmanagedType.LPStr)] string origFilename = "", ulong byteSize = 0, [MarshalAs(UnmanagedType.LPStr)] string errorText = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
public Form1()
{
InitializeComponent();
//RIOT_Show();
IntPtr hdib = IntPtr.Zero;
IntPtr hwnd = IntPtr.Zero;
string errorText = "";
Bitmap bmp = new Bitmap("dene.jpg");
hdib = bmp.GetHbitmap();
string fn = "optim2.jpg";
string fno = "dene.jpg";
bool result = RIOT_SaveToFile_U(hdib, hwnd, fn);
}
}
}
RIOT_Show() and RIOT_Load_From_File() are working as expected but when I try to call RIOT_SaveToFile() it gives me this error:
System.AccessViolationException was unhandled - Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
So my questions are:
How can I convert a System.Bitmap object to Windows DIB handle ?
If I can't convert is it possible to use a C++ library (if there is) to do the job for me and return the DIB handle?
Edit:
I've changed my code to this but it gives the same error.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace from_vb
{
public partial class Form1 : Form
{
[DllImport("gdi32.dll", SetLastError = true)]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref GDI32BITMAPINFOHEADER pbmi, uint pila, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
[DllImport("gdi32.dll")]
static extern int GetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan,
uint cScanLines, [Out] byte[] lpvBits, ref GDI32BITMAPINFOHEADER lpbmi, uint uUsage);
[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
static extern bool GdiFlush();
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RIOT_SaveToFile(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName, [MarshalAs(UnmanagedType.LPStr)] string origFilename = "", ulong byteSize = 0, [MarshalAs(UnmanagedType.LPStr)] string errorText = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
public const int BI_RGB = 0;
public const int DIB_PAL_COLORS = 1;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct GDI32BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public short bmPlanes;
public short bmBitsPixel;
public int bmBits;
}
[StructLayout(LayoutKind.Sequential)]
public struct GDI32BITMAPINFOHEADER
{
public int biSize;
public int biWidth;
public int biHeight;
public short biPlanes;
public short biBitCount;
public int biCompression;
public int biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (int)Marshal.SizeOf(this);
}
}
public Form1()
{
InitializeComponent();
IntPtr hdc = IntPtr.Zero;
IntPtr hSrcBitmap = IntPtr.Zero;
IntPtr pSrcBitmapInfo = IntPtr.Zero;
IntPtr hDestDIBitmap = IntPtr.Zero;
IntPtr hDstOldBitmap = IntPtr.Zero;
IntPtr pDestDIBits = IntPtr.Zero;
IntPtr hSection = IntPtr.Zero;
IntPtr hwnd = IntPtr.Zero;
IntPtr ccDC = IntPtr.Zero;
Bitmap dotNetBitmap;
int XDPI, YDPI;
GDI32BITMAP srcBitmapInfo = new GDI32BITMAP();
//ccDC = CreateCompatibleDC(hdc);
IntPtr hDstMemDC = CreateCompatibleDC(hdc);
GDI32BITMAPINFOHEADER DestDIBMIH = new GDI32BITMAPINFOHEADER();
dotNetBitmap = new Bitmap("dene.jpg");
hSrcBitmap = dotNetBitmap.GetHbitmap();
pSrcBitmapInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(srcBitmapInfo));
GetObject(hSrcBitmap, Marshal.SizeOf(srcBitmapInfo),pSrcBitmapInfo);
srcBitmapInfo = (GDI32BITMAP)Marshal.PtrToStructure(pSrcBitmapInfo, srcBitmapInfo.GetType());
if (pSrcBitmapInfo != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pSrcBitmapInfo);
}
DestDIBMIH.biSize = Marshal.SizeOf(DestDIBMIH);
DestDIBMIH.biWidth = srcBitmapInfo.bmWidth;
DestDIBMIH.biHeight = srcBitmapInfo.bmHeight;
DestDIBMIH.biPlanes = srcBitmapInfo.bmPlanes;
DestDIBMIH.biBitCount = 24;
DestDIBMIH.biCompression = BI_RGB;
hDestDIBitmap = CreateDIBSection(hDstMemDC, ref DestDIBMIH, 0, out pDestDIBits, hSection, 0);
string fn = "optim2.jpg";
string fno = "dene.jpg";
bool hede = RIOT_SaveToFile(hDestDIBitmap, hwnd, fn);
}
}
}
Here is the "documentation" on that method:
bool RIOT_SaveToFile(HANDLE hDIB, HWND hwndParent,const char *fileName,const char *origFilename=”", unsigned long byteSize=0,char *errorText=”",int flags=0, char *buf=”")
Saves the file with the specified parameters.
Parameters:
hDIB – handle to a Windows DIB image in memory
hwndParent – Not Used. Must be NULL.
fileName – full path to the file to be saved (only JPEG is supported)
origFilename – Fill this with the original file name if the DIB is not different than the image from the file
byteSize – filesize of the compressed JPEG image in bytes
errorText – On error errorText is filled with the error message
flags – save flags. See bellow
buf – not used. Leave blank.THe function returns true on success or false on error.If you specify byteSize you can specify any of the save flags, but the quality will not be used.
If you don’t specify byteSize flags are used.
If there are no flags or byteSize is 0 an error is thrown.Flags for RIOT_SaveToFile:0×0001 – keep EXIF
0×0002 – keep IPTC
0×0004 – keep XMP
0×0008 – keep Comments
0×1000 – keep ICC profile0x0800 – save greyscale
0×2000 – save progressive
0×10000 – disable chroma subsamplingAlso you can set a quality flag from 1 to 100Ex: flags=JPEG_SUBSAMPLING_444 | JPEG_PROGRESSIVE | 90
results in a file with no subsampling, progressive with a quality of 90
If you don’t specify quality 75 is used.
You must specify JPEG_PROGRESSIVE if you want progressive.
If you don’t specify JPEG_SUBSAMPLING_444 a default chroma of 4:2:0 is used.
The first issue is with errorText. The doc states, "On error errorText is filled with the error message." This suggests that you have to pass an array of bytes of un-specified length that will get filled in. That's hideous.
The second issue is where it says, "If there are no flags or byteSize is 0 an error is thrown."
My guess is that you're getting an error and it's trying to copy bytes into errorText. Try passing a largish byte[] instead of a string.
Your System.Drawing.Bitmap object is a Device Dependent Bitmap (DDB). You need a Device Independent Bitmap (DIB). I'm not aware of any help in the .Net framework for this, but you can p/Invoke CreateDIBSection to create one.

How to programmatically install a font

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

Categories

Resources