C# – Introduction to Aspect Oriented Programming with RealProxy

In many complex business applications, software developers are maybe asked for making protocol of all changes on an object. For example, in a task management system, changes of a task such as dead line, attachments, comments… by users should be logged and displayed in his history. Or in a fault management system, all changes of a fault such as status, companies, workers,… should be also recorded. Who adds what, who deletes what, tracking changes… is the point of interest. How should we solve these requirements without violating our software architecture and duplicating code? We need something that can cross the boundaries of an object or a layer and Aspect Oriented Programming (AOP) is exactly what we need. According to Wikipedia,

Continue reading C# – Introduction to Aspect Oriented Programming with RealProxy

C# – Introduction to SignalR

Mobile apps have a native support for pushing notifications from server to clients on many platforms such as Android, IOS or Windows Phone. I discussed about this feature in Android while ago in Google Cloud Messaging, ASP.NET Web Api and Android client post. Because it’s an interesting feature, we also want to have it in desktop or web application which can be done easily with SignalR, a new ASP.NET library for real-time web application. On SignalR’s homepage http://signalr.net/, you’ll find a lot of examples and codes for demonstrating how it works. In this post, I just want to show how to host SignalR on a WPF application (outside of IIS) and how SignalR basically works. The demo has a server-client model but the clients can also “broadcast” his message to other clients and the server can notify all clients with his notification.

Continue reading C# – Introduction to SignalR

C# – How to use Google Custom Search API?

Google search engine has a market share of over 60%. For some advanced features, such as searching metadata or relevant info of an object, we maybe want to integrate search result of Google search engine instead of inventing our own one. In this post, I would like to write down the steps how we can consume Google Custom Search API in .Net. The code itself is pretty short. However, because of lacking documentation it’s really time consuming to find out how the code should be, where to get the API Key or Search Engine ID for authentication. These all settings stuff drive me crazy because they locate on different control panel.
Please note that Custom Search Engine is a free API edition. For CSE users, the API provides 100 search queries per day for free. If you need more, you may sign up for billing in the Developers Console. Additional requests cost $5 per 1000 queries, up to 10k queries per day.
The other paid version is Google Site Search which is out of scope of this post.

Continue reading C# – How to use Google Custom Search API?

How to create a C++ dll with Visual Studio?

Following previous post How to create a CLR wrapper of C++ for using in C#, I will continue with C++ project in this post. C++ is not my main programming language anymore in last 10 years but I would like to keep some ‘important’ things (to me) of C++ projects before I have to leave it again in next 5 years for focusing on web development. I would like to spend more time for web development (backend and frontend) where C#, Javascript, HTML and CSS are in a more dominant position. In this post, I’ll write down the steps to create a C++ DLL by Visual Studio. This DLL can again be wrapped by a wrapper like in previous post and consumed in C#.

Continue reading How to create a C++ dll with Visual Studio?

C# – How to create a CLR wrapper of C++ for using in C#?

It has been almost 10 years since last time when I worked with C++. I don’t remember much about C++ syntax and can’t even write a small app with C++ anymore. Since Visual Studio introduces C# and CLR and a lot of changes in C++ development environment. I just ‘quit’ out of this programming language. Moreover in next years, I will focus more in web development, not only for private but also for occupational activities. That mean no chance to come back with C++. I’m afraid that many important things of C++ (that I want to keep) will go with the wind after years. When I need them again, it’ll take me days to bring them back. Creating a CLR wrapper is for me such important thing. So in this small post, I just would like to write down the steps to make a simple CLR wrapper for a C++. This is only a simple CLR wrapper, nothing special, but it always helps me a lot when I try to use C++ library in my C# program.
Continue reading C# – How to create a CLR wrapper of C++ for using in C#?

C# – WPF MVVM DataBinding 2014

It’s already 6 years since my first post about MVVM and data bindings in WPF MVVM – ListView SelectedItem and DataBinding. The MVVM pattern is now quite popular and comes into use in many WPF applications. However a lot of things have changed since 2008. We have now many new platforms where we can also apply MVVM pattern such as Windows 8 app, Windows phone app… When you use Xamarin (http://xamarin.com/) to develop cross platform applications with C#, maybe you want to use MVVM pattern too. In my last post 6 years ago, I introduced to you the concept of MVVM in ‘raw’ format which means no use of any external frameworks. Today I would like to make a supplementary post by introducing 2 MVVM frameworks for easing the use of MVVM pattern. The first one is Caliburn.Micro https://github.com/Caliburn-Micro/Caliburn.Micro and the second one is Mvvm Cross https://github.com/MvvmCross/MvvmCross . They’re both open source products and can be used in any commercial applications.

Continue reading C# – WPF MVVM DataBinding 2014

C#,iTextSharp – PDF file – Insert/extract image,text,font, text highlighting and auto fillin

Nowadays, Portable Document Format (PDF) is a most popular standard for document exchange. Created by Adobe System in 1993, this format independent of platform is used for representing contents including text, font, images and other information. However the PDF format could only be created by Adobe Acrobat Professional and does not allow user to edit the content of file. But then there were more and more wishes to create PDF without Adobe Acrobat Professional or to edit a PDF file. These wishes led to the birth of many open source libraries for PDF. One of them is iText, a library that allows creating and manipulating PDF documents. It enables developers looking to enhance web- and other applications with dynamic PDF document generation and/or manipulation. In this small blog I would like to illustrate some features of iTextSharp (http://sourceforge.net/projects/itextsharp/ – a port of iText in .Net platform) through small examples.

1. Insert image and text to PDF

Let’s think about a case that we are in a big company which has a lot of documentations in PDF format. We have a task that on the top of all of these documents should have the company’s logo. We have only PDF format the original editable documentations are not available. It’s will be nightmare if we open each one with Adobe Acrobat Professional and insert the logo but thanks to iTextSharp we can do this easily

private static void InsertImageToPdf(string sourceFileName, string imageFileName, string newFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	using (Stream imageStream = new FileStream(imageFileName, FileMode.Open))
	using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
		PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
		iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageStream);
		image.SetAbsolutePosition(300, 600);
		pdfContentByte.AddImage(image);
		pdfStamper.Close();
	}
}

Anytime if we want to insert any object or edit anything of PDF file with iTextSharp, we should use PdfStamper plus PdfContentByte like code above. The PdfStamper allow us to get current content GetOverContent() and add object through its functions Addxxx(). Closing the pdfStamper will save all changes back to PDF file. Image inserting makes nothing than that. Create an instance of iTextSharp image from normal image and follow the routine above. Text inserting is as same as image inserting. However we can set some more attributes for text like font, size, color, rotation, etc…. before “pasting” it to a specific location in PDF file.

private static void InsertTextToPdf(string sourceFileName, string newFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
		PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
		BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
		pdfContentByte.SetColorFill(BaseColor.BLUE);
		pdfContentByte.SetFontAndSize(baseFont, 8);
		pdfContentByte.BeginText();
		pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Kevin Cheng - A Hong Kong actor", 400, 600, 0);
		pdfContentByte.EndText();
		pdfStamper.Close();
	}
}

Before

iTextSharp insert image and text

After

iTextSharp insert image and text

2. Extract text from PDF

Text object extracting from PDF with iTextSharp is also pretty simple. Initializing a PdfReader() and call GetTextFromPage() of PdfTextExtractor() with appropriate strategy, we’ll get all text we need.

private static void ExtractTextFromPdf(string newFileNameWithImageAndText, string extractedTextFileName)
{
	using (Stream newpdfStream = new FileStream(newFileNameWithImageAndText, FileMode.Open, FileAccess.ReadWrite))
	{
		PdfReader pdfReader = new PdfReader(newpdfStream);
		string text = PdfTextExtractor.GetTextFromPage(pdfReader, 1, new iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy());
		File.WriteAllText(extractedTextFileName, text);
	}
}

Interesting is that we don’t have to read all of text of a page or of complete PDF file but we can define that we would like to read only text of specific region. It’s very useful if we just want to read the address of letter in PDF. We don’t need to read all of letter which is time and resource consuming. Just define region where address is and read it out. For example, we would like to extract text from region as image below

iTextSharp extract text from region

private static void ExtractTextFromRegionOfPdf(string sourceFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		System.util.RectangleJ rect = new System.util.RectangleJ(50, 650, 250, 140);
		RenderFilter[] renderFilter = new RenderFilter[1];
		renderFilter[0] = new RegionTextRenderFilter(rect);
		ITextExtractionStrategy textExtractionStrategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderFilter);
		Console.WriteLine(PdfTextExtractor.GetTextFromPage(pdfReader, 1, textExtractionStrategy));
	}
}

