Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Печать TImage

Самый простой способ напечатать TImage, это воспользоваться методом print в TForm, которая содержит только битмап. Этот способ работает, однако такая картинка напечатается либо очень маленькой, либо вообще не напечатается. Следующий код позволяет напечатать TImage на всю страницу. Так же Вы можете изменить масштаб и напечатать картинку любого размера.

Замечание: картинка должна содержать Bitmap.

/*-----------------------------------------------------------------------
Эта функция является обработчиком события OnClick для TButton, которая
находится на TForm. На TForm также присутствует TImage с именем image.
------------------------------------------------------------------------*/
void __fastcall Tmain_form::print_image_btnClick(TObject *Sender)
{
    TPrinter *p = Printer();

    // создаём в памяти dc для картинки
    HDC h_dc = image->Picture->Bitmap->Canvas->Handle;
    int bmp_w = image->Picture->Bitmap->Width,
    bmp_h = image->Picture->Bitmap->Height;
    HDC h_mem_dc = ::CreateCompatibleDC (h_dc);
    HBITMAP h_mem_bmp = ::CreateCompatibleBitmap (h_dc, bmp_w, bmp_h);
    HBITMAP h_old_bmp = ::SelectObject (h_mem_dc, h_mem_bmp);

    // фиксируем ошибки видео драйверов
    bool is_pal_dev = false;
    LOGPALETTE *pal;
    HPALETTE h_pal, h_old_pal;

    if (::GetDeviceCaps (image->Canvas->Handle, RASTERCAPS) & RC_PALETTE)
    {
        pal = static_cast(malloc (sizeof (LOGPALETTE) +
                                        (sizeof (PALETTEENTRY) * 256)));
        memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
        pal->palVersion = 0x300;
        pal->palNumEntries = ::GetSystemPaletteEntries(image->Canvas->Handle, 0,
                                                         256, pal->palPalEntry);
        if (pal->palNumEntries != 0)
        {
            h_pal = ::CreatePalette (pal);
            h_old_pal = ::SelectPalette (h_mem_dc, h_pal, false);
            is_pal_dev = true;
        }
        else
        {
            free (pal);
        }
    }

    // копируем картинку на dc в памяти
    ::BitBlt (h_mem_dc, 0, 0, bmp_w, bmp_h, h_dc, 0, 0, SRCCOPY);

    if (is_pal_dev)
    {
        ::SelectPalette (h_mem_dc, h_old_pal, false);
        ::DeleteObject (h_pal);
    }

    // удаляем dc в памяти
    ::SelectObject (h_mem_dc, h_old_bmp);
    ::DeleteDC (h_mem_dc);

    // выделяем память для структуры BITMAPIFO
    HANDLE h_bmp_info = ::GlobalAlloc (GHND,
                            sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 256));
    BITMAPINFO* bmp_info = static_cast(::GlobalLock (h_bmp_info));
    //Заполняем структуру
    memset (bmp_info, NULL, sizeof (BITMAPINFO) + (sizeof (RGBQUAD) * 255));
    bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmp_info->bmiHeader.biPlanes = 1;
    bmp_info->bmiHeader.biBitCount = 8;
    bmp_info->bmiHeader.biWidth = bmp_w;
    bmp_info->bmiHeader.biHeight = bmp_h;
    bmp_info->bmiHeader.biCompression = BI_RGB;

    // определяем размер памяти для битов
    ::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, NULL, bmp_info, DIB_RGB_COLORS);

    // Выделяем память для битов
    HANDLE h_bits = GlobalAlloc (GHND, bmp_info->bmiHeader.biSizeImage);
    void *bits = ::GlobalLock (h_bits);

    // получаем биты
    ::GetDIBits (h_dc, h_mem_bmp, 0, bmp_h, bits, bmp_info, DIB_RGB_COLORS);

    // фиксируем ошибки видео драйверов
    if (is_pal_dev)
    {
        for (int i = 0; i palNumEntries; i++)
        {
            bmp_info->bmiColors[i].rgbRed = pal->palPalEntry[i].peRed;
            bmp_info->bmiColors[i].rgbGreen = pal->palPalEntry[i].peGreen;
            bmp_info->bmiColors[i].rgbBlue = pal->palPalEntry[i].peBlue;
        }
        free (pal);
    }

    // начинаем печать
    p->BeginDoc ();

    // масштабируем размер печати
    int scale_x, scale_y;
    if (p->PageWidth PageHeight)
    {
        scale_x = p->PageWidth;
        scale_y = image->Picture->Height * (p->PageWidth / bmp_w);
    }
    else
    {
        scale_x = image->Picture->Width * (p->PageHeight / bmp_h);
        scale_y = p->PageHeight;
    }

    // устанавливаем палитру печати
    is_pal_dev = false;
    if (::GetDeviceCaps (h_dc, RASTERCAPS) & RC_PALETTE)
    {
        pal = static_cast(malloc (sizeof (LOGPALETTE) +
                                          (sizeof (PALETTEENTRY) * 256)));
        memset (pal, 0, sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256));
        pal->palVersion = 0x300;
        pal->palNumEntries = 256;
        for (int i = 0; pal->palNumEntries; i++)
        {
            pal->palPalEntry[i].peRed = bmp_info->bmiColors[i].rgbRed;
            pal->palPalEntry[i].peGreen = bmp_info->bmiColors[i].rgbGreen;
            pal->palPalEntry[i].peBlue = bmp_info->bmiColors[i].rgbBlue;
        }
        h_pal = CreatePalette(pal);
        free (pal);
        h_old_pal = SelectPalette(p->Canvas->Handle, h_pal, false);
        is_pal_dev = true;
    }

    // посылаем биты на принтер
    StretchDIBits(p->Canvas->Handle, 0, 0, scale_x, scale_y,
		0, 0, bmp_w, bmp_h, bits,bmp_info, DIB_RGB_COLORS, SRCCOPY);

    // конец печати
    p->EndDoc ();

    // освобождаем ресурсы
    ::DeleteObject (h_mem_bmp);
    if (is_pal_dev)
    {
        ::SelectObject (p->Canvas->Handle, h_old_pal);
        ::DeleteObject (h_pal);
    }
    ::GlobalUnlock (bits);
    ::GlobalFree (h_bits);
    ::GlobalUnlock (bmp_info);
    ::GlobalFree (h_bmp_info);
}

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
Аноним
+1 / -0
Мне нравитсяМне не нравится
26 декабря 2004, 10:59:24
Интересно, а кто-нибудь проверил этот пример? Ну содрали его с поддержки борланда, причем он и там с ошибками... Например, синтаксис: static_cast< T > (arg), т.е. надо так: pal = static_cast<LOGPALETTE *>(malloc(sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * 256))), ну и так далее... Фуфловый пример, не рабочий - либо исправляйте, либо убирайте, не путайте народ...
2.
Аноним
Мне нравитсяМне не нравится
2 ноября 2004, 17:58:42
Если не жалко, то хотелось бы то же увидеть и на Delphi...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог