Click here to Skip to main content
15,883,710 members
Articles / Desktop Programming / WPF

WPF Book Reader

Rate me:
Please Sign up or sign in to vote.
4.29/5 (16 votes)
10 May 2012GPL35 min read 110.7K   120  
A WPF book reader for cbz/cbr files
using System;
using System.Configuration;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using System.Windows.Controls;
using System.Collections;
using System.Threading;
using System.Windows.Media;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using SevenZip;

namespace BookReader
{
	/// <summary>
	/// Interaction logic for Window1.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		#region -----------------private and constructor-----------------

		private DispatcherTimer _TimerClock;
		private Catalog _Catalog = new Catalog();
		private IBook _CurrentBook = null;

		//full screen
		private GridLength _oldCatalogSize;
		private bool _isFullSreen = false;

		public MainWindow()
		{
			InitializeComponent();
		}

		#endregion

		#region -----------------loading/closing and timer-----------------
		/// <summary>
		/// On loading, create the timer and catalog
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			try
			{
				//create a dispatch timer to load the image cache
				_TimerClock = new DispatcherTimer();
				_TimerClock.Interval = new TimeSpan(0, 0, 5);
				_TimerClock.IsEnabled = true;
				_TimerClock.Tick += new EventHandler(TimerElapse);

				//CollapsCatalog();

				LoadCatalog();
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:Window_Loaded", err);
			}
		}

		private void LoadCatalog()
		{
			//load the catalog of books
			_Catalog.Load(Properties.Settings.Default.Catalog);
			CatalogListBox.DataContext = _Catalog.Books;

			this.Splitter.Title = string.Format("CATALOG ({0} book(s))", _Catalog.Books.Count);
		}

		/// <summary>
		/// Save the catalog on closing
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			try
			{
				_Catalog.Save();
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:Window_Closing", err);
			}
		}

		/// <summary>
		/// Ask the book to manage his cache
		/// </summary>
		/// <param name="tag"></param>
		/// <param name="args"></param>
		public void TimerElapse(object tag, EventArgs args)
		{
			try
			{
				if (_CurrentBook != null)
				{
					_CurrentBook.ManageCache();
					this.Info.Content = _CurrentBook.Cache.GetCacheInfo();
				}

				this.Splitter.Title = string.Format("CATALOG ({0} book(s))", _Catalog.Books.Count);
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:TimerElapse", err);
			}
		}
		#endregion

		#region -----------------manage zoom and page changes-----------------

		/// <summary>
		/// Update the Page viewer regarding the slider value
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			if( this.SimplePageView != null )
				this.SimplePageView.Scale = e.NewValue/100;
		}

		/// <summary>
		/// Update the slider regarding the page viewer scale
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void SimplePageView_ZoomChanged(object sender, PageViewer.ZoomRoutedEventArgs e)
		{
			this.zoomSlider.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(this.Slider_ValueChanged);
			this.zoomSlider.Value = Math.Round( e.Scale * 100, 0);
			this.zoomSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(this.Slider_ValueChanged);
		}

		/// <summary>
		/// manage page changes
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void SimplePageView_PageChanged(object sender, PageViewer.PageRoutedEventArgs e)
		{
			if (e.PageOffset == -1) //we go down
			{
				if (_CurrentBook.GotoPreviousPage())
				{
					this.SimplePageView.Source = _CurrentBook.GetCurrentPageImage();
					this.PageInfo.Content = _CurrentBook.CurrentPage.FilePath;
					this.SimplePageView.ScrollToBottom();
				}
			}
			else
				if (e.PageOffset == 1) //we go up
				{
					if (_CurrentBook.GotoNextPage())
					{
						this.SimplePageView.Source = _CurrentBook.GetCurrentPageImage();
						this.PageInfo.Content = _CurrentBook.CurrentPage.FilePath;
						this.SimplePageView.ScrollToHome();
					}
				}
		}

		#endregion

		#region -----------------menu item events-----------------

		/// <summary>
		/// Load a given book
		/// </summary>
		/// <param name="book"></param>
		private void LoadBook( IBook book )
		{
			try
			{
				if (_CurrentBook != null)
					_CurrentBook.UnLoad();

				_CurrentBook = book;
				_CurrentBook.Load();

                this.SimplePageView.Scale = 1.0;
                this.SimplePageView.Source = _CurrentBook.GetCurrentPageImage();
				this.PageInfo.Content = _CurrentBook.CurrentPage.FilePath;
				this.SimplePageView.ScrollToHome();
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:LoadBook", err);
			}
		}

		/// <summary>
		/// Load a book from the catalog
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MenuItem_Load(object sender, RoutedEventArgs e)
		{
			try
			{
				LoadBook((IBook)CatalogListBox.SelectedValue);
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:MenuItem_Load", err);
			}
		}

		/// <summary>
		/// Set a bookmark on the current page of the current book
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MenuItem_BookMark(object sender, RoutedEventArgs e)
		{
			try
			{
				if (_CurrentBook != null)
				{
					_CurrentBook.SetMark();
					_Catalog.IsChanged = true;
				}
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:MenuItem_BookMark", err);
			}
		}

		/// <summary>
		/// Open the book if needed and go to the bookmark
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MenuItem_GotoBookMark(object sender, RoutedEventArgs e)
		{
			try
			{
				if (_CurrentBook != (IBook)CatalogListBox.SelectedValue)
				{
					LoadBook((IBook)CatalogListBox.SelectedValue);
				}
				_CurrentBook.GotoMark();
                this.SimplePageView.Source = _CurrentBook.GetCurrentPageImage();
				this.SimplePageView.ScrollToHome();
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:MenuItem_GotoBookMark", err);
			}
		}

		/// <summary>
		/// Remove the bookmark from the current book
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MenuItem_ClearBookMark(object sender, RoutedEventArgs e)
		{
			try
			{
				((IBook)CatalogListBox.SelectedValue).Bookmark = string.Empty;
				_Catalog.IsChanged = true;
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:MenuItem_ClearBookMark", err);
			}
		}
		#endregion

		#region -----------------toolbar events-----------------


        private void btnFitWidth_Click(object sender, RoutedEventArgs e)
        {
			this.SimplePageView.FitWidth();
        }

        private void btnFitHeight_Click(object sender, RoutedEventArgs e)
        {
			this.SimplePageView.FitHeight();
        }

		/// <summary>
		/// Open an external book, not in the catalog folder
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnOpen_Click(object sender, RoutedEventArgs e)
		{
			using (System.Windows.Forms.OpenFileDialog browser = new System.Windows.Forms.OpenFileDialog())
			{
				if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					LoadBook( (IBook)_Catalog.Open(browser.FileName) );
				}
			}
		}

		/// <summary>
		/// Display the about box
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnAbout_Click(object sender, RoutedEventArgs e)
		{
			AboutWindow dlg = new AboutWindow();
			dlg.ShowDialog();
		}

		/// <summary>
		/// Refresh the covers and books
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnRefresh_Click(object sender, RoutedEventArgs e)
		{
			_Catalog.Refresh();
		}

		/// <summary>
		/// Close the soft, nothing special
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnQuit_Click(object sender, RoutedEventArgs e)
		{
			this.Close();
		}

		/// <summary>
		/// Display the options dialog
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnOptions_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				OptionWindow dlg = new OptionWindow();

				//load the catalog of books if we change significative values 
				if (dlg.ShowDialog() == true)
				{
					if (dlg.NeedToReload)
					{
						LoadCatalog();
					}
				}
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:btnOptions_Click", err);
			}
		}

		/// <summary>
		/// Swap the full screen state
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnFullScreen_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				if (_isFullSreen)
				{
					this.WindowState = WindowState.Normal;
					this.WindowStyle = WindowStyle.ToolWindow;
					_isFullSreen = false;
				}
				else
				{
					this.WindowState = WindowState.Maximized;
					this.WindowStyle = WindowStyle.None;
					_isFullSreen = true;
				}
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:btnFullScreen_Click", err);
			}
		}

		/// <summary>
		/// Convert the PDF to ZIP/RAR
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void bntConvertPDF_Click(object sender, RoutedEventArgs e)
		{
			try
			{
				string pdfFile;

				using (System.Windows.Forms.OpenFileDialog browser = new System.Windows.Forms.OpenFileDialog())
				{
					if (browser.ShowDialog() != System.Windows.Forms.DialogResult.OK)
						return;
					else
						pdfFile = browser.FileName;
				}
				
				string pdf2image = Assembly.GetExecutingAssembly().Location.Replace("BookReader.exe", "Dependencies\\pdftohtml.exe");

				FileInfo fi = new FileInfo(pdfFile);

				ProcessStartInfo p = new ProcessStartInfo(pdf2image);
				p.Arguments = string.Format("\"{0}\" ", fi.FullName); //pdf file
				p.Arguments += string.Format("\"{0}\\{1}", fi.DirectoryName, fi.Name.Replace(fi.Extension, ""));

				string output = Path.Combine(fi.DirectoryName, fi.Name.Replace(fi.Extension, "") );
				if (!Directory.Exists(output) )
					Directory.CreateDirectory( output );

				p.Arguments += string.Format("\\{0}", "export.html");
				p.UseShellExecute = false;
				p.WindowStyle = ProcessWindowStyle.Hidden;
				p.CreateNoWindow = true;
				Process bat = System.Diagnostics.Process.Start(p);
				bat.WaitForExit();

				string sevenZip = Assembly.GetExecutingAssembly().Location.Replace("BookReader.exe", "Dependencies\\7z.dll");
                SevenZipCompressor.SetLibraryPath(sevenZip);
				SevenZipCompressor zip = new SevenZipCompressor();
				zip.ArchiveFormat = OutArchiveFormat.Zip;
				zip.CompressionLevel = CompressionLevel.Normal;
				zip.CompressionMethod = CompressionMethod.Default;
				zip.CompressionMode = CompressionMode.Create;
				zip.DirectoryStructure = true;
				zip.CompressDirectory( output, fi.Name.Replace(fi.Extension, ".zip"), "*.jpg", false );

				Directory.Delete( output, true );
			}
			catch (Exception err)
			{
				ExceptionManagement.Manage("Main:bntConvertPDF_Click", err);
			}
		}

		#endregion
	}
}

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 GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions