Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
statusBar1.Text = "Load list (" + iCountMatchs.ToString() + ")…";
// …и заносим информацию о них в лист-бокс.
listBox1.BeginUpdate();
foreach(Match m in mc) {
// Для хранения информации о найденном вхождении
// мы используем созданный нами класс MyItem.
// Элементы управления (типа лист-бокса) в .Net
// позволяют хранить вместо текстового значения
// объект, а при отображении текста в строке вызывают
// метод – ToString. Так что объект любого класса,
// реализующего метод ToString, может выступать в
// качестве элемента лист-бокса.
listBox1.Items.Add(new MyItem(m.ToString(), m.Index, m.Length));
}
} catch(Exception e1) {
MessageBox.Show(e1.ToString(), "Error");
} finally {
listBox1.EndUpdate();
statusBar1.Text = "Done " + iCountMatchs.ToString();
}
}
ЗаключениеЭто только краткое ведение в регулярные выражения и их использование. Если вы хотите лучше разобраться в этом, попробуйте потренироваться в создании регулярных выражений самостоятельно. Практика показывает, что разбор чужих регулярных выражений практически бесполезен, читать их почти невозможно. Однако лучше научиться пользоваться ими – это часто упрощает жизнь.
ВОПРОС – ОТВЕТ
Как вывести на экран картинку в JPEG/GIF/PNG/др. формате?
7 способов как это сделать
Автор: Павел Блудов
Демонстрационное приложение (WTL) DrawImg (50kb)
Сегодня практически все программы используют различные картинки в качестве элементов интерфейса. Даже существует API функция ::LoadImage(), умеющая загружать файлы в формате bmp, ico и cur. Этого достаточно для панелей управления и диалогов. Но если размер картинки превышает 100x100 пикселов и их нужно несколько, файлы формата bmp использовать не удобно. Хочется что-то вроде jpg или gif.
Тут ::LoadImage() нам уже не помошник. Придется использовать специальные библиотеки. Наибольшей популярностью пользуются:
Independent JPEG Group
Portable Network Graphics
TIFF Software
Intel(R) JPEG Library
Image Library
CXImage
Small JPEG Decoder Library
Все они хорошо документированны и снабжены примерами. Подробное рассмотрение этих библиотек займет слишком много времени и выходит за рамки этой статьи. Давайте лучше уделим внимание некоторым специальным API, предназначенным для работы с файлами изображений.
Способ 1 (OleLoadPicture)Самый "официальный" способ. Появился вместе с OLE32 и работает до сих пор. Функции OleLoadPicture(Ex) и OleLoadPicturePath умеют загружать картинки в формате BMP, GIF, JPEG, ICO, WMF, и EMF:
#include <olectl.h>
HRESULT Load(LPCTSTR szFile) {
CComPtr<IStream> pStream;
// Load the file to a memory stream
HRESULT hr = FileToStream(szFile, &pStream);
if (SUCCEEDED(hr)) {
// Decode the picture
hr = ::OleLoadPicture(
pStream, // [in] Pointer to the stream that contains picture's data
0, // [in] Number of bytes read from the stream (0 == entire)
true, // [in] Loose original format if true
IID_IPicture, // [in] Requested interface
(void**)&m_pPicture // [out] IPictire object on success
);
}
return hr;
}
HRESULT DrawImg(HDC hdc, const RECT& rcBounds) {
if (m_pPicture) {
// Get the width and the height of the picture
long hmWidth = 0, hmHeight = 0;
m_pPicture->get_Width(&hmWidth);
m_pPicture->get_Height(&hmHeight);
// Convert himetric to pixels
int nWidth = MulDiv(hmWidth, ::GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
int nHeight = MulDiv(hmHeight, ::GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
// Display the picture using IPicture::Render
return m_pPicture->Render(
hdc, // [in] Handle of device context on which to render the image
rcBounds.left, // [in] Horizontal position of image in hdc
rcBounds.top, // [in] Vertical position of image in hdc
rcBounds.right - rcBounds.left, // [in] Horizontal dimension of destination rect.
rcBounds.bottom - rcBounds.top, // [in] Vertical dimension of destination rect.
0, // [in] Horizontal offset in source picture
hmHeight, // [in] Vertical offset in source picture
hmWidth, // [in] Amount to copy horizontally in source picture
-hmHeight, // [in] Amount to copy vertically in source picture
&rcBounds // [in, optional] Pointer to position of destination for a metafile hdc
);
}
return E_UNEXPECTED;
}
Достоинства: правильно работает с прозрачными картинками.
Недостатки: не поддерживает анимированный GIF (см. также CPicturEx). Не поддерживает PNG.
Способ 2 (GDI+)Недостаток ::LoadImage() с лихвой исправили в GDI+. Объект Gdiplus::Image умеет загружать картинки в формате bmp, gif, jpeg, png, TIFF, EXIF, WMF, и EMF:
#include <gdiplus.h>
HRESULT Load(LPCTSTR szFile) {
USES_CONVERSION;
// Create new Gdiplus::Image object
m_pImage = new Gdiplus::Image(T2CW(szFile));
ATLASSERT(m_pImage);
// Check for success
if (Gdiplus::Ok == m_pImage->GetLastStatus()) return S_OK;
// Cleanup on failure
Destroy();
return E_FAIL;
}
HRESULT DrawImg(HDC hdc, RECT& rcBounds) {
if (m_pImage) {
// Create Gdiplus::Graphics object from HDC
Gdiplus::Graphics graphics(hdc);
// Create Gdiplus::Rect object from RECT
Gdiplus::Rect rc(rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom);
// Draw the image
return Gdiplus::Ok == graphics.DrawImage(
m_pImage, // [in] Gdiplus::Image object
rc // [in] Position and dimensions
) ? S_OK : E_FAIL;
}
return E_UNEXPECTED;
}
Достоинства: понимает множество форматов, в том числе анимированный GIF, правильно работает с прозрачными картинками.
Недостатки: На сегодняшний момент реализован только в WindowsXP. Хотя простое копирование gdiplus.dll в system32 делает ее доступной, как минимум, в Windows2000. Скорее всего, в обозримом будущем ожидаются версии и для Win9x.
Способ 3 (IImgCtx)Не так давно Майкрософт предоставила заголовочные и библиотечные файлы к объекту ImgCtx, появившемуся еще в internet explorer 4.0. Он умеет заргужать картинки в формате BMP, GIF, JPEG, ICO, WMF, EMF, PNG, XBM, ICO, TIFF и, возможно, некоторых других:
#include <IImgCtx.h>
HRESULT Load(LPCTSTR szFile) {
// Create IImgCtx object
HRESULT hr = ::CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_ALL, IID_IImgCtx, (void**)&m_pImage);
if (SUCCEEDED(hr)) {
// Load URL
USES_CONVERSION;
hr = m_pImage->Load(
T2COLE(szFile), // [in] URL
0 // [in] Flags and preffered color format
);
}
return hr;
}
HRESULT DrawImg(HDC hdc, RECT& rcBounds) {
if (m_pImage) {
// Check download state
DWORD dwState = 0;
HRESULT hr = m_pImage->GetStateInfo(&dwState, NULL, true);
if (SUCCEEDED(hr)) {
if (IMGLOAD_LOADING & dwState) {
// Still loading - wait 50 msec and request again
::DrawText(hdc, _T("Loading, please wait..."), -1, &rcBounds, DT_SINGLELINE);
::Sleep(50);
Invalidate(false);
hr = S_FALSE;
} else if (IMGLOAD_COMPLETE & dwState) {
// Download successfully complete
hr = m_pImage->Draw(
hdc, // [in] Handle of device context on which to render the image
&rcBounds // [in] Position and dimensions
);
} else {
// Download failed
hr = E_UNEXPECTED;
}
}
return hr;
}
return E_UNEXPECTED;
}
Достоинства: правильно работает с прозрачными и анимированными картинками. Понимает URL (даже res:// и sysimage://).
Недостатки: не поддерживает загрузку из IStream. Не умеет загружать файлы синхронно.
ПРИМЕЧАНИЕ
Форматов, распознаваемых этим объектом, может быть меньше, например, если при установке IE4 позьзователь отключил поддержку PNG файлов.
Способ 4 (DirectXTransform)Не смотря на название, эта технология не имеет ничего общего с DirectX. Зато является частью Internet Explorer, внутри которого даже имется набор простеньких классов, реализующих IDirectDraw для нужд DirectXTransform. Этот способ поддерживает тот же набор форматов, что и предыдущий, более того, для этого используется один и тот же код. Разве что синхронно и на выходе получается IDXSurface объект.
#include <dxtrans.h>
HRESULT DrawImg(HDC hdc, const RECT& rcBounds) {
if (m_pDCLock) {
HDC hdcImage = m_pDCLock->GetDC();
// Get the bitmap
HGDIOBJ hObj = ::GetCurrentObject(hdcImage, OBJ_BITMAP);
BITMAP bm = {0};
// Get the size of the bitmap
if (hObj && ::GetObject(hObj, sizeof(BITMAP), &bm)) {
// Draw the image
return ::StretchBlt(hdc, rcBounds.left, rcBounds.top,
rcBounds.right - rcBounds.left, rcBounds.bottom - rcBounds.top,
hdcImage, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY
) ? S_OK : E_FAIL;
}
}
return E_UNEXPECTED;
}
HRESULT Load(LPCTSTR szFile) {