QuickImage – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #region Using directives
2  
3 using System;
4 using System.Windows.Forms;
5 using System.Diagnostics;
6 using System.Collections.Generic;
7 using Microsoft.Win32;
8 using System.IO;
9 using System.Text;
10 using System.Runtime.InteropServices;
11 using System.Globalization;
12 using System.Security;
13  
14 #endregion
15  
16 namespace DocToolkit
17 {
18 using StringList = List<String>;
19 using StringEnumerator = IEnumerator<String>;
20  
21 /// <summary>
22 /// MRU manager - manages Most Recently Used Files list
23 /// for Windows Form application.
24 /// </summary>
25 public class MruManager
26 {
27 #region Members
28  
29 // Event raised when user selects file from MRU list
30 public event MruFileOpenEventHandler MruOpenEvent;
31  
32 private Form ownerForm; // owner form
33  
34 private ToolStripMenuItem menuItemMRU; // Recent Files menu item
35 private ToolStripMenuItem menuItemParent; // Recent Files menu item parent
36  
37 private string registryPath; // Registry path to keep MRU list
38  
39 private int maxNumberOfFiles = 10; // maximum number of files in MRU list
40  
41 private int maxDisplayLength = 40; // maximum length of file name for display
42  
43 private string currentDirectory; // current directory
44  
45 private StringList mruList; // MRU list (file names)
46  
47 private const string regEntryName = "file"; // entry name to keep MRU (file0, file1...)
48  
49 #endregion
50  
51 #region Windows API
52  
53 [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
54 private static extern bool PathCompactPathEx(
55 StringBuilder pszOut,
56 string pszPath,
57 int cchMax,
58 int reserved);
59  
60 #endregion
61  
62 #region Constructor
63  
64 public MruManager()
65 {
66 mruList = new StringList();
67 }
68  
69 #endregion
70  
71 #region Public Properties
72  
73 /// <summary>
74 /// Maximum length of displayed file name in menu (default is 40).
75 ///
76 /// Set this property to change default value (optional).
77 /// </summary>
78 internal int MaxDisplayNameLength
79 {
80 set
81 {
82 maxDisplayLength = value;
83  
84 if (maxDisplayLength < 10)
85 maxDisplayLength = 10;
86 }
87  
88 get
89 {
90 return maxDisplayLength;
91 }
92 }
93  
94 /// <summary>
95 /// Maximum length of MRU list (default is 10).
96 ///
97 /// Set this property to change default value (optional).
98 /// </summary>
99 public int MaxMruLength
100 {
101 set
102 {
103 maxNumberOfFiles = value;
104  
105 if (maxNumberOfFiles < 1)
106 maxNumberOfFiles = 1;
107  
108 if (mruList.Count > maxNumberOfFiles)
109 mruList.RemoveRange(maxNumberOfFiles - 1, mruList.Count - maxNumberOfFiles);
110 }
111  
112 get
113 {
114 return maxNumberOfFiles;
115 }
116 }
117  
118 /// <summary>
119 /// Set current directory.
120 ///
121 /// Default value is program current directory which is set when
122 /// Initialize function is called.
123 ///
124 /// Set this property to change default value (optional)
125 /// after call to Initialize.
126 /// </summary>
127 public string CurrentDir
128 {
129 set
130 {
131 currentDirectory = value;
132 }
133  
134 get
135 {
136 return currentDirectory;
137 }
138 }
139  
140 #endregion
141  
142 #region Public Functions
143  
144 /// <summary>
145 /// Initialization. Call this function in form Load handler.
146 /// </summary>
147 /// <param name="owner">Owner form</param>
148 /// <param name="mruItem">Recent Files menu item</param>
149 /// <param name="regPath">Registry Path to keep MRU list</param>
150 public void Initialize(Form owner, ToolStripMenuItem mruItem, ToolStripMenuItem mruItemParent, string regPath)
151 {
152 // keep reference to owner form
153 ownerForm = owner;
154  
155 // keep reference to MRU menu item
156 menuItemMRU = mruItem;
157  
158 // keep reference to MRU menu item parent
159 menuItemParent = mruItemParent;
160  
161  
162 // keep Registry path adding MRU key to it
163 registryPath = regPath;
164 if (registryPath.EndsWith("\\"))
165 registryPath += "MRU";
166 else
167 registryPath += "\\MRU";
168  
169  
170 // keep current directory in the time of initialization
171 currentDirectory = Directory.GetCurrentDirectory();
172  
173 // subscribe to MRU parent Popup event
174 menuItemParent.DropDownOpening += new EventHandler(this.OnMRUParentPopup);
175  
176 // subscribe to owner form Closing event
177 // ownerForm.Closing += OnOwnerClosing;
178  
179 // load MRU list from Registry
180 LoadMRU();
181 }
182  
183 /// <summary>
184 /// Add file name to MRU list.
185 /// Call this function when file is opened successfully.
186 /// If file already exists in the list, it is moved to the first place.
187 /// </summary>
188 /// <param name="file">File Name</param>
189 public void Add(string file)
190 {
191 Remove(file);
192  
193 // if array has maximum length, remove last element
194 if (mruList.Count == maxNumberOfFiles)
195 mruList.RemoveAt(maxNumberOfFiles - 1);
196  
197 // add new file name to the start of array
198 mruList.Insert(0, file);
199 }
200  
201 /// <summary>
202 /// Remove file name from MRU list.
203 /// Call this function when File - Open operation failed.
204 /// </summary>
205 /// <param name="file">File Name</param>
206 public void Remove(string file)
207 {
208 int i = 0;
209  
210 StringEnumerator myEnumerator = mruList.GetEnumerator();
211  
212 while (myEnumerator.MoveNext())
213 {
214 if ((string)myEnumerator.Current == file)
215 {
216 mruList.RemoveAt(i);
217 return;
218 }
219  
220 i++;
221 }
222 }
223  
224 #endregion
225  
226 #region Event Handlers
227  
228 /// <summary>
229 /// Update MRU list when MRU menu item parent is opened
230 /// </summary>
231 /// <param name="sender"></param>
232 /// <param name="e"></param>
233 private void OnMRUParentPopup(object sender, EventArgs e)
234 {
235 // remove all childs
236 //if (menuItemMRU.IsParent)
237 //{
238 menuItemMRU.DropDownItems.Clear();
239 //}
240  
241 // Disable menu item if MRU list is empty
242 if (mruList.Count == 0)
243 {
244 menuItemMRU.Enabled = false;
245 return;
246 }
247  
248 // enable menu item and add child items
249 menuItemMRU.Enabled = true;
250  
251 ToolStripMenuItem item;
252  
253 StringEnumerator myEnumerator = mruList.GetEnumerator();
254 int i = 0;
255  
256 while (myEnumerator.MoveNext())
257 {
258 item = new ToolStripMenuItem();
259 item.Text = GetDisplayName((string)myEnumerator.Current);
260 item.Tag = i++;
261  
262 // subscribe to item's Click event
263 item.Click += OnMRUClicked;
264  
265 menuItemMRU.DropDownItems.Add(item);
266 }
267 }
268  
269 /// <summary>
270 /// MRU menu item is clicked - call owner's OpenMRUFile function
271 /// </summary>
272 /// <param name="sender"></param>
273 /// <param name="e"></param>
274 private void OnMRUClicked(object sender, EventArgs e)
275 {
276 string s;
277  
278 // cast sender object to MenuItem
279 ToolStripMenuItem item = (ToolStripMenuItem)sender;
280  
281 if (item != null)
282 {
283 // Get file name from list using item index
284 s = (string)mruList[(int)item.Tag];
285  
286 // Raise event to owner and pass file name.
287 // Owner should handle this event and open file.
288 if (s.Length > 0)
289 {
290 if (MruOpenEvent != null)
291 {
292 MruOpenEvent(this, new MruFileOpenEventArgs(s));
293 }
294 }
295 }
296 }
297  
298 /// <summary>
299 /// Save MRU list in Registry when owner form is closing
300 /// </summary>
301 /// <param name="sender"></param>
302 /// <param name="e"></param>
303 private void OnOwnerClosing(object sender, System.ComponentModel.CancelEventArgs e)
304 {
305 int i, n;
306  
307 try
308 {
309 RegistryKey key = Registry.CurrentUser.CreateSubKey(registryPath);
310  
311 if (key != null)
312 {
313 n = mruList.Count;
314  
315 for (i = 0; i < maxNumberOfFiles; i++)
316 {
317 key.DeleteValue(regEntryName +
318 i.ToString(CultureInfo.InvariantCulture), false);
319 }
320  
321 for (i = 0; i < n; i++)
322 {
323 key.SetValue(regEntryName +
324 i.ToString(CultureInfo.InvariantCulture), mruList[i]);
325 }
326 }
327  
328 }
329 catch (ArgumentNullException ex) { HandleWriteError(ex); }
330 catch (SecurityException ex) { HandleWriteError(ex); }
331 catch (ArgumentException ex) { HandleWriteError(ex); }
332 catch (ObjectDisposedException ex) { HandleWriteError(ex); }
333 catch (UnauthorizedAccessException ex) { HandleWriteError(ex); }
334 }
335  
336  
337 #endregion
338  
339 #region Private Functions
340  
341 /// <summary>
342 /// Load MRU list from Registry.
343 /// Called from Initialize.
344 /// </summary>
345 private void LoadMRU()
346 {
347 string sKey, s;
348  
349 try
350 {
351 mruList.Clear();
352  
353 RegistryKey key = Registry.CurrentUser.OpenSubKey(registryPath);
354  
355 if (key != null)
356 {
357 for (int i = 0; i < maxNumberOfFiles; i++)
358 {
359 sKey = regEntryName + i.ToString(CultureInfo.InvariantCulture);
360  
361 s = (string)key.GetValue(sKey, "");
362  
363 if (s.Length == 0)
364 break;
365  
366 mruList.Add(s);
367 }
368 }
369 }
370 catch (ArgumentNullException ex) { HandleReadError(ex); }
371 catch (SecurityException ex) { HandleReadError(ex); }
372 catch (ArgumentException ex) { HandleReadError(ex); }
373 catch (ObjectDisposedException ex) { HandleReadError(ex); }
374 catch (UnauthorizedAccessException ex) { HandleReadError(ex); }
375 }
376  
377 /// <summary>
378 /// Handle error from OnOwnerClosing function
379 /// </summary>
380 /// <param name="ex"></param>
381 private void HandleReadError(Exception ex)
382 {
383 Trace.WriteLine("Loading MRU from Registry failed: " + ex.Message);
384 }
385  
386 /// <summary>
387 /// Handle error from OnOwnerClosing function
388 /// </summary>
389 /// <param name="ex"></param>
390 private void HandleWriteError(Exception ex)
391 {
392 Trace.WriteLine("Saving MRU to Registry failed: " + ex.Message);
393 }
394  
395  
396 /// <summary>
397 /// Get display file name from full name.
398 /// </summary>
399 /// <param name="fullName">Full file name</param>
400 /// <returns>Short display name</returns>
401 private string GetDisplayName(string fullName)
402 {
403 // if file is in current directory, show only file name
404 FileInfo fileInfo = new FileInfo(fullName);
405  
406 if (fileInfo.DirectoryName == currentDirectory)
407 return GetShortDisplayName(fileInfo.Name, maxDisplayLength);
408  
409 return GetShortDisplayName(fullName, maxDisplayLength);
410 }
411  
412 /// <summary>
413 /// Truncate a path to fit within a certain number of characters
414 /// by replacing path components with ellipses.
415 ///
416 /// This solution is provided by CodeProject and GotDotNet C# expert
417 /// Richard Deeming.
418 ///
419 /// </summary>
420 /// <param name="longName">Long file name</param>
421 /// <param name="maxLen">Maximum length</param>
422 /// <returns>Truncated file name</returns>
423 private string GetShortDisplayName(string longName, int maxLen)
424 {
425 StringBuilder pszOut = new StringBuilder(maxLen + maxLen + 2); // for safety
426  
427 if (PathCompactPathEx(pszOut, longName, maxLen, 0))
428 {
429 return pszOut.ToString();
430 }
431 else
432 {
433 return longName;
434 }
435 }
436  
437 #endregion
438  
439 }
440  
441 public delegate void MruFileOpenEventHandler(object sender, MruFileOpenEventArgs e);
442  
443 public class MruFileOpenEventArgs : System.EventArgs
444 {
445 private string fileName;
446  
447 public MruFileOpenEventArgs(string fileName)
448 {
449 this.fileName = fileName;
450 }
451  
452 public string FileName
453 {
454 get
455 {
456 return fileName;
457 }
458 }
459 }
460 }
461  
462 #region Using
463  
464 /*******************************************************************************
465  
466 NOTE: This class works with new Visual Studio 2005 MenuStrip class.
467 If owner form has old-style MainMenu, use previous MruManager version.
468  
469 Using:
470  
471 1) Add menu item Recent Files (or any name you want) to main application menu.
472 This item is used by MruManager as popup menu for MRU list.
473  
474 2) Write function which opens file selected from MRU:
475  
476 private void mruManager_MruOpenEvent(object sender, MruFileOpenEventArgs e)
477 {
478 // open file e.FileName
479 }
480  
481 3) Add MruManager member to the form class and initialize it:
482  
483 private MruManager mruManager;
484  
485 Initialize it in the form initialization code:
486  
487 mruManager = new MruManager();
488 mruManager.Initialize(
489 this, // owner form
490 mnuFileMRU, // Recent Files menu item (ToolStripMenuItem class)
491 mruItemParent, // Recent Files menu item parent (ToolStripMenuItem class)
492 "Software\\MyCompany\\MyProgram"); // Registry path to keep MRU list
493  
494 mruManager.MruOpenEvent += this.mruManager_MruOpenEvent;
495  
496 // Optional. Call these functions to change default values:
497  
498 mruManager.CurrentDir = "....."; // default is current directory
499 mruManager.MaxMruLength = ...; // default is 10
500 mruMamager.MaxDisplayNameLength = ...; // default is 40
501  
502 NOTES:
503 - If Registry path is, for example, "Software\MyCompany\MyProgram",
504 MRU list is kept in
505 HKEY_CURRENT_USER\Software\MyCompany\MyProgram\MRU Registry entry.
506  
507 - CurrentDir is used to show file names in the menu. If file is in
508 this directory, only file name is shown.
509  
510 4) Call MruManager Add and Remove functions when necessary:
511  
512 mruManager.Add(fileName); // when file is successfully opened
513  
514 mruManager.Remove(fileName); // when Open File operation failed
515  
516 *******************************************************************************/
517  
518 // Implementation details:
519 //
520 // MruManager loads MRU list from Registry in Initialize function.
521 // List is saved in Registry when owner form is closed.
522 //
523 // MRU list in the menu is updated when parent menu is poped-up.
524 //
525 // Owner form OnMRUFileOpen function is called when user selects file
526 // from MRU list.
527  
528 #endregion