Опубликован: 28.04.2009 | Доступ: свободный | Студентов: 1838 / 107 | Оценка: 4.36 / 4.40 | Длительность: 16:40:00
Специальности: Программист
Лекция 4:

Хранитель экрана

4.5.1. Центрирование диалогового окна относительно Display Properties

Для выравнивания диалогового окна по центру окна Display Properties необходимо определить положение этого самого окна Display Properties на экране. Здесь самое время вспомнить о том, что при запуске хранителя экрана диалоговое окно Display Properties передает ему в качестве параметра свой дескриптор. Ну а немного поколдовав с Win32 API над дескриптором окна, можно легко получить об этом окне практически любую информацию.

Для начала мы добавим в класс диалогового окна еще один конструктор, принимающий в качестве параметра дескриптор окна Display Properties (листинг 4.17).

public partial class SettingsForm : Form
{
// Необходимо ли центрировать окно параметров относительно окна Display Properties. По
// умолчанию центрирование не выполняется
bool center = false; 
// Дескриптор окна Display Properties
IntPtr parentHandle;
public SettingsForm(IntPtr parentHandle):this() 
{
// Запоминаем дескриптор
this.parentHandle
= parentHandle;
// Включаем центрирование
 center = true; 
}
}
Листинг 4.17.

Чтобы задействовать новый конструктор в коде функции Main необходимо реализовать более детальный разбор параметров с выделением из ключа вида /C:n значения дескриптора (листинг 4.18).

static void Main() 
{
// Если приложение запущено без параметров (такое происходит, к примеру, при открытии окна 
// конфигурации при помощи контекстного меню) или с ключом "/C"
if ((args.Length == 1) || ((args.Length >= 2) && args[1].ToUpper() == "/C")) 
{ 
// Открываем диалоговое окно параметров приложения без центрирования
Application.Run(new SettingsForm()); return; 
}
// Если параметр хранителя экрана имеет вид /C:n
if ((args.Length == 2) && (args[1].Length > 3) &&
 (args[1].ToUpper().Substring(0, 3) == "/C:"))
{ 
// Выделяем из строки дескриптор окна и преобразуем его в значение типа IntPtr
IntPtr hWnd = (IntPtr)int.Parse(args[1].ToUpper().Substring(3, args[1].Length - 3));
// Открываем диалоговое окно с выравниванием по центру окна Display Properties с дескриптором 
// hWnd
Application.Run(new SettingsForm(hWnd)); 
}
}
Листинг 4.18.

Переходим к самому интересному - получению информации о положении окна по его дескриптору. Немного порывшись в MSDN мы обнаружим требуемую нам функцию:

BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);

где

  • hWnd - дескриптор окна;
  • lpRect - указатель на структуру rect, в которую заносятся координаты верхнего левого и нижнего правого углов окна.

К сожалению .NET Framework 2.0 не содержит ни определение функции GetWindowRect, ни структуры rect, так что нам придется определять их самим. Однако все не так уж и плохо - определения большинства структур и функций для платформы .NET Framework, включая GetWindowRect и rect, можно найти на сайте http://pinvoke.net. Так как методы Win32 API наверняка еще не один раз пригодиться нам, будет разумно вынести их в отдельный статический класс Win32 (листинг 4.19). Дополнительным плюсом подобного подхода является простая идентификация в тексте программы вызовов методов Win32, являющихся потенциальными источниками проблем при переносе приложения на другие платформы (например, на x64 или Xbox 360 ).

// Определения функций Win32 API, написанные на основе
 материалов сайта http://pinvoke.net
using System.Runtime.InteropServices;
public static class Win32
{
// Структура RECT
[StructLayout(LayoutKind.Sequential)]
 public struct RECT 
{
public int left; public
 int top; public int 
right; public int 
bottom;
// Добавляем "от себя" два свойства, позволяющие
 легко определить ширину и высоту
области public int Width { get { return right - left + 1;
 }
 }
 public int Height { get 
{
return bottom - top + 1; 
} 
} 
}
// Возвращает координаты окна
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
}
Листинг 4.19.

И, наконец, последний штрих - реализация в обработчике Load диалогового окна выравнивания по центру окна Display Properties (листинг 4.20).

private void SettingsForm_Load(object sender, EventArgs e) 
{
if (center) 
{ 
// Создаем структуру RECT
Win32.RECT rect = new Win32.RECT(); 
// Получаем информацию о местоположении окна Display Properties
Win32.GetWindowRect(parentHandle, out rect);
// Вычисляем координаты центра окна Display Properties int
centerX = (rect.right + rect.left) / 2; int centerY
= (rect.bottom + rect.top) / 2;
// Позиционируем наше диалоговое окно по центру окна Display Properties
Left = centerX - Width / 2;
Top = centerY - Height / 2; 
} 
}
Листинг 4.20.

Готовое приложение можно найти в example.zip в каталоге Examples\Ch04\Ex05.

Андрей Леонов
Андрей Леонов

Reference = add reference, в висуал студия 2010 не могу найти в вкладке Solution Explorer, Microsoft.Xna.Framework. Его нету.