Click here to Skip to main content
15,890,579 members
Articles / Programming Languages / C#

Adding Custom Paper Sizes to Named Printers

Rate me:
Please Sign up or sign in to vote.
4.92/5 (31 votes)
11 Nov 20054 min read 338.6K   10.1K   59   66
Using PIinvoke and marshaling techniques to call the winspool library's AddForm

Introduction

My company needed me to programmatically add a custom paper size (a printer form) to the default printer and set the printer to use the custom paper size. After looking around, the best alternative we could find was to make use of the printing and print spooling Win32 API functions found in winspool.drv. The functions used in the project are AddForm, DeleteForm, DocumentProperties, GetPrinter and SetPrinter along with some others. The target platform is WinNT / 2000 / XP although there was already some support for earlier versions of Windows added before I began working on the project. I've never tried to use that section of code but I'm pretty sure that it will only add the custom paper size and not set the printer to use it.

Challenges

Calling these from C# required a little bit more knowledge of marshaling techniques than I had under my belt as I was only able to get as far as getting a handle to the default printer using the winspool functions GetDefaultPrinter and OpenPrinter before requiring some help. At that point, we opened a support case with Microsoft and they sent a nice C# project with the working AddForm calls. However, when we asked about setting the printer to use the newly created form, the best they could do was provide a VB.NET project. So, I ported VB.NET over to C#. Our last requirement was to signal the previously open applications of the settings change and this was done using SendMessageTimeout from user32.dll.

Implementation

Rather than make a call to the Win32 GetDefaultPrinter function (which you have to call twice, once to get the size of the string and another time to get the string) there is an easier way to get the default printer name provided in the .NET platform:

C#
using System.Drawing.Printing;
...
PrintDocument pd = new PrintDocument();
string sPrinterName = pd.PrinterSettings.PrinterName;

After getting the printer name, get a handle to the printer:

C#
bool bGotPrinter = OpenPrinter(printerName, out hPrinter, ref defaults);

At this point, we can delete the custom paper size by name:

C#
// delete the form incase it already exists
DeleteForm(hPrinter, paperName);

And create the paper size:

C#
// 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;

Add the paper size to the printer's list of available paper sizes:

C#
bool bFormAdded = AddForm(hPrinter, 1, ref formInfo);

I'll leave setting the printer to use the newly added form and signaling open apps of the settings change out for now. Have a look at the demo project, it's all there.

Caveat

This project is currently set up to add a custom paper size of 104 mm*4000 mm to the default printer. It attempts to do this in the Form1_Load event of Test.cs. If you run this on a computer with a default printer that doesn't support these dimensions, the paper size will not show up in the list of available paper sizes for your default printer and no exceptions will be generated. If you'd like to test run a test that will work, specify a smaller paper size that your printer will support. You can convert millimeters to inches by multiplying the millimeters by 25.4. I didn't take the time to add any 'add custom paper size in inches' functionality to this project. It could be done very easily by dividing the inches by 25.4 and passing off to the 'add custom paper size by mm' function which already exists.

Check to See If It Worked

The project is set to open small form with single 'Open Dialog' button after adding the custom paper size. Clicking the button opens a print dialog window. To see the list of available printer sizes for the default printer, click the properties button (opens the Properties window) and then the advanced button (opens advanced options window). You can now see the list of available paper sizes for the printer.

To check that it worked from Windows XP, open the printers and faxes window (start menu, printers and faxes), right click on your default printer (the one with the check box next to it) and select properties (opens Properties window), click the printing preferences button (opens Preferences window), click the advanced button (opens Advanced Options window) and then you can see a list of paper sizes.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalthanks for this nice code Pin
Shah Kazmi18-Jan-07 6:48
Shah Kazmi18-Jan-07 6:48 
GeneralRe: thanks for this nice code Pin
twostepted18-Jan-07 17:12
twostepted18-Jan-07 17:12 
GeneralIt made some kind of problem Pin
Aviad Barel16-Nov-06 5:45
Aviad Barel16-Nov-06 5:45 
GeneralRe: It made some kind of problem Pin
twostepted16-Nov-06 7:42
twostepted16-Nov-06 7:42 
QuestionDo you have these code in VB.net? Pin
taneyezone14-Nov-06 22:13
taneyezone14-Nov-06 22:13 
AnswerRe: Do you have these code in VB.net? Pin
twostepted14-Nov-06 23:45
twostepted14-Nov-06 23:45 
AnswerRe: Do you have these code in VB.net? Pin
junk3305-Apr-07 12:14
junk3305-Apr-07 12:14 
AnswerRe: Do you have these code in VB.net? Pin
Deoinbox2-Aug-07 16:47
Deoinbox2-Aug-07 16:47 
'################################################################
'MJMCustomPrintForm (VB.net)
'################################################################
Imports System
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.ComponentModel
Imports System.Drawing.Printing

Namespace MJMCustomPrintForm
'''
''' Summary description for MJMCustomPrintForm.
'''

Public Class MJMCustomPrintForm
' Make a static class
Private Sub New()
End Sub

<structlayout(layoutkind.sequential, charset:="CharSet.Auto)"> _
Friend Structure structPrinterDefaults
<marshalas(unmanagedtype.lptstr)> _
Public pDatatype As String
Public pDevMode As IntPtr
<marshalas(unmanagedtype.i4)> _
Public DesiredAccess As Integer
End Structure

<dllimport("winspool.drv", entrypoint:="OpenPrinter" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function OpenPrinter(<marshalas(unmanagedtype.lptstr)> _
ByVal printerName As String, ByRef phPrinter As IntPtr, ByRef pd As structPrinterDefaults) As Boolean
End Function

<dllimport("winspool.drv", entrypoint:="ClosePrinter" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function ClosePrinter(ByVal phPrinter As IntPtr) As Boolean
End Function

<structlayout(layoutkind.sequential, charset:="CharSet.Auto)"> _
Friend Structure structSize
Public width As Int32
Public height As Int32
End Structure

<structlayout(layoutkind.sequential, charset:="CharSet.Auto)"> _
Friend Structure structRect
Public left As Int32
Public top As Int32
Public right As Int32
Public bottom As Int32
End Structure

<structlayout(layoutkind.[explicit], charset:="CharSet.Unicode)"> _
Friend Structure FormInfo1
<fieldoffset(0), marshalas(unmanagedtype.i4)=""> _
Public Flags As UInteger
<fieldoffset(4), marshalas(unmanagedtype.lpwstr)=""> _
Public pName As String
<fieldoffset(8)> _
Public Size As structSize
<fieldoffset(16)> _
Public ImageableArea As structRect
End Structure

' changed from CharSet=CharSet.Auto
<structlayout(layoutkind.sequential, charset:="CharSet.Ansi)"> _
Friend Structure structDevMode
<marshalas(unmanagedtype.byvaltstr, sizeconst:="32)"> _
Public dmDeviceName As String
<marshalas(unmanagedtype.u2)> _
Public dmSpecVersion As Short
<marshalas(unmanagedtype.u2)> _
Public dmDriverVersion As Short
<marshalas(unmanagedtype.u2)> _
Public dmSize As Short
<marshalas(unmanagedtype.u2)> _
Public dmDriverExtra As Short
<marshalas(unmanagedtype.u4)> _
Public dmFields As Integer
<marshalas(unmanagedtype.i2)> _
Public dmOrientation As Short
<marshalas(unmanagedtype.i2)> _
Public dmPaperSize As Short
<marshalas(unmanagedtype.i2)> _
Public dmPaperLength As Short
<marshalas(unmanagedtype.i2)> _
Public dmPaperWidth As Short
<marshalas(unmanagedtype.i2)> _
Public dmScale As Short
<marshalas(unmanagedtype.i2)> _
Public dmCopies As Short
<marshalas(unmanagedtype.i2)> _
Public dmDefaultSource As Short
<marshalas(unmanagedtype.i2)> _
Public dmPrintQuality As Short
<marshalas(unmanagedtype.i2)> _
Public dmColor As Short
<marshalas(unmanagedtype.i2)> _
Public dmDuplex As Short
<marshalas(unmanagedtype.i2)> _
Public dmYResolution As Short
<marshalas(unmanagedtype.i2)> _
Public dmTTOption As Short
<marshalas(unmanagedtype.i2)> _
Public dmCollate As Short
<marshalas(unmanagedtype.byvaltstr, sizeconst:="32)"> _
Public dmFormName As String
<marshalas(unmanagedtype.u2)> _
Public dmLogPixels As Short
<marshalas(unmanagedtype.u4)> _
Public dmBitsPerPel As Integer
<marshalas(unmanagedtype.u4)> _
Public dmPelsWidth As Integer
<marshalas(unmanagedtype.u4)> _
Public dmPelsHeight As Integer
<marshalas(unmanagedtype.u4)> _
Public dmNup As Integer
<marshalas(unmanagedtype.u4)> _
Public dmDisplayFrequency As Integer
<marshalas(unmanagedtype.u4)> _
Public dmICMMethod As Integer
<marshalas(unmanagedtype.u4)> _
Public dmICMIntent As Integer
<marshalas(unmanagedtype.u4)> _
Public dmMediaType As Integer
<marshalas(unmanagedtype.u4)> _
Public dmDitherType As Integer
<marshalas(unmanagedtype.u4)> _
Public dmReserved1 As Integer
<marshalas(unmanagedtype.u4)> _
Public dmReserved2 As Integer
End Structure

<structlayout(layoutkind.sequential, charset:="CharSet.Auto)"> _
Friend Structure PRINTER_INFO_9
Public pDevMode As IntPtr
End Structure

<dllimport("winspool.drv", entrypoint:="AddFormW" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="True," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function AddForm(ByVal phPrinter As IntPtr, <marshalas(unmanagedtype.i4)> _
ByVal level As Integer, ByRef form As FormInfo1) As Boolean
End Function

' This method is not used
' [DllImport("winspool.Drv", EntryPoint="SetForm", SetLastError=true,
' CharSet=CharSet.Unicode, ExactSpelling=false,
' CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
' internal static extern bool SetForm(IntPtr phPrinter, string paperName,
' [MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form);
'

<dllimport("winspool.drv", entrypoint:="DeleteForm" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function DeleteForm(ByVal phPrinter As IntPtr, <marshalas(unmanagedtype.lptstr)> _
ByVal pName As String) As Boolean
End Function

<dllimport("kernel32.dll", entrypoint:="GetLastError" ,="" setlasterror:="False," exactspelling:="True," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function GetLastError() As Int32
End Function

<dllimport("gdi32.dll", entrypoint:="CreateDC" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function CreateDC(<marshalas(unmanagedtype.lptstr)> _
ByVal pDrive As String, <marshalas(unmanagedtype.lptstr)> _
ByVal pName As String, <marshalas(unmanagedtype.lptstr)> _
ByVal pOutput As String, ByRef pDevMode As structDevMode) As IntPtr
End Function

<dllimport("gdi32.dll", entrypoint:="ResetDC" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function ResetDC(ByVal hDC As IntPtr, ByRef pDevMode As structDevMode) As IntPtr
End Function

<dllimport("gdi32.dll", entrypoint:="DeleteDC" ,="" setlasterror:="True," charset:="CharSet.Unicode," exactspelling:="False," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
End Function

<dllimport("winspool.drv", entrypoint:="SetPrinterA" ,="" setlasterror:="True," charset:="CharSet.Auto," exactspelling:="True," callingconvention:="CallingConvention.StdCall)," suppressunmanagedcodesecurityattribute()=""> _
Friend Shared Function SetPrinter(ByVal hPrinter As IntPtr, <marshalas(unmanagedtype.i4)> _
ByVal level As Integer, ByVal pPrinter As IntPtr, <marshalas(unmanagedtype.i4)> _
ByVal command As Integer) As Boolean
End Function

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

' changed from String to string
<dllimport("winspool.drv", entrypoint:="DocumentPropertiesA" ,="" setlasterror:="True," exactspelling:="True," callingconvention:="CallingConvention.StdCall)"> _
Public Shared Function DocumentProperties(ByVal hwnd As IntPtr, ByVal hPrinter As IntPtr, <marshalas(unmanagedtype.lpstr)> _
ByVal pDeviceName As String, ByVal pDevModeOutput As IntPtr, ByVal pDevModeInput As IntPtr, ByVal fMode As Integer) As Integer
End Function

' changed type from Int32
' chagned from Int32
<dllimport("winspool.drv", entrypoint:="GetPrinterA" ,="" setlasterror:="True," exactspelling:="True," callingconvention:="CallingConvention.StdCall)"> _
Public Shared Function GetPrinter(ByVal hPrinter As IntPtr, ByVal dwLevel As Integer, ByVal pPrinter As IntPtr, ByVal dwBuf As Integer, ByRef dwNeeded As Integer) As Boolean
' changed from Int32
End Function

' SendMessageTimeout tools
<flags()> _
Public Enum SendMessageTimeoutFlags As UInteger
SMTO_NORMAL = 0
SMTO_BLOCK = 1
SMTO_ABORTIFHUNG = 2
SMTO_NOTIMEOUTIFNOTHUNG = 8
End Enum
Const WM_SETTINGCHANGE As Integer = 26
Const HWND_BROADCAST As Integer = 65535

<dllimport("user32.dll", setlasterror:="True," charset:="CharSet.Auto)"> _
Public Shared Function SendMessageTimeout(ByVal windowHandle As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByVal flags As SendMessageTimeoutFlags, ByVal timeout As UInteger, _
ByRef result As IntPtr) As IntPtr
End Function

'Public Shared Sub AddMjm80MmPaperSizeToDefaultPrinter()
' AddCustomPaperSizeToDefaultPrinter("MJM 80mm * Receipt Length", 80.1F, 4003.9F)
'End Sub

'Public Shared Sub AddMjm104MmPaperSizeToDefaultPrinter()
' AddCustomPaperSizeToDefaultPrinter("MJM 104mm * Receipt Length", 104.1F, 4003.9F)
'End Sub

'''
''' Adds the printer form to the default printer
'''

''' <param name="paperName" />Name of the printer form
''' <param name="widthMm" />Width given in millimeters
''' <param name="heightMm" />Height given in millimeters
Public Shared Sub AddCustomPaperSizeToDefaultPrinter(ByVal paperName As String, ByVal widthMm As Single, ByVal heightMm As Single)
Dim pd As New PrintDocument()
Dim sPrinterName As String = pd.PrinterSettings.PrinterName
AddCustomPaperSizeToSelectedPrinter(sPrinterName, paperName, widthMm, heightMm)
End Sub

'''
''' Add the printer form to a printer
'''

''' <param name="printerName" />The printer name
''' <param name="paperName" />Name of the printer form
''' <param name="widthMm" />Width given in millimeters
''' <param name="heightMm" />Height given in millimeters
Public Shared Sub AddCustomPaperSizeToSelectedPrinter(ByVal printerName As String, ByVal paperName As String, ByVal widthMm As Single, ByVal heightMm As Single)
If PlatformID.Win32NT = Environment.OSVersion.Platform Then
' The code to add a custom paper size is different for Windows NT then it is
' for previous versions of windows

Const PRINTER_ACCESS_USE As Integer = 8
Const PRINTER_ACCESS_ADMINISTER As Integer = 4
Const FORM_PRINTER As Integer = 2

