getpixel in mouse hook procedure does not work after some time
-
- I am writing a color picker windows program in C language using WIN32 api
- I wrote a global mouse hook(WH_MOUSE_LL) to capture the x,y position of the mouse
- I use getpixel function to get the color from the mouse x,y position
- hdc(parameter 1) to getpixel is the screen. i.e GetDC(null).
- I created small window to show the color values and a small rectangle inside it to show the color in solid fill.
- When i ran the program it works well for some time. tested the program by hovering the mouse on different applications.
- After a while i get CLR_INVALID from getpixel.
- Besides, whenever i popup a color dialog box getpixes gives CLR_INVALID
I read in the documentation that it would be out of the clipping region if we get CLR_INVALID. It worked well for some time when i hovered mouse all over the screen by changing windows and after a while it gives out of clipping region error. why is that?
HDC screen;
screen = GetDC(NULL);LRESULT CALLBACK Mousy(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode >= 0)
{
ms = (MSLLHOOKSTRUCT *)lParam;
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);
//colorhex holds only CLR_INVALID after some timeToday's Beautiful Moments are Tomorrow's Beautiful Memories
-
- I am writing a color picker windows program in C language using WIN32 api
- I wrote a global mouse hook(WH_MOUSE_LL) to capture the x,y position of the mouse
- I use getpixel function to get the color from the mouse x,y position
- hdc(parameter 1) to getpixel is the screen. i.e GetDC(null).
- I created small window to show the color values and a small rectangle inside it to show the color in solid fill.
- When i ran the program it works well for some time. tested the program by hovering the mouse on different applications.
- After a while i get CLR_INVALID from getpixel.
- Besides, whenever i popup a color dialog box getpixes gives CLR_INVALID
I read in the documentation that it would be out of the clipping region if we get CLR_INVALID. It worked well for some time when i hovered mouse all over the screen by changing windows and after a while it gives out of clipping region error. why is that?
HDC screen;
screen = GetDC(NULL);LRESULT CALLBACK Mousy(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode >= 0)
{
ms = (MSLLHOOKSTRUCT *)lParam;
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);
//colorhex holds only CLR_INVALID after some timeToday's Beautiful Moments are Tomorrow's Beautiful Memories
Your code snippet does not show when you call
GetDC
and ifReleaseDC
is called. You should callGetDC
in your handler andReleaseDC
when no longer using the HDC. Storing the HDC in a global variable is bad even when it is the screen HDC. -
Your code snippet does not show when you call
GetDC
and ifReleaseDC
is called. You should callGetDC
in your handler andReleaseDC
when no longer using the HDC. Storing the HDC in a global variable is bad even when it is the screen HDC.oh i see. I thought one time reference to the screen is enough. I call GetDC before the message loop and ReleaseDC before the program terminates. So, the following should hold good.
ms = (MSLLHOOKSTRUCT *)lParam;
screen = GetDC(null); // ?
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);yes. it is. it is working fine. Besides, what would be the issue if device context is not released for a longer time? ... Meantime, I will search for the above info.
Today's Beautiful Moments are Tomorrow's Beautiful Memories
-
oh i see. I thought one time reference to the screen is enough. I call GetDC before the message loop and ReleaseDC before the program terminates. So, the following should hold good.
ms = (MSLLHOOKSTRUCT *)lParam;
screen = GetDC(null); // ?
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);yes. it is. it is working fine. Besides, what would be the issue if device context is not released for a longer time? ... Meantime, I will search for the above info.
Today's Beautiful Moments are Tomorrow's Beautiful Memories
Jayapal Chandran wrote:
I thought one time reference to the screen is enough
I'm not quite sure about that. But I would not do so to be safe. There is at least one situation when that fails: When the screen resolution or color depth is changed while your application is running. You should use something like this (and check if the problem still occurs):
ms = (MSLLHOOKSTRUCT *)lParam;
screen = GetDC(NULL);
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);
ReleaseDC(NULL, screen); -
Jayapal Chandran wrote:
I thought one time reference to the screen is enough
I'm not quite sure about that. But I would not do so to be safe. There is at least one situation when that fails: When the screen resolution or color depth is changed while your application is running. You should use something like this (and check if the problem still occurs):
ms = (MSLLHOOKSTRUCT *)lParam;
screen = GetDC(NULL);
colorhex = GetPixel(screen, ms->pt.x, ms->pt.y);
ReleaseDC(NULL, screen);Its working fine without using ReleaseDC inside the handler. Won't the program take more resource/time if GetDC/ReleaseDC used inside the handler? Will it lead to performance degradation if the program is running for a long time? Is there any other way to getpixel or is this the only feasible way?
Today's Beautiful Moments are Tomorrow's Beautiful Memories
-
Its working fine without using ReleaseDC inside the handler. Won't the program take more resource/time if GetDC/ReleaseDC used inside the handler? Will it lead to performance degradation if the program is running for a long time? Is there any other way to getpixel or is this the only feasible way?
Today's Beautiful Moments are Tomorrow's Beautiful Memories
You should always have a matching
ReleaseDC
call for eachGetDC
. See GetDC[^] in the MSDN. This is necessary for common DCs to free the allocated memory (your screen DC is a common DC). If not doing so you have a memory leak and may run out of memory when getting too much DCs. Private DCs do not allocate memory but callingReleaseDC
does not harm and you must not care about the DC type when always releasing. CallingGetDC
inside the handler will off course took some time. But that is the common and safe way and the consumed time is acceptable. You are checking only a single pixel in you handler. ThenGetPixel
is the best method. -
You should always have a matching
ReleaseDC
call for eachGetDC
. See GetDC[^] in the MSDN. This is necessary for common DCs to free the allocated memory (your screen DC is a common DC). If not doing so you have a memory leak and may run out of memory when getting too much DCs. Private DCs do not allocate memory but callingReleaseDC
does not harm and you must not care about the DC type when always releasing. CallingGetDC
inside the handler will off course took some time. But that is the common and safe way and the consumed time is acceptable. You are checking only a single pixel in you handler. ThenGetPixel
is the best method.I had been creating the program in two different machines both are win7 i7... When i run the program in one machine the mouse movement is a little slow were as in an other machine the mouse movement is fine. no lags. i assume that getpixel is the one which is using more resources. is there any other way of getting the pixel color on mouse move? when i searched in google i got resources suggesting to use CreateDIBSection, bitblt, etc... suggestions needed.
Today's Beautiful Moments are Tomorrow's Beautiful Memories
-
I had been creating the program in two different machines both are win7 i7... When i run the program in one machine the mouse movement is a little slow were as in an other machine the mouse movement is fine. no lags. i assume that getpixel is the one which is using more resources. is there any other way of getting the pixel color on mouse move? when i searched in google i got resources suggesting to use CreateDIBSection, bitblt, etc... suggestions needed.
Today's Beautiful Moments are Tomorrow's Beautiful Memories
Functions like
CreateDIBSection
andBitBlt
work on a whole screen region. They are recommended to process all pixels of the region using their own pixel addressing logic with increments to avoid the explicit address calculation for each pixel. An example can be found here at CP: A fast way to work on Windows bitmap pixel data without using the slow GetPixel and SetPixel methods[^] But you need only the value of a single pixel and the above approach would not be faster. Regarding the speed difference: Is desktop composition (Aero) enabled for one machine and disabled for the other? If so, that is the reason. -
Functions like
CreateDIBSection
andBitBlt
work on a whole screen region. They are recommended to process all pixels of the region using their own pixel addressing logic with increments to avoid the explicit address calculation for each pixel. An example can be found here at CP: A fast way to work on Windows bitmap pixel data without using the slow GetPixel and SetPixel methods[^] But you need only the value of a single pixel and the above approach would not be faster. Regarding the speed difference: Is desktop composition (Aero) enabled for one machine and disabled for the other? If so, that is the reason.No. Both have Aero. What i am trying to do is i wanted my own color picker. I am trying to create a program exactly like nattyware's pixie. when i used pixie it did not slow down when mouse moved were as when program is running at my home computer the mouse move is slow. I read pixie was written in Delphi. I have to pay to get the source code. So i thought of writing a similar one for windows using WIN32 API(C language).
Today's Beautiful Moments are Tomorrow's Beautiful Memories
-
No. Both have Aero. What i am trying to do is i wanted my own color picker. I am trying to create a program exactly like nattyware's pixie. when i used pixie it did not slow down when mouse moved were as when program is running at my home computer the mouse move is slow. I read pixie was written in Delphi. I have to pay to get the source code. So i thought of writing a similar one for windows using WIN32 API(C language).
Today's Beautiful Moments are Tomorrow's Beautiful Memories
You could speed up your program by not reading the pixel on every mouse position change. You could call that part of the code if the mouse has been hovering over a pixel for a while e.g. 500 ms or 1000 ms. Cheers!
"I had the right to remain silent, but I didn't have the ability!"
Ron White, Comedian