using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Drawing;
using System.IO;
// License: http://creativecommons.org/licenses/by-sa/2.0/uk/
namespace HewlettPackard
{
///
/// Managed wrapper for the unmanaged LSPrintLauncher.dll
///
public class LightScribe
{
public enum ContrastLevel
{
Best,
Normal,
Draft
}
private static IntPtr m_LightScribeDll = IntPtr.Zero;
///
/// Pointer to the LSPrintLauncher.dll. Only created once.
///
private static IntPtr LightScribeDll
{
get
{
if (m_LightScribeDll == IntPtr.Zero)
{
string dllPath = GetDllPath();
if (dllPath == string.Empty) return IntPtr.Zero;
try
{
m_LightScribeDll = Kernel32.LoadWin32Library(dllPath);
}
catch (ApplicationException)
{
return IntPtr.Zero;
}
}
return m_LightScribeDll;
}
}
///
/// Determines whether or not a LightScribe drive exists.
///
public static bool HasLightScribeDrive
{
get
{
IntPtr pProc = Kernel32.GetProcAddress(LightScribeDll, "haveLSDrive");
haveLSDrive cpv = (haveLSDrive)Marshal.GetDelegateForFunctionPointer(pProc, typeof(haveLSDrive));
return cpv();
}
}
///
/// Determines the path to LSPrintLauncher.dll, as described in
/// the official SDK.
///
/// empty string if path not found, otherwise absolute path
private static string GetDllPath()
{
RegistryKey key = Registry.LocalMachine;
key = key.OpenSubKey("Software\\LightScribe");
if (key == null) return string.Empty;
return key.GetValue("LsPrintLauncher", string.Empty) as string;
}
///
/// Generates an image which can be printed to disc (BMP).
///
/// Title to show on disc
/// Image to use as background
/// Number of the disc. Values less than 1 will be ignored.
/// Path of the generated image (located in the TEMP-directory)
public static string GenerateDiscImage(string title, string imagePath, int discNumber)
{
Image bitmap = new Bitmap(640, 640);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
// Draw image to background
if (!string.IsNullOrEmpty(imagePath) && File.Exists(imagePath))
{
Image background = Bitmap.FromFile(imagePath);
g.DrawImage(background, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
background.Dispose();
}
if (discNumber > 0)
{
title += string.Format(" (#{0})", discNumber);
}
if (!string.IsNullOrEmpty(title))
{
Font textFont = new Font("Verdana", 25, FontStyle.Bold);
// Draw the text centered
SizeF textSize = g.MeasureString(title, textFont);
float yPos = (bitmap.Height * 0.75f);
float xPos = ((bitmap.Width - textSize.Width) / 2f);
// Make sure that font is visible, by drawing a background
g.FillRectangle(Brushes.White, xPos, yPos, textSize.Width, textSize.Height);
using (Pen p = new Pen(Color.Black, 4))
{
g.DrawRectangle(p, xPos, yPos, textSize.Width, textSize.Height);
}
g.DrawString(title, textFont, Brushes.Black, new PointF(xPos, yPos));
}
}
// Determine save path
string path = Path.GetTempFileName() + ".bmp";
bitmap.Save(path, System.Drawing.Imaging.ImageFormat.Bmp);
return path;
}
private delegate int launchPrintOptions(IntPtr args);
private delegate int launchPrint(IntPtr args);
private delegate bool haveLSDrive();
///
/// Shows the LightScribe print options dialog.
///
/// Path to the image to print.
/// Set to true, if the given image should automatically be deleted.
/// 0 on success
public static int ShowPrintOptions(string fileName, bool deleteFile)
{
IntPtr pProc = Kernel32.GetProcAddress(LightScribeDll, "launchPrintOptions");
launchPrintOptions cpv = (launchPrintOptions)Marshal.GetDelegateForFunctionPointer(pProc, typeof(launchPrintOptions));
string arguments = string.Format("--filename \"{0}\"", fileName);
if (deleteFile)
{
arguments += " --deleteImageFile 1";
}
// We need to pass an *unmanaged* string (wchar_t*)
IntPtr args = Marshal.StringToHGlobalUni(arguments);
try
{
return cpv(args);
}
finally
{
Marshal.FreeHGlobal(args);
}
}
///
/// Starts the printing process and shows its status.
///
/// Path to the image file
/// Index of the target drive. The index only covers LS-enabled drives.
/// Display name of the drive.
/// Must match the index-parameter.
/// Printing quality
/// Delete the file after finishing?
///
/// From the official docs: The drive path must match
/// the actual path of the selected logical LightScribe drive. i.e. if there are 3 LightScribe
/// enabled drives, ‘E’, ‘F’ & ‘K’, they are normally drive indexes 0, 1 & 2 respectively.
///
public static int ShowPrintProgress(string fileName, int index, string driveDisplayName, string driveLetter, ContrastLevel quality, bool deleteFile)
{
IntPtr pProc = Kernel32.GetProcAddress(LightScribeDll, "launchPrint");
launchPrint cpv = (launchPrint)Marshal.GetDelegateForFunctionPointer(pProc, typeof(launchPrint));
Dictionary arguments = new Dictionary();
arguments["filename"] = fileName;
arguments["index"] = index;
arguments["name"] = driveDisplayName;
arguments["path"] = driveLetter;
arguments["quality"] = quality.ToString().ToLower();
if (deleteFile)
{
arguments["deleteImageFile"] = "1";
}
string argumentString = "";
foreach (KeyValuePair argument in arguments)
{
argumentString += " --" + argument.Key + " \"" + argument.Value.ToString() + "\"";
}
// We need to pass an *unmanaged* string (wchar_t*)
IntPtr args = Marshal.StringToHGlobalUni(argumentString);
try
{
return cpv(args);
}
finally
{
Marshal.FreeHGlobal(args);
}
}
///
/// Determines whether or not LightScribe is supported, that is
/// if the DLL can be loaded and a LS drive exists.
///
public static bool IsSupported
{
get
{
return (LightScribeDll != IntPtr.Zero && HasLightScribeDrive);
}
}
}
}