C# - Speciális célú MenuItem osztály létrehozása

forráskód letöltése
Bizonyára mindenki számára ismert a felhasználói programok azon viselkedése, miszerint a legutoljára megnyitott tetszőleges mennyiségű fájl nevét és elérési útvonalát tárolják egy listában, a FILE menüben („Most Recently Used Files”). Cikkünkben a MenuItem osztály továbbfejlesztésével létrehozunk egy saját menüelem osztályt, mely funkcionalitásában megvalósítja a fent említett működést.
A mellékelt alkalmazás FILE menüjében érhetjük majd el a legutoljára használt állományokat, a megnyitás időrendi sorrendjében. A program Form-ján elhelyezett TextBox kontrolban megadott szöveges állományt a ’Megnyit’ gombbal megnyithatjuk a Notepad.exe segédprogram felhasználásával. A Notepad.exe programot a Process osztály Start metódusának segítségével indítjuk el. A megnyitott fájlok nevei elérési úttal bekerülnek a listába, melyet a FILE – RECENT FILES menüpontban találunk meg. A program indulásakor a lista üres.
Új megnyitandó elemeket a FILE – FIND FILE menüpontban kereshetünk. A program indulásakor a mellékelt szöveges állományok egyikének nevét adjuk meg a szerkesztőmezőben, mellyel a működés rögtön tesztelhető.
Az elemeket tartalmazó lista valamely elemére kattintva az elem újra megnyitható a Notepad.exe programmal. Vizsgáljuk meg az osztályunkat.
Az osztály az MRUMenuItem nevet viseli, a megegyező nevű állományban elhelyezve. Van három privát változója, melyekből egy karakterlánc tömb tartalmazza majd az elemeket:
public class MRUMenuItem : MenuItem
{
  string[] mru;
Egy változó a lista kapacitását tartalmazza (count), egy másik pedig az aktuális elemszámot:
int count;
int fileCount = 0;
MRUFiles nevű property-jével kérdezhető le a tömb változó:
public string[] MRUFiles 
{
  get {return mru;}
}
Initialize metódusával adhatunk kezdő értéket a listának úgy, hogy paraméterként megadunk egy elemeket tartalmazó karakterlánc tömböt. A programban ezt úgy használjuk, hogy üres string elemekkel feltöltött tömbbel inicializáljuk a listát, így az üres karakterláncok nem kerülnek a listába:
public void Initialize(params string[] files) 
{
  mru = files;
  count = mru.Length;
  for (int i=0;i<count;i++) 
  {
    if (mru[i] != "")
    {
      fileCount++;
      MenuItem mmru = new MenuItem(Convert.ToString(fileCount) + " " + mru[i], new EventHandler(OnMRUClick));
      mmru.Click += new System.EventHandler(this.mmru_Click);
      this.MenuItems.Add(mmru);          
    }
  }
}
A FileOpened metódus gondoskodik arról, hogy a paraméterként megadott karakterlánc (példánkban állománynév) bekerüljön a listába, és a régi elemek törlődjenek. A metódus elején megvizsgáljuk, hogy a berakandó elem benne van-e a listában:
public void FileOpened(string file) 
{
  int found = count-1;
  for (int j=0;j<count;j++) 
  {
    if (file == mru[j]) 
    {
      found = j;
      break;
    }
  }
Amennyiben benne van, sorszámát (listában elfoglalt helyét) felhasználjuk. A tömbben az elemeket eggyel előrébb toljuk, és az új elemet betesszük az első helyre:
  while (found > 0)  mru[found] = mru[--found];
  mru[0] = file;
  ...
Majd az elemeket a végleges sorrendben a listára fűzzük úgy, hogy deklarálunk minden elemhez egy klikk eseménykezelőt:
  for (int i=0;i<count;i++) 
  {
    if (mru[i] != "") 
    {
      fileCount++;
      MenuItem mmru = new MenuItem(Convert.ToString(fileCount) + " " + mru[i], new EventHandler(OnMRUClick));
      mmru.Click += new System.EventHandler(this.mmru_Click);
      this.MenuItems.Add(mmru);          
    }
  }
  ...
}
Az osztályhoz létrehoztunk két saját eseménykezelőt, melyeket „delegálni” lehet az objektumhoz. Az elemre kattintáskor bekövetkező esemény:
public event EventHandler MRUClicked; 
protected virtual void OnMRUClick(object o, EventArgs e) 
{
  if (MRUClicked != null) 
  {
    MRUClicked(o, e); 
  }
}
Az elem megváltozásához kapcsolódó esemény:
public event EventHandler MRUChanged;
if (MRUChanged != null) 
{
  MRUChanged(this, new EventArgs()); 
}
Az egyes elemekre kattintva újra elindítjuk a Notepad.exe programot az elem Text property-jét használva paraméterként:
private void mmru_Click(object sender, EventArgs e)
{
  string sHelp = ((MenuItem)sender).Text.Substring(2);
  ProcessStartInfo psi = new ProcessStartInfo();
  psi.FileName = "notepad.exe";
  psi.Arguments = sHelp;
  Process.Start(psi);
}