[win32]récupérer la couleur d'un pixel à l'écran

Soyez le premier à donner votre avis sur cette source.

Vue 13 042 fois - Téléchargée 567 fois

Description

Ce source récupère la couleur du pixel qui se trouve sous la souris.

La couleur est affiché en décimal R, G, B et en hexa.

Le fond de la form prend la même couleur que celle du pixel.

Pour ceux qui voudraient juste utiliser ce programme sans avoir besoin de compiler, il suffit de renommer le fichier du zip .exec en .exe.

Source / Exemple :


#include "windows.h"

HINSTANCE _hThisInstance;              // Handle du module
HWND _hWnd;                            // Handle de la fenêtre
HWND _hTextBox;                        // Handle de la textbox
LPSTR _lpAppName = "GetPixelColor";    // Nom de l'appli

//
// Affiche le message d'erreur associé à la dernière
// erreur Win32.
//
void ShowLastError()
{
  DWORD nLastError;
  LPSTR lpMessageBuffer;

  // Récupération du numéro de l'erreur
  nLastError = GetLastError();

  // Formatage du message
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL);

  // Affichage du message et fin de l'appli
  MessageBox(NULL, lpMessageBuffer, "ERROR", MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
}

//
// Traitement des messages.
//
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
  static HBRUSH hBackBrush;     // Brush de dessin de l'arrière plan de la fenêtre
  static POINT cursor;          // Position de la souris
  static COLORREF nColor;       // Couleur du pixel sous la souris
  static RECT back;             // Rectangle de la zone cliente/fenêtre
  static char lpText[50];       // Affichage de la couleur en hexa et rgb
  static INT32 nHexa;           // La couleur swapée pour afficher un hexa comme on l'attend
  static HDC hScreenDC;         // HDC de l'écran
  
  switch (nMessage)
  {
    case WM_TIMER:
      // On met à jour seulement si on est hors de notre fenêtre
      GetCursorPos(&cursor);
      GetWindowRect(_hWnd, &back);
      
      // Pas besoin de ReleasDC pour ce GetDC : CS_OWNDC dans le style de la classe
      if (! PtInRect(&back, cursor)) SendMessage(_hWnd, WM_ERASEBKGND, (WPARAM)GetDC(_hWnd), 0);
      break;
    case WM_ERASEBKGND:
      // Récupération des coordonnées de la souris
      GetCursorPos(&cursor);
      
      // Récupération de la couleure du pixel sous la souris
      hScreenDC = GetDC(0);
      nColor = GetPixel(hScreenDC, cursor.x, cursor.y);
      nHexa = ReleaseDC(0, hScreenDC);

      // Création du brush de dessin de l'arrière plan de la form
      hBackBrush = CreateSolidBrush(nColor);
      
      // Dessin de la fenêtre
      GetClientRect(_hWnd, &back);
      FillRect((HDC)wParam, &back, hBackBrush);
      DeleteObject(hBackBrush);

      // On remet les octets dans le "bon" sens
      nHexa = ((nColor & 0xFF) << 16) | (nColor & 0xFF00) | ((nColor & 0xFF0000) >> 16);
      
      // Affichage de la couleur en hexa
      // Le dièze, c'est juste qu'en HTML on en met un.
      // %X, ça convertit l'entier en hexa (En majuscule)
      // %6X, ça complète la conversion avec des espaces pour que la chaîne fasse 6 caractères
      // %06X, ça demande des 0 à la place des espaces pour arriver à 6 caractères
      wsprintf(lpText, "#%06X (R = %d, G = %d, B = %d)", nHexa, nColor & 0xFF, (nColor & 0xFF00) >> 8, (nColor & 0xFF0000) >> 16);
      SetWindowText(_hTextBox, lpText);
      RedrawWindow(_hTextBox, NULL, NULL, RDW_INVALIDATE);
      return 1;
    case WM_DESTROY:
      // On signale que le thread va s'arrêter
      PostQuitMessage(0);
      break;
    default:
      // Application du traitement par défaut
      return DefWindowProc(hWnd, nMessage, wParam, lParam);
  }
  return 0;
}

//
// Initialise la fenêtre principale de l'appli.
//
void InitWindow()
{
  WNDCLASSEX wincl;       // Classe de la fenêtre utilisée

  // Création de la classe de fenêtre
  wincl.cbSize = sizeof(WNDCLASSEX);
  wincl.style = CS_OWNDC;
  wincl.lpfnWndProc = WindowProcedure;
  wincl.cbClsExtra = 0;
  wincl.cbWndExtra = 0;
  wincl.hInstance = _hThisInstance;
  wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  wincl.hbrBackground = NULL;
  wincl.lpszMenuName = 0;
  wincl.lpszClassName = _lpAppName;
  wincl.hIconSm = NULL;

  // Enregistrement de la classe
  if (!RegisterClassEx(&wincl)) ShowLastError();

  // Création de la fenêtre
  _hWnd = CreateWindowEx(0, _lpAppName, _lpAppName, WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, HWND_DESKTOP, NULL, _hThisInstance, NULL);
  _hTextBox = CreateWindowEx(0, "EDIT", "color", ES_READONLY | WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 294, 20, _hWnd, NULL, _hThisInstance, NULL);
}

#pragma comment(linker, "/entry:main")
INT32 _cdecl main()
{
  MSG messages;           // Réception des messages envoyés à l'application

  // Récupération du handle du module
  _hThisInstance = GetModuleHandle(NULL);

  InitWindow();
  if (!SetTimer(_hWnd, 1, 100, NULL)) ShowLastError();

  // Boucle de traitement des messages
  while (GetMessage(&messages, NULL, 0, 0))
  {
    // Traduit certains messages
    TranslateMessage(&messages);

    // Distribution des messages aux fenêtres
    DispatchMessage(&messages);
  }
  KillTimer(_hWnd, 1);

  // Code d'erreur en sortie
  return messages.wParam;
}

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

mogwai93
Messages postés
361
Date d'inscription
mardi 31 décembre 2002
Statut
Membre
Dernière intervention
19 mars 2015
-
pourquoi créer une deuxieme variable "_hWnd" ?
alors que _hWnd est égale à hWnd

et pour information, DevCpp (mingW) n'est pas "content" des 2 variables :
HANDLE hDC;
HANDLE _hThisInstance;

il préfère :
HDC hDC;
HINSTANCE _ThisInstance;
BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13 -
Jolie source.

Le bloc 'bon ordre' est aussi inutile que zoli, il faut dans tous les cas 2 shifts ensuite.
Me semble qu'il faut ReleaseDC pour GetDC(0).
SAKingdom
Messages postés
3213
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
12 -
De l'assembler en plein milieu d'une fonction... ça n'empêcherait pas son optimisation ça ?

(C'est toi, brunews, qui m'avais fais la remarque je crois)
BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13 -
ça c'est tout à fait certain.
racpp
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
7 -
Salut,
L'idée de source est bonne mais il parait que tu n'as pas pris le temps de la finaliser. En plus de ce qui a été dit voici quelques remarques:
1- Le message WM_ERASEBKGND fournit le HDC de la fenêtre dans wParam donc aucun besoin d'utiliser GetDC(). Cette fonction est même appelée inutilement trois fois de suite dans ton code.
2- La fonction OnCreate() est vide.
3- Il est préférable de déclarer les variables locales de WindowProcedure en static. Cela évitera l'usage de la pile à chaque appel de la procédure.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.