2010-04-15 80 views
1

我想模仿谷歌的Chrome/FireFox中的例如功能性,重新整理你的書籤時,當你拖動菜單項,它會創建在建議滴點黑線,像這樣:如何在WinForm上拖動菜單項時創建拖放行?

alt text http://www.freeimagehosting.net/uploads/977900a13a.jpg

我已經實現了拖放功能來重新排列菜單,但我想添加這些分隔線作爲附加功能。

有沒有辦法在.NET Framework(3.5)中執行此操作,還是必須使用Win32 API調用?只是想在我走下那條路之前問一下。

+0

我*想*這就是你問的 - 如果不是,請隨時回滾。 – MusiGenesis 2010-04-15 02:12:37

+0

@Bryan:你不需要將標題中的語言放在標題中。 – 2010-04-15 02:14:46

回答

0

在純.NET代碼中執行此操作的常用方法是創建一個無邊框窗體,其顏色和大小看起來像是放置點線。在此窗體上也將TopMost屬性設置爲True。

然後使用MouseDown/MouseUp/MouseMove事件來確定何時何地顯示拖放行以響應用戶操作。

要正確定位拖放線形式,您需要查看Control.PointToScreen和/或Control.RectangleToScreen(也可能是Control.PointToClient)方法。

0

我認爲最簡單的方法是獲取拖動的彈出菜單的句柄。一旦你有了手柄,你就可以用一個Graphics對象直接繪製它。

獲取句柄可能需要一些API mojo。我正在查找它。

更新:儘管有一個諷刺性的捕獲(見下文),但根本沒有太多的魔咒。爲此,請添加

using System.Runtime.InteropServices; 

位於窗體或類的頂部或其他位置。某處添加此聲明:

[DllImport("user32.dll", EntryPoint = "FindWindow")] 
    private static extern IntPtr FindWindowA(string lpClassName, 
    string lpWindowName); 

一個彈出菜單窗口(這意味着一部分,你通常不會看到)與類名「#32768」最頂層窗口。此代碼演示瞭如何獲取菜單的窗口辦理,並直接繪製到它:

IntPtr hWnd = FindWindowA("#32768", null); 
if (hWnd != IntPtr.Zero) 
{ 
    using (Graphics g = Graphics.FromHwnd(hWnd)) 
    { 
     g.FillRectangle(Brushes.Red, 
      new Rectangle(0, 0, 20, 20)); 
    } 
} 

此示例只是繪製一個20×20紅場菜單的左上角。爲了渲染放置線,你必須做更多的工作來確定它應該在哪裏,然後在那裏繪製任何你想要的。在我看來,它只是一個雙像素高黑線,每端都有小箭頭,所以它不應該很難模仿。

你可能不得不擔心清理任何你畫的東西,但我懷疑它。彈出式菜單窗口是暫時的,我認爲它們會在您將拖放光標移到它們上方時自動重新繪製。如果不是,每次拖放行更改位置時,可能必須將重新發送消息發送到彈出菜單窗口。

即使您打開了多個嵌套菜單(全部推測類名稱爲「#32768」) - FindWindow似乎總能返回z順序中的最頂層菜單。另外一件好事 - 因爲您正在繪製到菜單窗口本身,該線將位於半透明的放置光標下,這正是您想要的。

具有諷刺意味的是:我測試了一堆不同的程序和菜單。它適用於所有菜單和所有菜單,,但Internet Explorer中的收藏夾菜單中的除外。我猜測那個特定的菜單使用的不是內置的Windows菜單。如果你使用常規的.Net菜單來做這件事,它應該可以正常工作。