Блог

  • SmallSoft Decoder Pack 1.1

    Скачать на Github Releases
    Исходный код
    Этот проект довольно старый, но, судя по статистике, его еще кто-то скачивает, поэтому я решил выложить новую версию с небольшими изменениями:
    — Добавлена справка в формате HTML
    — Добавлена регистрация Small Media Player для программ по умолчанию
    — Версия Small Media Player обновлена до 2.6
    — Версия SmallSoft Multimedia Control panel обновлена до 1.3
    — Убраны устаревшие ярлыки в панели быстрого запуска и избранном
    — Теперь оболочка настройки автоматически требует прав администратора при запуске
    — Теперь для сборки используется Visual Studio 2012

    Настройка Small Media Player в программах по умолчанию

    Small Media Player при установке в составе данного пакета теперь регистрирует расширения файлов для функции «Выбор программ по умолчанию» в Windows. Благодаря этому вы можете настроить систему таким образом, чтобы определенные файлы автоматически открывались в нем. Это было необходимо, так как старый функционал ассоциаций фактически не работал начиная с Windows 8.

  • SmallSoft Multimedia Control Panel 1.3

    Вышла новая версия утилиты для управления кодеками с небольшими изменениями. Скачать, Посмотреть исходный код.

    — Теперь программа автоматически требует прав администратора при запуске
    — Исправлены опечатки в интерфейсе и в справке

    Примечание. Запуск с правами администратора необходим, так как начиная с Windows Vista любые действия по изменению конфигурации кодеков (регистрация, удаление, изменение приоритета и др.) выдают ошибку, когда программа запущена с правами обычного пользователя. Продвинутые пользователи, которые хотят запустить программу без прав администратора исключительно для просмотра информации о кодеках, могут собрать ее из исходного кода в конфигурации Debug (для этой конфигурации принудительное требование повышенных прав отключено).

  • Paint-X: версия 1.4

    Скачать

    Это запоздавшее более чем на 10 лет обновление с важными дополнениями и исправлениями.

    Изменения в новой версии:

    — Добавлена печать изображений

    — Добавлены новые значки для многих кнопок панелей инструментов

    — Добавлен особый вид указателя мыши для инструментов «Выделение» и «Перетаскивание»

    — Угол по умолчанию в окне поворота изображения изменен с 0 до 90 градусов

    — Функция смешивания изображений переработата и переименована в «Наложение изображения»: теперь она позволяет выбрать область, на которую накладывается изображение, и подогнать размер изображения под целевую область.

    — Параметр «Подогнать» для масштаба изображения переработан: теперь он только уменьшает изображение, если оно больше размера окна, но не увеличивает, если оно меньше.

    — Изменен порядок форматов в диалоге сохранения файла, так что более популярные форматы теперь расположены выше.

    — Переработано предупреждение о несохраненных изменениях, теперь оно показывается и для многостраничных файлов.

    — Исправлена ошибка: Предупреждение о несохраненных изменениях не показывалось при переходе к следующему/предыдущему файлу с помощью горячих клавиш.

    — Исправлена ошибка: Предупреждение о несохраненных изменениях при закрытии программы не показывалось до первого сохранения созданного файла.

    — Исправлена ошибка вычисления масштаба, из-за которой высота масштабированного изображения оказывалась на один пиксель меньше высоты окна.

    — Исправлена ошибка: при загрузке файлов из каталога файлы с раширением .jpeg дублировались.

    — Исправлена ошибка: нажатие кнопки «Отмена» в окне «Наложение изображения» некорректно делало активной кнопку «Отменить изменения».

    — Исправлена ошибка: прямоугольник выделения некорректно отрисовывался за пределами изображения.

    — Исправлена ошибка, из-за которой было невозможно выделить крайние правые и крайние нижние пиксели изображения.

    — Исправлена ошибка, из-за которой использование инструмента «Перетаскивание» сбрасывало содержимое буфера обмена.

    — Исправлены опечатки в справке.

  • Инженерный калькулятор: Версия 2.3

    Скачать: http://vadim—111.narod.ru/programs/calc/Calculator23.zip

    главное окно
    визуализация цветовой картой

    Изменения в новой версии:

    • Добавлена возможность сохранить результат как новую константу в главном окне
    • Добавлено отображение пяти последних вычисленных выражений в главном окне
    • Добавлена визуализация функции двух переменных в виде цветовой карты
    • Место хранения данных рабочего места перенесено из каталога программы в Application Data текущего пользователя (подкаталог ScientificCalculator)
    • Исправлена ошибка переполнения при попытке построить график функции, если функция не определена на некоторых точках интервала
    • Исправлена ошибка, из-за которой в окне интерполяции некорректно вычислялись значения при экстаполяции за конец интервала
    • Исправлена обработка некорректных выражений: теперь при использовании несуществующей константы или единицы измерения выводится сообщение об ошибке
  • Редактор изображений Paint-X

    Скачать программу бесплатно

    Paint-X v1.4 (108 КБ)

    Описание программы

    Программа для просмотра и редактирования изображений. Поддерживает форматы BMP, JPEG, GIF, PNG, TIFF, ICO
    Основные возможности:

    • просмотр изображений с прокруткой в пределах папки
    • удобная регулировка масштаба, можно подогнать изображение под размер окна
    • работа с буфером обмена
    • обрезка, поворот, зеркальное отражение
    • перемасштабирование, сжатие, растяжение изображений
    • добавление надписей
    • основные графические инструменты: карандаш, кисть, заливка
    • рисование геометрических фигур: прямая линия, прямоугольник, эллипс, многоугольник
    • настройка толщины линий, цвета линий и фона
    • редактирование изображений может осуществляться в любом масштабе: как в увеличенном, так и в уменьшенном
    • специальные фильтры: регулировка яркости, инверсия цветов, преобразование в черно-белый, удаление помех, размытие, тиснение

    Для работы программы требуется .NET Framework 3.5

    Справка по программе Paint-X
    Исходный код на Gitflic

    Скриншоты: 1,2, 3.

    Предыдущие версии:

    Paint-X 1.3 с установкой (593 KB)
    Paint-X 1.3 портативная (105 КБ)

    См. также:
    Форматы графических файлов
    Small Media Player — легкий проигрыватель

  • Структура сетевого приложения на примере загрузки файла с веб-сервера

    (Статья написана давно, перенесена со старого сайта.)

    В настоящее время существует много библиотек высокого уровня, которые позволяют программистам манипулировать сетевыми функциями. Приложения, которые их используют, в основном обращаются к интерфейсам прикладного уровня ОС (например WinHTTP в MS Windows). Однако для понимания принципов работы сети необходимо знать как все работает и на более низких уровнях. Канальный и сетевой уровни обычно реализуются аппаратно, и особого интереса не представляют. В данной статье я опишу сетевое приложение, обращающееся непосредственно к модулям транспортного уровня ОС.
    Транспортный уровень — уровень модели OSI, который отвечает за доставку данных от одного приложения к другому с заданным уровнем надежности. Этот уровень особенно интересует программистов. Существует две модели транспортного уровня — датаграммная передача и передача с установлением соединения. Датаграммы — небольшого размера сообщения (обычно служебные), которыми обмениваются приложения. Например протокол DNS использует датаграммы. И протокол DHT (в файлообменных сетях) тоже их использует. Но при передаче датаграмм невозможно восстановление поврежденных данных, поэтому при передаче файлов их не используют. Техника передачи с установлением соединения используется в протоколах HTTP, FTP, BitTorrent и др. Суть ее в том, что узлы перед процессом передачи данных устанавливают соединение, а в процессе передачи потерянные пакеты восстанавливаются. Вся прелесть этой техники в том, что программист может не париться, как именно пакеты восстанавливаются: важно то, что все пакеты дойдут именно в нужной последовательности (кроме случаев разрыва соединения). В стеке TCP/IP протокол TCP реализует эту технику.
    Программный интерфейс транспортного уровня называется sockets (Он есть в разных системах, конкретно для Windows это Winsock). Этот интерфейс предоставляет программистам функции, которые работают независимо от протоколов и сетевого оборудования (даже от системы адресации). И это круто! Например функции getaddrinfo можно передать как доменное имя, так и NetBIOS имя компьютера — и все будет одинаково работать. В принципе процесс передачи данных через протоколы разной технологии почти не отличается в Winsock — например в протоколе UDP можно вызвать функцию connect , хотя реально соединение не устанавливается. Вместе с тем можно писать приложения ориентируясь и на конкретный протокол. Словом, этот интерфейс очень гибкий. Но написание приложений в его среде довольно сложно. Поэтому на практике часто применяются другие интерфейсы. Но мы рассмотрим его с теоретической точки зрения, чтобы увидеть «внутренности» работы сетевых приложений.
    Приложение WinSock требует подключения библиотеки импорта ws2_32.lib (Это в среде разработки VisualStudio). Функции WinSock хранятся в библиотеке ws2_32.dll .

    Далее разбирается приложение, загружающее файл с веб-сервера по протоколу HTTP и отображающее его в экране консоли. Точнее оно отображает полный ответ сервера, включая заголовок. Интерес этого приложения также в том, что оно позволяет увидеть «своими глазами» ответы сервера, которые обычно скрыты.
    В начале приложения мы включаем заголовочные файлы.

    Код:


    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    #include <stdlib.h>

    Объявление переменных:

    Код:

    WSADATA wsaData; //для инициализации сетевой подсистемы
    char rq[]=//строка с запросом
    "GET / HTTP/1.1\r\n\
    Host: ya.ru\r\n\
    User-Agent: Mozilla/4.05 (WinNT; 1)\r\n\
    Accept: */*\r\n\r\n\
    ";
    char buf[5000]="";//переменная для хранения ответа сервера

    Здесь в строковой константе задан HTTP-запрос GET. Путь к документу обозначен «/», что значит главную страницу сайта. В качестве параметров задается версия протокола, имя узла, браузер — на всякий случай говорим что мы Mozilla Firefox. Параметр Accept: */* задает что мы принимаем любой тип данных.

    Теперь сама точка входа:

    Код:

    int main()
    {
    int iResult;
    struct addrinfo *result = NULL;
    struct addrinfo hints;
    SOCKET ConnectSocket = INVALID_SOCKET;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

    if (iResult != 0) {
    printf("WSAStartup failed: %d\n", iResult);

    system("PAUSE");
    return 1;
    }
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC; //любое семейство адресов
    hints.ai_socktype = SOCK_STREAM;//тип сокета
    hints.ai_protocol = IPPROTO_TCP;//протокол TCP
    iResult = getaddrinfo("ya.ru", "http", &hints, &result);//разрешение доменного имени

    if (iResult != 0) {
    printf("getaddrinfo failed: %d\n", iResult);
    system("PAUSE");
    WSACleanup();
    return 1;
    }

    В данной части происходит инициализация сетевой подсистемы, а затем разрешение доменного имени узла — в нашем случае «ya.ru» — в сетевой адрес. На этом этапе происходит запрос к DNS-серверу. В структуре hints мы задаем желаемые требования — семейство адресов Ipv4, Ipv6 или любое; тип сокета — для нашего случая это сокет-поток, который соответствует протоколу TCP (для других протоколов мог быть тип датаграмного сокета). Ну и задаем непосредственно протокол. Хотя это параметры необязательные — и так наверно все будет работать! У функции getaddrinfo второй параметр — номер порта или протокола, у нас «http», стандартный поpт 80. От DNS-сервера нам приходит IP-адрес сервера ( в переменной result), и теперь мы готовы соединится с ним. Для соединения мы создаем специальный объект — сокет. Фактически это набор ресурсов, связанных с сетевым соединением.

    Код:

    ConnectSocket=socket(result->ai_family,result->ai_socktype,result->ai_protocol);//создание сокета

    if (ConnectSocket == INVALID_SOCKET) {
    printf("Error at socket(): %ld\n", WSAGetLastError());

    system("PAUSE");
    freeaddrinfo(result);
    WSACleanup();
    return 1;
    }
    iResult=connect(ConnectSocket,result->ai_addr,(int)result->ai_addrlen); //соединение с сервером
    if (iResult == SOCKET_ERROR) {
    iResult=WSAGetLastError();
    printf("\nConnect error: %i\n",iResult);
    system("PAUSE");
    closesocket(ConnectSocket);
    ConnectSocket = INVALID_SOCKET;
    }
    freeaddrinfo(result);//информация об адресе нам больше не нужна

    Вот мы соединились с сервером. Теперь посылаем запрос.

    Код:

    // Send an initial buffer
    iResult = send(ConnectSocket, rq, (int) strlen(rq), 0);
    if (iResult == SOCKET_ERROR) {
    printf("send failed: %d\n", WSAGetLastError());
    system("PAUSE");
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
    }
    printf("\nSending a request - bytes Sent: %ld\n", iResult);
    // shutdown the connection for sending since no more data will be sent
    // the client can still use the ConnectSocket for receiving data
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
    printf("shutdown failed: %d\n", WSAGetLastError());
    system("PAUSE");
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
    }

    Функцией shutdown мы сигнализируем серверу, что посылка данных завершена, и мы ждем ответа. Ее вызов можно опустить (иногда он даже вреден). Теперь мы получаем ответ порциями по 5 кб и выводим на экран. Когда сервер закрывает соединение, выходим из цикла.

    Код:

    do {
    iResult = recv(ConnectSocket, buf, 5000, 0);//прием данных
    if (iResult > 0){ //данные успешно приняты
    //Start receiving answer
    printf("Server Answered.Bytes received: %d\n\n", iResult);

    printf("%s",buf);
    system("PAUSE");

    }
    else if (iResult == 0) //соединение закрыто сервером
    printf("Connection closed\n");

    else //произошла ошибка
    printf("recv failed: %d\n", WSAGetLastError());
    } while (iResult > 0);

    system("PAUSE");
    return 0;
    }

    Пример ответа сервера:

    Winsock Загрузка файла с веб-сервера

    Вот и все. Попробуйте усовершенствовать это приложение, чтобы оно сохраняло данные на жесткий диск. На основе него можно написать целый менеджер закачек. Ах да, еще — отключите сетевой экран и брендмауэр перед тестированием приложения, а то они почему-то могут его блокировать. Видимо считается хакерские технологии…
    Таким образом, прочитав эту статью, вы знаете как устроено простейшее клиент-серверное сетевое приложение, надеюсь это вам поможет в понимании архитектуры современных информационных систем.

    См. также: IP Address Power Tool — программа для просмотра информации об IP-адресе

  • Получение информации об устройствах вывода звука в Windows (C#)

    (Статья написана 27.09.2017, перенесена со старого сайта.)

    Иногда возникает необходимость определения присутствующих в системе устройств вывода звука, и какие из них активны в текущий момент. Для этих целей можно использовать Windows Multimedia Device API. Его интерфейс IMMDeviceEnumerator позволяет получить список устройств вывода звука (audio endpoints), их тип и различную информацию о них. Однако, в современных звуковых картах часто динамики и наушники представлены одним устройством с точки зрения системы, и выбор, на какое устройство выводить звук, осуществляется в настройках специальной утилиты производителя (или автоматически). В таком случае для определения путей вывода звука в конкретной ситуации можно использовать Device Topology API. С помощью него можно получить информацию о разъемах звукового адаптера и их состоянии.

    Для доступа к этим API из C# нам понадобятся декларации неуправляемых структур, интерфейсов и т.п. из библиотек Mmdeviceapi.h и Devicetopology.h, а также COM-объекта Property Store:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.IO;
    using System.Runtime.CompilerServices;
    
    namespace com_test
    {
        class Native
        {
            [DllImport("ole32.Dll")]
            static public extern uint CoCreateInstance(ref Guid clsid,
            [MarshalAs(UnmanagedType.IUnknown)] object inner, uint context, ref Guid uuid,
            [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);
    
            //************************************************************************
            [DllImport("ole32.dll")]
            private extern static int PropVariantClear(ref PropVariant pvar);
    
            public const int DEVICE_STATE_ACTIVE = 0x00000001;
            public const int DEVICE_STATE_DISABLE = 0x00000002;
            public const int DEVICE_STATE_NOTPRESENT = 0x00000004;
            public const int DEVICE_STATE_UNPLUGGED = 0x00000008;
            public const int DEVICE_STATEMASK_ALL = 0x0000000f;
                    
    
            public static PROPERTYKEY PKEY_Device_FriendlyName = 
                new PROPERTYKEY(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
            
            public static PROPERTYKEY PKEY_AudioEndpoint_FormFactor = 
                new PROPERTYKEY(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 0);
    
        }
    
        enum EndpointFormFactor
        {
            RemoteNetworkDevice	= 0,
            Speakers	= ( RemoteNetworkDevice + 1 ) ,
            LineLevel	= ( Speakers + 1 ) ,
            Headphones	= ( LineLevel + 1 ) ,
            Microphone	= ( Headphones + 1 ) ,
            Headset	= ( Microphone + 1 ) ,
            Handset	= ( Headset + 1 ) ,
            UnknownDigitalPassthrough	= ( Handset + 1 ) ,
            SPDIF	= ( UnknownDigitalPassthrough + 1 ) ,
            DigitalAudioDisplayDevice	= ( SPDIF + 1 ) ,
            UnknownFormFactor	= ( DigitalAudioDisplayDevice + 1 ) ,
            EndpointFormFactor_enum_count	= ( UnknownFormFactor + 1 ) 
        };
    
        enum EPcxConnectionType
        {
            eConnTypeUnknown=0,
            eConnType3Point5mm,
            eConnTypeQuarter,
            eConnTypeAtapiInternal,
            eConnTypeRCA,
            eConnTypeOptical,
            eConnTypeOtherDigital,
            eConnTypeOtherAnalog,
            eConnTypeMultichannelAnalogDIN,
            eConnTypeXlrProfessional,
            eConnTypeRJ11Modem,
            eConnTypeCombination
        } ;
    
        enum EPcxGeoLocation
        {
            eGeoLocRear = 0x1,
            eGeoLocFront,
            eGeoLocLeft,
            eGeoLocRight,
            eGeoLocTop,
            eGeoLocBottom,
            eGeoLocRearPanel,
            eGeoLocRiser,
            eGeoLocInsideMobileLid,
            eGeoLocDrivebay,
            eGeoLocHDMI,
            eGeoLocOutsideMobileLid,
            eGeoLocATAPI,
            eGeoLocNotApplicable,
            eGeoLocReserved6,
            EPcxGeoLocation_enum_count
        } ;
    
        public enum EDataFlow
        {
            eRender,
            eCapture,
            eAll,
            EDataFlow_enum_count
        }
    
        public enum ERole
        {
            eConsole,
            eMultimedia,
            eCommunications,
            ERole_enum_count
        }
    
        public enum CLSCTX : uint
        {
            CLSCTX_INPROC_SERVER = 0x1,
            CLSCTX_INPROC_HANDLER = 0x2,
            CLSCTX_LOCAL_SERVER = 0x4,
            CLSCTX_REMOTE_SERVER = 0x10,
            CLSCTX_SERVER = (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER |
                                                     CLSCTX_REMOTE_SERVER),
            CLSCTX_ALL = (CLSCTX_INPROC_HANDLER | CLSCTX_SERVER)
        };
    
        //Windows Core Audio API declarations
        //Источник: http://www.java2s.com/Code/CSharp/Windows/SoundUtils.htm
    
        [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"),
            InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IMMDeviceCollection
        {       
            int GetCount(ref uint pcDevices); 
            int Item(uint nDevice, [Out, MarshalAs(UnmanagedType.Interface)] out object ppDevice);
        }
    
        [Guid("D666063F-1587-4E43-81F1-B948E807363F"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IMMDevice
        {
            int Activate(ref Guid iid, uint dwClsCtx, IntPtr pActivationParams, 
                [Out, MarshalAs(UnmanagedType.Interface)] out object ppInterface);
    
            int OpenPropertyStore(int stgmAccess, [Out, MarshalAs(UnmanagedType.Interface)] out object ppProperties);
    
            int GetId(ref StringBuilder ppstrId);
    
            int GetState(ref int pdwState);
        }
    
        [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
        class MMDeviceEnumerator
        {
        }
    
        [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"),    
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IMMDeviceEnumerator
        {
    
             int EnumAudioEndpoints(EDataFlow dataFlow, int dwStateMask, 
                 [Out, MarshalAs(UnmanagedType.Interface)] out object ppDevices);
    
             int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, 
                 [Out, MarshalAs(UnmanagedType.Interface)] out object ppEndpoint);
                    
             int  GetDevice(string pwstrId, ref IntPtr ppDevice);
    
             int  RegisterEndpointNotificationCallback(IntPtr pClient);
    
             int  UnregisterEndpointNotificationCallback(IntPtr pClient);
        }
          
    
        //*********** Property store *****************************
    
        //Источник: https://blogs.msdn.microsoft.com/adamroot/2008/04/11/interop-with-propvariants-in-net/
    
        [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        interface IPropertyStore
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCount([Out] out uint cProps);
    
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetAt([In] uint iProp, out PROPERTYKEY pkey);
    
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            int GetValue([In] ref PROPERTYKEY key, out PropVariant pv);
    
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SetValue([In] ref PROPERTYKEY key, [In] ref object pv);
    
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void Commit();
        }
    
        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct PROPERTYKEY
        {
            public Guid fmtid;
            public uint pid;
    
            public PROPERTYKEY(Guid guid, int propertyId)
            {
                this.fmtid = guid;
                this.pid = (uint)propertyId;
            }
            public PROPERTYKEY(string formatId, int propertyId)
                : this(new Guid(formatId), propertyId)
            {
            }
            public PROPERTYKEY(uint a, uint b, uint c, uint d, uint e, uint f, 
                uint g, uint h, uint i, uint j, uint k, int propertyId)
                : this(new Guid((uint)a, (ushort)b, (ushort)c, (byte)d, (byte)e, 
                    (byte)f, (byte)g, (byte)h, (byte)i, (byte)j, (byte)k), propertyId)
            {
            }
        }
        
        [StructLayout(LayoutKind.Sequential)]
        public struct PropVariant
        {
            ushort vt;
            ushort wReserved1;
            ushort wReserved2;
            ushort wReserved3;
            IntPtr p;
            int p2;
    
            private byte[] GetDataBytes()
            {
                byte[] ret = new byte[IntPtr.Size + sizeof(int)];
                if (IntPtr.Size == 4)
                    BitConverter.GetBytes(p.ToInt32()).CopyTo(ret, 0);
                else if (IntPtr.Size == 8)
                    BitConverter.GetBytes(p.ToInt64()).CopyTo(ret, 0);
                BitConverter.GetBytes(p2).CopyTo(ret, IntPtr.Size);
                return ret;
            }
    
            sbyte cVal // CHAR cVal;
            {
                get { return (sbyte)GetDataBytes()[0]; }
            }
    
            short iVal // SHORT iVal;
            {
                get { return BitConverter.ToInt16(GetDataBytes(), 0); }
            }
    
            int lVal // LONG lVal;
            {
                get { return BitConverter.ToInt32(GetDataBytes(), 0); }
            }
    
            long hVal // LARGE_INTEGER hVal;
            {
                get { return BitConverter.ToInt64(GetDataBytes(), 0); }
            }
    
            float fltVal // FLOAT fltVal;
            {
                get { return BitConverter.ToSingle(GetDataBytes(), 0); }
            }
    
            public object Value
            {
                get
                {
                    switch ((VarEnum)vt)
                    {
                        case VarEnum.VT_I1:
                            return cVal;
                        case VarEnum.VT_I2:
                            return iVal;
                        case VarEnum.VT_I4:
                        case VarEnum.VT_INT:
                            return lVal;
                        case VarEnum.VT_UI4:
                        case VarEnum.VT_I8:
                            return hVal;
                        case VarEnum.VT_R4:
                            return fltVal;
                        case VarEnum.VT_FILETIME: return DateTime.FromFileTime(hVal);
                        case VarEnum.VT_BSTR:
                            return Marshal.PtrToStringBSTR(p);
                        case VarEnum.VT_BLOB:
                            byte[] blobData = new byte[lVal];
                            IntPtr pBlobData;
                            if (IntPtr.Size == 4)
                            {
                                pBlobData = new IntPtr(p2);
                            }
                            else if (IntPtr.Size == 8)
                            {
                                pBlobData = new IntPtr(BitConverter.ToInt64(GetDataBytes(), sizeof(int)));
                            }
                            else
                                throw new NotSupportedException();
                            Marshal.Copy(pBlobData, blobData, 0, lVal);
                            return blobData;
                        case VarEnum.VT_LPSTR:
                            return Marshal.PtrToStringAnsi(p);
                        case VarEnum.VT_LPWSTR:
                            return Marshal.PtrToStringUni(p);
                        case VarEnum.VT_UNKNOWN:
                            return Marshal.GetObjectForIUnknown(p);
                        case VarEnum.VT_DISPATCH:
                            return p;
                        default:
                            throw new NotSupportedException("0x"+vt.ToString("X4") + " type not supported");
                    }
                }
            }
    
        }
        //*****************************************************
            
        //Device Topology declarations
    
        [Guid("2A07407E-6497-4A18-9787-32F79BD0D98F"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IDeviceTopology
        {
            int GetConnectorCount([Out] out int pConnectorCount);
            int GetConnector(int nIndex, out IConnector ppConnector);
            int GetSubunitCount([Out] out int pCount);
            int GetSubunit(int nIndex, out /*ISubunit*/object ppSubunit);
            int GetPartById(int nId, out IPart ppPart);
            int GetDeviceId([Out, MarshalAs(UnmanagedType.LPWStr)] out string ppwstrDeviceId);
            int GetSignalPath(IPart pIPartFrom, IPart pIPartTo, bool bRejectMixedPaths, /*IPartsList*/object ppParts);
        }
    
        
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
        Guid("9c2c4058-23f5-41de-877a-df3af236a09e")]
        public interface IConnector
        {
            int GetType(out int pType);
            int GetDataFlow(out EDataFlow dataFlow);
            int ConnectTo([In] IConnector connector);
            int Disconnect();
            int IsConnected(out bool pbConnected);        
            int GetConnectedTo([MarshalAs(UnmanagedType.Interface)] out object ppConTo);
            int GetConnectorIdConnectedTo(out string ppwstrConnectorId);
            int GetDeviceIdConnectedTo(out string ppwstrDeviceId);
        }
    
        [Guid("AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IPart
        {
            int GetName(out StringBuilder ppwstrName);
            int GetLocalId(out int pnId);
            int GetGlobalId(out StringBuilder ppwstrGlobalId);
            int GetPartType(out int pPartType);
            int GetSubType(out Guid pSubType);
            int GetControlInterfaceCount(out uint pCount);
    
            int GetControlInterface(int nIndex, out /*IControlInterface*/ object ppFunction);
            int EnumPartsIncoming(out /*IPartsList[]*/object ppParts);
            int EnumPartsOutgoing(out /*IPartsList[]*/object ppParts);
                   
            int GetTopologyObject([Out,MarshalAs(UnmanagedType.Interface)] out object ppTopology);
    
            int Activate(UInt32 dwClsContext,
                     ref Guid refiid,
                     [MarshalAs(UnmanagedType.Interface)] 
                 out object interfacePointer);
            int RegisterControlChangeCallback(ref Guid riid, /*IControlChangeNotify*/object pNofity);
            int UnregisterControlChangeCallback(/*IControlChangeNotify*/object pNotify);
        }
    
        [ComVisible(false)]
        [ComImport,
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
        Guid("4509F757-2D46-4637-8E62-CE7DB944F57B")]
        public interface IKsJackDescription
        {
            int GetJackCount(out uint jacks);
            int GetJackDescription(uint jack, ref KSJACK_DESCRIPTION pDescription);
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct KSJACK_DESCRIPTION
        {
            public uint ChannelMapping;
            public uint Color;
            public uint ConnectionType;
            public uint GeoLocation;
            public uint GenLocation;
            public uint PortConnection;
            public uint IsConnected;
        } ;
    
    }
    

    Для вывода информации создадим форму в приложении WinForms с элементами TextBox и FlowLayoutPanel.

    Создадим COM-объект MMDeviceEnumerator и объявим необходимые интерфейсы:

    MMDeviceEnumerator devenum = new MMDeviceEnumerator();// CoClass
    IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)devenum;
    IMMDeviceCollection deviceCollection = null;
    IMMDevice dev = null;
    IMMDevice defDevice=null;
    IPropertyStore propertyStore=null;
    

    Устройство вывода звука по умолчанию и его FriendlyName можно получить так:

    deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, out o);
    defDevice = o as IMMDevice;
    
    defDevice.OpenPropertyStore(0/*STGM_READ*/, out o);
    propertyStore = o as IPropertyStore;
    PropVariant name = new PropVariant();
    propertyStore.GetValue(Native.PKEY_Device_FriendlyName, out name);
    

    Для получения списка всех устройств используем следующий код:

    deviceEnumerator.EnumAudioEndpoints(EDataFlow.eRender, 0x0000000F /*DEVICE_STATEMASK_ALL*/, out o);
    deviceCollection = o as IMMDeviceCollection;
    uint deviceCount = 0;
    deviceCollection.GetCount(ref deviceCount);
    

    Для вывода информации по устройству создадим метод PrintDevice

    string PrintDevice(IMMDevice dev)
    {
        IPropertyStore propertyStore = null;
        IDeviceTopology pDeviceTopology = null;
        IConnector pConnFrom = null;
        IConnector pConnTo = null;
        IPart pPart = null;
        IKsJackDescription pJackDesc = null;
        KSJACK_DESCRIPTION desc = new KSJACK_DESCRIPTION();
    
        StringBuilder res = new StringBuilder(300);
        StringBuilder id = new StringBuilder(500);
        object o = null;
        
        int state = 0;
        uint con_count = 0;
    
        FlowLayoutPanel pan = new FlowLayoutPanel();
        
        pan.Width = 390;
        pan.Height = 100;
        pan.FlowDirection = FlowDirection.TopDown;
        pan.WrapContents = false;
    
        try
        {
    
            //*********
            id = new StringBuilder(500);
            dev.GetId(ref id);                
            //*********
    
            //имя устройства
            dev.OpenPropertyStore(0/*STGM_READ*/, out o);                
            propertyStore = o as IPropertyStore;
    
            PropVariant friendlyName = new PropVariant();
            propertyStore.GetValue(Native.PKEY_Device_FriendlyName, out friendlyName);                
            res.AppendLine(friendlyName.Value.ToString());
    
            TextBox tb = new TextBox();
            tb.Text = friendlyName.Value.ToString();
            tb.Width = pan.Width - 10;
            tb.ReadOnly = true;
            pan.Controls.Add(tb);
    
            Label lab;
            lab = new Label(); lab.AutoSize = true;
            lab.Text = "ID: "+id.ToString(); pan.Controls.Add(lab);
    
            //form factor 
            PropVariant FormFactor = new PropVariant();
            propertyStore.GetValue(Native.PKEY_AudioEndpoint_FormFactor, out FormFactor);                
            EndpointFormFactor f=EndpointFormFactor.UnknownFormFactor;
            Enum.TryParse<EndpointFormFactor>(FormFactor.Value.ToString(), out f);
            res.AppendLine("Form factor: " + f.ToString());
    
            lab = new Label(); lab.AutoSize = true; 
            lab.Text = "Form factor: " + f.ToString();pan.Controls.Add(lab);
    
            //состояние устройства
            dev.GetState(ref state);                
    
            string str="";
            
            switch (state)
            {
                case Native.DEVICE_STATE_ACTIVE: str=("State: Active"); break;
                case Native.DEVICE_STATE_DISABLE: str = ("State: Disabled"); break;
                case Native.DEVICE_STATE_NOTPRESENT: str = ("State: Not present"); break;
                case Native.DEVICE_STATE_UNPLUGGED: str = ("State: Unplugged"); break;
            }
            
            res.AppendLine(str);
    
            lab = new Label(); lab.AutoSize = true;
            lab.Text = str; pan.Controls.Add(lab);
    
            /* DEVICE TOPOLOGY */
            Guid iidDeviceTopology = new Guid("2A07407E-6497-4A18-9787-32F79BD0D98F");
            dev.Activate(ref iidDeviceTopology, (uint)CLSCTX.CLSCTX_ALL, IntPtr.Zero, out o);                
            pDeviceTopology = o as IDeviceTopology;
    
            pDeviceTopology.GetConnector(0, out pConnFrom);                
    
            try
            {
                o = null;
                pConnFrom.GetConnectedTo(out o);
                pConnTo = o as IConnector;                    
    
                pPart = (IPart)pConnTo;//QueryInterface
    
                Guid iidKsJackDescription = new Guid("4509F757-2D46-4637-8E62-CE7DB944F57B");
                pPart.Activate((uint)CLSCTX.CLSCTX_INPROC_SERVER, ref iidKsJackDescription, out o);                    
                pJackDesc = (IKsJackDescription)o;
    
                if (pJackDesc != null)
                {
                    con_count = 0;
                    pJackDesc.GetJackCount(out con_count);
                    
                    if (con_count > 0)
                    {
                        StringBuilder sb;
                        Bitmap bmp;
    
                        //отобразить информацию о разъемах
                        for (uint i = 0; i < con_count; i++)
                        {
                            pJackDesc.GetJackDescription(i, ref desc);                                
                                                        
                            sb = new StringBuilder(100);
                            EPcxConnectionType con_type = (EPcxConnectionType)desc.ConnectionType;
                            EPcxGeoLocation loc = (EPcxGeoLocation)desc.GeoLocation;
                            res.Append("* ");
    
                            switch (con_type)
                            {
                                case EPcxConnectionType.eConnType3Point5mm: sb.Append("Разъем 3.5 мм ");
                                    break;
                                case EPcxConnectionType.eConnTypeAtapiInternal: sb.Append("Разъем ATAPI ");
                                    break;
                                case EPcxConnectionType.eConnTypeRCA: sb.Append("Разъем RCA ");
                                    break;
                                case EPcxConnectionType.eConnTypeQuarter: sb.Append("Разъем 1/2 дюйма ");
                                    break;
                                case EPcxConnectionType.eConnTypeOtherAnalog: sb.Append("Аналоговый разъем ");
                                    break;
                                case EPcxConnectionType.eConnTypeOtherDigital: sb.Append("Цифровой разъем ");
                                    break;
                                default: sb.Append(con_type.ToString()+" ");
                                    break;
                            }
    
                            switch (loc)
                            {
                                case EPcxGeoLocation.eGeoLocFront: sb.Append("- Передняя панель");
                                    break;
                                case EPcxGeoLocation.eGeoLocRear: sb.Append("- Задняя панель");
                                    break;
                                case EPcxGeoLocation.eGeoLocHDMI: sb.Append("- HDMI");
                                    break;
                                case EPcxGeoLocation.eGeoLocNotApplicable: sb.Append("- Расположение не определено");
                                    break;
                                default: sb.Append("- "+loc.ToString());
                                    break;
                            }
                            
                            if (desc.IsConnected == 0) sb.Append(" (Отключен)");
    
                            res.AppendLine(sb.ToString());
                            bmp = new Bitmap(pan.Width, 20);
                            
                            //генерация изображения
                            Graphics g = Graphics.FromImage(bmp);
                            
                            using (g)
                            {
                                //цвет получается сочетанием desc.Color и 0xFF для альфа-канала
                                Pen pen = new Pen(Color.FromArgb((int)(desc.Color | 0xFF000000)));
                                g.FillRectangle(SystemBrushes.Control, 0.0f, 0.0f, bmp.Width, bmp.Height);
                                using (pen)
                                {
                                    pen.Width = 5;
                                    g.DrawEllipse(pen, 2, 2, 15, 15);//нарисовать круг, используя цвет разъема
                                    Font fnt = new System.Drawing.Font(new FontFamily("Arial"), 9.0f);
                                    g.DrawString(sb.ToString(),fnt, Brushes.Black, 21, 0,StringFormat.GenericDefault);
                                }
                            }
    
                            PictureBox pb = new PictureBox();
                            pb.Image = bmp;
                            pb.SizeMode = PictureBoxSizeMode.AutoSize;
                            pan.Controls.Add(pb);
                            
                        }//end for
                    }
                    else
                    {
                        res.AppendLine("* Нет разъемов");
                        lab = new Label(); lab.Text = "* Нет разъемов";
                        lab.AutoSize = true;
                        pan.Controls.Add(lab);
                    }
                }
                else
                {
                    res.AppendLine("* Не удалось получить информацию о разъемах");
                    lab = new Label(); lab.Text = "* Не удалось получить информацию о разъемах";
                    lab.AutoSize = true;
                    pan.Controls.Add(lab);
                }                
            }
            catch (COMException ex)
            {
                if ((uint)ex.HResult == 0x80070490 /*E_NOTFOUND*/)
                {
                    res.AppendLine("Не подключен");
                    lab = new Label(); lab.Text = "* Не подключен";
                    lab.AutoSize = true;
                    pan.Controls.Add(lab);
                }
                else
                {
                    res.AppendLine("COM error: " + ex.Message);
                    lab = new Label(); lab.Text = "COM error: " + ex.Message;
                    lab.AutoSize = true;
                    pan.Controls.Add(lab);
                }
            }
            catch (Exception ex)
            {
                res.AppendLine("Не удалось получить информацию о разъемах: " + ex.Message);
                lab = new Label(); lab.Text = "Не удалось получить информацию о разъемах: " + ex.Message;
                lab.AutoSize = true;
                pan.Controls.Add(lab);
            }                
    
        }
        finally
        {
            //clean up resources                
            if (dev != null) Marshal.ReleaseComObject(dev);
            if (propertyStore != null) Marshal.ReleaseComObject(propertyStore);
    
            if (pDeviceTopology != null) { Marshal.ReleaseComObject(pDeviceTopology); pDeviceTopology = null; }
            if (pConnFrom != null) { Marshal.ReleaseComObject(pConnFrom); pConnFrom = null; }
            if (pConnTo != null) { Marshal.ReleaseComObject(pConnTo); pConnTo = null; }
            if (pPart != null) { Marshal.ReleaseComObject(pPart); pPart = null; }
            if (pJackDesc != null) { Marshal.ReleaseComObject(pJackDesc); pJackDesc = null; }                
        }
    
        int h = 0;
        foreach (Control c in pan.Controls){if (c.Bottom > h) h = c.Bottom;}
        pan.Height = h+10;
    
        flowLayoutPanel1.Controls.Add(pan);           
        return res.ToString();
    }
    

    Сначала мы с помощью IMMDevice и IPropertyStore получаем общие свойства устройств. Затем получаем IDeviceTopology и находим объект IConnector, который символизирует разъемы нашего устройства. Из него получаем IKsJackDescription, который выдает список разъемов. Для разъемов можно узнать тип порта, его расположение (даже его цвет), а также статус (подключен/не подключен). Следует отметить, что не у всех разъемов есть электрический детектор подключения — для них статус всегда будет “Подключено”. Используя эти данные, генерируем картинки разъемов и вставляем во FlowLayoutPanel.

    Используем данную функцию для вывода всех устройств:

    textBox1.Text = "Устройство по умолчанию : " + name.Value.ToString();
    flowLayoutPanel1.Controls.Clear();
    
    for (uint i = 0; i < deviceCount; i++)//вывести информацию о устройствах
    {
        deviceCollection.Item(i, out o);
        dev = o as IMMDevice;
        PrintDevice(dev); 
    
        //clean up resources
        if (dev != null) { Marshal.ReleaseComObject(dev); dev = null; }
    }
    

    Окончательная очистка ресурсов COM:

    if (devenum != null) Marshal.ReleaseComObject(devenum);
    if (deviceEnumerator != null) Marshal.ReleaseComObject(deviceEnumerator);
    if (deviceCollection != null) Marshal.ReleaseComObject(deviceCollection);
    if (dev != null) Marshal.ReleaseComObject(dev);
    if (defDevice != null) Marshal.ReleaseComObject(defDevice);
    if (propertyStore != null) Marshal.ReleaseComObject(propertyStore);
    

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

    Audio devices list

    Полный проект (VS2012)

    См. также: Small Media Player — легкий проигрыватель для Windows

  • SmallSoft Decoder Pack

    Внимание: Данный проект очень старый, и он потерял актуальность для новых версий Windows, так как декодеры для воспроизведения большинства популярных форматов уже встроены в систему. Он может быть полезен для старых компьютеров с Windows XP — 7.

    Скачать программу

    SmallSoft Decoder Pack v1.1 [4.07 MB]

    Описание программы

    Набор самых необходимых декодеров для домашнего воспроизведения музыки и видео. Пакет спроектирован так, чтобы быть компактным по размеру, но при этом содержать все декодеры для часто используемых мультимедийных форматов. Поддерживает почти все распространенные форматы аудио, а также форматы видео — AVI MPEG MKV с типами сжатия DIVX, XVID, H264, AVC1 и др. Имеет встроенную оболочку настройки, которая позволяет включать и отключать кодеки, настраивать их параметры. Также в пакет входит мультимедийный проигрыватель Small Media Player и утилита для управления кодеками.

    Cкриншот SmallSoft Decoder Pack

    Справка и подробная информация

    См. также:
    Small Media Player — легкий проигрыватель мультимедиа файлов
    Программа для управления кодеками

  • IP Address Power Tool

    Скачать программу бесплатно

    IP Address Power Tool 1.0 — инсталлятор (324 кб)
    IP Address Power Tool 1.0 — без установки (35 кб)

    Описание программы

    Программа для просмотра информации об IP-адресе. Позволяет выполнить следующие операции:

    • узнать класс, тип, регион заданного адреса, соответствующую регистратуру и WHOIS-сервер; адрес подсети
    • получить регистрационную информацию от WHOIS-сервера: страна, город, провайдер, адрес организации и т.п.;
    • перевести адрес из десятичной в шестнадцетиричную или двоичную форму представления и обратно;
    • узнать IP-адрес сайта по доменному имени
    • проверить принадлежность адреса конкретной подсети на основе класса, маски или длины префикса;
    • узнать локальный адрес и внешний (для модемных подключений) адрес компьютера.

    Руководство по использованию программы

    См. также: Структура сетевого приложения на примере загрузки файла с веб-сервера

  • SmallSoft Multimedia Control Panel

    Скачать программу бесплатно

    SmallSoft Multimedia Control Panel v1.3

    Программа SmallSoft Multimedia Control Panel

    Описание программы

    Утилита для управления кодеками в Windows. Поддерживает кодеки в виде DirectShow-фильтров и DMO. Программа позволяет просмотреть список кодеков по категориям, вывести информацию по каждому кодеку: имя, путь к файлу, GUID, приоритет; открыть его страницу свойств; изменить приоритет (для DirectShow-фильтров), удалить кодек из системы, зарегистрировать новый кодек. Есть возможность автоматического поиска некорректно установленных кодеков, для очистки реестра от лишних записей. Также можно повторно зарегистрировать системные кодеки, для исправления их настроек.
    Перед использованием программы ОБЯЗАТЕЛЬНО ПРОЧИТАЙТЕ ИНСТРУКЦИЮ в файле readme.txt, иначе можно повредить систему из-за неправильных действий в программе.

    Исходный код

    Руководство по использованию

    См. также:
    Small Media Player — легкий проигрыватель

Создайте подобный сайт на WordPress.com
Начало работы