Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

WPF Book Reader

, 10 May 2012
A WPF book reader for cbz/cbr files
BookReaderv1.zip
BookReader.exe.manifest
ICSharpCode.SharpZipLib.dll
SevenZipSharp.dll
WPFToolkit.dll
Dependencies
7z.dll
BookReader.application
BookReader.exe
BookReaderv1_source.zip
BookReader
ClassDiagram.cd
Dependencies
7-zip.dll
7z.dll
ICSharpCode.SharpZipLib.dll
SevenZipSharp.dll
WPFToolkit.dll
Properties
app.manifest
Settings.settings
Reader
Catalog
Common
Images
RAR
ZIP
Resources
TheRedPushPin.png
XAML
BookReaderv2.zip
BookReader.application
BookReader.exe
BookReader.exe.manifest
7z.dll
SevenZipSharp.dll
WPFToolkit.dll
BookReaderv2_8.zip
Release
BookReader.application
BookReader.exe
BookReader.exe.manifest
Dependencies
7z.dll
pdftohtml.exe
SevenZipSharp.dll
WPFToolkit.dll
BookReaderv2_8_source.zip
BookReader.csproj.user
BookReader.csproj.vspscc
7z.dll
pdftohtml.exe
SevenZipSharp.dll
WPFToolkit.dll
app.manifest
Settings.settings
acroread.png
document.png
ecran.png
exit.png
FitHeight.png
FitWidth.png
info.png
open_folder.png
refresh.png
Search.png
Theme
TheRedPushPin.png
tools.png
BookReaderv2_source.zip
BookReader.csproj.user
ClassDiagram.cd
7-zip.dll
7z.dll
ICSharpCode.SharpZipLib.dll
SevenZipSharp.dll
WPFToolkit.dll
app.manifest
Settings.settings
TheRedPushPin.png
BookReaderv3_0.zip
BookReader.application
BookReader.exe
BookReader.exe.manifest
BookReader.vshost.exe
7z.dll
pdftohtml.exe
SevenZipSharp.dll
WPFToolkit.dll
BookReaderv3_0_source.zip
BookReader.csproj.user
BookReader.csproj.vspscc
7z.dll
pdftohtml.exe
SevenZipSharp.dll
WPFToolkit.dll
app.manifest
Settings.settings
acroread.png
book.ico
document.png
ecran.png
exit.png
FitHeight.png
FitWidth.png
info.png
open_folder.png
refresh.png
Search.png
TheRedPushPin.png
tools.png
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;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Data;
using BookReader.Reader.Common;

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

                ICollectionView view = CollectionViewSource.GetDefaultView(_Catalog.Books);

                new SearchFilter(view, tbSearch);
			}
			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 --------------------TITLE BAR--------------------
        /// <summary>
        /// title bar close button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void closeButton_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// title bar maximize button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void maximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
                this.WindowState = WindowState.Normal;
            else
                this.WindowState = WindowState.Maximized;
        }

        /// <summary>
        /// title bar minimize button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void minimizeButton_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }

        /// <summary>
        /// Move the window in response to mose move on the title bar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        ///// <summary>
        ///// title bar double click event to change the state
        ///// </summary>
        ///// <param name="sender"></param>
        ///// <param name="e"></param>
        //private void TitleBarBorder_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        //{
        //    if (this.WindowState == WindowState.Maximized)
        //        this.WindowState = WindowState.Normal;
        //    else
        //        this.WindowState = WindowState.Maximized;
        //}

        #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);
			}
		}

        /// <summary>
        /// set the readed status on the book
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_MarkRead(object sender, RoutedEventArgs e)
        {
            MarkRead(true);
        }

        /// <summary>
        /// unset the readed status on the book
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_MarkUnread(object sender, RoutedEventArgs e)
        {
            MarkRead(false);
        }

        /// <summary>
        /// Change the read flag of the current selected book
        /// </summary>
        /// <param name="status"></param>
        private void MarkRead(bool status)
        {
            try
            {
                ((IBook)CatalogListBox.SelectedValue).IsRead = status;
                _Catalog.IsChanged = true;
            }
            catch (Exception err)
            {
                ExceptionManagement.Manage("Main:MarkRead", err);
            }
        }

        /// <summary>
        /// delete the current selected book
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_Delete(object sender, RoutedEventArgs e)
        {
            try
            {
                IBook bk = ((IBook)CatalogListBox.SelectedValue);
                File.Delete(bk.FileName);
                _Catalog.Books.Remove(bk);
                _Catalog.IsChanged = true;
            }
            catch (Exception err)
            {
                ExceptionManagement.Manage("Main:MenuItem_Delete", 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;
					_isFullSreen = false;
                    Splitter.IsExpanded = false;
				}
				else
				{
					this.WindowState = WindowState.Maximized;
					_isFullSreen = true;
                    Splitter.IsExpanded = 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

        private void CatalogListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            try
            {
                LoadBook((IBook)CatalogListBox.SelectedValue);
            }
            catch (Exception err)
            {
                ExceptionManagement.Manage("Main:CatalogListBox_MouseDoubleClick", err);
            }
        }
	}
}

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)

Share

About the Author

Guillaume Waser
Architect A.C.S.
France France
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 10 May 2012
Article Copyright 2009 by Guillaume Waser
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid