Сайт разработчика Александр Климова

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Вопрос-ответ

Не нужно изобретать велосипед, лучше катайтесь на нем. Возможно, ваш вопрос, над решением которого вы давно бьетесь, давно решен. Воспользуйтесь этой страницей для поиска ответа.

Не изобретайте велосипед

Графика

Получить список установленных принтеров

C помощью свойства InstalledPrinters класса PrinterSettings можно получить список установленных принтеров. При запуске программы выводим в выпадающем списке список всех установленных принтеров. Для этого проходим в цикле через коллекцию System.Drawing.Printing.PrinterSettings.InstalledPrinters и добавляем имя принтера в ComboBox (cboPrinter).


private void Form1_Load(object sender, EventArgs e)
{
    foreach (string printer in PrinterSettings.InstalledPrinters)
    {
        cboPrinter.Items.Add(printer);
    }
}

Пример получения более детальной информации о принтерах смотрите в разделе Графика.

Мультимедиа

Как воспроизвести системные звуки

В .NEТ Framework 2.0 появился класс System.Media.SystemSounds, при помощи которого можно воспроизвести системные звуки Asterisk, Beep, Exclamation, Hand, Question.


System.Media.SystemSounds.Asterisk.Play();
System.Media.SystemSounds.Beep.Play();
System.Media.SystemSounds.Exclamation.Play();
System.Media.SystemSounds.Hand.Play();
System.Media.SystemSounds.Question.Play();

WinForms

Как отслеживать момент блокировки и разблокировки компьютера

Момент блокировки или разблокировки компьютера можно отлавливать при помощи события SystemEvents.SessionSwitch.


private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
    //If the reason for the session switch is lock or unlock 
    //send the message to mute or unmute the system volume
    if (e.Reason == SessionSwitchReason.SessionLock)
    {
        SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
           (IntPtr)APPCOMMAND_VOLUME_MUTE); 
    }
    else if (e.Reason == SessionSwitchReason.SessionUnlock)
    {
        SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
            (IntPtr)APPCOMMAND_VOLUME_MUTE); 
    }
}

В этом примере при блокировке компьютера автоматически выключается микшер при помощи сообщения WM_APPCOMMAND. При разблокировке микшер включается снова.

Установлен ли пакет Excel на компьютере пользователя

При установке Excel в реестре прописываются определенные ключи. Можно считывать их для своей проверки.


using Microsoft.Win32
RegistryKey hkcr = Registry.ClassesRoot; 
RegistryKey excelKey = hkcr.OpenSubKey("Excel.Application"); 
bool excelInstalled = excelKey == null ? false : true;
MessageBox.Show(excelInstalled.ToString());

Как сделать первые символы слов заглавными

Для этой цели подойдет метод TextInfo.ToTitleCase.

Как из Bitmap получить Icon?

Используйте метод Bitmap.GetHicon


const string FileName = @"E:\sample\cat.png";  // ваш путь к графическомоу файлу

using (Bitmap bitmap = (Bitmap)Image.FromFile(FileName))
{
    IntPtr hIcon = bitmap.GetHicon();
    this.Icon = Icon.FromHandle(hIcon);  
}

Интернет

Работаем с FTP

В статье (англ.) показан простой пример закачки файла на FTP-сервер. Исходник прилагается.

Узнать размер файла, не скачивая его

Когда мы пытаемся скачать какой-нибудь файл, то видим в диалоговом окне, какого размера выбранный файл и стоит ли его качать. Для этого нам нужно знать URL-адрес нужного файла. Код для кнопки (также добавьте текстовое поле для URL):


using System.Net;

if (textBox1.Text == "")
{
    MessageBox.Show("Вы не ввели адрес файла", "URL Error", 
			MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else              
{                
    string URL = textBox1.Text;
    // получим тип файла (расширение)
    string filetype = URL.Substring(URL.LastIndexOf(".") + 1, 
			(URL.Length - URL.LastIndexOf(".") - 1));
    labelFileType.Text = filetype.ToUpper();

    // имя файла
    string filename = URL.Substring(URL.LastIndexOf("/") + 1, 
			(URL.Length - URL.LastIndexOf("/") - 1));
    labelFileName.Text = filename;

    WebRequest req = HttpWebRequest.Create(textBox1.Text);
    req.Method = "HEAD";
    WebResponse resp = req.GetResponse();

    long ContentLength = 0;
    long result;

    if (long.TryParse(resp.Headers.Get("Content-Length"), out ContentLength))
    {
        string File_Size;                   
        
        if (ContentLength >= 1073741824)
        {
            result = ContentLength / 1073741824;
            labelSize.Text = "GB";
        }
        else if (ContentLength >= 1048576)
        {
            result = ContentLength / 1048576;
            labelSize.Text = "MB";
        }
        else
        {
            result = ContentLength / 1024;
            labelSize.Text = "KB";                        
        }

        // Выводим размер файла
        File_Size = result.ToString("0.00");
        sizevaluelabel.Text = File_Size;
    }
} 

Получить IP-адрес, псевдоним и реальное имя сайта

Чтобы получить IP-адрес из имени сайта, воспользуйтесь методом GetHostEnry. Для одного имени хоста может быть сконфигурировано несколько IP-адресов. Поэтому, метод GetHostEntry может возвратить массив IP-адресов, а также псевдонимы и само имя хоста. В следующем примере мы получим IP-адрес для имени хоста www.google.ru, затем с помощью свойства AddressList выведем все IP-адреса (массив объектов IPAddress). Далее при помощи свойства Aliases получим список псевдонимов (если есть), а также настоящее имя хоста.


using System.Net;

string hostname = "www.google.ru";

IPHostEntry entry = Dns.GetHostEntry(hostname);

Console.WriteLine("IP-адреса для {0}: ", hostname);

foreach (IPAddress address in entry.AddressList)
    Console.WriteLine(address.ToString());

Console.WriteLine("Псевдонимы: ");

foreach(string aliasName in entry.Aliases)
    Console.WriteLine(aliasName);

Console.WriteLine("Настоящее имя хоста: " + entry.HostName);

Как получить хост, порт, протокол и другие свойства из веб-адреса

С помощью свойств классов System.Uri и System.UriBuilder можно легко получить необходимую информацию из веб-адреса.


Uri sitename = new Uri("http://developer.alexanderklimov.ru:80/test.txt?name&price"); // адрес
Console.WriteLine(sitename.Scheme);  //схема (http)
Console.WriteLine(sitename.Segments[0]);  // сегмент
Console.WriteLine(sitename.AbsoluteUri);  // абсолютный URI. Если порт 80, то он не выводится
Console.WriteLine(sitename.Fragment);  // фрагмент
Console.WriteLine(sitename.LocalPath); // локальный путь. для HTTP-запроса совпадает с AbsolutePath
Console.WriteLine(sitename.Query); // строка после пути (?name&price)
Console.WriteLine(sitename.PathAndQuery);  // комбинация пути и строки запроса (test.txt?name&price)

Подключен ли компьютер к интернету?

Определить, подключен ли компьютер к интернету, можно при помощи метода NetworkInterface.GetIsNetworkAvailable. Следует заметить, что если компьютер подключен к локальной сети, то этот способ окажется бесполезным, так как ваша машина может иметь подключение к сети, но не иметь выхода в интернет. В этом случае попробуйте воспользоваться функцией Windows API InternetGetConnectedState, которая описана в моей книге C#.Cоветы программистам или в справочнике по функциям Windows API.


MessageBox.Show("Наличие подключения: " + 
    System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable().ToString());

Как создать ссылку (*.url) на страницу в Интернете

Ссылка Интернета является текстовым файлом с расширением URL и с определенной структурой записи, схожей с конфигурационными файлами INI. Вы можете программно создать такую ссылку, скажем, на Рабочем столе


//  Функция-обертка для создания ссылки интернета 
private void CreateInternetShortCut(string FileName, string URL)
{
    using (StreamWriter sw = new StreamWriter(FileName))
    {
        sw.WriteLine("[InternetShortcut]");
        sw.WriteLine("URL=" + URL);
        sw.WriteLine();

    }
}

private void Form1_Load(object sender, EventArgs e)
{
    // У вас будет свой путь к файлу
    CreateInternetShortCut(@"d:\mysite.url", "http://developer.alexanderklimov.ru");
}

Файлы

Как удалить файл с атрибутом только для чтения?

Используйте класс System.IO.FileInfo для получения атрибутов файла. Пример справедлив и для .NET Compact Framework


System.IO.FileInfo fi = new System.IO.FileInfo("filename");
// удаляем атрибут только для чтения
if ((fi.Attributes & System.IO.FileAttributes.ReadOnly) != 0)
    fi.Attributes -= System.IO.FileAttributes.ReadOnly;

System.IO.File.Delete("filename");

Установить дату и время создания файла и последней операции записи в файл

Вы можете самостоятельно изменить дату и время создания файла и последней операции записи в файл, если по каким-то причинам вас не устраивает дата и время, установленной системой. Для этого используются методы File.SetCreationTime и File.SetLastWriteTime.


// Меняем дату создания файла.
// path содержит путь к файлу
File.SetCreationTime(path, new DateTime(2008, 4, 6));
// Меняем дату последней операции записи в файл
File.SetLastWriteTime(path, new DateTime(2008, 5, 9));

Запрет на запуск второй копии программы

Многие программы запускаются в одном экземпляре: Outlook, ICQ и т.д. Если вам нужна подобная функциональность, то воспользуйтесь классом Mutex из пространства имен System.Threading. Если при старте программы мьютекс уже существует, значит программа уже запущена. Для удобства выводим соответствующее сообщение. Этот код можно поместить в Program.cs


bool onlyInstance;

Mutex mtx = new Mutex(true, "AppName", out onlyInstance); // используйте имя вашего приложения

// If no other process owns the mutex, this is the
// only instance of the application.
if (onlyInstance)
{
   Application.Run(new Form1());
}
else
{
   MessageBox.Show(
      "Приложение уже запущено",
      "Сообщение",
      MessageBoxButtons.OK, MessageBoxIcon.Stop);
}

Смотри также статью Запуск одного приложения

Использование клавиши-модификатора Ctrl для кнопки

Предположим, при нажатии на кнопку у нас выводится сообщение Здравствуй, друг, а если пользователь будет при этом держать нажатой клавишу Ctrl, то тогда будет выводиться сообщение Hello, friend. Чтобы при нажатии на кнопку выполнялись разные действия, прибегнем к следующему трюку.


private bool controlkeypressed = false;

private void button1_KeyDown(object sender, KeyEventArgs e)
{
    if(e.KeyCode == Keys.ControlKey)
    {
        controlkeypressed = true;
    }
}

private void button1_KeyUp(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.ControlKey)
    {
        controlkeypressed = false;
    }
}

private void button1_Click(object sender, EventArgs e)
{
    if (controlkeypressed)
    {
        MessageBox.Show("Hello, friend!");
    }
    else
    {
        MessageBox.Show("Здравствуй, друг");
    }
}

Как использовать системные значки

В составе .NET Framework есть класс SystemIcons, с помощью которого можно получить доступ к системным значкам Windows. Например, в Windows Vista появился новый значок Shield (щит), используемый в UAC. Чтобы показать этот значок на форме, используйте код:


using (Graphics g = CreateGraphics())
{
    g.DrawIcon(SystemIcons.Shield, 20, 30);
}

Если вам необходимо получить все системные значки Windows, то лучше это делать через отражение (нашел в MSDN Magazine):


using System.Reflection;

// Получаем PropertyInfo для всех статических
// свойств SystemIcons
PropertyInfo[] props = typeof(SystemIcons).GetProperties(BindingFlags.Public | BindingFlags.Static);
Graphics g = CreateGraphics();

int y = 0;
// Отображаем каждый значок. Все статические члены
// получаем через отражение — класс!
//
foreach (PropertyInfo p in props)
{
    Object obj = p.GetValue(null, null);
    if (obj.GetType() == typeof(Icon))
    {
        Icon icon = (Icon)obj;
        g.DrawIcon(icon, 0, y);
        g.DrawString(String.Format("SystemIcons.{0}",
        p.Name), new Font("Arial", 12), Brushes.Blue, icon.Width + 2, y);
        y += icon.Height;
    }
}
g.Dispose();

Как укоротить длинный путь к файлу

Если вам необходимо показать путь к файлу, например, в MessageBox, то слишком длинная строка будет выглядеть не очень красиво. Можно укоротить ее определенным образом, оставив названия первых двух папок, последнюю папку и имя файла. А среднюю часть путь можно заменить многоточием (...). Воспользуемся для этой цели регулярным выражением.


static string PathShortener(string path)
{
    const string pattern = @"^(\w+:|\\)(\\[^\\]+\\[^\\]+\\).*(\\[^\\]+\\[^\\]+)$";
    const string replacement = "$1$2...$3";
    if (Regex.IsMatch(path, pattern))
    {
        return Regex.Replace(path, pattern, replacement);
    }
    else
    {
        return path;
    }
} 

Теперь, вы можете вызвать данный метод для укорачивания длинного пути.


string myPath = @"C:\Documents\jatwood\SimpleEncryption\UnitTests\wumpus\public\Hilo Final\Introduction\Code\App_Themes\cellphone\photo-small.jpg";
            
MessageBox.Show(PathShortener(myPath));

У вас выведется путь: C:\Documents and Settings\jatwood\...\cellphone\photo-small.jpg (Источник: Coding Horror).
Существует еще вариант с использованием функции Windows API PathCompactPathEx, описаный в книге C#. Советы программистам. Системная функция работает по другому алгоритму, поэтому вы можете выбрать удобный для вас способ.

Как определить версию операционной системы

На данный момент Windows Vista SP1 и Windows Server 2008 имеют одинаковые номера 6.0.6001. Поэтому, чтобы различать эти системы, нужно прочитать дополнительно значения из реестра.


private const string  REG_PRODUCT_KEY = @"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion";

private string GetOSVersion()
{
    OperatingSystem osInfo = Environment.OSVersion;
    string osName = "Не определено";

    switch (osInfo.Platform)
    {
         case PlatformID.Win32NT:
            {
                switch (osInfo.Version.Major)
                {
                    
                   case 5:
                        {
                            if (osInfo.Version.Minor == 0)
                            {
                                osName = "Windows 2000";
                            }
                            else if (osInfo.Version.Minor == 1)
                            {
                                osName = "Windows XP";
                            }
                            else if (osInfo.Version.Minor == 2)
                            {
                                osName = "Windows Server 2003";
                            }
                            break;
                        }

                   case 6:
                        {
                            string info = 
                                Microsoft.Win32.Registry.GetValue(REG_PRODUCT_KEY, "ProductName", "").ToString();
                            if (info.ToLower().Contains("vista"))
                            {
                                osName = "Windows Vista";
                            }
                            if (info.ToLower().Contains("server"))
                            {
                                osName = "Windows 2008";
                            }

                            break;
                        }
                }
                break;
            }
    }

    return osName;
}

private void butGetOS_Click(object sender, EventArgs e)
{
    MessageBox.Show(GetOSVersion());
}

Упрощенный вариант, когда нужно показать, что требуется система от Windows XP и выше.


// Требуется система от Windows XP и выше
if (Environment.OSVersion.Version < new Version(5, 1))
{
    MessageBox.Show("Требуется Windows XP и выше.", 
         "Несовместимость операционной системы", MessageBoxButtons.OK,
                MessageBoxIcon.Error);
    return;
}

Как получить серийный номер материнской платы

Через WMI


// Добаввить ссылку на System.Management.
using System.Management;

private string GetMotherBoardSerialNumber()
{
    string result = null;
    string query = "SELECT * FROM Win32_BaseBoard";
    ManagementObjectSearcher searcher =
        new ManagementObjectSearcher(query);
    foreach (ManagementObject info in searcher.Get())
    {
        result = info.GetPropertyValue("SerialNumber").ToString();
    }

    return result;
}

private void butGetBoardNumber_Click(object sender, EventArgs e)
{
    txtSerialNumber.Text = GetMotherBoardSerialNumber();
}

Как заставить говорить компьютер

В .NET Framework 3.0 появилось новое пространство имен System.Speech, с помощью которого можно заставить компьютер говорить. Добавьте ссылку на System.Speech в проекте и напишите следующий код.


using System.Speech.Synthesis;

SpeechSynthesizer synth = new SpeechSynthesizer();
synth.Speak("I love .NET Framework!");

Получить список языковых движков

В продолжение предыдущей темы - консольное приложение, которое получает список установленных TTS-движков и их свойства. Не забываем добавить ссылку на System.Speech. (Источник)


using System;
using System.Collections.Generic;
using System.Speech;
using System.Speech.Synthesis;
using System.Speech.AudioFormat;

namespace SelectVoice
{
  class SelectVoice
  {
    static void Main(string[] args)
    {
      Console.WriteLine("SelectVoice Example");
      SpeechSynthesizer ttsSynth = new SpeechSynthesizer();

      Console.WriteLine("Listing installed speech synthesizer voices...");
      foreach (InstalledVoice ttsVoice in ttsSynth.GetInstalledVoices())
      {
        Console.WriteLine("Name:\t{0}", ttsVoice.VoiceInfo.Name);
        Console.WriteLine("Desc:\t{0}", ttsVoice.VoiceInfo.Description);
        Console.WriteLine("Id:\t{0}", ttsVoice.VoiceInfo.Id);
        Console.WriteLine("Gender:\t{0}", ttsVoice.VoiceInfo.Gender);
        Console.WriteLine("Age:\t{0}", ttsVoice.VoiceInfo.Age);

        Console.WriteLine("Supported Audio Formats:");
        foreach (SpeechAudioFormatInfo audioFormat in ttsVoice.VoiceInfo.SupportedAudioFormats)
        {
          Console.WriteLine("\tEncodingFormat:\t{0}", audioFormat.EncodingFormat);
          Console.WriteLine("\tChannelCount:\t{0}", audioFormat.ChannelCount);
          Console.WriteLine("\tBits/sec:\t{0}", audioFormat.BitsPerSample);
          Console.WriteLine("\tAvg Bytes/sec:\t{0}", audioFormat.AverageBytesPerSecond);
          Console.WriteLine("\tSamples/sec:\t{0}", audioFormat.SamplesPerSecond);
          Console.WriteLine("\tBlockAlign:\t{0}", audioFormat.BlockAlign);
        }

        Console.WriteLine("Additional Information:");
        foreach(KeyValuePair<string, string> kvp in ttsVoice.VoiceInfo.AdditionalInfo)
          Console.WriteLine("\t{0}:  {1}", kvp.Key, kvp.Value);
        Console.WriteLine();
      }
    Console.WriteLine("Finished listing installed voices.");

    ttsSynth.SelectVoice("Microsoft Anna");
    ttsSynth.Speak("Greetings, my name is " + ttsSynth.Voice.Name);    }
  }
}

Как создавать zip-архивы

Существут много способов архивации файлов. Предлагаю воспользоваться библиотекой DotNet Zip, которую можно найти по адресу http://www.codeplex.com/DotNetZip Вы можете скачать готовую библиотеку, исходный код, документацию, инсталлятор. На сегодняшний день библиотека DotNet Zip имет версию 1.9. Библиотека также работает в .NET Compact Framework. Чтобы воспользоваться этой библиотекой, необходимо добавить ссылку на Ionic.Utils.Zip и написать, например, такой код:


using (ZipFile zip = new ZipFile("MyZipFile.zip")
{
    zip.AddFile(@"c:\photos\cat.jpg");
    zip.AddFile(@"c:\Desktop\kitty.jpg");
    zip.AddFile("ReadMe.txt");
    zip.Save();
}

Экран и формы

Как узнать размеры экрана

Чтобы узнать ширину и высоту текущего экрана, воспользуйтесь свойством SystemInformation.PrimaryMonitorSize следующим образом:


textBox1.Text = SystemInformation.PrimaryMonitorSize.Width.ToString() + "X" + 
    SystemInformation.PrimaryMonitorSize.Height.ToString();

Второй способ через использование свойства PrimaryScreen.Bounds класса Screen описан в книге C#.Советы программистам

Как определить рабочую область экрана без панели задач

Иногда требуется узнать размеры не всего экрана, а только его рабочей части, в которую не входит панель задач, а также другие экранные панели (например, существовал пакет MS Office, который использовал собственную панель). В этом случае вам поможет свойство Screen.GetWorkingArea, способное определить рабочую область экрана без панели задач:


// Определяем рабочую область экрана
textBox1.Text = Screen.GetWorkingArea(this).Width.ToString() + "x" + Screen.GetWorkingArea(this).Height.ToString();

Соответственно, чтобы форма заполнила весь экран, можно использовать код:


this.Bounds = Screen.PrimaryScreen.WorkingArea;
this.StartPosition = (FormStartPosition.CenterScreen);

Даже при растягивании и перемещении панели задач в другие места экрана, приложение при загрузке всегда будет занимать только рабочую область экрана.

Form.Close() или Application.Exit() - Какой метод лучше использовать для выхода из программы

Когда вы закрываете приложение программно, например, из меню Файл | Выход , то должны использовать метод Form.Close() (this.Close()) вместо Application.Exit(). Вызов метода Application.Exit - это грубое принудительное закрытие окна, при этом не возникают события Form.Closed или Form_Closing. (Справедливо и для .NET Compact Framework)

Установить фоновый рисунок у родительской MDI-формы

Установка фонового рисунка для родительской MDI-формы достигается одной строчкой кода - достаточно присвоить его свойству BackgroundImage нужное значение. В свойстве BackgroundImageLayout можно задать способ вывода фонового рисунка: плитка, растянуть во весь экран, расположить в центре и т.д.

Дата и время

Перевести дату в число

Предположим, у нас есть дата в виде 27.07.1966 12:34:45, а мы хотим получить ее в виде числа 27071966123445


MessageBox.Show(System.DateTime.Now.ToString("ddMMyyyyhhmmss"));

Мы получим строку в нужном представлении и можем дальше работать с ней.

Сколько секунд содержится в минутах, часах, сутках

Используя свойство TotalSeconds, можно узнать, сколько секунд содержится в минутах, часах, сутках


// вместо того, чтобы вычислять сколько секунд в одном часе
// int totalseconds = 1 * 60 * 60;
int totalseconds;
totalseconds = (int)TimeSpan.FromMinutes(2).TotalSeconds; // сколько секунд в 2 минутах
Console.WriteLine(totalseconds);

totalseconds = (int)TimeSpan.FromHours(1).TotalSeconds;  // сколько секунд в 1 часе
Console.WriteLine(totalseconds);

totalseconds = (int)TimeSpan.FromDays(1).TotalSeconds;  // сколько секунд в сутках
Console.WriteLine(totalseconds);

Получить маркер текущего процесса

Пример из книги Защищенный код для Windows Vista


using System.Security;
using System.Security.Principal;

try
{
    WindowsIdentity id = WindowsIdentity.GetCurrent();
    IntPtr token = id.Token;
    // мы получили маркер и выводим на экран
    Console.WriteLine(token.ToString());
}
catch (SecurityException e)
{
    Console.WriteLine(e.Message);
}

Узнать редакцию Windows Vista

Чтобы узнать редакцию Windows Vista (Home Basic, Business и т.д.), нужно вызвать функцию Windows API GetProductInfo.

Преобразовать bytes[] в IO.Stream и наоборот


public static class StreamConverter
{
    public static Stream ToStream(byte[] bytes)
    {
        return new MemoryStream(bytes);
    }

    public static byte[] ToBytes(Stream stream)
    {
        long initialPosition = stream.Position;
        stream.Position = 0;
        byte[] bytes = new byte[stream.Length];
        stream.Read(bytes, 0, bytes.Length);
        stream.Position = initialPosition;

        return bytes;			
    }
}
Реклама