Saturday, December 5, 2009

Code4Food #3: Text Editor in 5 minutes – Part II. FileSystemWatcher class.

By the way I installed a rating widget on my blog. So now you can rate my posts if you like them, or if you dislike them you can put a 1 star rate too.

Hi,

Finally I found time to continue my little experiment with the text editor. Here you can read the previous post on text editor.

Today we’re going to talk about:

So here is the to download it :

ViewFile_0.2 sourcecode

 

SaVE FilE

This part actually was relatively easy to do. It was very similar to reading. Using TextWriter was enough to save the file. I still like looking fancy that’s why I used a SaveFileDialog for saving a file.

I indicated that saving would be possible by default in 2 formats without indicating extension (see saveFileDialog.Filter property), text files and C# class files.

private void btnSaveFile_Click(object sender, EventArgs e)
{
	SaveFileDialog saveFileDialog = new SaveFileDialog();
	saveFileDialog.Filter = "Text Files (*.txt)|*.txt|C# files (*.cs)|*.cs|All files (*.*)|*.*";

	saveFileDialog.SupportMultiDottedExtensions = true;

	DialogResult result = saveFileDialog.ShowDialog();

	if (result == DialogResult.OK)
	{
		_fileName = saveFileDialog.FileName;
		
		if (!string.IsNullOrEmpty(_fileName))
			SaveFileContent();
	}
}

private void SaveFileContent()
{
	lblFileName.Text = Path.GetFileName(_fileName);

	try
	{
		// we'll make only a textual file for instance
		TextWriter tw = File.CreateText(_fileName);

		try
		{
			tw.Write(txtFileContent.Text);
		}
		catch (Exception ex)
		{ MessageBox.Show(ex.Message); }
		finally
		{
			tw.Close();

			StartMonitorization();
		}
	}
	catch (UnauthorizedAccessException ex)
	{ MessageBox.Show("Sorry, you lack sufficient privileges."); }
	catch (Exception ex)
	{ MessageBox.Show(ex.Message); }
}
Notifications Sending when Your file is changed

I didn’t actually planned to implement this but I saw a great opportunity. It was already a class there that could permit me to do this in a very easy way.

So here it is:

FileSystemWatcher class – this class is particularly used to “watch” the changes that occur on a particular map or folder or a group of files (for example: textual files).

The most important things in this class are:

Properties

  • string Filter  -  Gets or sets the filter string used to determine what files are monitored in a directory.
  • string Path  -  Gets or sets the path of the directory to watch.

Both of these properties are indicated in constructor: FileSystemWatcher(String path, String filter)
Initializes a new instance of the FileSystemWatcher class, given the specified directory and type of files to monitor.

  • NotifyFilters NotifyFilter – Here you specify what kind of events do you want to watch:
    • FileName - The name of the file.
    • DirectoryName - The name of the directory.
    • Attributes - The attributes of the file or folder.
    • Size - The size of the file or folder.
    • LastWrite - The date the file or folder last had anything written to it.
    • LastAccess - The date the file or folder was last opened.
    • CreationTime - The time the file or folder was created.
    • Security - The security settings of the file or folder.
  • bool IncludeSubdirectories - Gets or sets a value indicating whether subdirectories within the specified path should be monitored.
  • bool EnableRaisingEvents - Gets or sets a value indicating whether the component is enabled.

Events

  • Created  -  Occurs when a file or directory in the specified Path is created.
  • Changed  -  Occurs when a file or directory in the specified Path is changed.
  • Renamed  -  Occurs when a file or directory in the specified Path is renamed.
  • Deleted  -  Occurs when a file or directory in the specified Path is deleted.
  • Error -  Occurs when the internal buffer overflows.

For more information consult MSDN on FileSystemWatcher.

So here is the code I implemented for support of notifications.

First I implemented StartMonitorization method where i initialized my FileSystemWatcher, and wired the events to it. I also specified the name of the file to monitor (it is always the file i load or save), and set the events I want to catch. This was done by setting NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite. This means that I would like to catch the events then the filename is changed or when the file is saved. Then i set EnableRaisingEvents = true for my _fileMonitor. If this property is set to false, events are not generated.

Then I implemented the event handlers. First of all I got to say that I made a single handler for Created and Changed event, and another two for Deleted and Renamed events.

The workflow was easy: when an event occurs I display a message box and ask if user wants to reload the file in case of Created, Renamed, Changed events, or remove the file from text editor if i get the Deleted event. If user answers OK, then I execute the needed method.

 

Problems I’ve met

  1. Now the first problem I saw was that my methods were not executed because I try to modify the UI thread from watcher thread. That is not working that way. We need to use BeginInvoke method and to create a delegate in UI thread, and to pass him the names of the methods to execute. The difference is that this delegate is on UI thread, and he is allowed to execute the methods from the same thread. So I created LoadContentCallback delegate.
  2. Second problem that I had was that the events were generated twice. To solve this problem I created 3 boolean fields to match the events. When the event is generated I set this boolean to true. Second time I set it to false, without actually executing the logic. With the Deleted event I had no problems because i dispose the _fileMonitor once user deletes file from text editor.
  3. Changed event handler handled 2 events Created and Changed, so I was wondering how am I gonna determine which event is actually handled. But the arguments of the event FileSystemEventArgs helped me because there is a property WatcherChangeTypes e.ChangeType which indicate what kind of change was made. From here it was easy because I knew what boolean to reset.
  4. To determine the new file name when Renamed event occurs was super easy thanks to RenamedEventArgs class which contains the following info, that did helped me:
    • FullPath - Gets the new fully qualifed path of the affected file or directory.
    • Name  -  Gets the new name of the affected file or directory.
    • OldName  -  Gets the old name of the affected file or directory.
    • OldFullPath - Gets the previous fully qualified path of the affected file or directory.

 

private FileSystemWatcher _fileMonitor;

private bool _wasChanged;
private bool _wasRenamed;
private bool _wasCreated;

public delegate void LoadContentCallback();

private void StartMonitorization()
{
	_fileMonitor = new FileSystemWatcher(Path.GetDirectoryName(_fileName), Path.GetFileName(_fileName))
		{
			NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
			IncludeSubdirectories = false
		};

	_fileMonitor.Changed += FileMonitor_OnChanged;
	_fileMonitor.Created += FileMonitor_OnChanged;
	_fileMonitor.Deleted += FileMonitor_OnDeleted;
	_fileMonitor.Renamed += FileMonitor_OnRenamed;

	_fileMonitor.EnableRaisingEvents = true;
}

private void FileMonitor_OnRenamed(object sender, RenamedEventArgs e)
{
	if (!_wasRenamed)
	{
		DialogResult result = MessageBox.Show("The file " + e.OldName + " was renamed. \r\n" +
											"Do you want to load the new file ?", "File was renamed", MessageBoxButtons.OKCancel);

		_wasRenamed = true;

		if (result == DialogResult.OK)
		{
			_fileName = e.FullPath;
			this.BeginInvoke(new LoadContentCallback(LoadFileContent));
		}
	}
	else
	{
		_wasRenamed = false;
	}
}

private void FileMonitor_OnDeleted(object sender, FileSystemEventArgs e)
{
	DialogResult result = MessageBox.Show("The file " + e.Name + " was deleted. \r\n" + "Do you want to remove it from text editor ?", "File was deleted",
MessageBoxButtons.YesNo);

	if (result == DialogResult.Yes)
	{
		_fileMonitor.Dispose();

		this.BeginInvoke(new LoadContentCallback(ResetUiContent));
	}

}

private void FileMonitor_OnChanged(object sender, FileSystemEventArgs e)
{
	if ((!_wasCreated && e.ChangeType == WatcherChangeTypes.Created) ||
		(!_wasChanged && e.ChangeType == WatcherChangeTypes.Changed))
	{
		DialogResult result = MessageBox.Show("The content of the file " + e.Name + " was changed. \r\n" + "Do you want to reload it ?", "File was changed",
MessageBoxButtons.OKCancel);

		if (e.ChangeType == WatcherChangeTypes.Changed)
		{
			_wasChanged = true;
		}
		else
		{
			_wasCreated = true;
		}

		if (result == DialogResult.OK)
		{
			this.BeginInvoke(new LoadContentCallback(LoadFileContent));
		}
	}
	else
	{
		if (e.ChangeType == WatcherChangeTypes.Changed && _wasChanged)
		{
			_wasChanged = false;
		}
		else if (e.ChangeType == WatcherChangeTypes.Created && _wasCreated)
		{
			_wasCreated = false;
		}
	}
}

