I have implemented all required code to get file type name from file path and it is working successfully but it returns subtracted type name e.g. if file path of .pdb or .pdf file then it will return "obe Acrobat Document" instead of "Adobe Acrobat Document"
I have used shell32.dll. I am not getting what happens please, help me to get rid out of it.
Source code:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct SHFILEINFO
{
public IntPtr hIcon;
public IntPtr iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
internal class Win32
{
public const uint FILE_ATTRIBUTE_NORMAL = 0x80;
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x10;
public const uint SHGFI_TYPENAME = 0x000000400;
public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
internal const uint SHGFI_SYSICONINDEX = 0x000004000;
internal const int ILD_TRANSPARENT = 0x1;
internal const uint SHGFI_ICON = 0x100;
internal const uint SHGFI_LARGEICON = 0x0;
internal const uint SHGFI_SMALLICON = 0x1;
[DllImport("shell32.dll", CharSet=CharSet.Unicode)]
internal static extern IntPtr SHGetFileInfo
(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbSizeFileInfo,
uint uFlags
);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
internal static extern int ExtractIconEx
(
string stExeFileName,
int nIconIndex,
ref IntPtr phiconLarge,
ref IntPtr phiconSmall,
int nIcons
);
[DllImport("comctl32.dll", SetLastError = true)]
internal static extern IntPtr ImageList_GetIcon
(
IntPtr himl,
int i,
int flags
);
[DllImport("user32.dll")]
internal static extern bool DestroyIcon(IntPtr hIcon);
}
internal static string GetFileType(string filename)
{
SHFILEINFO shinfo = new SHFILEINFO();
Win32.SHGetFileInfo
(
filename,
Win32.FILE_ATTRIBUTE_NORMAL,
ref shinfo, (uint)Marshal.SizeOf(shinfo),
Win32.SHGFI_TYPENAME |
Win32.SHGFI_USEFILEATTRIBUTES
);
return shinfo.szTypeName; //It return "obe Acrobat Document" Instead of "Adobe Acrobat Document"
}
The iIcon field in the C++ struct has type int.So, I just have to set the type of iIcon int only, not IntPtr. IntPtr works as per system platform so. I just set int type to iIcon like,
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
And It's working fine...
For my program I need to get detailed information about the current displays. In my research I came across this post with talks about linking the System.Windows.Forms.Screen class and its EDID information. At first I tried copying and pasting the code found with using p/invoke to supply all the required native methods and structs, but it did not work and only gave me a string of ? for the InstanceID. So instead I tried to use the MSDN resources and again p/invoke to create the code myself. This is what I came up with:
private static void Foo()
{
Guid DisplayGUID = new Guid(Bar.GUID_DEVINTERFACE_MONITOR);
IntPtr DisplaysHandle = Bar.SetupDiGetClassDevs(ref DisplayGUID, null, IntPtr.Zero, (uint)(Win32.DIGCF_PRESENT | Win32.DIGCF_DEVICEINTERFACE));
Bar.SP_DEVICE_INTERFACE_DATA Data = new Bar.SP_DEVICE_INTERFACE_DATA();
Data.cbSize = Marshal.SizeOf(Data);
for (uint id = 0; Bar.SetupDiEnumDeviceInterfaces(DisplaysHandle, IntPtr.Zero, ref DisplayGUID, id, ref Data); id++)
{
Bar.SP_DEVINFO_DATA SPDID = new Bar.SP_DEVINFO_DATA();
SPDID.cbSize = (uint)Marshal.SizeOf(SPDID);
Bar.SP_DEVICE_INTERFACE_DETAIL_DATA NDIDD = new Bar.SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8) //64 bit
NDIDD.cbSize = 8;
else //32 bit
NDIDD.cbSize = 4 + Marshal.SystemDefaultCharSize;
uint requiredsize = 0;
uint buffer = Bar.BUFFER_SIZE;
if (Bar.SetupDiGetDeviceInterfaceDetail(DisplaysHandle, ref Data, ref NDIDD, buffer, ref requiredsize, ref SPDID))
{
uint size = 0;
Bar.CM_Get_Device_ID_Size(out size, SPDID.DevInst);
IntPtr ptrInstanceBuf = Marshal.AllocHGlobal((int)size);
Bar.CM_Get_Device_ID(SPDID.DevInst, ref ptrInstanceBuf, size);
string InstanceID = Marshal.PtrToStringAuto(ptrInstanceBuf);
Console.WriteLine("InstanceID: {0}", InstanceID);
Marshal.FreeHGlobal(ptrInstanceBuf);
Console.WriteLine("DevicePath: {0}\n", NDIDD.DevicePath);
}
}
Bar.SetupDiDestroyDeviceInfoList(DisplaysHandle);
}
private class Bar
{
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string Enumerator, IntPtr hwndParent, uint Flags);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport(#"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, IntPtr devInfo, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);
[DllImport(#"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr hDevInfo, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData, UInt32 deviceInterfaceDetailDataSize, ref UInt32 requiredSize, ref SP_DEVINFO_DATA deviceInfoData);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern int CM_Get_Device_ID_Size(out uint pulLen, UInt32 dnDevInst, int flags = 0);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern int CM_Get_Device_ID(uint dnDevInst, ref IntPtr Buffer, uint BufferLen, int ulFlags = 0);
public const int BUFFER_SIZE = 168; //guess
public const string GUID_DEVINTERFACE_MONITOR = "{E6F07B5F-EE97-4a90-B076-33F57BF4EAA7}";
[Flags]
public enum DiGetClassFlags : uint
{
DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE
DIGCF_PRESENT = 0x00000002,
DIGCF_ALLCLASSES = 0x00000004,
DIGCF_PROFILE = 0x00000008,
DIGCF_DEVICEINTERFACE = 0x00000010,
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public Int32 cbSize;
public Guid interfaceClassGuid;
public Int32 flags;
private UIntPtr reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVINFO_DATA
{
public uint cbSize;
public Guid classGuid;
public uint DevInst;
public IntPtr reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public int cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
public string DevicePath;
}
}
My code compiles and runs, but it does not give me the output I am looking for.
The output that I am looking for is:
InstanceID: DISPLAY\DELA00B\5&786e6ca&0&UID1048832
DevicePath: \\?\display#dela00b#5&786e6ca&0&uid1048832#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
But this is the output I am receiving:
InstanceID: l
DevicePath: \\?\display#dela00b#5&786e6ca&0&uid1048832#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
My question comes in the form of what is the problem causing the InstanceID to not output correctly.
Turns out I was using the wrong p/invoke signature. CM_Get_Device_ID should look like this:
[DllImport("setupapi.dll", SetLastError = true)]
public static extern int CM_Get_Device_ID(uint dnDevInst, StringBuilder Buffer, int BufferLen, int ulFlags = 0);
Also Updated Usage Code:
StringBuilder IDBuffer = new StringBuilder((int)buffer);
Bar.CM_Get_Device_ID(SPDID.DevInst, IDBuffer, (int)buffer);
Console.WriteLine("InstanceID: {0}", IDBuffer.ToString());
Console.WriteLine("DevicePath: {0}\n", NDIDD.DevicePath);
I need to add a custom form size to the local Print Server through code. I would like to do it in a bat file or in C#, or possibly in something else I can run when running my InstallShield installer.
To better explain, to do this manually, open Devices and Printers and click on a printer. Then click Print Server Properties. The form below will open, and you can view/add/delete Forms. I would like to add a new one here through code (then eventually select this new paper size in the printers Advanced options).
This code project article explains how to do it, and presumably has some helper classes and methods. Some sample code is below:
var formInfo = new FormInfo1();
formInfo.Flags = 0;
formInfo.pName = paperName;
// all sizes in 1000ths of millimeters
formInfo.Size.width = (int)(widthMm * 1000.0);
formInfo.Size.height = (int)(heightMm * 1000.0);
formInfo.ImageableArea.left = 0;
formInfo.ImageableArea.right = formInfo.Size.width;
formInfo.ImageableArea.top = 0;
formInfo.ImageableArea.bottom = formInfo.Size.height;
// Add the paper size to the printer's list of available paper sizes:
bool bFormAdded = AddForm(hPrinter, 1, ref formInfo);
http://www.codeproject.com/Articles/12229/Adding-custom-paper-sizes-to-named-printers
I get code from here: http://www.codeproject.com/Articles/12229/Adding-custom-paper-sizes-to-named-printers. But it dosnt work.
You need to replace FormInfo1 from source code to this --v--v--v--
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct FormInfo1
{
public uint Flags;
public String pName;
public structSize Size;
public structRect ImageableArea;
};
And dont use this method "AddCustomPaperSize" - it dosn't work
Only method "AddCustomPaperSizeToDefaultPrinter" is working (for me)
Here is result:
Here is full work code:
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.ComponentModel;
using System.Drawing.Printing;
namespace MJMCustomPrintForm
{
/// <summary>
/// Summary description for MJMCustomPrintForm.
/// </summary>
public class MJMCustomPrintForm
{
// Make a static class
private MJMCustomPrintForm()
{
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct structPrinterDefaults
{
[MarshalAs(UnmanagedType.LPTStr)] public String pDatatype;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.I4)] public int DesiredAccess;
};
[DllImport("winspool.Drv", EntryPoint="OpenPrinter", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)]
string printerName,
out IntPtr phPrinter,
ref structPrinterDefaults pd);
[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,
CallingConvention=CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool ClosePrinter(IntPtr phPrinter);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct structSize
{
public Int32 width;
public Int32 height;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct structRect
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct FormInfo1
{
public uint Flags;
public String pName;
public structSize Size;
public structRect ImageableArea;
};
//[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
//internal struct FormInfo1
//{
// [FieldOffset(0), MarshalAs(UnmanagedType.I4)] public uint Flags;
// [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)] public String pName;
// [FieldOffset(8)] public structSize Size;
// [FieldOffset(16)] public structRect ImageableArea;
//};
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi/* changed from CharSet=CharSet.Auto */)]
internal struct structDevMode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String
dmDeviceName;
[MarshalAs(UnmanagedType.U2)] public short dmSpecVersion;
[MarshalAs(UnmanagedType.U2)] public short dmDriverVersion;
[MarshalAs(UnmanagedType.U2)] public short dmSize;
[MarshalAs(UnmanagedType.U2)] public short dmDriverExtra;
[MarshalAs(UnmanagedType.U4)] public int dmFields;
[MarshalAs(UnmanagedType.I2)] public short dmOrientation;
[MarshalAs(UnmanagedType.I2)] public short dmPaperSize;
[MarshalAs(UnmanagedType.I2)] public short dmPaperLength;
[MarshalAs(UnmanagedType.I2)] public short dmPaperWidth;
[MarshalAs(UnmanagedType.I2)] public short dmScale;
[MarshalAs(UnmanagedType.I2)] public short dmCopies;
[MarshalAs(UnmanagedType.I2)] public short dmDefaultSource;
[MarshalAs(UnmanagedType.I2)] public short dmPrintQuality;
[MarshalAs(UnmanagedType.I2)] public short dmColor;
[MarshalAs(UnmanagedType.I2)] public short dmDuplex;
[MarshalAs(UnmanagedType.I2)] public short dmYResolution;
[MarshalAs(UnmanagedType.I2)] public short dmTTOption;
[MarshalAs(UnmanagedType.I2)] public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String dmFormName;
[MarshalAs(UnmanagedType.U2)] public short dmLogPixels;
[MarshalAs(UnmanagedType.U4)] public int dmBitsPerPel;
[MarshalAs(UnmanagedType.U4)] public int dmPelsWidth;
[MarshalAs(UnmanagedType.U4)] public int dmPelsHeight;
[MarshalAs(UnmanagedType.U4)] public int dmNup;
[MarshalAs(UnmanagedType.U4)] public int dmDisplayFrequency;
[MarshalAs(UnmanagedType.U4)] public int dmICMMethod;
[MarshalAs(UnmanagedType.U4)] public int dmICMIntent;
[MarshalAs(UnmanagedType.U4)] public int dmMediaType;
[MarshalAs(UnmanagedType.U4)] public int dmDitherType;
[MarshalAs(UnmanagedType.U4)] public int dmReserved1;
[MarshalAs(UnmanagedType.U4)] public int dmReserved2;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct PRINTER_INFO_9
{
public IntPtr pDevMode;
}
[DllImport("winspool.Drv", EntryPoint="AddFormW", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool AddForm(
IntPtr phPrinter,
[MarshalAs(UnmanagedType.I4)] int level,
ref FormInfo1 form);
[DllImport("winspool.Drv", EntryPoint="DeleteForm", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool DeleteForm(
IntPtr phPrinter,
[MarshalAs(UnmanagedType.LPTStr)] string pName);
[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern Int32 GetLastError();
[DllImport("GDI32.dll", EntryPoint="CreateDC", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,
CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPTStr)]
string pDrive,
[MarshalAs(UnmanagedType.LPTStr)] string pName,
[MarshalAs(UnmanagedType.LPTStr)] string pOutput,
ref structDevMode pDevMode);
[DllImport("GDI32.dll", EntryPoint="ResetDC", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,
CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern IntPtr ResetDC(
IntPtr hDC,
ref structDevMode
pDevMode);
[DllImport("GDI32.dll", EntryPoint="DeleteDC", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=false,
CallingConvention=CallingConvention.StdCall),
SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool DeleteDC(IntPtr hDC);
[DllImport("winspool.Drv", EntryPoint="SetPrinterA", SetLastError=true,
CharSet=CharSet.Auto, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
internal static extern bool SetPrinter(
IntPtr hPrinter,
[MarshalAs(UnmanagedType.I4)] int level,
IntPtr pPrinter,
[MarshalAs(UnmanagedType.I4)] int command);
/*
LONG DocumentProperties(
HWND hWnd, // handle to parent window
HANDLE hPrinter, // handle to printer object
LPTSTR pDeviceName, // device name
PDEVMODE pDevModeOutput, // modified device mode
PDEVMODE pDevModeInput, // original device mode
DWORD fMode // mode options
);
*/
[DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern int DocumentProperties(
IntPtr hwnd,
IntPtr hPrinter,
[MarshalAs(UnmanagedType.LPStr)] string pDeviceName /* changed from String to string */,
IntPtr pDevModeOutput,
IntPtr pDevModeInput,
int fMode
);
[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool GetPrinter(
IntPtr hPrinter,
int dwLevel /* changed type from Int32 */,
IntPtr pPrinter,
int dwBuf /* chagned from Int32*/,
out int dwNeeded /* changed from Int32*/
);
// SendMessageTimeout tools
[Flags] public enum SendMessageTimeoutFlags : uint
{
SMTO_NORMAL = 0x0000,
SMTO_BLOCK = 0x0001,
SMTO_ABORTIFHUNG = 0x0002,
SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
}
const int WM_SETTINGCHANGE = 0x001A;
const int HWND_BROADCAST = 0xffff;
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr windowHandle,
uint Msg,
IntPtr wParam,
IntPtr lParam,
SendMessageTimeoutFlags flags,
uint timeout,
out IntPtr result
);
public static void AddMjm80MmPaperSizeToDefaultPrinter()
{
AddCustomPaperSizeToDefaultPrinter("MJM 80mm * Receipt Length", 80.1f, 4003.9f);
}
public static void AddMjm104MmPaperSizeToDefaultPrinter()
{
AddCustomPaperSizeToDefaultPrinter("MJM 104mm * Receipt Length", 104.1f, 4003.9f);
}
/// <summary>
/// Adds the printer form to the default printer
/// </summary>
/// <param name="paperName">Name of the printer form</param>
/// <param name="widthMm">Width given in millimeters</param>
/// <param name="heightMm">Height given in millimeters</param>
public static void AddCustomPaperSizeToDefaultPrinter(string paperName, float widthMm, float heightMm)
{
PrintDocument pd = new PrintDocument();
string sPrinterName = pd.PrinterSettings.PrinterName;
AddCustomPaperSize(sPrinterName, paperName, widthMm, heightMm);
}
/// <summary>
/// Add the printer form to a printer
/// </summary>
/// <param name="printerName">The printer name</param>
/// <param name="paperName">Name of the printer form</param>
/// <param name="widthMm">Width given in millimeters</param>
/// <param name="heightMm">Height given in millimeters</param>
public static void AddCustomPaperSize(string printerName, string paperName, float
widthMm, float heightMm)
{
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
// The code to add a custom paper size is different for Windows NT then it is
// for previous versions of windows
const int PRINTER_ACCESS_USE = 0x00000008;
const int PRINTER_ACCESS_ADMINISTER = 0x00000004;
const int FORM_PRINTER = 0x00000002;
structPrinterDefaults defaults = new structPrinterDefaults();
defaults.pDatatype = null;
defaults.pDevMode = IntPtr.Zero;
defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
IntPtr hPrinter = IntPtr.Zero;
// Open the printer.
if (OpenPrinter(printerName, out hPrinter, ref defaults))
{
try
{
// delete the form incase it already exists
DeleteForm(hPrinter, paperName);
// create and initialize the FORM_INFO_1 structure
FormInfo1 formInfo = new FormInfo1();
formInfo.Flags = 0;
formInfo.pName = paperName;
// all sizes in 1000ths of millimeters
formInfo.Size.width = (int)(widthMm * 1000.0);
formInfo.Size.height = (int)(heightMm * 1000.0);
formInfo.ImageableArea.left = 0;
formInfo.ImageableArea.right = formInfo.Size.width;
formInfo.ImageableArea.top = 0;
formInfo.ImageableArea.bottom = formInfo.Size.height;
if (!AddForm(hPrinter, 1, ref formInfo))
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.AppendFormat("Failed to add the custom paper size {0} to the printer {1}, System error number: {2}",
paperName, printerName, GetLastError());
throw new ApplicationException(strBuilder.ToString());
}
// INIT
const int DM_OUT_BUFFER = 2;
const int DM_IN_BUFFER = 8;
structDevMode devMode = new structDevMode();
IntPtr hPrinterInfo, hDummy;
PRINTER_INFO_9 printerInfo;
printerInfo.pDevMode = IntPtr.Zero;
int iPrinterInfoSize, iDummyInt;
// GET THE SIZE OF THE DEV_MODE BUFFER
int iDevModeSize = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0);
if(iDevModeSize < 0)
throw new ApplicationException("Cannot get the size of the DEVMODE structure.");
// ALLOCATE THE BUFFER
IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100);
// GET A POINTER TO THE DEV_MODE BUFFER
int iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER);
if(iRet < 0)
throw new ApplicationException("Cannot get the DEVMODE structure.");
// FILL THE DEV_MODE STRUCTURE
devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType());
// SET THE FORM NAME FIELDS TO INDICATE THAT THIS FIELD WILL BE MODIFIED
devMode.dmFields = 0x10000; // DM_FORMNAME
// SET THE FORM NAME
devMode.dmFormName = paperName;
// PUT THE DEV_MODE STRUCTURE BACK INTO THE POINTER
Marshal.StructureToPtr(devMode, hDevMode, true);
// MERGE THE NEW CHAGES WITH THE OLD
iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName,
printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
if(iRet < 0)
throw new ApplicationException("Unable to set the orientation setting for this printer.");
// GET THE PRINTER INFO SIZE
GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);
if(iPrinterInfoSize == 0)
throw new ApplicationException("GetPrinter failed. Couldn't get the # bytes needed for shared PRINTER_INFO_9 structure");
// ALLOCATE THE BUFFER
hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);
// GET A POINTER TO THE PRINTER INFO BUFFER
bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt);
if(!bSuccess)
throw new ApplicationException("GetPrinter failed. Couldn't get the shared PRINTER_INFO_9 structure");
// FILL THE PRINTER INFO STRUCTURE
printerInfo = (PRINTER_INFO_9)Marshal.PtrToStructure(hPrinterInfo, printerInfo.GetType());
printerInfo.pDevMode = hDevMode;
// GET A POINTER TO THE PRINTER INFO STRUCTURE
Marshal.StructureToPtr(printerInfo, hPrinterInfo, true);
// SET THE PRINTER SETTINGS
bSuccess = SetPrinter(hPrinter, 9, hPrinterInfo, 0);
if(!bSuccess)
throw new Win32Exception(Marshal.GetLastWin32Error(), "SetPrinter() failed. Couldn't set the printer settings");
// Tell all open programs that this change occurred.
SendMessageTimeout(
new IntPtr(HWND_BROADCAST),
WM_SETTINGCHANGE,
IntPtr.Zero,
IntPtr.Zero,
MJMCustomPrintForm.SendMessageTimeoutFlags.SMTO_NORMAL,
1000,
out hDummy);
}
finally
{
ClosePrinter(hPrinter);
}
}
else
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.AppendFormat("Failed to open the {0} printer, System error number: {1}",
printerName, GetLastError());
throw new ApplicationException(strBuilder.ToString());
}
}
else
{
structDevMode pDevMode = new structDevMode();
IntPtr hDC = CreateDC(null, printerName, null, ref pDevMode);
if (hDC != IntPtr.Zero)
{
const long DM_PAPERSIZE = 0x00000002L;
const long DM_PAPERLENGTH = 0x00000004L;
const long DM_PAPERWIDTH = 0x00000008L;
pDevMode.dmFields = (int)(DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH);
pDevMode.dmPaperSize = 256;
pDevMode.dmPaperWidth = (short)(widthMm * 1000.0);
pDevMode.dmPaperLength = (short)(heightMm * 1000.0);
ResetDC(hDC, ref pDevMode);
DeleteDC(hDC);
}
}
}
}
}
I got a problem when using the following code to get the icon from an application with Mono.
The background color is black, which is really not my expect.
Is there any suggestion?
[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
public IntPtr hIcon;
public IntPtr iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
private const uint SHGFI_ICON = 0x100;
private const uint SHGFI_LARGEICON = 0x0; // 'Large icon
private const uint SHGFI_SMALLICON = 0x1; // 'Small icon
[DllImport("shell32.dll")]
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
[DllImport("shell32.dll")]
private static extern uint ExtractIconEx(string lpszFile, int nIconIndex, int[] phiconLarge, int[] phiconSmall, uint nIcons);
[DllImport("User32.dll")]
public static extern int DestroyIcon(IntPtr hIcon);
public static Bitmap GetExeIcon(string filename, bool smallIcon)
{
SHFILEINFO shinfo = new SHFILEINFO();
uint index = 0;
uint largeIcom = SHGFI_LARGEICON;
if (smallIcon)
{
largeIcom = SHGFI_SMALLICON;
}
SHGetFileInfo(filename, (uint)index, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | largeIcom);
Icon icon = (Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone();
DestroyIcon(shinfo.hIcon);
return icon.ToBitmap();
}
BTW, I can just use Bitmap.FromHicon(shinfo.hIcon) to get the bitmap object, but the image shown is so rough, which i don't think the client will like it.
I use SHGetFileInfo() or GetDisplayNameOf() to get the name of a special folder.
If a localized operating system to change the setting "Current language for non-Unicode programs", these functions return a value "??? ?????????".
This combination of settings encountered by users.
shell32 is not fully unicode compatible?
Shell32.STRRET STRRET;
STRRET.uType = (uint)Shell32.STRRET_TYPE.STRRET_WSTR;
if (Windows.S_OK != ishellfolder_parent.GetDisplayNameOf(ptr_pidllast, (uint)Shell32.SHGNO.SHGDN_NORMAL | (uint)Shell32.SHGNO.SHGDN_INFOLDER, out STRRET))
return null;
StringBuilder sbuilder = new StringBuilder(260);
Shell32.StrRetToBuf(ref STRRET, ptr_pidllast, sbuilder, (uint)sbuilder.Capacity);
what is wrong?
***added later
Another example to demonstrate my question:
public static partial class Program
{
const Int32 CSIDL_DESKTOP = (0x0000);
const uint SHGFI_DISPLAYNAME = 0x000000200; // get display name
const uint SHGFI_PIDL = 0x000000008; // pszPath is a pidl
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public static int NAMESIZE = 80;
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[DllImport("shell32.dll")]
static extern IntPtr SHGetFileInfo(IntPtr pidl, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("shell32.dll")]
public static extern IntPtr SHCloneSpecialIDList(IntPtr hwnd, Int32 CSIDL, bool create);
[STAThread]
static void Main(string[] args)
{
IntPtr pidl = SHCloneSpecialIDList(IntPtr.Zero, CSIDL_DESKTOP, false);
SHFILEINFO shfi = new SHFILEINFO();
if (IntPtr.Zero != SHGetFileInfo(
pidl,
0,
ref shfi,
(uint)Marshal.SizeOf(typeof(SHFILEINFO)),
SHGFI_PIDL | SHGFI_DISPLAYNAME))
{
System.Windows.Forms.MessageBox.Show(shfi.szDisplayName);
}
This code not correct. Some cases wrong return values, described above.
Can anyone help me with an example of the correct code, fully compatible with Unicode and works with non-default system settings?
Thank you all! After some experiments, and found a solution. My error was here:
Shell32.StrRetToBuf(ref STRRET, ptr_pidllast, sbuilder, (uint)sbuilder.Capacity);
The signature should be:
[DllImport("shlwapi.dll", CharSet=CharSet.Unicode, EntryPoint="StrRetToBufW")]
public static extern Int32 StrRetToBufW( ...
Someone asked the same question. You can use the code example there.
How to get the actual (localized) folder names?