![]() |
Languages »
C# »
Windows Forms
Intermediate
Document Management Toolkit LibraryBy Alex FrSet of classes for creating full-featured Windows Forms applications. |
C#.NET 1.0, .NET 1.1, Win2K, WinXPVS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
DocToolkit library is a set of classes which may be used to create full-featured Windows Forms applications for document management. Suppose we want to create an application with the following functions:
Reading this list of functions, we can see that editing file in the window is program-specific and changes in every project. All other tasks may be encapsulated to number of classes and used by a unified way. DocToolkit library is a framework which may be used to develop such applications.
DocToolkit library contains a number of classes. Some of them are published in the CodeProject in my previous articles, two classes use code from another articles. Links to the class source is provided in class description in the article and in the class code. All classes have a unified programming interface; source code is tested for conformance to the Microsoft .NET Framework Design Guidelines using the FxCop tool.
DocManager class. Makes file-related operations: Open, New, Save, updating of the form title, registering of file type for Windows Shell. This class is written using the MSDN Magazine article "Creating Document-Centric Applications in Windows Forms" by Chris Sells.
This class has a number of functions which are called by owner form, like NewDocument, OpenDocument, SaveDocument. The class raises a number of events which should be handled in the owner form, like SaveEvent, LoadEvent and DocChangedEvent. For handling these events, the owner form provides task-specific code for serialization, refreshing information in the window etc.
DragDropManager class. Encapsulates the code required to open files dropped to the program window from Windows Explorer. Class subscribes to the owner form DragEnter and DragDrop events and raises event FileDroppedEvent passing file name(s) to open.
MruManager class. Manages list of recently opened files (MRU) - shows it in the owner form menu and saves it to the Registry. When user selects file from the MRU list, class raises MruOpenEvent event which is handled in the owner form.
PersistWindowState class. Keeps main application window state when program exits, and restores this state on the next run. Class is written by Joel Matthias and published in the article: Saving and Restoring the Location, Size and Window State of a .NET Form. Step-by-step instructions to create Windows Forms application using the DocToolkit library.
| Item Text | Item Name |
| New | menuFileNew |
| Open | menuFileOpen |
| Save | menuFileSave |
| Save As | menuFileSaveAs |
| - (separator) | |
| Recent Files | menuFileRecent |
| - (separator) | |
| Exit | menuFileExit |
DocClass. Paste the following code to this class file: using System;
using System.Runtime.Serialization;
using System.Windows.Forms;
using System.Drawing;
using System.Security.Permissions;
using System.Globalization;
namespace UIDocSample
{
/// <summary>
/// Document class which makes program-specific tasks
/// </summary>
[Serializable]
public class DocClass : ISerializable
{
private int sampleData;
public DocClass()
{
sampleData = 0;
}
public bool Empty
{
get
{
return (sampleData == 0);
}
}
public void Draw(Graphics g)
{
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
PointF drawPoint = new PointF(10.0F, 10.0F);
g.DrawString(sampleData.ToString(CultureInfo.InvariantCulture),
drawFont, drawBrush, drawPoint);
}
public void Change()
{
sampleData++;
}
// Serialization
// This function is called when file is loaded
protected DocClass(SerializationInfo info,
StreamingContext context)
{
sampleData = info.GetInt32("sampleData");
}
// Serialization
// This function is called when file is saved
[SecurityPermissionAttribute(SecurityAction.Demand,
SerializationFormatter=true)]
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
{
info.AddValue("sampleData", sampleData);
}
}
}
This class is prototype for a class which performs program-specific tasks. It has some data, has function for changing of this data, knows to draw itself to the Graphics object and supports ISerializable interface, this allows to save/load class instance.
DocClass member to the Form1 class and initialize it in the class constructor: private DocClass docClass;
public Form1()
{
InitializeComponent();
docClass = new DocClass();
}
Add Paint and MouseDown event handlers to the Form1 class and fill them by the following way:
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
docClass.Draw(e.Graphics);
}
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( e.Button == MouseButtons.Left )
{
docClass.Change();
Refresh();
}
}
Now, we have the prototype of the application which manages some data in the window and changes it by clicking on the window client area. The next steps show how to add DocToolkit helper classes to this application.
DocManager member to the Form1 class: private DocManager docManager;
Add the following functions to the Form1 class:
private void docManager_ClearEvent(object sender, EventArgs e)
{
// DocManager reports that document should be cleared
// (user selected New command)
docClass = new DocClass();
Refresh();
}
private void docManager_DocChangedEvent(object sender, EventArgs e)
{
// DocManager reports that document was changed
// (loaded from file)
Refresh();
}
private void docManager_OpenEvent(object sender,
OpenFileEventArgs e)
{
// DocManager reports about successful/unsuccessful
// Open File operation
// Will be filled later
}
private void docManager_LoadEvent(object sender,
SerializationEventArgs e)
{
// DocManager asks to load document from supplied stream
try
{
docClass =
(DocClass)e.Formatter.Deserialize(e.SerializationStream);
}
catch ( Exception ex )
{
MessageBox.Show(this,
"Open File operation failed. File name: "
+ e.FileName + "\n" +
"Reason: " + ex.Message,
Application.ProductName);
e.Error = true;
}
}
private void docManager_SaveEvent(object sender,
SerializationEventArgs e)
{
// DocManager asks to save document to supplied stream
try
{
e.Formatter.Serialize(e.SerializationStream, docClass);
}
catch ( Exception ex )
{
MessageBox.Show(this,
"Save File operation failed. File name: "
+ e.FileName + "\n" +
"Reason: " + ex.Message,
Application.ProductName);
e.Error = true;
}
}
InitializeHelperObjects to the Form1 class: void InitializeHelperObjects()
{
string registryPath = "Software\\YourCompany\\UIDocSample";
// docManager
DocManagerData data = new DocManagerData();
data.FormOwner = this;
data.UpdateTitle = true;
data.FileDialogFilter = "UIDocSample files" +
" (*.uds)|*.uds|All Files (*.*)|*.*";
data.NewDocName = "Untitled.uds";
data.RegistryPath = registryPath;
docManager = new DocManager(data);
// Subscribe to DocManager events
docManager.SaveEvent +=
new SaveEventHandler(docManager_SaveEvent);
docManager.LoadEvent +=
new LoadEventHandler(docManager_LoadEvent);
docManager.OpenEvent +=
new OpenFileEventHandler(docManager_OpenEvent);
docManager.DocChangedEvent +=
new EventHandler(docManager_DocChangedEvent);
docManager.ClearEvent +=
new EventHandler(docManager_ClearEvent);
docManager.NewDocument();
// Register file type for Windows Shell
docManager.RegisterFileType("uds", "udsfile",
"UIDocSample File");
}
Call InitializeHelperObjects function from Form1 constructor:
public Form1() { InitializeComponent(); docClass = new DocClass(); InitializeHelperObjects(); }
Open function Form1_MouseDown added before and add these lines to it:
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if ( e.Button == MouseButtons.Left )
{
docClass.Change();
docManager.Dirty = true; // add this line
Refresh();
}
}
Form1 class which call various DocManager functions: public void OpenDocument(string file)
{
docManager.OpenDocument(file);
}
// User Selected File - Open command.
private void CommandOpen()
{
docManager.OpenDocument("");
}
// User selected File - Save command
private void CommandSave()
{
docManager.SaveDocument(DocManager.SaveType.Save);
}
// User selected File - Save As command
private void CommandSaveAs()
{
docManager.SaveDocument(DocManager.SaveType.SaveAs);
}
// User selected File - New command
private void CommandNew()
{
docManager.NewDocument();
}
Closing event: private void menuFileNew_Click(object sender, System.EventArgs e)
{
CommandNew();
}
private void menuFileOpen_Click(object sender, System.EventArgs e)
{
CommandOpen();
}
private void menuFileSave_Click(object sender, System.EventArgs e)
{
CommandSave();
}
private void menuFileSaveAs_Click(object sender, System.EventArgs e)
{
CommandSaveAs();
}
private void Form1_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
if ( ! docManager.CloseDocument() )
e.Cancel = true;
}
Main function by the following way: [STAThread]
static void Main(string[] args)
{
// Check command line
if( args.Length > 1 )
{
MessageBox.Show("Incorrect number" +
" of arguments. Usage: UIDocSample.exe [file]",
"UIDocSample");
return;
}
Form1 form = new Form1();
if ( args.Length == 1 )
// OpenDocument calls docManager.OpenDocument
form.OpenDocument(args[0]);
Application.Run(form);
}
DocManager is the most complicated class in the DocToolkit library. Adding of other classes is relatively simple.
DragDropManager class support.
Add function which is used to open file dropped to the from:
private void dragDropManager_FileDroppedEvent(object sender,
FileDroppedEventArgs e)
{
OpenDocument(e.FileArray.GetValue(0).ToString());
}
Add DragDropManager member to the Form1 class:
private DragDropManager dragDropManager;
and initialize it in the InitializeHelperObjects function:
void InitializeHelperObjects()
{
// ...
// dragDropManager
dragDropManager = new DragDropManager(this);
dragDropManager.FileDroppedEvent += new
FileDroppedEventHandler(this.dragDropManager_FileDroppedEvent);
}
MruManager class support.
Add function which is used to open file selected from the MRU list:
private void mruManager_MruOpenEvent(object sender,
MruFileOpenEventArgs e)
{
OpenDocument(e.FileName);
}
Add MruManager member to the Form1 class:
private MruManager mruManager;
and initialize it in the InitializeHelperObjects function:
void InitializeHelperObjects()
{
// ...
// mruManager
mruManager = new MruManager();
mruManager.Initialize(
this, // owner form
menuFileRecent, // Recent Files menu item
registryPath); // Registry path to keep MRU list
mruManager.MruOpenEvent += new
MruFileOpenEventHandler(this.mruManager_MruOpenEvent);
}
Open function docManager_OpenEvent added before, and add this code to it:
private void docManager_OpenEvent(object sender,
OpenFileEventArgs e)
{
// DocManager reports about
// successful/unsuccessful Open File operation
if ( e.Succeeded )
{
mruManager.Add(e.FileName);
}
else
{
mruManager.Remove(e.FileName);
}
}
PersistWindowState class support.
Add PersistWindowState member to the Form1 class:
private PersistWindowState persistState;
and initialize it in the InitializeHelperObjects function:
void InitializeHelperObjects()
{
// ...
// persistState
persistState = new PersistWindowState(registryPath, this);
}
Program has MRU files list. Every successfully opened file is added to this list. Program window is opened in the state it was closed last time. Open Registry key HKEY_CURRENT_USER\Software\YourCompany\UIDocSample. You can see information written by DocToolkit helper classes under this key. To convert this sample to real application, replace DocClass class with class which implements your application-specific tasks.
Commands in the UIDocSample program may be executed by selecting the menu items. Generally, applications may have also toolbar, buttons and other controls. In different situations, these controls may have different states: enabled/disabled, checked, visible/invisible etc. Every user action may change the controls' state. We need generic way to do this in the program. The way I am using is setting controls' state at application idle time. This way is very good for toolbar buttons and dialog controls. The best way for updating of menu items is handling of the Popup event. However, they may be handled at idle time as well.
Suppose we want to keep Save As command enabled when DocClass is not in its initial state (not empty). Save command should be enabled if DocClass is not empty and last changes are not saved yet. Add the following line to the Form1 constructor:
Application.Idle += new EventHandler(Application_Idle);
and add the Application_Idle function:
private void Application_Idle(object sender, EventArgs e)
{
menuFileSaveAs.Enabled = (!docClass.Empty);
menuFileSave.Enabled = (docManager.Dirty & (!docClass.Empty));
// State of any controls may be set here:
// menu items, toolbar buttons, dialog controls etc.
}
Now, a menu item's state is changed together with program state. This way works like ON_UPDATE_COMMAND_UI MFC handler for toolbar buttons.
When writing Windows Forms applications for document management, we need to implement the same standard tasks in every project. .NET is missing MFC-style framework for creating applications of this type. DocToolkit library is attempting to create such a framework. Developing applications using this library allows to concentrate on implementation of project-specific tasks, having standard document management stuff in the DocToolkit classes.
Client program shown in this article is very simple. The question is whether DocToolkit library is good enough to be used in real world applications. In my next article, I want to introduce the DrawTools program which shows how to draw graphic objects on the window client area using mouse. This program uses DocToolkit library and I found it convenient to use this library in it.
| You must Sign In to use this message board. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 12 Jul 2004 Editor: Smitha Vijayan |
Copyright 2004 by Alex Fr Everything else Copyright © CodeProject, 1999-2009 Web10 | Advertise on the Code Project |