private void ResetUiContent()
{
	txtFileContent.Text = string.Empty;
	lblFileName.Text = string.Empty;
	_fileName = string.Empty;
}
PUTTING Keyboard shortcuts on your buttons

This is I think really the easiest part. First you wire up your form with KeyDown event, make a event handler (in my case it was ViewFile_KeyDown handler). Then you need to set your form KeyPreview property on true, because otherwise it would not be able to catch keyboard events.

Than you just indicate what kind of combination will execute your action. For example I wanted my app to react at       Ctrl + S as a save action shortcut. In event handler I just indicate that I want it to react on Control + S for saving and Control + O for loading/opening the file.

this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ViewFile_KeyDown);
this.KeyPreview = true;

private void ViewFile_KeyDown(object sender, KeyEventArgs e)
{
	if (e.Modifiers == Keys.Control)
	{
		switch (e.KeyCode)
		{
			case Keys.S:
				btnSaveFile_Click(btnSaveFile, null);
				break;
			case Keys.O:
				btnLoadFile_Click(btnSaveFile, null);
				break;
		}
	}
}
New Features coming…

Now I think about new features that could be done on top of what already exists:

I also think about migrating this app on WPF to provide better visual experience. I think I will do it in the next 2 releases.

The Entire Sourcecode

Here you can see entire sourcecode file in collapsed way.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// Author : Poperecinii Timur
namespace ViewFile
{
    public partial class ViewFile : Form
    {
        private string _fileName;
        private FileSystemWatcher _fileMonitor;

        private bool _wasChanged;
        private bool _wasRenamed;
        private bool _wasCreated;

        public delegate void LoadContentCallback();

        public ViewFile()
        {
            InitObjects();

            InitializeComponent();
        }

        private void InitObjects()
        {
            _fileName = string.Empty;
        }

        private void btnLoadFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            ofd.CheckFileExists = true;
            ofd.Multiselect = false;

            DialogResult result = ofd.ShowDialog();

            if (result == DialogResult.OK)
            {
                _fileName = ofd.FileName;

                if (_fileName != string.Empty)
                    LoadFileContent();
            }
        }

        private void LoadFileContent()
        {
            lblFileName.Text = Path.GetFileName(_fileName);

            try
            {
                TextReader tr = new StreamReader(_fileName);
                try
                { txtFileContent.Text = tr.ReadToEnd(); }
                catch (Exception ex)
                { MessageBox.Show(ex.Message); }
                finally
                {
                    tr.Close();

                    StartMonitorization();
                }
            }
            catch (FileNotFoundException ex)
            { MessageBox.Show("Sorry, the file does not exist."); }
            catch (UnauthorizedAccessException ex)
            { MessageBox.Show("Sorry, you lack sufficient privileges."); }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
        }

        private void StartMonitorization()
        {
            _fileMonitor = new FileSystemWatcher(Path.GetDirectoryName(_fileName), Path.GetFileName(_fileName))
                               {
                                   NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
                                   IncludeSubdirectories = false
                               };

            _fileMonitor.Changed += FileMonitor_OnChanged;
            _fileMonitor.Created += FileMonitor_OnChanged;
            _fileMonitor.Deleted += FileMonitor_OnDeleted;
            _fileMonitor.Renamed += FileMonitor_OnRenamed;

            _fileMonitor.EnableRaisingEvents = true;
        }

