Упражнение 2. Имитация полноэкранного режима с отключением системных клавиш
Иногда может потребоваться перевести монитор в полноэкранный режим, чтобы получить стиль игровых программ или старого доброго DOS. Обычно в таком случае отключают и курсор, а все управление программой перекладывают на клавиатуру. Из существующих вариантов переключения в полноэкранный режим наиболее простой, это настроить окно window так:
window.WindowStyle = WindowStyle.None;window.ResizeMode = ResizeMode.NoResize; Но такой способ не убирает панель задач и не блокирует появление меню Пуск, которое также включает панель задач.
Есть более сложный способ, приведенный в "http://www.swart.ws/2009/03/kiosk-full-screen-wpf-applications.html", но он имеет те же недостатки.
Для достижения полной иллюзии режима FullScreen следует отключить системные клавиши, вызывающие панель задач и меню Пуск, и самый эффективный (на мой взгляд) способ приведен в "http://www.sql.ru/Forum/actualthread.aspx?tid=632552", которым мы и воспользуемся в данном упражнении.
Из приведенного в статье http://support.microsoft.com/kb/126449/ru сочетания клавиш мы воспользуемся только следующими вариантами:
- CTRL + ESC: открытие меню Пуск.
- Клавиша WIN: открытие меню Пуск.
- ALT + ESC: показать панель задач и переключать развернутые окна.
- ALT + TAB: переключение между программами.
Этого будет достаточно, чтобы поддерживать полноэкранный режим и одновременно не блокировать остальную функциональность клавиатуры.
- Добавьте к решению командой File/Add/New Project новый проект с именем FullScreen и назначьте его стартовым
увеличить изображение
- В панели Solution Explorer добавьте к корню проекта FullScreen новую папку Images командой контекстного меню Add/New Folder
- В панели Solution Explorer командой Add/Existing Item контекстного меню для папки Images скопируйте в нее файл flower2.jpg из прилагаемого каталога Source
- Определите в интерфейсной части окна следующий код
<Window x:Class="FullScreen.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" Background="Green" Loaded="Window_Loaded" KeyDown="Window_KeyDown" KeyUp="Window_KeyDown" > <Window.ContextMenu> <ContextMenu> <MenuItem Name="changeScreen" Click="MenuItem_Click" /> </ContextMenu> </Window.ContextMenu> <DockPanel> <Menu Name="menu" DockPanel.Dock="Top"> <MenuItem Header="File"> <MenuItem Header="Open" /> <MenuItem Header="Save" /> <MenuItem Header="SaveAs" /> <MenuItem Header="Exit" /> </MenuItem> <MenuItem Header="Edit"> <MenuItem Header="Cut" /> <MenuItem Header="Copy" /> <MenuItem Header="Paste" /> </MenuItem> </Menu> <Image Source="Images/flower2.jpg" Stretch="Uniform" /> </DockPanel></Window> Для настройки окна и его элементов мы применили синтаксис атрибута, а для создания каркаса контекстного меню - синтаксис тега свойства ( свойства зависимости, присоединенные свойства ). Атрибут Stretch элемента Image может принимать следующие значения:
- None - изображение масштабируется до естественного размера и в области просмотра справа внизу видно столько, сколько поместилось
- Fill - изображение масштабируется по всей области просмотра без соблюдения пропорций
- Uniform - изображение масштабируется с соблюдением пропорций, чтобы полностью поместиться в область просмотра
- UniformToFill - изображение масштабируется с соблюдением пропорций так, чтобы в область просмотра полностью вместился хотя бы один размер, а для другой стороны видно столько, сколько поместилось
Теперь необходимо создать обработчики для событий, выделеных в листинке, в файле присоединенного кода Window1.xaml.cs. Для этого:
- Найдите в разметке файла Window1.xaml атрибуты событий
- Loaded="Window_Loaded"
- KeyDown="Window_KeyDown"
- KeyUp="Window_KeyDown"
- Click="MenuItem_Click"
- В любом месте каждого из этих атрибутов щелкните правой кнопкой мыши и выполните команду Navigate to Event Handler.
Оболочка создаст обработчики с указанными именами, а если обработчик уже существует, то перейдет к нему.
- Заполните файл поддержки разметки Window1.xaml.cs следующим кодом
using System;using System.Collections.Generic;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes; namespace FullScreen{ public partial class Window1 : Window { // Объявляем как поля для видимости в функциях bool fullScreen = false;// Состояние экрана WindowStyle windowStyle; WindowState windowState; ResizeMode resizeMode; public Window1() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // Запоминаем начальные параметры окна windowState = this.WindowState; windowStyle = this.WindowStyle; resizeMode = System.Windows.ResizeMode.CanResizeWithGrip; this.ResizeMode = resizeMode; changeScreen.Header = "FullScreen"; } private void MenuItem_Click(object sender, RoutedEventArgs e) { FullScreen(); } private void FullScreen() { if (!fullScreen)// Переходим в полноэкранный режим { if (this.WindowState == WindowState.Maximized) { // Чтобы скрыть панель задач и не было мерцания this.Hide(); this.WindowState = WindowState.Normal; } App.Current.MainWindow.WindowStyle = WindowStyle.None;// Без заголовка App.Current.MainWindow.Topmost = true; // На передний план App.Current.MainWindow.WindowState = WindowState.Maximized;// Развернуть App.Current.MainWindow.ResizeMode = ResizeMode.NoResize;// Неизменяемое menu.Visibility = Visibility.Collapsed;// Скрываем меню HookSystemKeys.FunHook();// Запрещаем системные клавиши this.Visibility = Visibility.Visible; fullScreen = true; changeScreen.Header = "WindowScreen"; } else // Восстанавливаем оконный режим { this.WindowStyle = windowStyle; this.Topmost = false; this.WindowState = windowState; this.ResizeMode = resizeMode; menu.Visibility = Visibility.Visible;// Показываем меню HookSystemKeys.FunUnHook();// Освобождаем системные клавиши fullScreen = false; changeScreen.Header = "FullScreen"; } } private void Window_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) this.Close(); } }} В приведенном коде используется класс HookSystemKeys, который нам нужно подключить к приложению и который взят из "http://www.sql.ru/Forum/actualthread.aspx?tid=632552" (там же и описан).
- Добавьте к текущему проекту FullScreen командой Project/Add New Item новый файл с именем HookSystemKeys.cs
увеличить изображение
- Заполните файл HookSystemKeys.cs так
using System;using System.Diagnostics;using System.Runtime.InteropServices; // Для перечисления Keys using System.Windows.Forms; namespace FullScreen{ // Отключение системной клавиши // http://www.sql.ru/Forum/actualthread.aspx?tid=632552 class HookSystemKeys { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYUP = 257;// Отпускание любой клавиши private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; // Поддержка флагов состояния системных клавиш static bool CtrlKey, AltKey, WinKey; private static void StateKey(int vkCode, IntPtr wParam) { switch ((Keys)vkCode) { case Keys.LControlKey: case Keys.RControlKey: if (wParam == (IntPtr)WM_KEYUP) CtrlKey = false; else CtrlKey = true; break; case Keys.LMenu: case Keys.RMenu: if (wParam == (IntPtr)WM_KEYUP) AltKey = false; else AltKey = true; break; case Keys.LWin: case Keys.RWin: if (wParam == (IntPtr)WM_KEYUP) WinKey = false; else WinKey = true; break; } } // Общедоступная упаковка оригинала public static void FunHook() { _hookID = SetHook(_proc); } public static void FunUnHook() { UnhookWindowsHookEx(_hookID); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { int vkCode = Marshal.ReadInt32(lParam); StateKey(vkCode, wParam); if (WinKey // Системная || CtrlKey && (Keys)vkCode == Keys.Escape // Ctrl+Esc || AltKey && (Keys)vkCode == Keys.Escape // Alt+Esc || AltKey && (Keys)vkCode == Keys.Tab) // Alt+Tab { return (IntPtr)1; } else return CallNextHookEx(_hookID, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); }} - Командой Project/Add Reference добавьте к проекту ссылку на библиотеку System.Windows.Forms.dll, в которой находится перечисление Keys кодов клавиш
- Запустите проект FullScreen и испытайте построенную нами имитацию полноэкранного режима
Оконный и полноэкранный (уменьшенный масштаб) режимы будут выглядеть так
Главное меню мы создали для примера, чтобы показать, что его можно отключать в полноэкранном режиме. Переключение режимов выполняется вызовом контекстного меню по щелчку правой кнопки мыши на окне приложения. В полноэкранном режиме отключаются нежелательные для нас системные клавиши, которые могли бы привести к сбою режима:
- CTRL + ESC: открытие меню Пуск.
- Клавиша WIN: открытие меню Пуск.
- ALT + ESC: показать панель задач и переключать развернутые окна.
- ALT + TAB: переключение между программами.
В оконном режиме функциональность системных клавиш восстанавливается.
Для полного сходства можно было бы отключить мышь, но тогда все управление окном нужно будет возложить на клавиатуру. В нашем приложении мы для закрытия окна использовали клавишу Esc. Закрыть окно можно и системной комбинацией Alt+F4, которую мы не отключали. Осталась активной комбинация Alt+Space, вызывающая системное меню приложения.
Мы использовали в классе HookSystemKeys перечисление System.Windows.Forms.Keys библиотечной сборки System.Windows.Forms, а в обработчике Window_KeyDown - перечисление System.Windows.Input.Key библиотечной сборки WindowsBase.dll. Это разные перечисления и их нельзя путать.
- Попробуйте разобраться с кодом
Дата добавления: 2015-04-15; просмотров: 1029;