Опубликован: 11.09.2006 | Доступ: свободный | Студентов: 7326 / 281 | Оценка: 4.26 / 3.45 | Длительность: 30:46:00
ISBN: 978-5-9556-0080-2
Лекция 5:

Использование библиотек кода в windows-формах

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >

Получение имени пользователя. Библиотека secur32.dll

Итак, приступим к практике. Создайте новое Windows-приложение и назовите его GetUserName. Перетаскиваем на форму из окна ToolBox кнопку и надпись. Устанавливаем следующие свойства формы и элементов управления:

Form1, форма, свойство Значение
Size 560; 96
Text Получение имени пользователя
label1, свойство Значение
Name lblGetUserName
Location 168; 20
Size 368; 23
Text
Button1, свойство Значение
Name btnGetUserName
Location 16; 20
Text Получить!

В окне Solution Explorer щелкаем правой кнопкой на названии проекта и выбираем Add\Add New Item…. В появившемся окне шаблонов выбираем класс и называем его WinAPIClass.cs. Переходим в его код и добавляем пространство имен для работы с библиотеками dll и объектом StringBuilder:

using System;
using System.Runtime.InteropServices;
using System.Text;

Обращаемся к библиотеке secur32.dll и создаем метод GetUserNameEx (привожу пространство имен класса полностью 11Конструктор класса был удален ):

namespace GetUserName
{
		public class WinAPIClass
	{
		#region Получение имени текущего пользователя
		/// <summary>
		/// Получение имени текущего пользователя.
		/// </summary>
		/// <param name="nameFormat">Формат имени из перечисления NameFormat.</param>
		/// <param name="userName">Выходной параметр — имя.пользователя</param>
		/// <param name="userNameSize">Количество символов в имени.</param>
		/// <returns></returns>
		//Подключение библиотеки secur32.dll
		[DllImport("secur32.dll", CharSet=CharSet.Auto)]
		public static extern int GetUserNameEx (int nameFormat, StringBuilder userName, ref uint userNameSize);
		
		/// <summary>
		/// Формат имени.
		/// </summary>
		public enum NameFormat:int
		{
			NameUnknown = 0,
			NameFullyQualifiedDN = 1,
			NameSamCompatible = 2,
			NameDisplay = 3,
			NameUniqueId = 6,
			NameCanonical = 7,
			NameUserPrincipal = 8,
			NameCanonicalEx = 9,
			NameServicePrincipal = 10,
			NameDnsDomain = 12
		};
		#endregion
	
	}
}
Листинг 5.1.

Все! Класс, использующий функцию WinAPI, готов. В обработчике кнопки btnGetUserName обращаемся к созданному классу:

private void btnGetUserName_Click(object sender, System.EventArgs e)
	{
	StringBuilder builder = new StringBuilder(100);
	uint size = 100;
WinAPIClass.GetUserNameEx((int)WinAPIClass.NameFormat.NameSamCompatible, builder, ref size);
	lblGetUserName.Text = String.Format("Имя пользователя: {0}", builder.ToString());
	}

Обратите внимание на то, что в качестве значения перечисления идет тип данных int, объект StringBuilder передается в качестве строки и к последнему параметру добавляется ключевое слово ref, т.к. параметр передается по ссылке. Результатом запуска приложения будет определение имени текущего пользователя (рис. 5.1).

Результат запуска приложения GetUserName

Рис. 5.1. Результат запуска приложения GetUserName

Класс WinAPIClass, в котором происходит обращение к библиотеке secur32.dll, мог быть написан на другом, C-подобном языке, в оригинале он был реализован именно на C. Интересно сравнить типы данных двух листингов объявления методов:

  • Метод GetUserNameEx на языке С
    BOOLEAN GetUserNameEx(
    EXTENDED_NAME_FORMAT 
    // формат имени
    NameFormat,  
    // буфер для названия
    LPTSTR lpNameBuffer, 
    // размер буфера для названия
    PULONG nSize  
     );
  • Метод GetUserNameEx на языке С#
    [DllImport("secur32.dll", CharSet=CharSet.Auto)]
    public static extern int GetUserNameEx 
    (int nameFormat, StringBuilder userName, 
    ref uint userNameSize);

Выбор типа данных может повлиять на выполнение преобразования входящих и исходящих параметров. Например, в библиотеках WinAPI тип данных long — 32-битный, в то время как в C# тип данных long — 64-битный.

На диске, прилагаемом к книге, вы найдете приложение GetUserName (Code\Glava5\GetUserName).

Диалоговые окна. Библиотека user32.dll

Всякий раз, когда мы начинаем изучать новый язык программирования, в число первых примеров входит вывод текстовой строки на экран. Операционная система Windows содержит определенное число типов диалоговых окон, с помощью которых пользователь получает уведомления о различных событиях. Создайте новое Windows-приложение и назовите его MessageBox. Располагаем на форме четыре кнопки и устанавливаем следующие свойства формы и кнопок:

Form1, форма, свойство Значение
Size 232; 144
Text Message Box
Button1, свойство Значение
Name btnABORTRETRYIGNORE
Location 8; 8
Size 200; 23
Text Прервать Повторить Пропустить
Button2, свойство Значение
Name btnYESNOCANCEL
Location 8; 32
Size 200; 23
Text Да Нет Отмена
Button3, свойство Значение
Name btnOK
Location 8; 56
Size 200; 23
Text OK
Button4, свойство Значение
Name btnYESNO
Location 8; 80
Size 200; 23
Text Да Нет

