Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WPF-практика 4 Двумерная графика.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
1.03 Mб
Скачать

Упражнение 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. Это разные перечисления и их нельзя путать.

  • Попробуйте разобраться с кодом