I am new to C#. As a first (and increasingly urgent) task, I am
required to interop with the GDI to obtain a list of the printer
device fonts. I then need to send text to the printer to represent
each of them.
I decided to start by ensuring that the callback function "fires off"
for each font. I have put together a script that I felt would
accomplish this, including the callback functions, and logical font
structures etc (see script).
I really expected that this would work but on debugging found that the
callback function was not "firing off". I cant figure out why and
have tried every
combination that I could think of. Can somebody please help me?
Best Regards
Paul Y
The Script:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
namespace WindowsApplication6
{
/// <summary>
/// Summary description for Form1.
/// </summary>
///
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnGetFonts;
private System.Windows.Forms.ListBox lbFonts;
private System.ComponentModel.Container components = null;
public delegate int EnumFontFamProc(IntPtr lpelfe, IntPtr lpntme, int
FontType, int lParam);
[DllImport("gdi32", EntryPoint="EnumFontFamiliesEx")]
static extern int EnumFontFamiliesEx(
IntPtr hdc,
ref LOGFONT lpLogFont,
EnumFontFamProc lpEnumFontFamExProc,// callback function
int lParam,
int dw //not used; must be 0
);
public struct Printer_Defaults
{
public int pDatatype;
public int pDevMode;
public int DesiredAccess;
}
[ StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto) ]
class LOGFONT
{
public int lfHeight = 0;
public int lfWidth = 0;
public int lfEscapement = 0;
public int lfOrientation = 0;
public int lfWeight = 0;
public byte lfItalic = 0;
public byte lfUnderline = 0;
public byte lfStrikeOut = 0;
public byte lfCharSet = 1; // 1 = DEFAULT_CHARSET
public byte lfOutPrecision = 0;
public byte lfClipPrecision = 0;
public byte lfQuality = 0;
public byte lfPitchAndFamily = 0;
[ MarshalAs(UnmanagedType.ByValTStr, SizeConst=32) ] public string
lfFaceName = null;
}
static IntPtr listBoxHandle;// IntPtr is a class in System namespace
[DllImport("winspool.Drv", EntryPoint="GetDefaultPrinter")]
public static extern bool GetDefaultPrinter(
StringBuilder pszBuffer, // printer name buffer
ref int pcchBuffer // size of name buffer
);
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA",
SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)]
string szPrinter, out IntPtr hPrinter, Printer_Defaults pd);
[DllImport("winspool.Drv", EntryPoint="ClosePrinter",
SetLastError=true, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnGetFonts = new System.Windows.Forms.Button();
this.lbFonts = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// btnGetFonts
//
this.btnGetFonts.Location = new System.Drawing.Point(96, 40);
this.btnGetFonts.Name = "btnGetFonts";
this.btnGetFonts.TabIndex = 0;
this.btnGetFonts.Text = "Get Fonts";
this.btnGetFonts.Click += new
System.EventHandler(this.btnGetFonts_Click);
//
// lbFonts
//
this.lbFonts.Location = new System.Drawing.Point(16, 104);
this.lbFonts.Name = "lbFonts";
this.lbFonts.Size = new System.Drawing.Size(264, 134);
this.lbFonts.TabIndex = 1;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.AddRange(new System.Windows.Forms.Control[]
{
this.lbFonts,
this.btnGetFonts});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
// your callback function
int EnumFontFamiliesExCallBack(IntPtr lpelfe, IntPtr lpntme, int
FontType, int lParam)
{
MessageBox.Show("works","ok");
return 1;
}
private void btnGetFonts_Click(object sender, System.EventArgs e)
{
Printer_Defaults pd = new Printer_Defaults();
String name1;
StringBuilder name = new StringBuilder();
int length = 100;
listBoxHandle = lbFonts.Handle;
int unused = 0, unused1 = 1;
GetDefaultPrinter(name, ref length);
name1 = name.ToString();
IntPtr aPrinter;
LOGFONT mylogfont = new LOGFONT();
// Specify the character set
mylogfont.lfCharSet = 1;//DEFAULT_CHARSET;
// Must be zero unless Hebrew or Arabic
mylogfont.lfPitchAndFamily = 0;
if( OpenPrinter(name.ToString() , out aPrinter, pd ) )
{
EnumFontFamProc callback = new
EnumFontFamProc(EnumFontFamiliesExCallBack);
EnumFontFamiliesEx(aPrinter, ref mylogfont, callback, unused1, unused
);
ClosePrinter(aPrinter);
}
}
}
}
--
Feng Yuan (http://blogs.msdn.com/fyuan www.fengyuan.com)
This posting is provided "AS IS" with no warranties, and confers no rights.
Thanks for your reply.
I must admit to never having worked with GDI before. The script that
I provided in my last posting is converted from visual basic scripts
found on the internet. I have also read the relevant sections of your
book: "Windows Graphics Programming" and taken some ideas from there.
I did try the C# .Net debugger to try to reveal the problem. I found
that the point where I expect the control to pass to the callback
function - the statement in my code: "EnumFontFamiliesEx(aPrinter, ref
mylogfont, callback, unused1, unused);", it just steps on to it then
past it to the next statement: "ClosePrinter(aPrinter);".
Best Regards
Paul
. to and also some of the