CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    [RESOLVED] How to implement a screen color picker

    I am trying to implement a screen color picker. I think the attached image is a better explanation of what I want do achieve than a bunch of words. I'm thinking of something similar to what Spy used to pick a window to spy on.

    The following attempt failed so miserably that I hardly dare to post the code:

    Code:
    System::Void Form1::btnScreenPicker_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e)
    {
      if (static_cast<bool>(e->Button & System::Windows::Forms::MouseButtons::Left)) {
        Graphics ^gr = Graphics::FromHwnd(static_cast<Button ^>(sender)->Handle);
    #ifdef _DEBUG
        Diagnostics::Debug::Assert(!gr->Clip->IsInfinite(gr), "Mouse move handler got passed a Graphics with an infinite clipping region");
    #endif
        Bitmap ^bmp = gcnew Bitmap(gr->ClipBounds.Width, gr->ClipBounds.Height, gr);
        lblScreenPickerPreview->BackColor = bmp->GetPixel(e->X, e->Y);
      }
    }
    Clicking on the button in question and holding down the mouse key results in some kind of "machine gun" sound, indicating that the assertion you can see gets fired repeatedly and Windows tries to play the assertion sound but but doesn't get far with that until I release the button. (That's not the real problem here, but why doesn't the app get blocked once the assertion fails for the first time? )

    Picking colors from my own button is of course really boring, but I tried that as a first test, and not even that works. And I'm uncertain about the concept of the color picker in general: It would certainly be terribly inefficient to bitblt the entire screen to my own bitmap just to pick a single pixel on every mouse move. But capturing the screen only once in the MouseDown handler and then keep using that bitmap would lead to missing every screen change that happens while I hold the button...

    Yes, lots of open questions here...

    I'd appreciate any help. TIA
    Attached Images Attached Images  
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  2. #2
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Resolved Re: How to implement a screen color picker

    Ok, first I have to apologize to anyone who might already have done some research in order to answer this question for bothering him yet again with a question that I can find the answer for myself in less than 24 hours. Of course I intended to do a tag search on Codeguru, a full-text search on CodeGuru and a Google search before posting. I did the tag search which didn't come up with any useful information, then got tired and went to bed. At the end of the next day I wrote my post above without doing any further search... My fault.

    The following is a modified translation of the C# code I found in post #3 of http://www.codeguru.com/forum/showthread.php?t=476181:

    Code:
    System::Void Form1::btnScreenPicker_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e)
    {
      if (static_cast<bool>(e->Button & System::Windows::Forms::MouseButtons::Left)) {
        Control ^ctl = static_cast<Control ^>(sender);
        Bitmap ^bmp = gcnew Bitmap(1, 1);
        Graphics ^gr = Graphics::FromImage(bmp);
        Point ptScreen = ctl->PointToScreen(e->Location);
        gr->CopyFromScreen(ptScreen.X, ptScreen.Y, 0, 0, Drawing::Size(1, 1));
        lblScreenPickerPreview->BackColor = bmp->GetPixel(0, 0);
      }
    }
    Yet again, that was one of these "easier than I expected" kind of things. And it doesn't contain a single Win32 API call, unlike some C# code I found in a post on that topic on codeproject.com which had lots of them.

    In fact I already came across Graphics::CopyFromScreen() fefore while researching this topic, but for some obscure reason that I don't even know anymore now I didn't consider it to be a candidate.

    Just before the version you see above, I had one that actually copied the entire screen before pickig a single pixel, and it imposed a CPU load of almost 100&#37; as I was afraid of. But this 1-pixel version now only needs less than 10%. And as a side effect I now know how to capture anything from a single pixel up to the entire screen.

    I was, BTW, surprised by the fact that I didn't even had to capture the mouse in order to reach any point on the screen. Is this the standard behaviour of a button or a special feature of the Windows Forms incarnation?
    Last edited by Eri523; October 31st, 2010 at 11:56 PM. Reason: Syntactically corrected the link
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured