Копирование экрана

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

Всё-таки, можно через Bitblt?
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
&quot писал(а):На cout внимания не обращай, т.к. они использованы для отладочного вывода ссообщений в случае ошибки. Можешь заменить на WINAPI-шный MessageBox или что там есть специфического в Борланде (ShowMessage?)
Воще не надо. Трассировщиком прогоню без свяких мессаг, за то в релизе точно не останутся. Контрольный же TImage останется. Его назначение - дать юзверю возможность ещё раз проверить правльность выделения фрагмента. В окне TImageа ещё можно будет поменять масштаб на крупный и проскролить картинку по обеим осям.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

atavin-ta писал(а):Всё-таки, можно через Bitblt?
А в чем проблема-то? Почему нельзя?

Я нашел свой пробный (тестовый) кусок. Но он писан был на MS C++, MFC. Там используется не BitBlt, а StretchBlt. Чтобы как раз отмасштабировать на всю клиентскую область окна. В общем, писалось это досаточно давно, вываливаю кусок кода as is.
Код именно "тестовый", так как каждый раз в прилагаемом обработчике OnPaint картинка грузится из файла. Т.е. цель этого кода - именно убедиться, что картинка рисуется в окне.

Код: Выделить всё

void CBitmapIggle::OnPaint()
{
//  CStatic::OnPaint ();

  CPaintDC dc (this); // device context for painting

 // load IDB_BITMAP1 from file
  HBITMAP hBMP = 0;
  if (hBMP == 0) {

     GFL_ERROR iGFLerror;
     GFL_LOAD_PARAMS rLoadParams;
     //---------------------
      if ((iGFLerror = gflLibraryInit ()) != GFL_NO_ERROR) {
        return;
      };
      gflGetDefaultLoadParams (&rLoadParams);
      if ((iGFLerror = gflLoadBitmapIntoDDB (
          "D:\\TEMP\\IMG_5324_TRUNCATED.JPG",
             &hBMP, //  GFL_BITMAP ** bitmap,
             &rLoadParams, // GFL_LOAD_PARAMS * params,  
             NULL // &rInformations // GFL_FILE_INFORMATION * informations,  
          )) != GFL_NO_ERROR) {
        return;
      };

      gflLibraryExit ();
  };

  if (hBMP)
   {
      HDC hImageDC;
      hImageDC = CreateCompatibleDC (dc.m_ps.hdc);

     // Select the bitmap into the in-memory DC
      HBITMAP hOldBitmap = 0;
      hOldBitmap = (HBITMAP)SelectObject (hImageDC, hBMP);
      // Find a centerpoint for the bitmap in the client area
      CRect rect;
      GetClientRect (&rect);
      int nX = 0;
      int nY = 0;

      // Copy the bits from the in-memory DC into the on-
      // screen DC to actually do the painting. Use the centerpoint
      // we computed for the target offset.

    BITMAP              bm;
    GetObject (hBMP, sizeof(bm), &bm);    // get size of bitmap

      ::SetStretchBltMode (dc.m_ps.hdc, HALFTONE);
      ::StretchBlt (dc.m_ps.hdc, nX, nY, rect.Width (), rect.Height (),
                    hImageDC,
                   0, 0,
                   bm.bmWidth,bm.bmHeight,
                   SRCCOPY);
      DeleteObject ((HBITMAP)SelectObject (hImageDC, hOldBitmap));
      DeleteDC (hImageDC);   // добавлено 16.10.2009 (похоже, ошибочка была - не было этого вызова)

   };


};  // CBitmapIggle::OnPaint()
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

Различие в назначении bitblt и strechblt я знаю. Мне лучше файл снять в натуральном масштабе (пиксел в пиксел), а масштабирование поручить каждому компу, на который буду грузить, так как размеры TImageов у всех разные. И я знаю, как реализовать масштабирование средствами TImageа. Поэтому лучше bitblt. Так пойдёт:

Код: Выделить всё

 void CopyRect(TImage *Image, RECT Rect, AnsiString s)
 {
  HDC DisplayContext;
  HDC ImageContext;
  HBITMAP Handle;
  Image->Picture->Bitmap->Width =Rect.right   -Rect.left;
  Image->Picture->Bitmap->Height=Rect.bottom-Rect.top;
  DisplayContext=GetDeviceContext(NULL);
  ImageContext=CreateCompatibleDC(DisplayContext);
  Handle=(HBITMAP)SelectObject(ImageContext,*Image->Picture->Bitmap->Handle);
  BitBlt(DisplayContext,Rect.left,Rect.top,Rect.right-Rect.left,Rect.bottom-Rect.top,ImageContext,0,0);
  DeleteObject ((HBITMAP)SelectObject(ImageContext, Handle));
  DeleteDC(ImageContext);
  DeleteDC(DisplayContext);
  Image->Picture->Bitmap->SaveToFile(s); 
 }
?
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

atavin-ta писал(а):Так пойдёт?
Эээ... Ну так пробуй! :) ))

Походу, я в своем примере ошибочку нашел. Не освобождается hImageDC, созданный через CreateCompatibleDC (нет вызова DeleteDC).
Но у тебя ImageContext как раз удаляется.
Но зато также удаляется DisplayContext, чего делать, как я понимаю, как раз не стоит. Т.к. DisplayContext не создавался тобой, а был получен через GetDeviceContext.
Я, правда, не очень понял, что такое GetDeviceContext (это не что-то специфическое для Борланда?)
Может, для DisplayContext надо сделать ReleaseDC?
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

&quot писал(а):получен через GetDeviceContext.
Я, правда, не очень понял, что такое GetDeviceContext (это не что-то специфическое для Борланда?)
Может, для DisplayContext надо сделать ReleaseDC?
Учи API! Это одна из функций создания контекста на основе хендла окна.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

&quot писал(а):Учи API! Это одна из функций создания контекста на основе хендла окна.
atavin-ta, это ты учи API :) GetDeviceContext - это не Win API функция, а примочка VCL.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

Какой к фигам вцл? Я так под мелкософтом писал. И у Петзолда видел. А унего вцл не рассмотрен.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Что-то путаешь.

1. MSDN 2005 функции не знает.
2. Все ссылки в google ведут в код, написанный на Delphi. Если бы эта функция была Win API, то первая же ссылка в поисковике вела бы в online версию MSDN.

Если тебе этих аргументов не достаточно, то скажи в каком хедере в Microsoft Visual Studio эта функция лежит либо из какой системной библиотеке Windows она экспортируется. Думаю, ты на этот вопрос ответить не сможешь.

P.S. Только давай без объяснений на страницу. Мне нужны только факты либо короткий ответ "Не бейте, облажался" :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Romeo писал(а): 1. MSDN функции GetDeviceContext не знает.
2. Все ссылки в google ведут в код, написанный на Delphi.
Во-во. У меня та же фигня.
MSDN на GetDevice... дает только GetDeviceCap :)
atavin-ta
Сообщения: 585
Зарегистрирован: 30 янв 2009, 06:38

Спросите у Чарлза Петзода.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Ответить