        private void FileMonitor_OnRenamed(object sender, RenamedEventArgs e)
        {
            if (!_wasRenamed)
            {
                DialogResult result = MessageBox.Show("The file " + e.OldName + " was renamed. \r\n" +
                                                    "Do you want to load the new file ?", "File was renamed", MessageBoxButtons.OKCancel);

                _wasRenamed = true;

                if (result == DialogResult.OK)
                {
                    _fileName = e.FullPath;
                    this.BeginInvoke(new LoadContentCallback(LoadFileContent));
                }
            }
            else
            {
                _wasRenamed = false;
            }

        }

        private void FileMonitor_OnDeleted(object sender, FileSystemEventArgs e)
        {
            DialogResult result = MessageBox.Show("The file " + e.Name + " was deleted. \r\n" +
                                                  "Do you want to remove it from text editor ?", "File was deleted",
                                                  MessageBoxButtons.YesNo);

            if (result == DialogResult.Yes)
            {
                _fileMonitor.Dispose();

                this.BeginInvoke(new LoadContentCallback(ResetUiContent));
            }

        }

        private void FileMonitor_OnChanged(object sender, FileSystemEventArgs e)
        {
            if ((!_wasCreated && e.ChangeType == WatcherChangeTypes.Created) ||
                (!_wasChanged && e.ChangeType == WatcherChangeTypes.Changed))
            {
                DialogResult result = MessageBox.Show("The content of the file " + e.Name + " was changed. \r\n" +
                                                      "Do you want to reload it ?", "File was changed",
                                                      MessageBoxButtons.OKCancel);

                if (e.ChangeType == WatcherChangeTypes.Changed)
                {
                    _wasChanged = true;
                }
                else
                {
                    _wasCreated = true;
                }

                if (result == DialogResult.OK)
                {
                    this.BeginInvoke(new LoadContentCallback(LoadFileContent));
                }
            }
            else
            {
                if (e.ChangeType == WatcherChangeTypes.Changed && _wasChanged)
                {
                    _wasChanged = false;
                }
                else if (e.ChangeType == WatcherChangeTypes.Created && _wasCreated)
                {
                    _wasCreated = false;
                }
            }
        }

        private void ResetUiContent()
        {
            txtFileContent.Text = string.Empty;
            lblFileName.Text = string.Empty;
            _fileName = string.Empty;
        }



        private void btnSaveFile_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Text Files (*.txt)|*.txt|C# files (*.cs)|*.cs|All files (*.*)|*.*";

            saveFileDialog.SupportMultiDottedExtensions = true;

            DialogResult result = saveFileDialog.ShowDialog();

            if (result == DialogResult.OK)
            {
                _fileName = saveFileDialog.FileName;
                
                if (!string.IsNullOrEmpty(_fileName))
                    SaveFileContent();
            }
        }

        private void SaveFileContent()
        {
            lblFileName.Text = Path.GetFileName(_fileName);

            try
            {
                // we'll make only a textual file for instance
                TextWriter tw = File.CreateText(_fileName);

                try
                {
                    tw.Write(txtFileContent.Text);
                }
                catch (Exception ex)
                { MessageBox.Show(ex.Message); }
                finally
                {
                    tw.Close();

                    StartMonitorization();
                }
            }
            catch (UnauthorizedAccessException ex)
            { MessageBox.Show("Sorry, you lack sufficient privileges."); }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
        }

        private void ViewFile_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control)
            {
                switch (e.KeyCode)
                {
                    case Keys.S:
                        btnSaveFile_Click(btnSaveFile, null);
                        break;
                    case Keys.O:
                        btnLoadFile_Click(btnSaveFile, null);
                        break;
                }
            }
        }
    }
}

Friday, October 23, 2009

Windows 7 officially released today + Visual Studio 2010 Beta 2 is available

 

Windows 7

 

Hi,

since the Vista “nightmare” begun, the end-users, Microsoft customers and general client in software development had fear passing multimillion companies to Vista, and after all why XP is bad? What made Vista so bug full ?

The answer is evident. In windows Vista Microsoft tried to do something very different that they were doing before. With the power of WPF, and a lot of other new features for Windows, as Sidebar for example with all those gadgets, came the possibility to make bugs, because then people try something new, at first it is not really an ideal thing.

