1. 前言本來打算寫一篇《自定義Window》的文章,但寫著寫著發(fā)覺內(nèi)容太多,所以還是把使用WindowChrome自定義Window需要用到的部分基礎(chǔ)知識(shí)獨(dú)立出來,于是就形成了這篇文章。 無論是桌面編程還是日常使用,Window(窗體)都是最常接觸的UI元素之一,既然Window這么重要那么多了解一些也沒有壞處。 2.標(biāo)準(zhǔn)Window這篇文章主要討論標(biāo)準(zhǔn)的Window,不包括奇形怪狀的無邊框、非矩形Window,即只討論 一個(gè)標(biāo)準(zhǔn)的Window的基本構(gòu)成如上圖所示,它主要由非工作區(qū)(non-client area)和工作區(qū)(client area)組成。上圖中中間白色的部分即client area,在WPF對(duì)應(yīng)下面代碼中注釋的部分:
標(biāo)準(zhǔn)window中除client之外的部分稱為non-client area,通常稱之為chrome,它提供了提供了標(biāo)準(zhǔn)的窗口功能和行為,具體包含以下部分:
邊框標(biāo)準(zhǔn)Window肯定會(huì)有邊框的,在Windows 7上因?yàn)橛蠥ero效果所以看上去很棒,現(xiàn)在偶爾用用Windows 7還是覺得很漂亮。但就如上圖所示圓角不夠平滑,如果電腦不是高分屏的話應(yīng)該會(huì)更明顯,例如這樣: 因?yàn)閳A角總是很難處理所以我不是很喜歡圓角的設(shè)計(jì)。 Windows 10的邊框就時(shí)髦很多,如果在“個(gè)性化>顏色”設(shè)置頁面取消 陰影陰影用于體現(xiàn)UI的深度,屬于裝飾元素,Windows 的窗體通常都帶有陰影,除非在“系統(tǒng)屬性->高級(jí)->性能選項(xiàng)->視覺效果”里關(guān)閉“在窗口下顯示陰影”選項(xiàng)。 標(biāo)題欄只要是標(biāo)準(zhǔn)的Window就應(yīng)該有標(biāo)題欄。一些瀏覽器看上去沒有標(biāo)題欄;當(dāng)Fluent Design System出來后流行將內(nèi)容擴(kuò)展到標(biāo)題欄,越來越多的應(yīng)用看上去沒有了標(biāo)題欄。其實(shí)標(biāo)題欄總是存在,能拖動(dòng),點(diǎn)擊右鍵會(huì)彈出 雙擊標(biāo)題欄還可以執(zhí)行 有一點(diǎn)細(xì)節(jié)可能不太容易注意到,當(dāng)Window處于最大化狀態(tài)時(shí)標(biāo)題欄比較矮。在100% DPI時(shí)標(biāo)題欄的高度為30像素,最大化時(shí)變?yōu)?2像素,這時(shí)候右上角的幾個(gè)按鈕縮小了,其它元素的Margin也減少了一些。 IconIcon是指標(biāo)題欄左邊的窗體圖標(biāo),這倒真的很常消失。在100% DPI的情況下它是個(gè)16 * 16 像素的圖片。 順便一提雙擊Icon會(huì)關(guān)閉Window,但我想一般都會(huì)用右邊的 標(biāo)題標(biāo)準(zhǔn)Window的標(biāo)題位于Icon右邊。如果Window邊框是深色,標(biāo)題文字顏色為白色;反之則為黑色。 SystemMenu在標(biāo)題欄上點(diǎn)擊鼠標(biāo)右鍵出現(xiàn)的ContextMenu即是 不過很少見到有人用 最小化、最大化和還原按鈕當(dāng)Window的 關(guān)閉按鈕因?yàn)?code>關(guān)閉按鈕基本上一定會(huì)存在所以把它獨(dú)立出來,只是 調(diào)整大小當(dāng)Window的 大小調(diào)整手柄當(dāng)Window的 拖動(dòng)有些Window會(huì)做成整個(gè)Window都可以通過拖動(dòng)來改變位置,標(biāo)準(zhǔn)Window則只有標(biāo)題欄可以拖動(dòng)。 激活激活或非激活的Window之間的區(qū)別主要體現(xiàn)在標(biāo)題欄、邊框及標(biāo)題文字的顏色。在標(biāo)題欄使用了AcrylicBrush的UWP應(yīng)用還體現(xiàn)在非激活時(shí)AcrylicBrush變成純色不透明的Brush。 焦點(diǎn)一個(gè)Window中只有client area中的內(nèi)容可以獲得鍵盤焦點(diǎn),而且 動(dòng)畫Window在最大化、最小化、還原有縮放的動(dòng)畫,這個(gè)動(dòng)畫可以清晰地指示W(wǎng)indow的最終位置。當(dāng)任務(wù)欄內(nèi)容很多的時(shí)候,向下縮放到任務(wù)欄對(duì)應(yīng)位置的動(dòng)畫尤其重要。 FlashWindow如果一個(gè)Window設(shè)置了Owner并且以ShowDialog的方式打開,點(diǎn)擊它的Owner將對(duì)這個(gè)Window調(diào)用FlashWindowEx功能,即閃爍幾下,并且還有提示音。除了這種方式還可以用編程的方式調(diào)用FlashWindow功能。 Window的大小最后要說的是Window的大小。Window的實(shí)際大小并不是表面上看到的大小。在Windows 10,以1920 * 1080 分辨率,100% DPI為例,打開以下XAML定義的一個(gè)Window:
通過實(shí)時(shí)可視化樹可以看到,Window本身的小時(shí)確實(shí)是800 * 600,但LayoutRoot的大小只有784 * 561。將Window最大化后Window的大小變?yōu)?936 * 1066,而LayoutRoot的大小變?yōu)?920 * 1027。 如果將Window設(shè)置為啟動(dòng)位置在左上角:
結(jié)果它并不會(huì)完全貼著左上角,而是左邊有一點(diǎn)空間,上面沒有。 通過Inspect看到的Window如下,黃色邊框?yàn)樗膶?shí)際范圍: 可以看到系統(tǒng)理解的Window范圍和我們看到的不同,這是Window設(shè)計(jì)的問題,有幾個(gè)值用于計(jì)算chrome的尺寸:
在有標(biāo)題的標(biāo)準(zhǔn)Window,chrome的頂部尺寸為SM_CYFRAME SM_CXPADDEDBORDER SM_CYCAPTION = 31,左右兩邊尺寸為SM_CXFRAME SM_CXPADDEDBORDER = 8,底部尺寸為SM_CYFRAME SM_CXPADDEDBORDER = 8。 最大化情況下Border和ResizeBorder都超出屏幕范圍而且被隱藏了,所以Window的尺寸會(huì)超過顯示器工作區(qū)的尺寸,這時(shí)候標(biāo)題欄也會(huì)相應(yīng)地變矮。在Windows 10,系統(tǒng)認(rèn)為Window有4像素的ResizeBorder,但因?yàn)閃indows 10是窄邊框設(shè)計(jì),而且在普通狀態(tài)下和最大化狀態(tài)下的標(biāo)題欄高度還不一樣,導(dǎo)致用UISpy觀察Window和我們看到的Window不一致,也常常導(dǎo)致位置計(jì)算上的問題。 注意,上面的尺寸計(jì)算都是基于100 % DPI,在不同DPI的情況下還需要將DPI的值納入計(jì)算。 3. 結(jié)語標(biāo)準(zhǔn)Window的外觀和行為基本上已經(jīng)列出來了(其實(shí)還有很多,例如按住標(biāo)題欄抖一抖可以縮小其它所有窗口這種功能,但這些不影響自定義Window的行為就不一一列出了),更多的內(nèi)容請(qǐng)見下面給出的參考鏈接。 順便一提設(shè)置 4. 參考WPF Windows 概述 _ Microsoft Docs SystemParameters Class (System.Windows) Microsoft Docs 來源:http://www./content-4-238201.html |
|