Dim defaults As New structPrinterDefaults()
defaults.pDatatype = Nothing
defaults.pDevMode = IntPtr.Zero
defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE

Dim hPrinter As IntPtr = IntPtr.Zero

' Open the printer.
If OpenPrinter(printerName, hPrinter, defaults) Then
Try
' delete the form incase it already exists
DeleteForm(hPrinter, paperName)
' create and initialize the FORM_INFO_1 structure
Dim formInfo As New FormInfo1()
formInfo.Flags = 0
formInfo.pName = paperName
' all sizes in 1000ths of millimeters
formInfo.Size.width = CInt((widthMm * 1000))
formInfo.Size.height = CInt((heightMm * 1000))
formInfo.ImageableArea.left = 0
formInfo.ImageableArea.right = formInfo.Size.width
formInfo.ImageableArea.top = 0
formInfo.ImageableArea.bottom = formInfo.Size.height
If Not AddForm(hPrinter, 1, formInfo) Then
Dim strBuilder As 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())
End If

' INIT
Const DM_OUT_BUFFER As Integer = 2
Const DM_IN_BUFFER As Integer = 8
Dim devMode As New structDevMode()
Dim hPrinterInfo As IntPtr, hDummy As IntPtr
Dim printerInfo As PRINTER_INFO_9
printerInfo.pDevMode = IntPtr.Zero
Dim iPrinterInfoSize As Integer, iDummyInt As Integer


' GET THE SIZE OF THE DEV_MODE BUFFER
Dim iDevModeSize As Integer = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0)

If iDevModeSize < 0 Then
Throw New ApplicationException("Cannot get the size of the DEVMODE structure.")
End If

' ALLOCATE THE BUFFER
Dim hDevMode As IntPtr = Marshal.AllocCoTaskMem(iDevModeSize + 100)

' GET A POINTER TO THE DEV_MODE BUFFER
Dim iRet As Integer = DocumentProperties(IntPtr.Zero, hPrinter, printerName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER)

If iRet < 0 Then
Throw New ApplicationException("Cannot get the DEVMODE structure.")
End If

' FILL THE DEV_MODE STRUCTURE
devMode = DirectCast(Marshal.PtrToStructure(hDevMode, devMode.[GetType]()), structDevMode)

' SET THE FORM NAME FIELDS TO INDICATE THAT THIS FIELD WILL BE MODIFIED
devMode.dmFields = 65536
' 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 Or DM_OUT_BUFFER)

If iRet < 0 Then
Throw New ApplicationException("Unable to set the orientation setting for this printer.")
End If

' GET THE PRINTER INFO SIZE
GetPrinter(hPrinter, 9, IntPtr.Zero, 0, iPrinterInfoSize)
If iPrinterInfoSize = 0 Then
Throw New ApplicationException("GetPrinter failed. Couldn't get the # bytes needed for shared PRINTER_INFO_9 structure")
End If

' ALLOCATE THE BUFFER
hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100)

' GET A POINTER TO THE PRINTER INFO BUFFER
Dim bSuccess As Boolean = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, iDummyInt)

If Not bSuccess Then
Throw New ApplicationException("GetPrinter failed. Couldn't get the shared PRINTER_INFO_9 structure")
End If

' FILL THE PRINTER INFO STRUCTURE
printerInfo = DirectCast(Marshal.PtrToStructure(hPrinterInfo, printerInfo.[GetType]()), PRINTER_INFO_9)
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 Not bSuccess Then
Throw New Win32Exception(Marshal.GetLastWin32Error(), "SetPrinter() failed. Couldn't set the printer settings")
End If

' Tell all open programs that this change occurred.
SendMessageTimeout(New IntPtr(HWND_BROADCAST), WM_SETTINGCHANGE, IntPtr.Zero, IntPtr.Zero, MJMCustomPrintForm.SendMessageTimeoutFlags.SMTO_NORMAL, 1000, _
hDummy)
Finally
ClosePrinter(hPrinter)
End Try
Else
Dim strBuilder As New StringBuilder()
strBuilder.AppendFormat("Failed to open the {0} printer, System error number: {1}", printerName, GetLastError())
Throw New ApplicationException(strBuilder.ToString())
End If
Else
Dim pDevMode As New structDevMode()
Dim hDC As IntPtr = CreateDC(Nothing, printerName, Nothing, pDevMode)
If hDC <> IntPtr.Zero Then
Const DM_PAPERSIZE As Long = 2
Const DM_PAPERLENGTH As Long = 4
Const DM_PAPERWIDTH As Long = 8
pDevMode.dmFields = CInt((DM_PAPERSIZE Or DM_PAPERWIDTH Or DM_PAPERLENGTH))
pDevMode.dmPaperSize = 256
pDevMode.dmPaperWidth = CShort((widthMm * 1000))
pDevMode.dmPaperLength = CShort((heightMm * 1000))
ResetDC(hDC, pDevMode)
DeleteDC(hDC)
End If
End If
End Sub
End Class
End Namespace
'################################################################
GeneralWhy does it not work Pin
Murre5-Nov-06 21:40
Murre5-Nov-06 21:40 
GeneralRe: Why does it not work Pin
Murre6-Nov-06 20:28
Murre6-Nov-06 20:28 
GeneralRe: Why does it not work Pin
tommydxz220-Aug-07 3:35
tommydxz220-Aug-07 3:35 
GeneralAdding form Pin
Amphysvena6-Dec-05 20:27
Amphysvena6-Dec-05 20:27 
GeneralRe: Adding form Pin
twostepted7-Dec-05 18:44
twostepted7-Dec-05 18:44 
GeneralRe: Adding form Pin
Amphysvena7-Dec-05 19:28
Amphysvena7-Dec-05 19:28 
GeneralRe: Adding form Pin
twostepted11-Dec-05 16:56
twostepted11-Dec-05 16:56 
GeneralRe: Adding form Pin
Amphysvena11-Dec-05 17:16
Amphysvena11-Dec-05 17:16 
QuestionRemoving forms Pin
o_pontios15-Nov-05 17:14
o_pontios15-Nov-05 17:14 
AnswerRe: Removing forms Pin
twostepted16-Nov-05 16:08
twostepted16-Nov-05 16:08 
GeneralRe: Removing forms Pin
o_pontios16-Nov-05 18:16
o_pontios16-Nov-05 18:16 
GeneralDownload link Pin
o_pontios13-Nov-05 10:30
o_pontios13-Nov-05 10:30 
GeneralRe: Download link Pin
twostepted15-Nov-05 15:34
twostepted15-Nov-05 15:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.