Снова добавляем к проекту класс и называем его WinAPIClass.cs.

Листинг этого класса:

using System;
using System.Runtime.InteropServices;
namespace MessageBox
{
	
	public class WinAPIClass
	{
		#region Вызов диалогового окна MessageBox
		/// <summary>
		/// Вызов диалогового окна MessageBox.
		/// </summary>
		/// <param name="handle">Родительская форма окна</param>
		/// <param name="text">Текст окна.</param>
		/// <param name="title">Заголовок окна.</param>
		/// <param name="type">Тип окна.</param>		
		/// <returns></returns>
		[DllImport("user32.dll", CharSet=CharSet.Auto)]
		public static extern int MessageBox(IntPtr handle, string text, string title, uint type);
		/// <summary>
		/// Тип диалогового окна.
		/// </summary>
		public enum MessageBoxType:int
		{
			/// <summary>
			/// Три кнопки — Abort, Retry, Ignore
			/// </summary>
			MB_ABORTRETRYIGNORE = 2,
			/// <summary>
			/// Три кнопки — Cancel, Try, Continue
			/// </summary>
			MB_CANCELTRYCONTINUE = 6,			
			/// <summary>
			/// Одна кнопка — Ok.
			/// </summary>
			MB_OK = 0,
			/// <summary>
			/// Две кнопки — Ok, Cancel.
			/// </summary>
			MB_OKCANCEL = 1,
			/// <summary>
			/// Две кнопки — Retry, Cancel
			/// </summary>
			MB_RETRYCANCEL = 5,
			/// <summary>
			/// Две кнопки — Yes, No
			/// </summary>
			MB_YESNO = 4,
			/// <summary>
			///  Три кнопки — Yes, No, Cancel
			/// </summary>
			MB_YESNOCANCEL = 3,
			/// <summary>
			/// Иконка-восклицание
			/// </summary>
			MB_ICONEXCLAMATION = 0x30,
			/// <summary>
			/// Иконка-предупреждение
			/// </summary>
			MB_ICONWARNING = 0x30,
			/// <summary>
			/// Иконка-информация
			/// </summary>
			MB_ICONINFORMATION = 0x40,
			/// <summary>
			/// Иконка-вопрос
			/// </summary>
			MB_ICONQUESTION = 0x20,
			/// <summary>
			/// Иконка-стоп
			/// </summary>
			MB_ICONSTOP = 0x10,
			/// <summary>
			/// Иконка-ошибка
			/// </summary>
			MB_ICONERROR = 0x10,
					
		}
		/// <summary>
		/// Тип возвращаемого значения.
		/// </summary>
		public enum MessageBoxReturnType:int
		{
			IDABORT = 3,
			IDCANCEL = 2,
			IDCONTINUE = 11,
			IDIGNORE = 5,
			IDNO = 7,
			IDOK = 1,
			IDRETRY = 4,
			IDTRYAGAIN = 10,
			IDYES = 6
		}
		#endregion
	}
}
Листинг 5.2.

В перечислении MessageBoxType приводятся различные типы стандартных окон и иконок. В обработчиках кнопок выбираем несколько вариантов окон и иконок:

private void btnABORTRETRYIGNORE_Click(object sender, System.EventArgs e)
		{
			//Текст сообщения
			string text = "Hello World";
			//Заголовок окна
			string title = "From WinApi";
			// Тип данных IntPtr — указатель на объект. 
			WinAPIClass.MessageBox(IntPtr.Zero, text, title, (uint)(WinAPIClass.MessageBoxType.MB_ABORTRETRYIGNORE | WinAPIClass.MessageBoxType.MB_ICONQUESTION));
			
			
		}

		private void btnYESNOCANCEL_Click(object sender, System.EventArgs e)
		{
			string text = "Hello World";
			string title = "From WinApi";
		WinAPIClass.MessageBox(IntPtr.Zero, text, title, (uint)(WinAPIClass.MessageBoxType.MB_YESNOCANCEL | WinAPIClass.MessageBoxType.MB_ICONINFORMATION));
		}

		private void btnOK_Click(object sender, System.EventArgs e)
		{
			string text = "Hello World";
			string title = "From WinApi";
			WinAPIClass.MessageBox(IntPtr.Zero, text, title, (uint)(WinAPIClass.MessageBoxType.MB_OK | WinAPIClass.MessageBoxType.MB_ICONSTOP));
		
		
		}

		private void btnYESNO_Click(object sender, System.EventArgs e)
		{
			string text = "Hello World";
			string title = "From WinApi";
			WinAPIClass.MessageBox(IntPtr.Zero, text, title, (uint)(WinAPIClass.MessageBoxType.MB_YESNO | WinAPIClass.MessageBoxType.MB_ICONEXCLAMATION));
		
		
		}
Листинг 5.3.

Запускаем приложение. При нажатии на кнопки появляются соответствующие диалоговые окна (рис. 5.2).

Результат работы приложения MessageBox

Рис. 5.2. Результат работы приложения MessageBox

На языке С метод в обработчике будет выглядеть следующим образом (сравните преобразование типов данных!):

INT MessageBox(HWND hWnd, LPCTSTR lpText, 
LPCTSTR lpCaption, UINT uType);

На диске, прилагаемом к книге, вы найдете приложение MessageBox. (Code\Glava5\MessageBox).

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >
Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/