Color Take

Introduction

This program gets the color of pixels from the desktop, displays them in a window, and has a 4x1 magnifier by default. 2x or 8x can be selected from the menu. The color value can later be copied to the Clipboard.

Background

The selected colors fill the five boxes. The associated button copies its color to the copy window in the format selected by the Select Format option. The buttons are initially disabled; otherwise, the background color of the dialog window would be copied. Press Copy to sent this value to the Clipboard.

Using the Code

The elements:

  • A menu
  • Window to display the color of the pixel
  • Zoom window (4x1 magnifier)
  • Display HEX, HTML, or RGB
  • Mouse coordinates
  • Five boxes to show the last five selected colors
  • Copy to Clipboard
  1. The Menu, no biggie, used the resource editor. Here is the first challenge: ON_UPDATE_COMMAND_UI does not work for non-system menus. This function toggles menu items. Call it with ToggleMenuItem(0, 1). I hand coded the menu items and sub items; this call sets a check mark on Options menu, Stay on Top.
  2. void CColorTakeDlg::ToggleMenuItem(int nMenu, int nPos)
    {
       // Onupdate command UI doesn't work in a non-system menu
       CMenu *pMenu = GetMenu();
       CMenu *pSubMenu = pMenu->GetSubMenu(nMenu);
       UINT nID = pSubMenu->GetMenuItemID(nPos);
       UINT nState = pSubMenu->GetMenuState(nID, MF_BYCOMMAND);
       ASSERT(nState != 0xFFFFFFFF);
    
       if(nState & MF_CHECKED)
          pSubMenu->CheckMenuItem(nID, MF_UNCHECKED |
             MF_BYCOMMAND);
       else
          pSubMenu->CheckMenuItem(nID, MF_CHECKED |
             MF_BYCOMMAND);
    }
    
  3. Display current color.
  4. CDC *pSDC = m_current.GetDC();
    CRect sRect;
    m_current.GetClientRect(&sRect);
    pSDC->FillSolidRect(&sRect, m_colCurrent);
    ReleaseDC(pSDC);
    
  5. Zoom window.
  6. if (bEnableZoom)
    {
        CDC *pDC = m_zoom.GetDC();
        CRect m_rect;
        m_zoom.GetClientRect(&m_rect);
        InflateRect(&m_rect, -1, 0);
        pDC->SetStretchBltMode(COLORONCOLOR);
        // stretch the 20 x 20 to the 81 x 81 window, close to
        // 4 to 1 magnifier
        pDC->StretchBlt(m_rect.left, m_rect.top, m_rect.Width(),
                        m_rect.Height(), pDesktopDC,
                        pt.x - m_nOffset, pt.y - m_nOffset,
                        m_nWidth, m_nWidth, SRCCOPY);
    
       pen.DeleteObject();
       pen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
       CPen *pOldPen = pDC->SelectObject(&pen);
       CPoint point;
       // draw a red line at the mid point of the x and y axis
       point.x = m_rect.Width()/2;
       point.y = m_rect.top;
       pDC->MoveTo(point);
       point.y = m_rect.bottom;
       pDC->LineTo(point);
       point.x = m_rect.left;
       point.y = m_rect.Height()/2;
       pDC->MoveTo(point);
       point.x = m_rect.right;
       pDC->LineTo(point);
       pDC->SelectObject(pOldPen);
       ReleaseDC(pDC);
    }
    
  7. Display HEX, HTML, or RGB.
  8. switch (m_nSelect)
    {
       case 0:    // Hex
          str.Format("%02X, %02X, %02X", rVal, gVal, bVal);
          m_color.SetWindowText((LPCTSTR)str);
          break;
    
       case 1:    // HTML
          str.Format("#%02X%02X%02X", rVal, gVal, bVal);
          m_color.SetWindowText((LPCTSTR)str);
          break;
    
       case 2:    // RGB
          str.Format("%d, %d, %d", rVal, gVal, bVal);
          m_color.SetWindowText((LPCTSTR)str);
          break;
    }
    
  9. Mouse coordinates. This was quite a challenge. I used SetCapture() to get the cursor from the desktop. In the previous version, that was an error.
  10. void CColorTakeDlg::OnTimer(UINT nIDEvent)
    {
       // TODO: Add your message handler code here and/or
       // call default
    
       HWND m_hwnd = ::GetDesktopWindow();
       CString str;
       POINT pt;
       pt.x = pt.y = 0;
    
       //  =====================================================
       //  Get the mouse pointer position and display it
       //  =====================================================
       GetCursorPos(&pt);
       str.Format("X: %d, Y: %d", pt.x, pt.y);
       m_mouse.SetWindowText((LPCTSTR)str);
       ...
       ..
    
  11. Five boxes to show the last five selected colors.
  12. // Store the current selected color in the left most of
    // five boxes, shifting the old ones right.
    void CColorTakeDlg::CopyColor()
    {
       m_nColor[4] = m_nColor[3];
       m_nColor[3] = m_nColor[2];
       m_nColor[2] = m_nColor[1];
       m_nColor[1] = m_nColor[0];
       m_nColor[0] = m_colCurrent;
    
       DrawColorBoxes();
    }
    
  13. Copy to the Clipboard.
  14. void CColorTakeDlg::OnCopy()
    {
       // TODO: Add your control notification handler code here
       m_edit1.SetSel(0, -1);
       // Copy selected color to the Clipboard
       m_edit1.Copy();
    }
    

Points of Interest

This program uses a CHotKeyCtrl class to copy the selected color to the list and the first box. The void GetHotKey( WORD &wVirtualKeyCode, WORD &wModifiers ) const; function is used to get the hot key from the control. wVirtualKeyCode is the keyboard key (A–Z) pressed and wModifiers are the control keys (Shift, Ctrl, Alt, and the Windows key). The modifier flags defined in CommCtrl.h can be a combination of the following values:

#define HOTKEYF_SHIFT           0x01
#define HOTKEYF_CONTROL         0x02
#define HOTKEYF_ALT             0x04
#define HOTKEYF_EXT             0x08

Then, the hot key has to be registered by using:

BOOL RegisterHotKey(
   HWND hWnd,           // handle to window
   int id,              // hot key identifier
   UINT fsModifiers,    // key-modifier options
   UINT vk              // virtual-key code
);

The values for fsModifiers are defined in WinUser.h.

#define MOD_ALT         0x0001
#define MOD_CONTROL     0x0002
#define MOD_SHIFT       0x0004
#define MOD_WIN         0x0008

As you can see, the values are not the same, so I have:

void CColorTakeDlg::OnNewHotkey()
{
   // TODO: Add your control notification handler code here
   UnregisterHotKey(m_hWnd, HOTKEYID);
   m_hotkey1.GetHotKey(wVirtualKeyCode, wModifiers);
   switch(wModifiers)
   {
   case HOTKEYF_SHIFT:
      fsModifiers = MOD_SHIFT;
      break;
   case HOTKEYF_CONTROL:
      fsModifiers = MOD_CONTROL;
      break;
   case HOTKEYF_ALT:
      fsModifiers = MOD_ALT;
      break;
   case HOTKEYF_EXT:
      fsModifiers = MOD_WIN;
      break;
   }
   RegisterHotKey(m_hWnd, HOTKEYID, fsModifiers,
                  wVirtualKeyCode);
}

These are only four combinations. I didn't want to allow all 16, so I used SetRules().

m_hotkey1.SetHotKey(0x43, HOTKEYF_ALT);
m_hotkey1.SetRules(HKCOMB_CA | HKCOMB_SA | HKCOMB_SC |
                   HKCOMB_SCA | HKCOMB_NONE, HOTKEYF_ALT);
RegisterHotKey(m_hWnd, HOTKEYID, MOD_ALT, 0x43);
wVirtualKeyCode = 0x43;
wModifiers = HOTKEYF_ALT;
fsModifiers = MOD_ALT;

You want something zany, position the cursor in the magnifier window. When you get close to the cross-hairs that are 1 pixel wide, you will see in the window they are 4 pixels wide. If you get closer, they appear 16 pixels wide. About the time they get to be 64 pixels wide, the window will turn red.

Warning

If you use this program on older versions of Windows, Win95/Win98, and the zoom window fails to function, you have a problem. The GDI resource causes StretchBlt(...) to return FALSE. Please see the MSDN Knowledge Base article.



Downloads

Comments

  • Nice tool

    Posted by kirants on 12/14/2005 08:34pm

    One suggestion. Most websites and most GUIs these days have different images for hover state. So, as soon as you move mouse over those places the appearance is changed.. So, you see, as soon as you have moved your mouse over the button to find the color, the appearance has changed. It would be cool to have a feature in your application to be able to provide co-ordinates and find the color from that spot

    • Not exactly

      Posted by Roger65 on 12/22/2005 05:21pm

      Sorry!

      Reply
    • Not exactly

      Posted by kirants on 12/22/2005 12:52pm

      What I mean to say is this: Say you have colortake up. Now, you see a cool image on a webpage and you like the color. You move your mouse over the image and suddenly the image has changed to a hover image. So, you see, you won't be able to capture the previous color since the mouse move spoils the image that you wanted to capture. Basically, what I am saying is to be able to capture non-hover color

      Reply
    • hover color

      Posted by Roger65 on 12/15/2005 06:04am

      My program does this. The five buttons are initially disabled, try a normal button or select a color first then check button 1.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

  • Best-in-Class organizations execute on a strategy that supports the multi-channel nature of customer requests. These leading organizations do not just open up their service infrastructures to accommodate new channels, but also empower their teams to deliver an effective and consistent experience regardless of the channel selected by the customer. This document will highlight the key business capabilities that support a Best-in-Class customer engagement strategy.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds