2013-09-28 152 views
2

我嘗試了幾次不同的代碼,但每次都遇到錯誤。 基本上,我試圖讓「窗口」類似資源管理器中說,油漆,MediaPlayer的,在那裏你可以拖動然後圍繞,與它們進行交互,最小化和關閉。當然,如果你點擊一個窗口,它下面的一個窗口(它們可以重疊)不應該受到影響。如何製作窗口管理器?

我知道如何做到這一點,我有I類呼叫窗口,循環列表,通過它,我只與第一窗口交互包含鼠標點擊的位置。這樣,其他窗口重疊不會受到影響。 [1]

接下來,我不得不這樣做,以便兩個重疊的按鈕不會在用戶單擊「兩個按鈕的交集」時被激活。我通過使用上面使用的相同方法來處理這個問題。但我現在面臨的問題是,如果我按住左鍵單擊,但我決定不單擊按鈕,則將鼠標從按鈕上拖離,然後釋放左鍵單擊,以便按鈕單擊事件不會被激活。但是,當我從按鈕的邊界移除鼠標,並說,進入另一個...新按鈕被激活。它不應該。 [3]

我的設置是這樣的: 我有一個叫Window的類。 在Window中,我有一個名爲Interface的類的列表(類似於WinForms中的Control類)。 每個接口中有一個結構,其中包含4個布爾變量,如果左/右目前下跌了,如果他們在先前的處理了。 (prevLeft,prevRight,currLeft,currRight)

所以,我準備放棄(我還沒有,所以我仍然有源代碼),但我需要一個良好的結構,使面向對象類型的應用程序。但是,我沒有使用WinForms。我需要單獨的結構幫助,因此不需要實際的代碼,描述就足夠了。我需要避免上面提到的三個問題。

+0

你說你不使用WinForms,那麼什麼平臺你還在使用嗎?你仍然應該顯示你的代碼。 – OneFineDay

+0

我使用的是Xna。 d渲染速度比GDI快。代碼非常冗長。我應該將其上傳到Pastebin,還是應該只在一小部分中進行編輯? – Dave

+0

我只會說你遇到麻煩的代碼。所以我們可以看到是否可以看到任何優化或錯誤。瞭解事件如何響應以及如何佈置將有助於您的邏輯。 – OneFineDay

回答

0

而不必用4個布爾值(類似XNA),你怎麼樣讓一個辦法告訴在鼠標結構「是。」因此,在某種意義上,所述小鼠是在窗口數5這是油漆,並且用戶被保持按下鼠標上接口/控制數2其爲按鈕。 這聽起來像它可以工作。

+0

聽起來像一個計劃,但我需要4布爾結構,所以我可以做事件。 (prevLeft關閉,currLeft不關閉意味着鼠標剛被釋放,也就是點擊事件)。 – Dave

2

創建自己的Window Manager不是一件容易的事。我知道它,因爲我也是這樣做的)

您可以使用現有的,但可能不是最好的解決方案,例如Nuclex.UI,我個人在第一次看到它時拒絕了,但如果您不是死定在做自己的WM,我建議使用那個或hybrid WinForms-XNA approach

但如果你是在實現定製窗口管理器真的死心塌地,你要明白任何其他WM是如何工作的。由於我們談論的是XNA,它意味着Windows,這意味着Windows資源管理器,這是一個偉大的事情可以借鑑。

你必須認識到最簡單的事情是如何工作的,這真的不是那麼難。最難的部分是弄清什麼時候更新邏輯,以及如何不把所有的CPU都花在UI更新上。讓我給你一些關於如何解決你在問題中提到的問題的提示。

  • 爲了讓所有窗口的賽道,我使用的是Dictionary<string, Window>,其中Window是一個自定義類,以及string是其獨特的罕見情況下,我必須通過名字來調用Windows的名稱。把它想象成一個窗口GUID或Handle。但是你可以使它成爲「Form」只能出現一次,並將所有引用存儲在靜態變量中。

  • 爲了讓WM明白控制你點擊我用矩形和檢查它們是否包含Point這是光標座標和具有{1; 1}像素大小,這可能是差不多的方式,在Windows資源管理器來完成。要做到這一點,WM需要知道以何種順序更新活動窗口。通常你想從最上面的窗口開始,繼續往活動窗口列表的末尾。爲此,您可以使用foreach循環遍歷列表。

  • 但是這還不是全部,因爲每個窗口本身是一個Container,這意味着它包含其他控件,其中一些甚至可能是Container s ^自己,喜歡的WinForms Panel類。這意味着您必須循環訪問Window的每個控件。更新順序也應該有意義 - 從最上面的孩子更新到最下面,遞歸地控制Container控件,以防他們也有Container。這基本上意味着你想爲你的WindowManager類實現遞歸GetAllControls()方法,該方法將遍歷所有Containers並返回所有Control的列表。

  • 繪製所有這些Control S的關係在更新它們相反的順序來完成,這樣你就可以在foreach遍歷,只是GetAllControls().Reverse()和迭代。

  • 繪畫的位置和更新內容取決於當前容器的所有父容器以及它們與遊戲窗口左上角的組合偏移量。我通過在所有子控件中存儲ParentContainer引用來解決此問題,以通過遞歸屬性獲取適當的DrawRectangle和更新區域。

  • 當你點擊某個地方在屏幕上,點擊註冊在Control,使WindowManager記得(bool clickRegistered),而不是對任意Control的run任何OnClick事件。

  • Windows資源管理器會記住您單擊的控件,並且如果在同一控件的更新區域中釋放了光標,它將激活它的OnRelease事件。所以基本上Windows管理器只會在您釋放鼠標按鈕時發揮作用。您可以讓自己的WindowManagerControl以不同的方式處理點擊事件,例如在按下鼠標按鈕後立即觸發事件,即OnMouseDown。但請記住,微軟不是新手,在Windows資源管理器中有這種行爲的原因,這是因爲如果你不小心按下了你不打算的地方的鼠標按鈕,你仍然可以通過將光標移動到按下的控件更新之外來修復它區域並且不運行它的行動。

在這一點上,你可能會想:「真的值得實施這一切嗎?「對我來說,答案可能是」可能「,因爲在我開始的時候,我在C#和XNA都是noob,現在我知道我原本應該使用某個窗口管理器的遊戲會受益於我自己的WM實現遠遠超過現成的第三方解決方案,此外,這是一個偉大的邏輯和編程練習

但是,如果你想把自己想象成遊戲開發者,你應該考慮所以在這種情況下,最好利用現有的解決方案並開始銷售你的產品。

+0

非常感謝!我已經在做一些你所說的子彈了,但現在我想我可以像你說的那樣正確地創建窗口管理器。我會看到結果如何。 – Dave

相關問題