2012年2月22日 星期三

Drag and Drop in C#

現在越來越多應用程式以及網站使用拖放 (Drag and Drop) 技術
於是就開始動手用 C# 寫看看,使用之元件:

  • PictureBox
  • Button
  • Label
  • OpenFileDialog
  • ContextMenuStrip
欲設計的功能:

  • 允許從電腦中將圖片拖進 PictureBox 中
  • 或者點下 Button 後瀏覽欲放進 PictureBox 的圖片
  • 點擊 PictureBox 的右鍵菜單可刪除 PictureBox 上的圖片

-------------------------------------------------------------------------------------------------


一開始是超級陽春的介面
整個 Form 上只有一個名為 pictureBox1 的元件
我們要讓 pictureBox1 可以被 drag and drop
首先寫下這行
pictureBox1.AllowDrop = True;

但一開始在這裡已經遇到一個疑問,先來看看下面這張圖
pictureBox1 中竟然沒有 AllowDrop 這個屬性
但我也不管就直接寫,沒想到 compiler 就過了...

接著要處理 DragEnterDragDrop 這兩個事件

DragEnter:當有物件拖進 pictureBox 中會觸發此事件
private void pictureBox1_DragEnter(object sender, DragEventArgs e)
{
   if (e.Data.GetDataPresent("FileNameW"))
   {
      string[] data = (e.Data.GetData("FileNameW") as string[]);
      fileName = data[0];
      e.Effect = DragDropEffects.All;
   }
}

Note:
這部分我真的卡關很久,最後在藍色小舖發問才解惑
我一直以為當我從某資料夾中拖了一張圖片
拖至 PictureBox 中時,程式會清楚明白我拖進去的是 "一張圖片"
這個想法應該算很直覺吧!
只是,我們雖然是選取一張圖片拖至 PictureBox 中
但其實我們只是把檔名/目錄名拖進去!
所以我們可將檔名記錄下來
如此就能掌握到到底拖了電腦中的哪個物件進 PictureBox 中


DragDrop:拖放物件至 pictureBox 中會觸發此事件
private void pictureBox1_DragDrop(object sender, DragEventArgs e)
{
    try
    {
       if (File.Exists(fileName))
       {
          Image img = new Bitmap(fileName);
          PictureBox myPictureBox = (PictureBox)sender;
          myPictureBox.Image = img;
       }
    }
    catch (Exception ex)
    {
       MessageBox.Show("不是有效的圖檔格式!!");
    }
}

Note:
先檢查拖進去的物件是否為一張圖片
是則將拖曳的圖片 assign 給 pictureBox1

這兩個事件寫好之後,記得加入到 pictureBox1 的事件中

pictureBox1.DragEnter += new DragEventHandler(pictureBox1_DragEnter);
pictureBox1.DragDrop += new DragEventHandler(pictureBox1_DragDrop);

這樣就完成了將圖片拖曳至 pictureBox1 中的程式碼囉
剩下的就是一些小功能,大家就可自由發揮要加入甚麼功能
首先,畫面上只有 pictureBox1 實在是太單調了
所以加入了 Label 和 Button


我絕對沒有說是參考Picasa的

這樣看起來好多了
除了可從電腦中拖曳圖片之外
也可透過 Button 選取電腦中的圖片至 pictureBox1 中

接著,我將 pictureBox1 的長寬設定為 800x600
但如果欲放置的圖片比 pictureBox1 小或大該如何呈現呢?
較小:將圖片置中
較大:等比例縮圖
用這段 code 搞定

void AdjustSizeMode(PictureBox pictureBox, Image image)
{
    if (image.Width > pictureBox.Width && image.Height > pictureBox.Height)
    {
       pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
    }
    else
    {
       pictureBox.SizeMode = PictureBoxSizeMode.CenterImage;
    }
}

拉一張圖進去試試!

Oops!Label 及 Button 還在畫面上,這不是我想要的結果
所以一旦圖片已載入到 pictureBox1 上時,我想讓 Label 及 Button 看不見
這小功能應可用很多種方式達成
我是直接將 Label 及 Button 的 Visible 屬性設為 False

最後,我想加入一個右鍵菜單,能將 pictureBox1 的圖片消掉
這時利用 ContextMenuStrip 可順利完成此功能

記得圖片消掉後,要讓 Label 及 Button 又要看的見喔!
這樣就大功告成拉。



沒有留言:

張貼留言