That is why most costumers continued to stay on XP and Microsoft was obliged in a way to make the SP3 for Windows XP. At the same time another team was working on Windows Vista SP1, which eliminated most problems. But these people seem to forget that we had 3 Service packs for XP and the original version was far from ideal too.

But as clients were already disappointed they were actively refusing to accept Vista as a default OS on their computers, and Microsoft in a year started to develop the new brand Windows 7, which was labeled lately Windows Heaven. :)

Windows 7 in comparison with Vista and even XP SP3 is:

Faster loading, more responsive, more intuitive and much more compatible + ideal on 64 bits machines. You will fall in love with this OS, and I think it is the release which will make people forget about Vista, and try to create with it better quality software. Anyway the future year will show us all the improvements that can be done on Windows 7, because nothing is really ideal. 

And it is already released today! So from now on I will also be publishing tips for Windows 7. Hope that you will grab your copy in next months. And by the way here is the link for the requirements for Windows 7.

Visual Studio 2010 Beta 2

While a lot of us, .NET developers still try to learn all the features from the framework and .NET 3.5 in general, because as one man said

Framework big, brain small :)

.NET 4.0 is coming out, which a whole new bunch of features and possibilities and a new IDE: Visual Studio 2010 is coming out and bringing with it a lot of goodies. And first what I appreciated was the new look of Visual Studio

The new design plus a lot of different new features of Visual Studio 2010, I won’t describe them but I will give you the starting points

So go and check Visual Studio 2010 Beta 2 right now, because the RTM is announced on March 22, 2010. And we’ll have some time to play with Beta 2.

Monday, October 12, 2009

Tips 003: Integrating Google Chrome with Delicious and Evernote and other cool tools

 

Hi,I use Google Chrome a lot and also I am already used with such beautiful tools which make my life easier and more structured :). One of those tools are Delicious bookmarks and Evernote notes. I use them almost everywhere.

I can talk hours about the worth of both of these tools, but I think about making a special series about useful tools in our life, I will definitely write about Evernote. So enough about that.

EVERNOTE

  • Now to test it, select something on a webpage and click on this bookmark.

  • So what do you need to do is just login into Evernote and everything selected will be saved as a note.

Delicious

 

Delicious in another cool app which will take care about your bookmarks. You can add tags, description, title to have the possibility to search through all your bookmarks using one of these attributes.

The annoying thing was that you would usually use the web site of the Delicious. What’s why I always liked the add-ons to Firefox and IE from Delicious it permitted me to use a shortcut to bookmark a website directly in Delicious system.

That’s why I missed it so much in Chrome.

  • Here you should find a very nice description how you can add 2 Delicious bookmarklets in Chrome. Just a simple drag-n-drop opperation will make it for you. Now you can see on your Chrome bookmarks bar these 2 buttons.

 

That’s the way to add some more functionality to Chrome while surfing the web with the great speed of JavaScript loading, that it’s offering. I love this browser and I think we could give it even more functionality.

If you know any other apps which can be used with Chrome as well or have any ideas, words to share, please leave a comment.

.

Monday, October 5, 2009

Code4Food #2: Create a Text Editor in 5 minutes. C# - magic

Hi, guys!
It is October and it's the time for another Code4Food episode.

Today I'm gonna show you some magic. We'll make a text editor in C#.


Here is the sourcecode for Downloading:
ViewFile sourcecode


Note: This part will contain only loading certain file in a textbox.

1st minute.

a) Create a new WinForms app in Visual Studio (File -> New -> Project -> Windows Forms Application) and change the name of the project to ViewFile.


b) Delete the form Form1.cs from the solution.



c) Add a new form to the project and name it ViewFile


2nd minute

a) Open the ViewFile form in Designer mode. Add a textbox to this form and name it txtFileContent. Change it's 'Multiline' property to true, and 'ScrollBars' to 'Both'.


b) Change it's size to fit the form. After this change the 'Anchor' property to 'Top, Bottom, Left, Right'.


c) Add a button to the form and name it btnLoadFile and change it's 'Text' property to 'Load File'.
d) Add a button to the form and name it btnSaveFile and change it's 'Text' property to 'Save File'.

