При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.Xna.Framework.Graphics;
namespace Application1 { public partial class MainForm : Form { // Объявим поле графического устройства для видимости в методах GraphicsDevice device;
public MainForm() { InitializeComponent();
// Подпишемся на событие Load формы this.Load += new EventHandler(MainForm_Load);
// Попишемся на событие FormClosed формы this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed); }
void MainForm_FormClosed(object sender, FormClosedEventArgs e) { // Удаляем (освобождаем) устройство device.Dispose(); // На всякий случай присваиваем ссылке на устройство значение null device = null; }
void MainForm_Load(object sender, EventArgs e) { // Создаем объект представления для настройки графического устройства PresentationParameters presentParams = new PresentationParameters(); // Настраиваем объект представления через его свойства presentParams.IsFullScreen = false; // Включаем оконный режим presentParams.BackBufferCount = 1; // Включаем задний буфер // для двойной буферизации // Переключение переднего и заднего буферов // должно осуществляться с максимальной эффективностью presentParams.SwapEffect = SwapEffect.Discard; // Устанавливаем размеры заднего буфера по клиентской области окна формы presentParams.BackBufferWidth = this.ClientSize.Width; presentParams.BackBufferHeight = this.ClientSize.Height;
// Создадим графическое устройство с заданными настройками device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle, presentParams); }
protected override void OnPaint(PaintEventArgs e) { device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
base.OnPaint(e); } } } Выбрасывается исключение: Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Графика в WPF
Упражнение 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); } }