Custom Window Style and Accounting for the Taskbar
来源:互联网 发布:农业大学网络教育 编辑:程序博客网 时间:2024/06/01 07:41
November 10, 2010 by bbauer42
A little while back I was tasked with creating a custom window in WPF that had its own look and feel. In order to do this you must first set the WindowStyle to None. This is great because it opens the door for you to customize your new window to look however you want. Unfortunately, when you set your WindowStyle to None you lose all of the base functionality of the window. You now have to implement native window actions such as sizing, dragging, the minimize, maximize/restore, and close buttons, etc. After looking around the web for a while I found a really good starting point for creating my custom window. Here is a link to a sample project that has an Office Style custom window already created.
http://blog.opennetcf.com/ayakhnin/content/binary/OfficeStyleWindow.zip
In this project you will find a nicely styled window whose look should be easily customizable. Now we just have to add some code to make our new window accommodate for the taskbar. One thing we must be especially aware of is accommodating for the taskbar when it is set to auto-hide. When the taskbar is auto-hidden, you have to leave 2 pixels available for the bar on the docked edge so the user can mouse over that area to restore the hidden taskbar.
After much testing and digging I ended up writing a public static WindowSizing class that should handle the bar correctly. Using the sample linked above, we must first insert these two lines inside of the Window1 constructor after InitializeComponent(); in the Window1.xaml.cs file.
this.Loaded += new RoutedEventHandler(Window1_Loaded);this.SourceInitialized += new EventHandler(Window1_SourceInitialized);
Here is the code for the event handlers.
void Window1_Loaded(object sender, RoutedEventArgs e){ this.WindowState = WindowState.Maximized;}void Window1_SourceInitialized(object sender, EventArgs e){ WindowSizing.WindowInitialized(this);}
And here is the public static WindowSizing class code which should be self explanatory.
using System;using System.Runtime.InteropServices;using System.Windows;namespace OfficeStyleWindowProject{ public static class WindowSizing { const int MONITOR_DEFAULTTONEAREST = 0x00000002; #region DLLImports [DllImport("shell32", CallingConvention = CallingConvention.StdCall)] public static extern int SHAppBarMessage(int dwMessage, ref APPBARDATA pData); [DllImport("user32", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32")] internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); [DllImport("user32")] internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); #endregion private static MINMAXINFO AdjustWorkingAreaForAutoHide(IntPtr monitorContainingApplication, MINMAXINFO mmi) { IntPtr hwnd = FindWindow("Shell_TrayWnd", null); if (hwnd == null) return mmi; IntPtr monitorWithTaskbarOnIt = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (!monitorContainingApplication.Equals(monitorWithTaskbarOnIt)) return mmi; APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.hWnd = hwnd; SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref abd); int uEdge = GetEdge(abd.rc); bool autoHide = System.Convert.ToBoolean(SHAppBarMessage((int)ABMsg.ABM_GETSTATE, ref abd)); if (!autoHide) return mmi; switch (uEdge) { case (int)ABEdge.ABE_LEFT: mmi.ptMaxPosition.x += 2; mmi.ptMaxTrackSize.x -= 2; mmi.ptMaxSize.x -= 2; break; case (int)ABEdge.ABE_RIGHT: mmi.ptMaxSize.x -= 2; mmi.ptMaxTrackSize.x -= 2; break; case (int)ABEdge.ABE_TOP: mmi.ptMaxPosition.y += 2; mmi.ptMaxTrackSize.y -= 2; mmi.ptMaxSize.y -= 2; break; case (int)ABEdge.ABE_BOTTOM: mmi.ptMaxSize.y -= 2; mmi.ptMaxTrackSize.y -= 2; break; default: return mmi; } return mmi; } private static int GetEdge(RECT rc) { int uEdge = -1; if (rc.top == rc.left && rc.bottom > rc.right) uEdge = (int)ABEdge.ABE_LEFT; else if (rc.top == rc.left && rc.bottom < rc.right) uEdge = (int)ABEdge.ABE_TOP; else if (rc.top > rc.left) uEdge = (int)ABEdge.ABE_BOTTOM; else uEdge = (int)ABEdge.ABE_RIGHT; return uEdge; } public static void WindowInitialized(Window window) { IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(window)).Handle; System.Windows.Interop.HwndSource.FromHwnd(handle).AddHook(new System.Windows.Interop.HwndSourceHook(WindowProc)); } private static IntPtr WindowProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) { switch (msg) { case 0x0024: WmGetMinMaxInfo(hwnd, lParam); handled = true; break; } return (IntPtr)0; } private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) { MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (monitorContainingApplication != System.IntPtr.Zero) { MONITORINFO monitorInfo = new MONITORINFO(); GetMonitorInfo(monitorContainingApplication, monitorInfo); RECT rcWorkArea = monitorInfo.rcWork; RECT rcMonitorArea = monitorInfo.rcMonitor; mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x; //maximum drag X size for the window mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y; //maximum drag Y size for the window mmi.ptMinTrackSize.x = 800; //minimum drag X size for the window mmi.ptMinTrackSize.y = 600; //minimum drag Y size for the window mmi = AdjustWorkingAreaForAutoHide(monitorContainingApplication, mmi); //need to adjust sizing if taskbar is set to autohide } Marshal.StructureToPtr(mmi, lParam, true); } public enum ABEdge { ABE_LEFT = 0, ABE_TOP = 1, ABE_RIGHT = 2, ABE_BOTTOM = 3 } public enum ABMsg { ABM_NEW = 0, ABM_REMOVE = 1, ABM_QUERYPOS = 2, ABM_SETPOS = 3, ABM_GETSTATE = 4, ABM_GETTASKBARPOS = 5, ABM_ACTIVATE = 6, ABM_GETAUTOHIDEBAR = 7, ABM_SETAUTOHIDEBAR = 8, ABM_WINDOWPOSCHANGED = 9, ABM_SETSTATE = 10 } [StructLayout(LayoutKind.Sequential)] public struct APPBARDATA { public int cbSize; public IntPtr hWnd; public int uCallbackMessage; public int uEdge; public RECT rc; public bool lParam; } [StructLayout(LayoutKind.Sequential)] public struct MINMAXINFO { public POINT ptReserved; public POINT ptMaxSize; public POINT ptMaxPosition; public POINT ptMinTrackSize; public POINT ptMaxTrackSize; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO { public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); public RECT rcMonitor = new RECT(); public RECT rcWork = new RECT(); public int dwFlags = 0; } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int x; public int y; public POINT(int x, int y) { this.x = x; this.y = y; } } [StructLayout(LayoutKind.Sequential, Pack = 0)] public struct RECT { public int left; public int top; public int right; public int bottom; } }}
- Custom Window Style and Accounting for the Taskbar
- Create custom checkbox style button for iPhone
- three main situations and corresponding recommendations for building your custom extensions to the E-Business Suite
- The RightCoding Style for JAVA
- What's the difference between windowBackground and background for activities style?
- Tailor Your DataGrid Apps Using Table Style and Custom Column Style Objects
- Preparing for Application and Service Deployment-Differences Between the Storage Emulator and Window
- Drawing a Custom Mainframe Window for MFC SDI Applications
- the difference between imperative style and functional style
- Notes for Accounting II
- coding style for the linux kernel
- coding style for the linux kernel
- Window Style
- Window Style
- 《The Accounting Game》读书笔记
- Jscalendar popup window is hidden in top of the screen for IE7 and XP
- Custom Sublime Text Build Systems For Popular Tools And Languages
- useful function & operator & custom operator for Row and Array Comparisons
- 在 CentOS 6.5 上安装和配置 Xen
- forEach方法(原生js学习)
- 分布式文件系统FastDFS原理介绍
- 应对编程困难的JAVA小技巧
- Json学习
- Custom Window Style and Accounting for the Taskbar
- poj 2481 Cows(线段树)
- 用UIPickerView制作密码锁
- Spark + Flume
- 如何把选择屏幕放到标准屏幕上
- EL表达式-----$
- perl 调试
- apple个人开发者证书无线发布app的实现
- http响应状态码大全