Hey everyone,
I had some time last night so I decided to write a simple Notepad clone application using C# and WPF. You can see the screenshot here:
You can see the C# code (also attached):
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using Microsoft.Win32;
using System.Text;
using System.Windows.Input;
using System.ComponentModel;
namespace kNotepad
{
public partial class MainApp
{
private bool dataChanged = false;
private string filePath = null;
public MainApp()
{
this.InitializeComponent();
}
//
// When New is selected from the Menu
//
private void NewItem(object sender, RoutedEventArgs e)
{
ProcessNewCommand();
}
//
// When New is selected from the Menu
//
private void OpenItem(object sender, RoutedEventArgs e)
{
ProcessOpenCommand();
}
//
// When Save is selected from the Menu
//
private void SaveItem(object sender, RoutedEventArgs e)
{
ProcessSaveCommand();
}
//
// When Save As is selected from the Menu
//
private void SaveAsItem(object sender, RoutedEventArgs e)
{
ShowSaveDialog();
}
//
// When Exit is selected from the Menu
//
private void ExitItem(object sender, RoutedEventArgs e)
{
if (dataChanged)
{
SaveFirst();
this.Close();
}
else
{
this.Close();
}
}
//
// Display Open File dialog window
//
private void ShowOpenDialog()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Text Files|*.txt|All|*.*";
//
// If user selected a file and pressed OK, process it.
//
if (ofd.ShowDialog() == true)
{
filePath = ofd.FileName;
ReadFile(filePath);
SetTitle(ofd.SafeFileName);
dataChanged = false;
}
}
//
// When given a file path, read that information and load it into the textfield
//
private void ReadFile(string path)
{
StreamReader reader = new StreamReader(path);
StringBuilder sb = new StringBuilder();
string r = reader.ReadLine();
while (r != null)
{
sb.Append(r);
sb.Append(Environment.NewLine);
r = reader.ReadLine();
}
reader.Close();
//
// Sending text data to the text box
//
txtBoxContent.Text = sb.ToString();
}
//
// Given a path to a file, write the contents of the textbox into it
//
private void SaveFile(string path)
{
StreamWriter writer = new StreamWriter(path);
writer.Write(txtBoxContent.Text);
writer.Close();
dataChanged = false;
}
//
// Display the Save Dialog window to specify the location to save your file
//
private void ShowSaveDialog()
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Text Document (.txt)|*.txt";
bool? saveResult = sfd.ShowDialog();
if (saveResult == true)
{
string s = sfd.FileName;
filePath = s;
SaveFile(s);
SetTitle(sfd.SafeFileName);
}
}
//
// Ensure that your save your changes before doing anything that might alter your textbox contents or close the program
//
private string SaveFirst()
{
MessageBoxResult mbr = MessageBox.Show("Do you want to save your changes first?", "Save File?", MessageBoxButton.YesNoCancel);
if (mbr == MessageBoxResult.Yes)
{
if (filePath != null)
{
SaveFile(filePath);
}
else
{
ProcessSaveCommand();
}
}
else if (mbr == MessageBoxResult.Cancel)
{
return "Cancel";
}
return "Nothing";
}
//
// Clears all of the information from the screen
//
private void ClearState()
{
filePath = null;
dataChanged = false;
txtBoxContent.Text = "";
ResetTitle();
}
//
// Display the About Dialog window
//
private void ShowAbout(object sender, RoutedEventArgs e)
{
ShowAboutDialog();
}
//
// Process the details about where the About Dialog window will actually show
//
private void ShowAboutDialog()
{
About a = new About();
a.WindowStartupLocation = WindowStartupLocation.Manual;
a.Left = this.Left + 75;
a.Top = this.Top + 75;
a.ShowDialog();
}
//
// Determine best way to Save document
//
private void ProcessSaveCommand()
{
if (filePath == null)
{
ShowSaveDialog();
}
else
{
SaveFile(filePath);
}
}
//
// Determine best way to setup New document
//
private void ProcessNewCommand()
{
if (dataChanged)
{
string sf = SaveFirst();
if (sf != "Cancel")
{
ClearState();
}
}
else
{
ClearState();
}
}
//
// Determine best way to Open document
//
private void ProcessOpenCommand()
{
if (dataChanged)
{
SaveFirst();
ShowOpenDialog();
}
else
{
ShowOpenDialog();
}
}
//
// Save document before closing application
//
private void AppClosing(object sender, CancelEventArgs e)
{
if (dataChanged)
{
SaveFirst();
}
}
//
// Whenever a key is pressed inside the text field, take care of it
//
private void ContentChanged(object sender, KeyEventArgs e)
{
dataChanged = true;
}
//
// This is done to check whether our content had changed or not
//
private void FocusChanged(object sender, RoutedEventArgs e)
{
dataChanged = true;
}
//
// Process Key Combinations for Saving, New, and Open
//
private void KeyCombinations(object sender, KeyEventArgs e)
{
// Ctrl + S
if ((Keyboard.Modifiers == ModifierKeys.Control) && (e.Key == Key.S))
{
ProcessSaveCommand();
}
// Ctrl + N
if ((Keyboard.Modifiers == ModifierKeys.Control) && (e.Key == Key.N))
{
ProcessNewCommand();
}
// Ctrl + O
if ((Keyboard.Modifiers == ModifierKeys.Control) && (e.Key == Key.O))
{
ProcessOpenCommand();
}
}
//
// Change the Window title to include the file's name when opened or saved
//
private void SetTitle(string newTitle)
{
Window.Title = "kNotepad - " + newTitle;
}
//
// Reset the Window Title
//
private void ResetTitle()
{
Window.Title = "kNotepad";
}
}
}
And the XAML markup is only:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xml:lang="en-US"
x:Class="kNotepad.MainApp"
x:Name="Window"
Title="kNotepad"
Width="640" Height="480" Icon="note.png" Closing="AppClosing" KeyUp="KeyCombinations">
<Grid x:Name="gridMain">
<Menu Margin="0,0,2,0" x:Name="menuMain" VerticalAlignment="Top" Height="20">
<MenuItem x:Name="mnuFile" Header="File">
<MenuItem x:Name="mnuItemNew" InputGestureText="Ctrl+N" Header="New" Click="NewItem"/>
<MenuItem x:Name="mnuItemOpen" InputGestureText="Ctrl+O" Header="Open" Click="OpenItem"/>
<MenuItem x:Name="mnuItemSave" InputGestureText="Ctrl+S" Header="Save" Click="SaveItem"/>
<MenuItem RenderTransformOrigin="0.498,-1.5" x:Name="mnuItemSaveAs" Header="Save As..." Click="SaveAsItem"/>
<Separator/>
<MenuItem x:Name="mnuItemExit" Header="Exit" Click="ExitItem"/>
</MenuItem>
<MenuItem x:Name="mnuHelp" Header="Help">
<MenuItem x:Name="mnuItemAbout" Header="About" Click="ShowAbout"/>
</MenuItem>
</Menu>
<TextBox Margin="0,20,0,0" x:Name="txtBoxContent" FontFamily="Courier New" Text="" TextWrapping="Wrap" AcceptsReturn="True" AcceptsTab="True" VerticalScrollBarVisibility="Auto" GotFocus="FocusChanged" KeyDown="ContentChanged"/>
</Grid>
</Window>
Some of the code might be interesting such as how to fire a method when an application close is detected, how to use Key Combinations, etc.
Cheers!
Kirupa :cap: