Поиск:

Ответ в темуСоздание новой темы Создание опроса
> StretchBlt работает не на всех компах, Не работает на XP без установленной VS. 
:(
    Опции темы
Dreamer_0x01
  Дата 29.11.2010, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Здравствуйте. Обнаружил в программе глюк - во время печати используется функция StretchBlt() в контекст принтера. Корректно работает только на тех компах, где либо установлена Вижуал Студия, либо установлена Виндоу 7. На ВинХР без установленной "вижуал студии" не работает. 
Причем, все остальное, то что выводится не через StretchBlt(), а функциями рисования - работает везде.

Свел код вот к такому минимуму. Есть какое-то окно, производное от CWnd, в котором делается прорисовка на экран.
При печати вывожу на принтер информацию из этого окна с помощью StretchBlt(), а дополнительную информацию вывожу функциями рисования (типа TextOut(), LineTo() и др.) напрямую в контексте принтера.

Собственно, сам код:

Вот это класс, в котором что-то рисую на экране:
Код

class Donor : public CWnd
{
    DECLARE_DYNAMIC(Donor)
public:
    Donor();
    virtual ~Donor();
protected:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnPaint();
};

void Donor::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CWnd::OnPaint() for painting messages
    CRect r;
    dc.GetClipBox(r);
    dc.Ellipse(r);
}


А это уже код, с помощью которого вывожу содержимое окна на печать.


Код


//ранее объявлено:    Donor m_donor;

void CSBltPrintTestDlg::OnBnClickedButtonPrint()
{
    HDC hdcPrinter = NULL;
    CPrintDialog dlgPrint(FALSE);

    if(IDOK != dlgPrint.DoModal())return;;

    hdcPrinter = dlgPrint.GetPrinterDC();
    if (hdcPrinter == NULL)
    {
        MessageBox(_T("Не удалось сконфигурироваь принтер"));
        return;
    }

   CDC dcPrinter;
   dcPrinter.Attach(hdcPrinter);

   DOCINFO docinfo;
   memset(&docinfo, 0, sizeof(docinfo));
   docinfo.cbSize = sizeof(docinfo);
   docinfo.lpszDocName = _T("Тестовая_печать");

   if (dcPrinter.StartDoc(&docinfo) < 0)
   {
      MessageBox(_T("Printer wouldn't initalize"));
   }
   else
   {
      if (dcPrinter.StartPage() < 0)
      {
         MessageBox(_T("Could not start page"));
         dcPrinter.AbortDoc();
      }
      else 
      {
        CRect rCl,rc;
        m_donor.GetClientRect(rCl);
        dcPrinter.GetClipBox(rc);
        CDC * dcSRC = m_donor.GetDC();

        dcSRC->SetMapMode(dcPrinter.GetMapMode());
        dcPrinter.SetStretchBltMode(HALFTONE);
        dcPrinter.SetBrushOrg(0,0);

        dcPrinter.StretchBlt(rc.left, rc.top, rc.Width(), rc.Height(), dcSRC,0, 0, rCl.Width(),rCl.Height(),SRCCOPY);
        m_donor.ReleaseDC(dcSRC);

        dcPrinter.MoveTo(0,0);
        dcPrinter.LineTo(dcPrinter.GetDeviceCaps(HORZRES),dcPrinter.GetDeviceCaps(VERTRES)/2);
        dcPrinter.EndPage();
        dcPrinter.EndDoc();
      }
   }
   dcPrinter.Detach();

}


Подскажите, в чем может быть проблема?

Прикладываю тестовый проект с исходниками. (Печать по кнопочке "StretchBlt to printer context").








Это сообщение отредактировал(а) Dreamer_0x01 - 29.11.2010, 21:05

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  SBltPrintTest.rar 132,70 Kb


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Dreamer_0x01
Дата 1.12.2010, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Так что, ни у кого никаких идей нет?
Проверьте хотя бы, наблюдается ли этот глюк на вашем компе.
МОжет, это только у меня такая хрень?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Albor
Дата 2.12.2010, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 7
Всего: 9



Проверил на XP Pro версия 2002, SP3. При печати выводится только прямая линия. Окружности нет. Студия на машине установлена.
PM MAIL ICQ   Вверх
Dreamer_0x01
Дата 2.12.2010, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(Albor @  2.12.2010,  11:16 Найти цитируемый пост)
При печати выводится только прямая линия. Окружности нет. Студия на машине установлена.


А какая студия установлена?

И может гляните исходник незамыленным глазом, может, какой-то явный косяк видно?



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Albor
Дата 2.12.2010, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 7
Всего: 9



Цитата(Dreamer_0x01 @  2.12.2010,  12:59 Найти цитируемый пост)
А какая студия установлена?

2008-я. Исходник просмотрел мельком, не знаю... Я как-то пытался копировать картинку, так-же в тестовом диалоговом проекте, по нажатию кнопки, получая контекст через GetDC() - у меня что-то не получилось, хотя тот же код работал в OnCtrlColor с тем контекстом, который в неё передаётся. 
PM MAIL ICQ   Вверх
Dreamer_0x01
Дата 2.12.2010, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Проверил, StretchBlt возвращает FALSE.
А GetLastError() возвращает 87.

Посмотрел в справочнике, кот этой ошибки означает вот что:

ERROR_INVALID_PARAMETER(87): The parameter is incorrect. 

А что тут может быть инкорректным?



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Albor
Дата 3.12.2010, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 7
Всего: 9



Цитата(Dreamer_0x01 @  2.12.2010,  19:22 Найти цитируемый пост)
А что тут может быть инкорректным?

По логике - CDC. Остальное просто числа. Хотя и числа могут не соответствовать координатам.

PM MAIL ICQ   Вверх
Earnest
Дата 3.12.2010, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Dreamer_0x01, конкретно ничего сказать не могу, кроме одного: в коде MFC, который вызывает печать документа очень много букв, гораздо больше, чем у тебя - между получением принтера и вызовом OnPrint. Все какие-то параметры устанавливаются. Посмотри код CView::OnFilePrint(), может что-то извлечешь полезное.
От себя могу сказать, что моя программа тоже при печати использует StretchBlt, и проблем вроде бы не было. Но она вызывает печать стандартным образом, через View::OnFilePrint.



--------------------
...
PM   Вверх
Dreamer_0x01
Дата 3.12.2010, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(Earnest @  3.12.2010,  19:49 Найти цитируемый пост)
Посмотри код CView::OnFilePrint()

Где его посмотреть?

Добавлено через 1 минуту и 28 секунд
Цитата(Earnest @  3.12.2010,  19:49 Найти цитируемый пост)
моя программа тоже при печати использует StretchBlt


А тот контекст, из которого копируется содержимое в контекст принтера - у тебя он какого типа и как ты его получаешь?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Earnest
Дата 6.12.2010, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Dreamer_0x01 @  3.12.2010,  22:42 Найти цитируемый пост)
Где его посмотреть?

В коде MFC, где же еще. 
Цитата(Dreamer_0x01 @  3.12.2010,  22:42 Найти цитируемый пост)
А тот контекст, из которого копируется содержимое в контекст принтера - у тебя он какого типа и как ты его получаешь? 

Точно сказать не могу, досконально разбираться времени нет, там очень много букв в разных местах. Но код рисования общий - что на экран, что на принтер, только контекст меняется + функции установки координат. Но насколько помню, StretchBlt используется для прямого вывода растров в форме DIB, причем разной цветности. Контекст же передается из оболочки MFC; не знаю точно, как оно его извлекает, когда-то разбиралась, но давно забыла. Вот я и говорю - посмотри код. 



--------------------
...
PM   Вверх
Dreamer_0x01
Дата 18.1.2011, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Хрень какая-то. BitBlt работает, а StretchBlt хоть об стенку убейся, с теми же контекстами не пашет.



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Dreamer_0x01
Дата 19.1.2011, 00:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Чем дальше, тем прикольнее. Если выводить в контекст принтера с помощью BitBlt, то печатается, но естественно изображеине получается очень маленьким. 
Тогда делаю так - создаю еще один контекст и битмап в памяти, на него с помощь StretchBlt масштабирую свой рисунок, и уже с этого контекста делаю BitBlt. Симптом тот же - на тех же компах снова не работает, на других по-прежнему работает.
Такое чувство, что работоспособность этих функций зависит от размера прорисовываемой области в пикселах.


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Dreamer_0x01
Дата 19.1.2011, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



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

То есть на тех компах, где контекст принтера возвращается небольшим, и увеличение изображения происходит примерно в 5-6 раз, все печатается нормально.
А там, где разрешение принтера превосходит разрешение исходного контекста раз в 10-15, растровая операция уже ничего не выводит.

Что делать-то?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Dreamer_0x01
Дата 20.1.2011, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(Earnest @  3.12.2010,  19:49 Найти цитируемый пост)
в коде MFC, который вызывает печать документа очень много букв, гораздо больше, чем у тебя - между получением принтера и вызовом OnPrint. Все какие-то параметры устанавливаются. Посмотри код CView::OnFilePrint(), может что-то извлечешь полезное.



Я не только посмотрел, но еще и эксперимент провел.
Сделал проект на архитектуре SDI. 
Нарисовал простецкий рисунок во View.
Сделал печать в обработчике OnPrint  с момощью StretchBlt.

И тот же самый эффект - не работает на тех же компах, что и моя программа, сделанная на диалоге.

Я вообще в шоке, что делать...Еще чуток, и я лишусь этого заказа, так как все уже давно сделано, но не подписать акт о завершении из-за этой долбанной печати, причем один из компов, на котором печать не работает, оказался как назло естественно именно у заказчика =(




--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Earnest
Дата 21.1.2011, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Dreamer_0x01, а посмотри-ка GetDeviceCaps. В том смысле, что разные устройства поддерживаю разные возможности. Скорее всего, это что-то из разряда RASTERCAPS. Если удастся найти зависимость между результатом GetDeviceCaps и работой функции, нужно думать в направлении замены реализации вывода. Например, ты вроде говорил о том, что BitBlt маленького кусочка работает всегда.


--------------------
...
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0561 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.