Wednesday, February 29, 2012

[Csharp] Window Context Menu

Today, I read some topic on http://diendan.congdongcviet.com/
I found an enjoyable question on this topic: http://diendan.congdongcviet.com/showthread.php?t=85813
Create an custom menu in Window Context Menu, that I never thought. Get code of creator, I try to make menu.
After some minutes, I successfully create it. Then I have same question, how can get clicked file to my application. Try some ways and search Google. Yes, solution in here:
http://www.jfitz.com/tips/rclick_custom.html
Now, I will show you how to make a menu and do something with file.

For create new menu and remove it, I write a class:

   1:      public static class WindowContextMenu
   2:      {
   3:          public static void RemoveContextMenuItem(string extension, string menuName)
   4:          {
   5:              RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(extension);
   6:   
   7:              if (registryKey != null)
   8:              {
   9:                  string extstring = registryKey.GetValue("").ToString(); //root
  10:   
  11:                  registryKey.Close();
  12:   
  13:                  if (!string.IsNullOrEmpty(extstring))
  14:                  {
  15:                      registryKey = Registry.ClassesRoot.OpenSubKey(extstring, true);
  16:                      if (registryKey != null)
  17:                      {
  18:                          RegistryKey subky = registryKey.OpenSubKey("shell\\" + menuName);
  19:                          if ( subky != null )
  20:                          {
  21:                              subky.Close();
  22:                              registryKey.DeleteSubKeyTree("shell\\" + menuName);
  23:                              registryKey.Close();
  24:                          }
  25:                      }
  26:                  }
  27:              }
  28:          }
  29:   
  30:          public static void AddContextMenuItem(string extension, string menuName, string menuDescription, string menuCommand)
  31:          {
  32:              RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(extension);
  33:   
  34:              if (registryKey != null)
  35:              {
  36:                  string extstring = registryKey.GetValue("").ToString(); //root
  37:   
  38:                  registryKey.Close();
  39:   
  40:                  if (!string.IsNullOrEmpty(extstring))
  41:                  {
  42:                      registryKey = Registry.ClassesRoot.OpenSubKey(extstring, true);
  43:   
  44:                      if (registryKey != null)
  45:                      {
  46:                          string strkey = "shell\\" + menuName + "\\command";
  47:   
  48:                          RegistryKey subky = registryKey.CreateSubKey(strkey);
  49:   
  50:                          if (subky != null)
  51:                          {
  52:                              subky.SetValue("", menuCommand);
  53:                              subky.Close();
  54:                          }
  55:   
  56:                          subky = registryKey.OpenSubKey("shell\\" + menuName, true);
  57:                          if (subky != null)
  58:                          {
  59:                              subky.SetValue("", menuDescription);
  60:                              subky.Close();
  61:                          }
  62:                          registryKey.Close();
  63:                      }
  64:                  }
  65:              }
  66:          }
  67:      }
You can simply understand, it only write and delete key on Registry Editor. So, for use this class here is my sample:
   1:          private void btnRemove_Click(object sender, EventArgs e)
   2:          {
   3:              WindowContextMenu.RemoveContextMenuItem(".xls", "NewMenuOption");
   4:          }
   5:   
   6:          private void btnCreate_Click(object sender, EventArgs e)
   7:          {
   8:              WindowContextMenu.AddContextMenuItem(".xls", "NewMenuOption", "QuangHoang", Application.ExecutablePath + " \"%1\"");
   9:          }
This is code for two buttons Add and Remove.

So, now is the answer of question of topic I mention in top of post.

How your application open file? 
You can use args parameter. When user click on your menu, you can run you application and send file path to. Your application get the path and do what you want. Like this:
   1:          static void Main(string[] args)
   2:          {
   3:              Application.EnableVisualStyles();
   4:              Application.SetCompatibleTextRenderingDefault(false);
   5:   
   6:              if (args != null && args.Length > 0)
   7:              {
   8:                  Application.Run(new FormDemo(args[0]));
   9:              }
  10:              else Application.Run(new FormDemo());
  11:          }
Here, I am overload constructor of Main form.

How can get file's path user click on?
You can see on code I demo in above, you can see menuCommad parameter is Application.ExecutablePath + " \"%1\""
 - First part is path of you application, you can set what you want
 - Second part is "%1", it mean path of file you click on.

Source demo: http://www.mediafire.com/?qdg4ler3gt0guat
I think it so useful for some application.
Enjoy it :)

4 comments:

  1. Một bài viết rất hay!

    Cảm ơn bạn!

    ReplyDelete
  2. Mình đã làm theo hướng dẫn của bạn, nhưng mình gặp 1 vấn đề về hàm void Main(). Project của mình có class MainTool.cs để xử lý dữ liệu trên file excel. Như vậy hàm static void main() của mình sẽ là:

    static void Main(string[] args)
    {

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    frmMain main = new frmMain();
    MainTool.frmmain = main;

    Application.Run(main);

    }

    Như vậy hàm void Main() của tôi phải viết ra sao để lấy được đường dẫn của file Excel. Nếu làm theo cách viết void Main() của bạn thì chương trình ko xử lý file Excel được.

    Cảm ơn bạn nhiều!

    ReplyDelete
  3. What different between my Main function and your Main function?
    Answer of this question is answer for your question.
    This args[0] is link of Excel file, I send it on constructor of form main.

    ReplyDelete
  4. Sự khác nhau giữa Main function của bạn và của mình như sau:

    Main function của bạn truyền trực tiếp đường dẫn Excel vào chương trình và chương trình bắt lấy đường dẫn rồi hiển thị ra, không thông qua 1 lớp xử lý dữ liệu trên Excel.

    Tuy nhiên, Main function của mình phải thông qua 1 lớp xử lý dữ liệu, dữ liệu sẽ được xử lý, bắt lỗi, ngoại lệ ở lớp này rồi mới hiện thị trong chương trình dưới dạng grid. Vì vậy, Main fuction của mình trước đây khi chưa có truyền đường dẫn file Excel vào sẽ là:

    static void Main(string[] args)
    {

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    frmMain main = new frmMain();
    //Gán lớp xử lý vào với frmMain
    MainTool.frmmain = main;

    Application.Run(main);

    }

    Mình đã cố gắng gán link của mình vào lớp xử lý nhưng chưa được. Nên chương trình hiện giờ đã đăng ký được vào ContextMenu, chọn vào chương trình vẫn chạy nhưng không thể tải file Excel và xử lý dữ liệu được.

    Trân trọng cảm ơn bạn.

    ReplyDelete