Click here to Skip to main content
15,887,083 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
The code below writes in console x,y and color of a pixel pointed by the mouse. 
It's working, but has 3 faults:

1. After 9997 calls GetDC(HWND_DESKTOP) stops giving sensible data.
My pragmatic solution is to count loops, call a link pointing to exe and exit.
2. Size of memory used increases - of order of 1 kB / loop.
3. It is slow - 3 milliseconds is a high price for checking color of a single pixel.

Please tell me how to correct those problems, especially 1 and 3.
I mean something simple and usable with MS Express Edition 2013 and Windows 7.
I use similar code to simulate response of a user to somebody else's application by monitoring color of a few points on the screen.

C++
#include "stdafx.h"
#include "iostream"
#include "mmdeviceapi.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
  int x, y, n = 0;	HDC hdc;	POINT curPos;	BOOL result;
    do {
      hdc = GetDC(HWND_DESKTOP);		n++;
      if (n > 9990) { 
        ShellExecute(NULL, L"open", L"\"C:\\Users\\me\\Desktop\\xyColor.lnk\"", 
	             NULL, NULL, SW_SHOWDEFAULT);
         exit(0);
    } 
    result = GetCursorPos(&curPos);
    if (result) {
      x = curPos.x;
      y = curPos.y;
      cout << "n=" << n << " x=" << x << " y=" << y 
           << hex << " BGR= " << GetPixel(hdc, x, y) << dec << endl;
      Sleep(10);
    }
  } while (result);
  return 0;
}
Posted

(1) In every loop iteration you are aquiring a new DC and you obviously never return it by calling ReleaseDC as you should. That is probably the reason why your program runs out of resources after nine thousand and something iterations.

Why don't you acquire the hdc before the loop, instead of inside?

(2) Very understandable after you have read my comment for (1).

(3) Considering that you are acquiring a DC and doing some formatting and in addition do a sleep of 10 ms it is not surprising that you loop runs "slow".
 
Share this answer
 
Comments
enhzflep 2-Dec-13 17:05pm    
Bingo! My +5. I was waiting for mention of the repeated calls to GetDC, without cleanup.
Further to your answer, I'd like to paste the relevant part of the docs:

"After painting with a common device context, the ReleaseDC function must be called to release the device context. Class and private device contexts do not have to be released. The number of device contexts is limited only by available memory."

Clearly, the OPs question isn't using a class or private HDC, so the number of calls to ReleaseDC must match the number made to GetDC, as you've already said.
nv3 2-Dec-13 17:11pm    
Thanks for your comments, enhzflep. Indeed I was considering to lay out the fine points of common, private, and class DCs, but didn't want to confuse OP.
Why not save the desktop bitmap to a memory buffer and loop through that to check the pixels? Seems like getting the desktop pixel would be an expensive operation that you can buffer.

I would look at code examples on taking a screen shot, then save the screen shot to a bitmap, then you can call GetPixel on the memory bitmap.

I'd give you an example but I'm pretty rusty in using DC's.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 2-Dec-13 16:35pm    
This is not so direct and easy. Please see my answer.
—SA
Ron Beyer 2-Dec-13 16:43pm    
I guess I misunderstood the basis of the program, I thought he was looping the entire desktop looking for a color, whereas he's looping and just looking at the mouse position...
No, 3 milliseconds for individual pixel is not the high price. It would be high price if it was average time per pixel for massive pixel operations. That simply should tell you that GetPixel/SetPixel is only acceptable when you only need to operate on just one pixel or very few of them. For all other cases, such operations are prohibitively slow. Can you see the point? If you have to touch 3 pixels, who would care about 10 milliseconds? If you need many pixels, you can sped more overall time, but its okay as you can read/modify a lot of pixels in one operation.

You need to use Bitmap::LockBits instead: http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298%28v=vs.85%29.aspx[^].

—SA
 
Share this answer
 
Comments
Ron Beyer 2-Dec-13 16:39pm    
Does that work when he's reading the DC directly from the desktop? It seems like he's working off of the desktop DC and not a memory bitmap, so does LockBits cause problems with windows interacting with the desktop (think an automatic background change in Win7 while LockBits is set)?
Sergey Alexandrovich Kryukov 2-Dec-13 18:30pm    
Good point. However, one could put all data in a bitmap in a single operation, which is fast enough, do the manipulations and, it needed, draw a bitmap on the said DC.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900