Сайт для программистов

вторник, 9 февраля 2010 г.

Получить информацию о BMP-файле

Если вам приходится работать с графическими файлами, то, возможно, у вас появится задача получить дополнительную информацию - узнать размеры файла, глубину цвета и т.п. Безусловно, вы можете загрузить картинку из файла на форму или подходящий элемент управления (PictureBox) и получить требуемую информацию. Но, предположим, ваш проект предназначен только для сбора информации о файлах. В этом случае загружать 10-мегапиксельный рисунок в форму неоправданно - получается слишком большой расход памяти. Есть другой способ получения нужной информации. О нем и пойдет речь сегодня.

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

Но, вернемся к файлам BMP. В начале каждого файла в формате BMP идет так называемый заголовок файла. В документации он описывается структурой BITMAPFILEHEADER, которая имеет общую длину 14 байтов: три UInt16 и два UInt32. Нас не интересует данный заголовок, поэтому вы его должны просто проигнорировать. Таким образом в коде нам нужно открыть файл и пропустить 14 байт:

reader.ReadBytes(14);

Обратите внимание, что функцию sizeof в данном случае использовать нельзя. Функция sizeof работает только с неуправляемыми ресурсами. После структуры BITMAPFILEHEADER идет структура BITMAPINFOHEADER. Именно, в этой структуре хранится необходимая информация, которую необходимо извлечь (кстати, описание структуры можно найти в справочнике по функциям Windows API для Visual Basic). Вот как будет выглядеть код извлечения информации из файла:

private void ShowBMPInfo(String file)
{
FileStream fs = new FileStream(file, FileMode.Open);
BinaryReader reader = new BinaryReader(fs);

// Пропускаем заголовок файла (14 байтов)
reader.ReadBytes(14);

// Пропускаем размер структуры BITMAPINFOHEADER
reader.ReadUInt32();

// Получаем ширину и высоту
int width = reader.ReadInt32();
int height = reader.ReadInt32();

// опять пропускаем часть байтов
reader.ReadInt16();

// Получаем глубину цвета (битов на пиксел)
Int16 bitsPerPixel = reader.ReadInt16();

// Освобождаем ресурсы
reader.Close();
fs.Close();

// Выводим информацию
MessageBox.Show(width + " x " + height + " x " + bitsPerPixel);
}

private void button1_Click(object sender, EventArgs e)
{
ShowBMPInfo(textBox1.Text); // подставляем путь к файлу
}

Тут есть одна тонкость. Пропускаемые в коде байты на самом деле все равно считываются. Чтобы действительно перепрыгнуть через заданное число байтов, вы должны использовать методы и свойства объекта потока (stream object). Например, получить текущий поток через свойство BaseStream и пропустить первые 14 байтов можно так:


reader.BaseStream.Seek(14, SeekOrigin.Begin);

Кроме того, можно передвинуть внутренний указатель на заданное смещение от конца потока или от текущей позиции. Вот как пропустить короткое целое (2 байта):


reader.BaseStream.Seek(2, SeekOrigin.Current);

С учетом этих особенностей я написал второй вариант извлечения данных из файла.


private void ShowBMPInfo2(String file)
{
FileStream fs = new FileStream(file, FileMode.Open);
BinaryReader reader = new BinaryReader(fs);

// Пропускаем заголовок файла (14 байтов) без считывания
reader.BaseStream.Seek(14, SeekOrigin.Begin);

// Пропускаем размер структуры без считывания
reader.BaseStream.Seek(4, SeekOrigin.Current);

// Получаем ширину и высоту
int width = reader.ReadInt32();
int height = reader.ReadInt32();

// Пропускаем
reader.ReadInt16();

// Получаем глубину цвета (битов на пиксел)
Int16 bitsPerPixel = reader.ReadInt16();

reader.Close();
fs.Close();

// Выводим информацию
MessageBox.Show(width + " x " + height + " x " + bitsPerPixel * planes);
}

private void button2_Click(object sender, EventArgs e)
{
ShowBMPInfo2(textBox1.Text);
}

Толчком к написаню данного топика послужила статья из журнала MSDN за август 2002 года. Там же вы можете найти код для Visual Basic.NET.

Данный совет также будет помещен в раздел Графика на моем сайте.

Удачного вам программирования!

воскресенье, 31 января 2010 г.

Установка шкурок (skin) к эмулятору в Visual Studio для коммуникаторов Samsung

На Новый год я купил себе новый телефон Samsung GT-i8000 Omnia 2 с Windows Mobile 6.5 и экраном 800х480 на борту. Естественно, разрабатывая программы для своего мобильника в Visual Studio, хочется видеть, как будет выглядеть программа не в абстрактном эмуляторе, а в своем телефоне. К счастью, разработчики из компании Samsung Mobile сделали собственные шкурки для моделей GT-B7300 Omnia Lite, GT-B7330 Omnia Pro, GT-B7620 Armani, GT-i8000 Omnia 2, SPH-i350 Intrepid. Вы можете скачать файлы шкурок и внедрить их в Visual Studio. Я расскажу, как это делается на одном примере для своей модели GT-i8000.

Следует предупредить вас о некоторых особенностях шкурок:

  • Установленные шкурки от Samsung не изменяют функциональность эмулятора Microsoft. То есть, он будет работать как прежде, и никаких новых предустановленных программ, идущих в комплекте к телефонам Samsung, вы не увидите.
  • Некоторые кнопки на устройстве в эмуляторе могут работать некорректно. Поэтому рекомендуется нажимать на эти кнопки не в эмуляторе мышкой, а через обычную настольную клавиатуру.
  • Собственные кнопки устройств от Samsung, такие как кнопка камеры, в эмуляторе не поддерживаются.
  • Размеры самого устройства в эмуляторе нельзя изменять. Некоторые модели настолько большие, что могут не помещаться полностью на экране вашего монитора. Попробуйте увеличить разрешение вашего монитора.

Системные требования

Чтобы использовать эмуляторы для Samsung-телефонов, необходимо иметь Windows 7, Visual Studio 2008 Professional (и выше), Windows Mobile 6 SDK Refresh и Windows Mobile 6.5 Developer Tool Kit.

Установка

Дальше пошагово расскажу процесс установки шкурки.

  1. Скачиваем пакет эмуляторов (около 6 мб), в котором содержатся все вышеперечисленные эмуляторы телефонов. Сами шкурки для эмуляторов состоят из нескольких файлов XML и PNG. В файле XML содержится информация о размерах экрана, раскладке клавиатуры и другие конфигурационные данные. Картинки в формате PNG содержат изображения самого телефона в различных состояниях.
  2. Распаковываем файл DeviceSkins.zip и копируем файлы в удобное для вас место. По умолчанию, стандартные шкурки телефонов хранятся в папке C:\Program Files\Windows Mobile 6 SDK\PocketPC\DeviceemulationV650 или C:\Program
    Files\Windows Mobile 6 SDK\Smartphone\DeviceemulationV650. Но вы можете выбрать свою папку, например, на диске D:\.
  3. Запускаем Visual Studio и открываем меню Tools Options. В диалоговом окне Options открываем раздел Device Tools Devices. В списке Devices выбираем подходящую модель для нашего телефоноа. В моем случае мне подходит модель USA Windows Mobile 6.5 Professional WVGA. Для модели GT-B7330 Omnia Pro следует выбрать USA Windows Mobile 6.5 Standard Square Emulator.

  4. Выделив нужную модель, щелкните на кнопке Save As и введите имя для сохраняемой модели, например, Samsung GT-i8000 Omnia 2.

  5. После сохранения в списке появится ваш телефон. Выделите его и нажмите на кнопку Properties. У вас откроется новое диалоговое окно.


  6. Щелкните на кнопке Emulator Options, чтобы открыть еще одно диалоговое окно.
  7. Перейдите на вкладку Display и для переключателя Skin укажите местоположение XML-файла, который хранится в папке шкурок вашего телефона. Щелкните кнопку OK.


  8. Возвращаемся к диалоговому окну Options и выбираем раздел Device Tools Form Factors.
  9. В списке Form factors выбираем опять подходящую модель эмулятора, как мы это уже делали несколько шагов назад и сохраняем через кнопку Save As под тем же именем, под которым вы собираетесь работать.

  10. Выбираем свой телефон в списке и щелкаем на кнопке Properties.
  11. Снова указывем местоположение XML-файла, в котором содержится информация о шкурке.

Для моделей Omnia II, Omnia Lite, and Armani необходимо временно снять флажок Show skin, ввести новые значения ширины и высоты экрана устройств (480x800 для Omnia II and Armani; 240x400 для Omnia Lite) и установить обратно флажок Show skin. Нажмите кнопку OK, чтобы закрыть окно.



Совет: Если вы собираетесь постоянно работать с эмулятором Samsung, то можете в окне настроек выбрать из списка Default form factor свою модель. В этом случае во время разработки программ в дизайнере форм у вас будет выводиться изображение вашего телефона (об этом чуть позже).

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

Использование шкурки в Device Emulator

С настройками закончено. Теперь мы можем использовать шкурки в эмуляторе при отладке собственных программ. У вас есть два варианта - залить программу на стандартный Device Emulator или запустить эмулятор через Device Emulator Manager. Рассмотрим первый вариант:


  1. Выберите меню Debug Start Debugging.

  2. Выберите из списка нужный вам телефон и щелкните кнопку Deploy.


Ваша программа запустится в эмуляторе Samsung. Так как даже на моем 22-дюймовом мониторе не помещается полностью эмулятор, я развернул его в горизонтальное положение.



Использование шкурки во время разработки

Вы можете использовать внешний вид телефона не только во время запуска программы, но и во время разработки в дизайнере форм. Когда мы устанавливали шкурку, то уже сделали необходимые настройки (настройка Form Factors). Поэтому вам достаточно открыть дизайнер форм, щелкнуть правой кнопкой мыши на самой форме и выбрать пункт Properties. В окне свойств найдите параметр FormFactor и выберите нужный пункт. В данном случае я опять развернул устройство на 90 градусов, чтобы показать, как выглядит устройство в дизайнере форм.



Как видите, после несложной настройки, у вас появилась возможность увидеть свой телефон в Visual Studio. Следующим шагом будет использование SDK от Samsung, чтобы использовать возможности устройства в своих программах, например, акселерометр. Чем я и собираюсь заняться в ближайшее время.

пятница, 6 ноября 2009 г.

Coding4Fun

Если сегодня зайти в книжный магазин и подойти к полке, где выставлены книги по C# или Visual Basic.NET, то глаза... нет, не разбегаются от изобилия названий. Да откуда взяться этому изобилию. Создается впечатление, что издатели тасуют некую колоду, состоящую из карт с подписанными словами. И мы видим на полках книги-близнецы: Полное-руководство-шаг за шагом-самоучитель-за 21 день-неделю-по 15 минут-для профессионалов-новичков-с примерами. Даже обложки одинаковы и выдержаны в одной цветовой гамме. А примеры в книгах для профессионалов на 70% совпадают с примерами в книгах для новичков. Спрашивается, какая между ними разница?
И, как гром среди ясного неба, для меня стало известие, что издательство Символ и его интернет-магазин Books.ru выпустили книгу Coding4Fun.Программируем для удовольствия.
Честно говоря, не ожидал, что в России напечатают эту книгу (и достаточно оперативно).
Сам я давно являюсь постоянным читателем блога Coding4Fun, начиная с самых первых выпусков 2005 года. Уже тогда статьи из блога привлекали меня своей нестандартностью. Несколько раз я не удержался и разместил на своем сайте статьи в вольном переводе. К счастью, недавно появилось русскоязычное зеркало блога, где достаточно оперативно выкладываются новые материалы. Но, к сожалению, по словам координатора русской версии, старые материалы переводиться не будут. А жаль, там встречаются интересные проекты.
Вернемся к книге. В ней представлено 10 проектов из тех примеров, которые были описаны в блоге. Кто-то может спросить, а зачем читать эту книгу. Разве нельзя почитать эти же материалы в блоге? Конечно, можно. Но, иногда чтение книги более продуктивнее и удобнее. Возможно, это дело привычки. Лично мне было приятно держать бумажный вариант на руках и читать главу за главой об интересных примерах.
Примеры поражают своей широтой - здесь есть примеры для Windows, Xbox, ASP.NET, Wiimote, светомузыки и т.д.
Кстати, пусть вас не вводит в заблуждение малое количество проектов. Возьмем, для примера проект InnerTube. В этом проекте описывается процесс взаимодействия с популярным онлайн-сервисом YouTube. Авторы знакомят нас с YouTube API, при помощи которых мы можем скачать нужный ролик. Но это еще не все. Попутно, мы узнаем, как можно сконвертировать скачанный ролик в нужный нам формат, а также синхронизировать полученные материалы с iTunes и Zune. Фактически, в одном проекте описываются три разных задачи, каждая из которых вполне может потянуть на отдельный проект.
Также мне порадовало наличие примеров для Wiimote, так как я являюсь счастливым обладателем приставки Wii. Надеюсь, что у меня дойдут руки для подробного изучения примеров, и я напишу какое-нибудь приложение, использующее возможности Wiimote.
Теперь добавлю ложку дегтя в бочку меда, чтобы не перехвалить книгу. Откровенно говоря, меня удивило, что в текстах книги используется слово броузер. Мне это напомнило далекие 90-е, когда половина людей использовала это слово, а другая половина говорила - браузер. Мне кажется, что на данный момент больше прижился термин браузер. Я даже не поленился, и во время написания этих строчек, запустил поиск в справочной системе Windows 7. По слову броузер было найдено 0 документов.
Второй момент, который мне не понравился - это обложка. Оригинальная обложка американского издания мне нравится больше. Возможно, это дело вкуса. Не будем спорить.
Если вы интересуетесь программированием под .NET Framework как хобби, то эта книга для вас из категории Must Have. Советую вам поторопиться с приобретением книги. Тираж у книги небольшой и, есть предположение, что до книжных прилавков он не дойдет. Самый удобный способ - приобрести через интернет-магазины, например, ОЗОН.
Приятного вам чтения!

суббота, 24 октября 2009 г.

Фотоотчет о посещении офиса Microsoft

Утро 23 октября 2009 было мерзким. На улице шел противный дождь. Еще вчера я взял отгул в счет отпуска на работе и мог спокойно спать. Но пришлось вставать. Ведь отгул я брал не просто так. У меня было запланировано посещение офиса мегакорпорации Microsoft. Дело в том, что меня попросили возглавить московское представительство Microsoft. Впрочем, нет, Билл Гейтс и Стив Балмер еще не созрели для такого предложения.

Я поперся туда в такую погоду по другой причине - Microsoft проводила очередной семинар Techdays в Москве.

В прошлом году семинар проходил в Бауманском Доме Культуры (или как он там называется). На этот раз устроители пригласили разработчиков к себе в логово. Упускать такой шанс было нельзя.

Преодолев стойкое желание поспать, я встал и стал собираться. Холодильник был пустой, если не считать замороженного мяса. Мясо предназначалось коту, я не имел права отнимать у него последний кусок. Попил пустой чай и поехал через всю Москву в Крылатское. Вся надежда была на Microsoft, которая не даст умереть с голоду разработчика под платформу Windows.

Мои надежды оправдались - в фойе, где проходила регистрация, были накрыты столы с пирожками, а также стояли термосы с чаем/кофем. Семинар проходил целый день с 10.00 до 19.00. Через каждый час устраивались перерывы - народ ломился из учебного зала, чтобы подкрепиться. Тут Microsoft не подкачал. Молодые девушки и юноши успевали к каждому такому перерыву обновлять содержимое стола. Кроме пирожков, появились также вкусные бутерброды, соки, минеральная вода.

Во время перерыва я изобразил из себя праздношатающего зеваку и стал обследовать офис. Конечно, в закрытые двери ломиться я стал, а просто прошелся по коридору. И, неожиданно, оказался в кафе для сотрудников и посетителей Windows Vista Cafe. В кафе оказалось четыре компа (два не работало), подключенных к интернету. Также имелась пара автоматов XBox. Повсюду были шарики по случаю релиза Windows 7 и Visual Studio 2010 beta.

На семинаре одному из участников достался приз - фирменная банка пива Windows 7. Интересно, можно ее купить где-нибудь?

О самом семинаре рассказывать не буду. Все равно все материалы устроители выложат на сайте.

После окончания семинара всех также угостили пивом и фирменными тортами с надписями MSDN и Windows 7. Решение объединить два продукта мне показалось спорным (я о пиве и торте). Лично я сначала выпил бокал пива, а потом уже стал пить чай с тортом. Рядом со мной находился человек, который совершал обряд в обратном порядке. Не знаю, не знаю.

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

По традиции всех участников одарили блокнотами, ручками, брошюрами. А вот футболки стали приятным сюрпризом. Только почему-то всегда дарят белые футболки (ворчу про себя).

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

Спасибо, Microsoft. Было очень вкусно.










четверг, 22 октября 2009 г.

WM_APPCOMMAND

Недавно в справочник по функциям Windows API я добавил новый материал - описание сообщения WM_APPCOMMAND. Предлагаю вашему вниманию рассказ об этом интересном сообщении в сжатом виде. Само сообщение объявляется следующим образом:

private const int WM_APPCOMMAND = 0x319;

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

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

private const int APPCOMMAND_VOLUME_MUTE = 0x8 * 0x10000;

private void button2_Click(object sender, EventArgs e)
{
// выключаем/включаем микшер
SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_MUTE);
}

Обратите внимание, что микшер включается или выключаетя циклически, т.е. для включения микшера нужно еще раз послать данное сообщение.

Также можно увеличивать или уменьшать уровень громкости микшера(константы APPCOMMAND_VOLUME_DOWN и APPCOMMAND_VOLUME_UP). Кроме того, среди используемых констант можно найти управление микрофоном, браузером или универсальным проигрывателем. Вот как можно поставить на паузу Windows Media Player из своей программы:

private const int APPCOMMAND_MEDIA_PLAY_PAUSE = 0x14 * 0x10000;

SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_MEDIA_PLAY_PAUSE);

Полный список доступных констант вы найдете в справочнике. Хочу обратить ваше внимание, что все значения констант в сообщении WM_APPCOMMAND необходимо умножить на 0x10000, что я и сделал в предыдущих примерах. Используются ли данные константы без умножения в других сообщениях , я не знаю. Кто в курсе - отзовитесь.

Кстати, при изучении документации MSDN, я обнаружил еще одну интересную константу APPCOMMAND_DWM_FLIP3D, который включает режим FLIP 3D в Windows 7 (Кстати, сегодня первый день розничной продажи Windows 7).

Удачного вам программирования!

воскресенье, 23 августа 2009 г.

Кнопка Пуск и панель задач в Windows 7

Недавно я установил себе новую операционную систему Windows 7. Свои первые впечатления о системе я описал в личном блоге. С появлением новой системы приходится пересматривать старые проекты, чтобы убедиться в работоспособности прежних проектов. Один из таких примеров - поведение кнопки Пуск. В своем справочнике по функциям Windows API для .NET Framework я использовал пример скрытия кнопки Пуск, а также панели задач, области уведомлений и часов. Все, кроме кнопки Пуск, работает замечательно. Вот только кнопка Пуск не желает исчезать. Ее можно скрыть только с панелью задач, но никак не отдельно. На сайте CodeProject приводится пример, в котором по утверждению автора, кнопка исчезает. Но тут есть одна проблема - в его коде используется слово Start для кнопки Пуск. Возможно, его пример работает в американской версии Windows, но в русской версии кнопка не исчезает. Я пробовал изменить слово на Пуск в коде, но это тоже не принесло результата.
Также на CodeProject имеется другой пример для работы с кнопкой. Но он также мне ничем не помог.
Сам пример описан в моей книге C#.Советы программистам, поэтому нет смысла его приводить здесь. Просто имейте в виду, что пример с кнопкой Пуск из книги в Windows 7 работать не будет.

суббота, 13 июня 2009 г.

Windows Mobile

Сегодня новости будут посвящены платформе Windows Mobile. Во-первых, недавно был запущен Русский блог Windows Mobile. Материалы для блога готовит команда из нескольких человек. Ребята с энтузиазмом взялись за работу, очень активно переводят статьи из зарубежных блогов. Качество перевода пока оставляет желать лучшего, но, надеюсь, это временные проблемы. Советую занести адрес блога в закладки.
На моем сайте также появилось несколько новых материалов. Например, статья о разработке виджетов для Windows Mobile 6.5. На самом деле, эта тема более обширна, чем изложено в статье. Я также написал расширенный вариант для одного журнала. Посмотрим, опубликуют ли статью.
Кроме того, Андрей Коновалов (кстати, один из лучших участников блога о Windows Mobile) на Хабре стал публиковать статьи Криса Крафта, того самого человека, который обещал за тридцать дней написать тридцать приложений. Я сам подумывал о переводах этого цикла, но времени совсем нет. Поэтому я решил использовать с небольшими сокращениями переводы Андрея, внося свои изменения. Вот, например, вы можете прочитать первую статью Обратный отсчёт до полуночи.
Обратите внимание, кстати, что вышел набор разработчика Windows Mobile 6.5 DTK. В этом наборе появилось несколько новых эмуляторов с различными разрешениями. После установки эмуляторов, вы можете использовать их и для старых проектов. Например, для Windows Mobile 6.1 есть модели с разрешением 800х400. Раньше нельзя было посмотреть в эмуляторе, как выглядит ваше приложение на экране с таким разрешением. Теперь это стало возможным. Сам проект не обязательно компилировать под новую платформу, просто запускайте нужный эмулятор.
И последнее. Как вы знаете, в этому году у меня вышла книга Программирование для мобильных устройств под управлением Windows Mobile. Хочу провести небольшую акцию - за 250 рублей вы можете приобрести эту книгу + получите годовую подписку на мой справочник по Windows API для .NET Framework. В эту цену входит и почтовая доставка. Так как количество книг ограничено, то вам сначала нужно написать мне письмо о своем желании (rusproject@mail.ru) и я вам вышлю свой номер кошелька WebMoney (также можно перечислить Яндекс-деньгами). Акция расчитана на жителей России. Заказывайте!
Удачного вам программирования!