ผมได้สร้างไลบรารีที่ทำให้สามารถนำ UI ของแอปไปไว้บนแถบงานของ Windows 11 ได้
(github.com/airtaxi)ผมเพิ่งเผยแพร่ไลบรารีที่สามารถฝัง UI ของแอปลงไปในแถบงาน (taskbar) ของ Windows 11 ได้โดยตรง ชื่อว่า Deskband11Lib และเมื่อติดตั้งผ่าน NuGet ก็สามารถทำให้แอป WinUI 3 หรือ WPF กลายเป็นวิดเจ็ตบนแถบงานได้
ผมจะเล่าต่อว่าทำไมถึงสร้างมันขึ้นมา มันทำงานอย่างไร และรวมถึงวิดเจ็ต PoC ที่ผมนำขึ้น Store จริงด้วย
เบื้องหลัง: deskband ที่หายไปใน Windows 11
จนถึง Windows 10 ยังมีฟีเจอร์ Deskbands ที่สามารถแสดงแถบเครื่องมือขนาดเล็กบนแถบงานได้ แต่พอมาเป็น Windows 11 ฟีเจอร์นี้ก็หายไปทั้งชุด สำหรับคนที่อยากมี “วิดเจ็ตเล็ก ๆ ที่ลอยอยู่ตลอดเวลา” อย่างตัวควบคุมมีเดีย, system monitor หรือ quick launch ไว้บนแถบงาน นี่ถือเป็นการเปลี่ยนแปลงที่น่าเสียดายไม่น้อย
แรงบันดาลใจ: Deskband11 ของ zadjii
เมื่อไม่นานมานี้ผมเห็น zadjii/Deskband11 บน GitHub แล้วรู้สึกว่าหลักการเข้าถึงปัญหานั้นยอดเยี่ยมมาก
วางหน้าต่าง WinUI 3 แบบโปร่งใสทับลงไปบนแถบงาน จากนั้นใช้
SetParentทำให้หน้าต่างนั้นกลายเป็น child HWND ของแถบงาน แล้วกำหนด clip region ตามขนาดของคอนเทนต์ เพื่อให้มันดูเหมือนเป็นส่วนหนึ่งของแถบงาน
สุดท้ายแล้วมันก็ “เป็นแค่หน้าต่างที่ลอยอยู่บนแถบงาน” แต่ไอเดียนี้ฉลาดมาก อย่างไรก็ตาม โปรเจกต์ต้นฉบับเองก็ระบุไว้ว่าเป็น “โค้ดระดับแฮกกาธอน” และยังมีจุดที่ไม่พร้อมสำหรับการนำไปใช้ในผลิตภัณฑ์จริง
ผมเลยทำมันใหม่เป็นไลบรารี
เพราะรู้สึกว่าไอเดียนี้น่าเสียดายถ้าจะปล่อยผ่าน ผมจึงเขียนมันใหม่เป็นไลบรารีเพื่อให้ใคร ๆ ก็ใช้ได้ด้วยคำสั่ง dotnet add package เพียงบรรทัดเดียว
- GitHub: https://github.com/airtaxi/Deskband11Lib
- NuGet:
Deskband11Lib.WinUI/Deskband11Lib.Wpf
วิธีใช้ก็ง่ายมาก
สร้างหน้าต่าง WinUI 3 ขึ้นมาหนึ่งอัน แล้วส่งเข้า TaskbarContentHost ก็เสร็จแล้ว
var window = new MainWindow();
var host = new TaskbarContentHost(window, rootElement, new TaskbarContentHostOptions
{
PreferredWidth = 360,
PreferredHeight = 48
});
await host.AttachWhenLayoutReadyAsync();
window.Activate();
ฝั่ง WPF ก็มี API ที่แทบจะเหมือนกัน ไลบรารีจะจัดการให้เองทั้งการตรวจจับการจัดวางแถบงาน (ซ้าย/กลาง), การหลีกเลี่ยงการซ้อนทับกับปุ่ม Start และพื้นที่แจ้งเตือน, การกู้คืนเมื่อ Explorer รีสตาร์ต และแม้แต่แอนิเมชันตอนเลย์เอาต์เปลี่ยน
กว่าจะทำให้มันใช้งานได้จริงก็ใช้เวลาไม่น้อย
ตอนลองรันโค้ดต้นฉบับแบบตรง ๆ มันเปิดขึ้นมาได้ก็จริง แต่ตำแหน่งและขนาดของหน้าต่างกลับเพี้ยนไปหมด เนื่องจากต้นฉบับเป็นโค้ดที่เขียนตอนแฮกกาธอน ตอนแรกผมเองก็ไม่แน่ใจว่าเป็นเพราะ Windows 11 อัปเดตแล้วเปลี่ยน implementation ของแถบงาน หรือว่าโค้ดเดิมมีจุดคลาดเคลื่อนอยู่แล้วกันแน่ ซึ่งทั้งสองอย่างก็อาจเป็นสาเหตุได้ เลยไม่มีทางเลือกนอกจากค่อย ๆ แกะฝั่งแถบงานออกมาดูทีละส่วน แล้วตรวจสอบด้วยตัวเองว่าใน build ปัจจุบันมันถูกจับอย่างไรจริง ๆ นอกจากนี้ต้นฉบับยังไม่ได้คำนึงถึงกรณีที่ปุ่ม Start อยู่ตรงกลาง หรือองค์ประกอบอย่างปุ่ม Widgets เลย ทำให้ตอนทำเป็นไลบรารีต้องใส่ใจเรื่องเหล่านี้เพิ่มใหม่ทั้งหมด
ดังนั้นจากต้นฉบับ ผมอ้างอิงเพียงวิธีใช้ UI Automation และ Win32 API สำหรับจับขนาด/ตำแหน่งหน้าต่างเท่านั้น ส่วน logic ในการคำนวณพื้นที่ว่างนั้นผมเขียนใหม่ทั้งหมดตั้งแต่ต้น เพราะต้องอ่านตำแหน่งของปุ่ม Start, กลุ่มปุ่มแอปบนแถบงาน, ปุ่ม Widgets และพื้นที่แจ้งเตือน เพื่อหาพื้นที่ที่เหลืออยู่ และตำแหน่งของพื้นที่ว่างก็ยังเปลี่ยนไปตามการจัดวางแถบงานว่าชิดซ้ายหรืออยู่ตรงกลางอีกด้วย จึงต้องออกแบบส่วนนี้ขึ้นมาใหม่
ผมทำแอปจริงขึ้นมาหนึ่งตัวและนำขึ้น Store แล้ว: BarPlay
เพื่อเช็กว่าไลบรารีนี้ใช้งานได้จริงแค่ไหน ผมจึงสร้างแอปหนึ่งตัวด้วยมันแล้วนำขึ้น Microsoft Store ชื่อว่า BarPlay
มันเป็นวิดเจ็ตที่แสดงภาพปก, ชื่อเรื่อง และปุ่มควบคุมของมีเดียที่กำลังเล่นอยู่บนแถบงาน ใช้งานได้กับทุกแอปที่รองรับ Windows System Media Transport Controls (SMTC) เช่น Spotify, เบราว์เซอร์ และแอป YouTube PWA ผมคอมไพล์มันด้วย NativeAOT เพื่อลดเวลาเริ่มต้นและการใช้ทรัพยากรให้เหลือน้อยที่สุด
ผมลองแนะนำให้คนรู้จักรอบตัวดูก่อนแล้ว และกระแสตอบรับก็ค่อนข้างดี
เอาไปใช้ทำอะไรได้บ้าง
คุณสามารถนำคอนเทนต์ที่สร้างด้วย WinUI 3 หรือ WPF ไปวางไว้ในตำแหน่งที่มองเห็นได้ตลอดเวลาโดยไม่ต้องเปิดหน้าต่างแยกต่างหาก จะใช้ทำตัวจับเวลา, ตัวควบคุมการเล่นมีเดีย (แบบ BarPlay), สถานะบิลด์หรือการแจ้งเตือนจาก CI, system monitor, quick launcher, ตัวสลับบัญชี หรือ indicator สำหรับการแจ้งเตือนก็ได้
เพราะสามารถนำคอนโทรลและสไตล์ของแอปตัวเองขึ้นไปใช้บนแถบงานได้โดยตรง ผมจึงคิดว่านี่น่าจะเป็นไลบรารี .NET แทบจะตัวเดียวที่ทำให้สร้างประสบการณ์แบบนี้ได้บน Windows 11 ซึ่ง deskband ได้หายไปแล้ว
รวมลิงก์
- Deskband11Lib (ไลบรารี)
- NuGet (WinUI)
- NuGet (WPF)
- BarPlay (Proof of Concept, Store)
- BarPlay (ซอร์สโค้ด)
- ต้นฉบับที่เป็นแรงบันดาลใจ (zadjii/Deskband11)
เป็นไลเซนส์ MIT และคุณสามารถเริ่มต้นได้ด้วยการคัดลอกโปรเจกต์ตัวอย่าง (Deskband11Lib.WinUI.Sample, Deskband11Lib.Wpf.Sample) ผมยินดีต้อนรับทั้ง feedback, issue และ PR และถ้าคุณสร้างวิดเจ็ตแถบงานที่น่าสนใจขึ้นมาได้ ก็อย่าลืมบอกกันด้วยนะครับ
2 ความคิดเห็น
โอ้ ไอเดียดีมากเลยนะ
ขอบคุณครับ! จริงๆ แล้วผมแค่ทำให้มันเป็นไลบรารีเท่านั้น แต่คิดว่าน่าจะเป็นเพราะไอเดียของคนที่ทำต้นฉบับไว้ก่อนด้วยครับ.. 555