Получение отдельных пикселей другого окна с помощью BitBlt

Это то, что я сейчас делаю:

  • получить DC окна через GetWindowDC
  • создайте совместимый DC с CreateCompatibleDC
  • позвонить GetPixel на мой совместимый контроллер домена

К сожалению, все мои вызовы GetPixel возвращают CLR_INVALID. Вот мой код.

bool Gameboard::Refresh()
{
  bool  ret = false;
  HDC   context, localContext;

  context = GetWindowDC(m_window);
  if (context != NULL)
  {
    localContext = CreateCompatibleDC(context);
    if (localContext != NULL)
    {
      if (BitBlt(localContext, 0, 0, GameboardInfo::BoardWidth, GameboardInfo::BoardHeight,
        context, GameboardInfo::TopLeft.x, GameboardInfo::TopLeft.y, SRCCOPY))
      {
        ret = true;
        // several calls to GetPixel which all return CLR_INVALID
      }
      DeleteDC(localContext);
    }
    ReleaseDC(m_window, context);
  }
  return ret;
}

Любые идеи?


person Community    schedule 02.01.2012    source источник


Ответы (1)


Я считаю, что вам нужно выбрать растровое изображение в контексте вашего устройства.

«Растровое изображение должно быть выбрано в контексте устройства, в противном случае CLR_INVALID возвращается для всех пикселей». - GetPixel()

bool Gameboard::Refresh()
{
  bool  ret = false;
  HDC   context, localContext;


  HGDIOBJ origHandle;


  context = GetWindowDC(m_window);
  if (context != NULL)
  {
    localContext = CreateCompatibleDC(context);


    origHandle = SelectObject(localcontext,CreateCompatibleBitmap(context, GameboardInfo::BoardWidth, GameboardInfo::BoardHeight));


    if (localContext != NULL)
    {
      if (BitBlt(localContext, 0, 0, GameboardInfo::BoardWidth, GameboardInfo::BoardHeight,
        context, GameboardInfo::TopLeft.x, GameboardInfo::TopLeft.y, SRCCOPY))
      {
        ret = true;
        // several calls to GetPixel which all return CLR_INVALID
      }

      SelectObject(localcontext, origHandle);


      DeleteDC(localContext);
    }
    ReleaseDC(m_window, context);
  }
  return ret;
}
person Motes    schedule 02.01.2012
comment
Я почти уверен, что значения x/y в моих вызовах GetPixel уже являются смещениями, а не абсолютными местоположениями. - person ; 02.01.2012
comment
Вам все еще нужно выбрать растровое изображение в совместимый DC, иначе BitBlt некуда будет копировать пиксели. Кроме того, используйте GetDIBits — это намного быстрее, чем использование GetPixel. - person Roger Lipscombe; 02.01.2012
comment
@RogerLipscombe Что, если мне нужно только 64 пикселя из квадрата 480x480? GetDIBits по-прежнему быстрее? - person ; 02.01.2012
comment
Любая расширенная информация об ошибке? API-интерфейсы Win 32 обычно не зависают без каких-либо ошибок, по крайней мере, в отладчике. - person Motes; 03.01.2012
comment
Если вы получаете более одного пикселя, CreateComaptilbeBitmap(hDC,nWidth,nHieght). Если вы хотите вместо этого использовать GetDIBits, вы не используете BitBlt. GetDIBits возвращает указатель на сами биты, так что вы можете просматривать или проверять их самостоятельно, или вы можете использовать CreateDIBSection и StretchDIBits для копирования только тех битов, которые вы хотите проверить. - person Motes; 03.01.2012
comment
Внезапная мысль: указатель на биты можно эффективно преобразовать в COLORREF*, верно? - person ; 05.01.2012
comment
См. stackoverflow.com/questions/ 3688409/ о том, как использовать getdibits для получения массива пикселей. Да, я думаю, вы могли бы перевести точку в буфер на COLORREF* и перейти к следующему пикселю с помощью myCOLORREF += 4; - person Motes; 06.01.2012
comment
На самом деле COLORREF имеет порядок цветов 0x00bbggrr, цвета из getdibits будут иметь порядок байтов 0xrrggbb00, поэтому не следует использовать colorref, если вы не хотите изменить порядок байтов на противоположный - person Motes; 06.01.2012