Click here to Skip to main content
15,896,063 members
Articles / Programming Languages / C#

SCSI Library in C# - Burn CDs and DVDs, Access Hard Disks, etc.

Rate me:
Please Sign up or sign in to vote.
4.77/5 (48 votes)
19 Jun 2017Ms-PL6 min read 146.3K   8.1K   146  
Ever wonder how programs like Nero work? They make their own SCSI libraries... like this!
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System;
using System.Diagnostics;

namespace Helper.Forms
{
	[SuppressUnmanagedCodeSecurity, ComImport, Guid("EBBC7C04-315E-11d2-B62F-006097DF5BD4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IProgressDialog
	{
		void StartProgressDialog([In, Optional] IntPtr hwndParent, [In, Optional] object punkEnableModless, ProgressDialogStartFlags dwFlags, IntPtr pvResevered);
		void StopProgressDialog();
		void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pwzTitle);
		void SetAnimation(IntPtr hInstAnimation, int idAnimation);
		[PreserveSig]
		int HasUserCancelled();
		void SetProgress(int dwCompleted, int dwTotal);
		void SetProgress64(long ullCompleted, long ullTotal);
		[PreserveSig]
		int SetLine(int dwLineNum, IntPtr pwzString, bool fCompactPath, IntPtr pvResevered);
		void SetCancelMsg([MarshalAs(UnmanagedType.LPWStr)] string pwzCancelMsg, IntPtr pvResevered);
		void Timer(ProgressDialogTimerAction dwTimerAction, IntPtr pvResevered);
	}

	[SuppressUnmanagedCodeSecurity, ComImport, Guid("F8383852-FCD3-11d1-A6B9-006097DF5BD4"), ClassInterface(ClassInterfaceType.AutoDispatch)]
	internal class ProgressDialogInternal : IProgressDialog
	{
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void StartProgressDialog([In, Optional] IntPtr hwndParent, [In, Optional] object punkEnableModless, ProgressDialogStartFlags dwFlags, IntPtr pvResevered);
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void StopProgressDialog();
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pwzTitle);
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void SetAnimation(IntPtr hInstAnimation, int idAnimation);
		[PreserveSig]
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern int HasUserCancelled();
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void SetProgress(int dwCompleted, int dwTotal);
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void SetProgress64(long ullCompleted, long ullTotal);
		[PreserveSig]
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern int SetLine(int dwLineNum, IntPtr pwzString, bool fCompactPath, IntPtr pvResevered);
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void SetCancelMsg([MarshalAs(UnmanagedType.LPWStr)] string pwzCancelMsg, IntPtr pvResevered);
		[MethodImpl(MethodImplOptions.InternalCall)]
		public extern void Timer(ProgressDialogTimerAction dwTimerAction, IntPtr pvResevered);
	}

	public enum ProgressDialogTimerAction
	{
		Reset = 0x00000001, // Reset the timer so the progress will be calculated from now until the first ::SetProgress() is called so those this time will correspond to the values passed to ::SetProgress().  Only do this before ::SetProgress() is called.
		Pause = 0x00000002, // Progress has been suspended
		Resume = 0x00000003, // Progress has resumed
	}

	[Flags]
	public enum ProgressDialogStartFlags : int
	{
		Normal = 0x00000000, // default normal progress dlg behavior
		Modal = 0x00000001, // the dialog is modal to its hwndParent (default is modeless)
		AutoTime = 0x00000002, // automatically updates the "Line3" text with the "time remaining" (you cant call SetLine3 if you passs this!)
		NoTime = 0x00000004, // we dont show the "time remaining" if this is set. We need this if dwTotal < dwCompleted for sparse files
		NoMinimize = 0x00000008, // Do not have a minimize button in the caption bar.
		NoProgressBar = 0x00000010, // Don't display the progress bar
		MarqueeProgressBar = 0x00000020, // Use marquee progress (comctl32 v6 required)
		NoCancel = 0x00000040, // No cancel button (operation cannot be canceled) (use sparingly)
	}

	public class ProgressDialog
	{
		private readonly IProgressDialog obj = new ProgressDialogInternal();
		private long lastCompleted = 0;
		private long lastTotal = 0;
		public void Start(IntPtr hWndParent, object pUnkEnableModless, ProgressDialogStartFlags flags) { this.obj.StartProgressDialog(hWndParent, pUnkEnableModless, flags, IntPtr.Zero); }
		public void Stop() { this.obj.StopProgressDialog(); }
		public void SetAnimation(IntPtr hInstance, int animationID) { this.obj.SetAnimation(hInstance, animationID); }
		public string Title { set { this.obj.SetTitle(value); } }
		public bool Canceled { get { return this.obj.HasUserCancelled() != 0; } }
		
		public void SetProgress(int completed, int total)
		{
			Debug.Assert(this.lastTotal == 0 || this.lastCompleted * total <= completed * this.lastTotal, "Progress went backwards!!!");
			this.lastCompleted = completed;
			this.lastTotal = total;
			this.obj.SetProgress(completed, total);
		}
		
		public void SetProgress(long completed, long total)
		{
			Debug.Assert(this.lastTotal == 0 || this.lastCompleted * total <= completed * this.lastTotal);
			this.lastCompleted = completed;
			this.lastTotal = total;
			this.obj.SetProgress64(completed, total);
		}

		public void SetLine(int lineNumber, string value, bool compactPath) { unsafe { fixed (char* pValue = value) { int result = this.obj.SetLine(lineNumber, (IntPtr)pValue, compactPath, IntPtr.Zero); if (result != 0) { Marshal.ThrowExceptionForHR(result); } } } }
		public string CancelMessage { set { this.obj.SetCancelMsg(value, IntPtr.Zero); } }
		public void SetTimer(ProgressDialogTimerAction action) { this.obj.Timer(action, IntPtr.Zero); }
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


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