The code for reading from region uses same function GetTextFromPage() but with another strategy LocationTextExtractionStrategy(). This strategy will be parsed in an instance of FilteredTextRenderListener() with a RegionTextRenderFilter(). This filter contains the defined region which we want to extract exactly the text from, in this case is a rectangle.

3. Auto Fill-in PDF form

Let’s think about this case that we have an interactive form in PDF format. We would like to send this template to many users with some pre-fill-in fields, for example, the username and their addresses will be automatically filled. It’s suitable when we would like to make a survey or a new contract from current data. We can also accomplish it with help of iTextSharp, just get all Acrobat fields of PDF out, set their values and save them back. Of course as I say before, we should use PdfStamper for any editing action on PDF file. The image below shows an interactive form in PDF as example

Interactive PDF form

private static void AutoFillInFormOfPdf(string fillableFormFileName, string newfillableFormFileName)
{
	using (Stream pdfStream = new FileStream(fillableFormFileName, FileMode.Open))
	using (Stream newpdfStream = new FileStream(newfillableFormFileName, FileMode.Create, FileAccess.ReadWrite))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
		foreach (KeyValuePair<string, iTextSharp.text.pdf.AcroFields.Item> pair in pdfReader.AcroFields.Fields)
		{
			Console.WriteLine(pair.Key + " - " + pair.Value);
		}
	
		AcroFields acroFields = pdfStamper.AcroFields;
		acroFields.SetField("Text_01", "ServusKevin");
		acroFields.SetField("Radio Button_01", acroFields.GetAppearanceStates("Radio Button_01")[0]);
		acroFields.SetField("Radio Button_02", acroFields.GetAppearanceStates("Radio Button_02")[1]);
		acroFields.SetField("Radio Button_03", acroFields.GetAppearanceStates("Radio Button_03")[2]);
		acroFields.SetField("Check Box_03", acroFields.GetAppearanceStates("Check Box_03")[0]);
		acroFields.SetField("Combo Box_01", pdfReader.AcroFields.GetListOptionDisplay("Combo Box_01")[4]);

		pdfStamper.Close();
	}
}

First I use a loop to list all AcroFields with his name plus his current value and then I set them with what I want. “Text_01”, “Radio Button_01”, “Radio Button_02”, “Radio Button_03″… are the names of the controls in form. Although we can easily set text of text box, the other components are not the case. The radio button and check box have custom defined values. Only setting correct value will display the control correctly (check or not checked). If we set false value, the control will be displayed as default (normally as unchecked, it depends on author of the form). These values can be enumerated with the GetAppearanceStates() function with name of field as argument. However this function is not available for combo box because he is again another case. To enumerate combo box’s values, we should use the GetListOptionDisplay(). This function will return all available choices of combo box. It’s a little confused that each component has its own behavior, but if you know the functions then it’s not complicated anymore.

Source code : https://bitbucket.org/hintdesk/dotnet-itextsharp-pdf-file-insertextract-imagetext-and-auto

4. Updates

4.1 Extract list of fonts used in PDF file – 27.04.2012

try listing below

private static void ExtractFontNameOfPdf(string sourceFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		List<BaseFont> set = new List<BaseFont>();
		PdfDictionary resources;

		for (int index = 1; index <= pdfReader.NumberOfPages; index++)
		{
			resources = pdfReader.GetPageN(index).GetAsDict(PdfName.RESOURCES);
			ProcessResource(set, resources);
		}

		foreach (BaseFont item in set)
			Console.WriteLine(item.PostscriptFontName + " " + item.FontType.ToString());
	}
}

private static void ProcessResource(List<BaseFont> set, PdfDictionary resources)
{
	if (resources == null)
		return;
	PdfDictionary xObjects = resources.GetAsDict(PdfName.XOBJECT);
	if (xObjects != null)
	{
		foreach (PdfName key in xObjects.Keys)
		{
			ProcessResource(set, xObjects.GetAsDict(key));
		}
	}

	PdfDictionary fonts = resources.GetAsDict(PdfName.FONT);

	if (fonts == null)
		return;
	foreach (PdfName key in fonts.Keys)
	{
		PdfDictionary fontDict = (PdfDictionary)PdfReader.GetPdfObject(fonts.Get(key));
		PdfName baseFontName = (PdfName)PdfReader.GetPdfObject(fontDict.Get(PdfName.BASEFONT));
		PRIndirectReference iRef = (PRIndirectReference)fonts.Get(key);
		if (iRef != null)
			set.Add(BaseFont.CreateFont(iRef));
	}
}

4.2 Highlighting text in existing PDF file – 30.07.2012

private static void ChangeTextColorOfPdf(string sourceFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		using (PdfStamper stamper = new PdfStamper(pdfReader, pdfStream))
		{
			iTextSharp.text.Rectangle rect = new Rectangle(130, 635, 230, 650);
			float[] quadPoints = { rect.Left, rect.Bottom, rect.Right, rect.Bottom, rect.Left, rect.Top, rect.Right, rect.Top };
			PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quadPoints);
			highlight.Color = BaseColor.GREEN;
			stamper.AddAnnotation(highlight, 1);
		}
		Console.WriteLine("Text was highlighted");
	}
}

4.3 Extract all text from .pdf – 18.08.2013

Using Parallel to extract text from .pdf file

using (Stream newpdfStream = new FileStream(newFileNameWithImageAndText, FileMode.Open, FileAccess.ReadWrite))
{
	PdfReader pdfReader = new PdfReader(newpdfStream);

	int pageSize = (int)Math.Ceiling((double)pdfReader.NumberOfPages / (double)(Environment.ProcessorCount * 2));
	int numberOfThreads = (int)Math.Ceiling((double)pdfReader.NumberOfPages / (double)pageSize);
	IList<Task> tasks = new List<Task>();
	for (int index = 0; index < numberOfThreads; index++)
	{
		int currentIndex = index;
		int page = Math.Min((index + 1) * pageSize, pdfReader.NumberOfPages);
		tasks.Add(Task.Factory.StartNew<string>(() =>
			{
				StringBuilder taskResult = new StringBuilder();
				for (int subIndex = currentIndex * pageSize + 1; subIndex <= page; subIndex++)
					taskResult.Append(PdfTextExtractor.GetTextFromPage(pdfReader, subIndex, new iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy()));
				return taskResult.ToString();
			})
			.ContinueWith((t) => File.WriteAllText(currentIndex.ToString() + ".txt", t.Result)));
	}

	Task.WaitAll(tasks.ToArray());
	Console.WriteLine("Finish");
}

4.4 Get roman page numbers – 21.03.2015

Get roman page numbers of first pages such as cover, back cover, table of contents…

private static void ExtractRomanPageNumbers(string sourceFileName)
{
	using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
	{
		PdfReader pdfReader = new PdfReader(pdfStream);
		
		foreach (string s in GetRomanPageNumbers(pdfReader))
			Console.WriteLine(s);

	}
}

private static IEnumerable<string> GetRomanPageNumbers(PdfReader pdfReader)
{
	int n = pdfReader.NumberOfPages;

	PdfDictionary dict = pdfReader.Catalog;
	PdfDictionary labels = (PdfDictionary)PdfReader.GetPdfObjectRelease(dict.Get(PdfName.PAGELABELS));
	if (labels == null)
		return null;

	String[] labelstrings = new String[n];
	Dictionary<int, PdfObject> numberTree = PdfNumberTree.ReadTree(labels);

	int pagecount = 1;
	String prefix = "";
	char type = 'D';
	for (int i = 0; i < n; i++)
	{
		if (numberTree.ContainsKey(i))
		{
			PdfDictionary d = (PdfDictionary)PdfReader.GetPdfObjectRelease(numberTree[i]);
			if (d.Contains(PdfName.ST))
			{
				pagecount = ((PdfNumber)d.Get(PdfName.ST)).IntValue;
			}
			else
			{
				pagecount = 1;
			}
			if (d.Contains(PdfName.P))
			{
				prefix = ((PdfString)d.Get(PdfName.P)).ToUnicodeString();
			}
			if (d.Contains(PdfName.S))
			{
				type = ((PdfName)d.Get(PdfName.S)).ToString()[1];
			}
		}
		switch (type)
		{
			default:
				labelstrings[i] = pagecount.ToString();
				break;
			case 'R':
				labelstrings[i] = RomanNumberFactory.GetUpperCaseString(pagecount);
				break;
			case 'r':
				labelstrings[i] = RomanNumberFactory.GetLowerCaseString(pagecount);
				break;
			case 'A':
				labelstrings[i] =  RomanAlphabetFactory.GetUpperCaseString(pagecount);
				break;
			case 'a':
				labelstrings[i] = RomanAlphabetFactory.GetLowerCaseString(pagecount);
				break;
		}
		pagecount++;
	}
	return labelstrings;
}