e) Add a label where we'll show the file name. Name it lblFileName and change it's 'Text' property to 'File Name'

f) In Program.cs change the following line so that your application runs the ViewFile form.
Application.Run(new ViewFile());

At this point you can run the User Interface of our app.


3rd minute

a) Create a private field _fileName where we'll store the name of the file we want to open. Create than a method where we'll initialize all the fields in our app and name it InitObjects. Initialize there _fileName to string.Empty. Also we'll make the filename label empty for now, because we don't have a file opened.

b) Double click the 'Load File' button and in the event generated by Visual Studio create an instance of OpenFileDialog. Set the properties of this instance: 'CheckFileExists' (verifies if the file exists) - true, 'Multiselect' (the ability to select multiple files in the dialog at once) - false. And call the method ShowDialog.

c) When the file is selected we'll show in the label only the name of the file which is stored in 'SafeFileName' property of the OpenFileDialog instance. Also save the full path to the file in _fileName field, and it is equal to 'FileName' property of the instance of the dialog.

Now our code should look like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ViewFile
{
public partial class ViewFile : Form
{
private string _fileName;

public ViewFile()
{
InitializeComponent();
InitObjects();
}

private void InitObjects()
{
lblFileName.Text = string.Empty;
_fileName = string.Empty;
}

private void btnLoadFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();

ofd.CheckFileExists = true;
ofd.Multiselect = false;

ofd.ShowDialog();

_fileName = ofd.FileName;
lblFileName.Text = ofd.SafeFileName;
}
}
}


4th minute

Now what we need to do is read the file and show its content in our textbox.
We'll use the StreamReader class, specifically its method ReadToEnd() and nested try-catch blocks to catch all the potential exceptions while we are trying to open a file.

So the final version of our app logic is this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ViewFile
{
public partial class ViewFile : Form
{
private string _fileName;

public ViewFile()
{
InitializeComponent();
InitObjects();
}

private void InitObjects()
{
lblFileName.Text = string.Empty;
_fileName = string.Empty;
}

private void btnLoadFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();

ofd.CheckFileExists = true;
ofd.Multiselect = false;

ofd.ShowDialog();

_fileName = ofd.FileName;
lblFileName.Text = ofd.SafeFileName;

if (_fileName != string.Empty)
LoadFileContent(_fileName);
}

private void LoadFileContent(string chosenFileName)
{
try
{
TextReader tr = new StreamReader(chosenFileName);
try
{ txtFileContent.Text = tr.ReadToEnd(); }
catch (Exception ex)
{ MessageBox.Show(ex.Message); }
finally
{ tr.Close(); }
}
catch (System.IO.FileNotFoundException ex)
{ MessageBox.Show("Sorry, the file does not exist."); }
catch (System.UnauthorizedAccessException ex)
{ MessageBox.Show("Sorry, you lack sufficient privileges."); }
catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
}
}

5th minute


For now we can really open any file but I wanted to make it look like a source code file. And disable some things we don't actually use.



a) We'll make the button 'Save File' disabled. Because we don't actually use it.

b) We'll change the 'Font' property of the txtFileContent to 'Courier New; 9pt'









Sunday, September 20, 2009

Tip 002: Thumbnails not showing in Vista, Pictures folder

Hi, once in a while we all have this thing which seems to be a kinda sick problem, because nobody knows how to deal with it, and more nobody have ever seen or heard about things like that. There was this guy calling me and saying that he has this kinda crazy problem, he had a lot of photos, but the thumbnails didn't show up no matter what the poor guy was doing about it, just ordinary Vista icon for the image was shown (like mountains or something like that). First I was thinking that he has some hidden file where all the thumbnails info should be (something like Thumbnails.db in XP), which should deleted and than creating it one more time. But this wasn't the case. What it turned out to be is a simple option in Tools menu: Tools -> Folder Options -> View tab -> Advanced settings -> Files and Folders section, the check box "Always show icons, never thumbnails" should be unchecked. Because if it is checked, then you'll always see icons instead of thumbnails, and this refers not only to photos but to all kind of files like PDF or video files. So be aware of this option. See ya!