0

This is what I am currently doing:

  • get window DC via GetWindowDC
  • create a compatible DC with CreateCompatibleDC
  • call GetPixel on my compatible DC

Unfortunately, all of my GetPixel calls are returning CLR_INVALID. Here is my code.

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;
}

Any ideas?

1 Answers1

1

I believe you need to select a bitmap into your device context.

"A bitmap must be selected within the device context, otherwise, CLR_INVALID is returned on all pixels." - 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;
}
Motomotes
  • 4,111
  • 1
  • 25
  • 24
  • I'm pretty sure the x/y values in my GetPixel calls are already offsets not absolute locations. –  Jan 02 '12 at 08:01
  • You still need to select a bitmap into your compatible DC, otherwise BitBlt has nowhere to copy the pixels to. Also, use GetDIBits -- it's much quicker than using GetPixel. – Roger Lipscombe Jan 02 '12 at 08:05
  • @RogerLipscombe What if I only need 64 pixels, out of a 480x480 square? Is GetDIBits still faster? –  Jan 02 '12 at 08:17
  • Any extended error information? Win 32 APIs usually don't hang without generating some error, at least in the debugger. – Motomotes Jan 03 '12 at 04:19
  • If you're getting more than one pixel CreateComaptilbeBitmap(hDC,nWidth,nHieght). If you want to use GetDIBits instead, you don't use BitBlt. GetDIBits returns a pointer to the bits themselves, so you could actually traverse or examine them yourself, or you could use CreateDIBSection and StretchDIBits to copy only the bits you want to examine. – Motomotes Jan 03 '12 at 14:56
  • Sudden thought: a pointer to the bits could be effectively casted as a `COLORREF*`, right? –  Jan 05 '12 at 06:32
  • See http://stackoverflow.com/questions/3688409/getdibits-and-loop-through-pixels-using-x-y for how to use getdibits to get an array of pixels. Yes, I believe you could could cast the point to the buffer to a `COLORREF*` and move to the next pixel with `myCOLORREF += 4;` – Motomotes Jan 05 '12 at 23:11
  • ***Actually, COLORREF is a 0x00bbggrr color order, colors from getdibits will be 0xrrggbb00 byte order, so you shouldn't use colorref unless you want to reverse the byte order*** – Motomotes Jan 05 '12 at 23:28