4.5 Add annotation – 13.03.2017

private static void AddAnnotation(string fileName)
{
	var result = StampPDFDocument(File.ReadAllBytes(fileName), "hintdesk annotation");
	File.WriteAllBytes("stampedTest.pdf",result);
	Console.WriteLine("Add annotations successfully");
}

private static byte[] StampPDFDocument(byte[] pdf, string stampString)
{
	using (var ms = new MemoryStream())
	{
		var reader = new iTextSharp.text.pdf.PdfReader(pdf);
		var stamper = new iTextSharp.text.pdf.PdfStamper(reader, ms);

		int rotation = reader.GetPageRotation(1);

		var box = reader.GetPageSizeWithRotation(1);
		var cropbox = reader.GetCropBox(1);

		float left = cropbox.Left;
		float top = cropbox.Top;

		if (rotation == 90)
		{
			left = cropbox.Bottom;
			top = box.Height - cropbox.Left;
			cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Height, top - cropbox.Width);
		}
		else if (rotation == 180)
		{
			left = box.Width - cropbox.Left - cropbox.Width;
			top = box.Height - cropbox.Bottom;
			cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Width, top - cropbox.Height);
		}
		else if (rotation == 270)
		{
			left = box.Width - cropbox.Top;
			top = cropbox.Right;
			cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Height, top - cropbox.Width);
		}

		iTextSharp.text.Rectangle newRectangle = new iTextSharp.text.Rectangle(left + 20, top - 20, left + 250, top - 40);

		var pcb = new iTextSharp.text.pdf.PdfContentByte(stamper.Writer);
		pcb.SetColorFill(iTextSharp.text.BaseColor.RED);

		var annot = iTextSharp.text.pdf.PdfAnnotation.CreateFreeText(stamper.Writer, newRectangle, stampString, pcb);
		annot.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_PRINT;
		annot.Rotate = reader.GetPageRotation(1);

		annot.BorderStyle = new iTextSharp.text.pdf.PdfBorderDictionary(0, 0);
		stamper.AddAnnotation(annot, 1);
		stamper.Close();
		return ms.ToArray();
	}
}

C#, Tools – Video Converter with ffmpeg

Last month I bought a new digital camera Canon PowerShot SX210IS 14.1 MP Digital Camera with 14x Wide Angle Optical Image Stabilized Zoom and 3.0-Inch LCD (Black) . My old one is somehow broken, the taken photos were not as good as before. So I decide to buy a new one with better video capturing feature. Canon PowerShot SX210IS can capture
– stunning HD movies with Dynamic mode for enhanced image stabilization when shooting movies using wide-angle settings or
– smooth HD video (720p) with stereo sound for a truly natural, high quality HD experience.
It sounds great, doesn’t it?

However, as you know, the file size of a HD video is always too big. It’s about over 100 MB for only some minutes which is a big disadvantage for sharing over internet. Therefore I would like to write a small tool basing on ffmpeg – an open source command line video converter – to convert the video from MOV to AVI format (can be played in any version of Windows Media Player ) and to reduce simultaneously the file size up to 90% of the original. The GUI of this tool is very simple as below

VidCon

This tool takes path to original video file as his input then call the ffmpeg with this syntax

ffmpeg.exe -i "inputfile" "outputfile"

to convert file into AVI. The important metadata like duration and fps will be displayed when user gives him the input video file. It is very simple tool because I do not write any code for video converting. I simply parse ffmpeg input / output and write this tool as ffmpeg GUI. There is nothing special in the code if you read this blog post before http://hintdesk.com/c-read-console-output-asynchronously/

Just using the same code of this post in combination with some regex rules you can read the metadata of input file as well as the current progress when converting

enum VideoProperties
{
	[DescriptionAttribute(@"[D|d]uration:.((\d|:|\.)*)")]
	Duration,
	[DescriptionAttribute(@"[s,].([0-9]+(?:\.[0-9]*)?) fps")]
	Fps,
	[DescriptionAttribute(@"frame=\s+([0-9]*)")]
	CurrentFrame,	
}

There is only a small problem with Drag and Drop on text box when I was writing this software because in the text box control of WPF, the Drag and Drop events are marked as handled and prevent us from handling these events ourselves. Therefore although we set the AllowDrop on true, the cursor is always shown as not drop allowed when we drop something on it. To solve this problem we must set the triggers for 3 events: PreviewDragEnter, PreviewDragOver, PreviewDrop and handle these events as below

<TextBox AllowDrop="True" Grid.Column="0" Text="{Binding SelectedFilePath}"   Name="txtIpodPath" VerticalAlignment="Center" Height="31">
	<i:Interaction.Triggers>                        
		<i:EventTrigger EventName="PreviewDragEnter">
			<cmd:EventToCommand Command="{Binding PreviewDragCommand, Mode=OneWay}" PassEventArgsToCommand="True" />
		</i:EventTrigger>
		<i:EventTrigger EventName="PreviewDragOver">
			<cmd:EventToCommand Command="{Binding PreviewDragCommand, Mode=OneWay}" PassEventArgsToCommand="True" />
		</i:EventTrigger>
		<i:EventTrigger EventName="PreviewDrop">
			<cmd:EventToCommand Command="{Binding PreviewDropCommand, Mode=OneWay}" PassEventArgsToCommand="True" />
		</i:EventTrigger>
	</i:Interaction.Triggers>
</TextBox>   
private RelayCommand<DragEventArgs> handleDropCommand;
public ICommand HandleDropCommand
{
	get
	{
		if (handleDropCommand == null)
			handleDropCommand = new RelayCommand<DragEventArgs>(e => HandleDropEvent(e));
		return handleDropCommand;
	}
}

private void HandleDropEvent(DragEventArgs e)
{
	if (e.Data == null)
	{
		return;
	}

	string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
	SelectedFilePath = files[0];
	ffmpegWrapper.ReadInputFile(SelectedFilePath);
}

private RelayCommand<DragEventArgs> previewDragCommand;
public ICommand PreviewDragCommand
{
	get
	{
		if (previewDragCommand == null)
			previewDragCommand = new RelayCommand<DragEventArgs>(e => HandlePreviewDragEvent(e));
		return previewDragCommand;
	}
}

private void HandlePreviewDragEvent(DragEventArgs e)
{
	e.Effects = DragDropEffects.All;
	e.Handled = true;
}


private RelayCommand<DragEventArgs> previewDropCommand;
public ICommand PreviewDropCommand
{
	get
	{
		if (previewDropCommand == null)
			previewDropCommand = new RelayCommand<DragEventArgs>(e => HandleDropEvent(e));
		return previewDropCommand;
	}
}

You can see that in the code above I use the same function to handle 2 events PreviewDragEnter and PreviewDragOver. Just allow all DragDropEffects and set the Handled on true to tell that we would like to handle these events ourselves. If you do not set Handled on true, you won’t get any information when catching the Drop event.

Maybe it’s interesting for you about the formula to calculate the number of frames of a video file : Frame = Duration * Fps. Using this information I can display the converting progress smoothly with a progress bar because ffmpeg does not give us any info about number of frames but he shows the current frame when he converts the video. Knowing total number of frames of video file in combining with current frame, we can estimate how long ffmpeg will take until finishing. In C#, the formula will be implemented as below.

public int Frame
{ 
	get 
	{
		TimeSpan tempTimeSpan = new TimeSpan();
		string[] timepieces = Duration.Split(new char[] { ':', '.' });
		if (timepieces.Length == 4)
		{
			 tempTimeSpan = new TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3]));
		}

		if (Duration != null && Fps != null)
			return (int)(tempTimeSpan.TotalSeconds * double.Parse(Fps, CultureInfo.InvariantCulture));
		else
			return 0;
	}
}

In this first version, I do not provide any advanced features so that one can set the frame rate,fps, codec or something like that. And I do not intend to build these features into this tool because I think as normal user I have no idea about frame rate or codec. In next version I will build only one feature more allowing user to set the size of output video. For example, user can set that he would like to have an AVI about 2 MB so that he can attach it in an email. The tool will change the video properties inside to reach the given output size.

In summary, this tool can be used to convert any video format to AVI format which has smaller file size and is compatible to any version of Windows Media Player meaning can be played under any version of Windows operating system. If you want to try it, you can easily download it here “VidCon – Video Converter with ffmpeg“. As normal no source code avaible for any tool.