pobieranie koloru piksela okna spoza ekranu

0

napisałem taką procedurę, która pobiera kolor danego piksela, w sumie dowolnego okna:

var
h:thandle;
begin
h:=FindWindow(nil, 'Form1');
label1.Caption:=inttostr(getrvalue(GetPixel(GetWindowDC(h),250,250)));
label2.Caption:=inttostr(getgvalue(GetPixel(GetWindowDC(h),250,250)));
label3.Caption:=inttostr(getbvalue(GetPixel(GetWindowDC(h),250,250)));

ale jak to przerobić tak, żeby sprawdzać co się dzieje z danym oknem nawet kiedy jest poza obszarem ekranu? nawet nie próbuję się zagłębiać w okna zminimalizowane, ale żeby się dało choćby przesunięte poza krawędź ekranu, to już by było bosko
z góry dzięki

0
{Pobranie koloru pixela 1x1}

  public
    ScreenDC: HDC;

var
 CursorPos: TPoint;
begin
 GetCursorPos(CursorPos);
 Panel1.Color := GetPixel(ScreenDC, CursorPos.X, CursorPos.Y);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ScreenDC := GetDC(0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ReleaseDC(0, ScreenDC);
end;


  public
    procedure WMLButtonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
    procedure WMRButtonDown(var Msg: TMessage); message WM_RBUTTONDOWN;

{Można dodać wyłączanie pobierania poprzez Lewy/Prawy przycisk myszki}
procedure TMainForm.WMLButtonDown(var Msg: TMessage);
begin
  inherited;
  PostMessage(MainForm.Handle, WM_ACTIVATE, word(true), 0);
end;

procedure TMainForm.WMRButtonDown(var Msg: TMessage);
begin
  inherited;
  WMLButtonDown(Msg);
end;



{Pobranie koloru pixeli 3x3 i 5x5 odbywa się za pomocą metod 1 i 2}
procedure TForm1.PickTmrTimer(Sender: TObject);
var
  CursorPos: TPoint;
  AverageR, AverageG, AverageB: Cardinal;
  x, y: shortint;
begin
  GetCursorPos(CursorPos);

// 1  (3x3)
  begin
    AverageR := 0;
    AverageG := 0;
    Averageb := 0;
    for y := -1 to 1 do
      for x := -1 to 1 do begin
        Panel1.Color := GetPixel(ScreenDC, CursorPos.x + x, CursorPos.y + y);
        AverageR := AverageR + GetRValue(PixelCol);
        AverageG := AverageG + GetGValue(PixelCol);
        AverageB := AverageB + GetBValue(PixelCol);
      end;
    AverageR := AverageR div 9;
    AverageG := AverageG div 9;
    AverageB := AverageB div 9;

    Panel1.Color := RGB(Lo(AverageR), Lo(AverageG), Lo(AverageB));
  end;

 // 2  (5x5)
  begin
    AverageR := 0;
    AverageG := 0;
    Averageb := 0;
    for y := -2 to 2 do
      for x := -2 to 2 do begin
        Panel1.Color := GetPixel(ScreenDC, CursorPos.x + x, CursorPos.y + y);
        AverageR := AverageR + GetRValue(PixelCol);
        AverageG := AverageG + GetGValue(PixelCol);
        AverageB := AverageB + GetBValue(PixelCol);
      end;
    AverageR := AverageR div 25;
    AverageG := AverageG div 25;
    AverageB := AverageB div 25;

    Panel1.Color := RGB(Lo(AverageR), Lo(AverageG), Lo(AverageB));
  end;
end;
0

A jest jakiś odpowiednik HDC pod Lazarusa?

0

No nie do końca się z Tobą zgodzę, Opi...
Bo po pierwsze skoro pobiera kolor spod myszy, to znaczy że pobiera go z obszaru ekranu, poza który nie da się myszą wyjechać
Po drugie jak przerobiłem kod na swoją modłę, i wklepałem współrzędne poza ekranem czyli (1290, 1035) (przy rozdzielczości ekranu 1280x1024) to i tak zwróciło mi RGB(255,255,255) zamiast szarego koloru okna.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    ScreenDC:HDC;
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
ScreenDC:=GetDC(0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ReleaseDC(0,ScreenDC);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
label1.Caption:=inttostr(getrvalue(GetPixel(ScreenDC, 1290, 1035)));
label2.Caption:=inttostr(getgvalue(GetPixel(ScreenDC, 1290, 1035)));
label3.Caption:=inttostr(getbvalue(GetPixel(ScreenDC, 1290, 1035)));
end;

end.
0

zrobiłem też dokładnie tak jak napisałeś
tylko nie wiedziałem gdzie upchnąć:

var
CursorPos: TPoint;
begin
GetCursorPos(CursorPos);
Panel1.Color := GetPixel(ScreenDC, CursorPos.X+250, CursorPos.Y+250);
end;

więc wsadziłem pod OnClick, ale efekt jest dokładnie ten sam
zawsze czarny ekran :/

0

nie jestem pewien, ale wydaje mi się że poza ekranem okno na windowsach XP i niżej może w ogóle się nie rysować, na siódemce okna są rysowane na jakiś wewnętrznych buforach z tego co kiedyś czytałem, więc pewnie idzie się do nich jakoś dostać. z ekranu odczytanie bezpośrednio pewnie nie jest możliwe (z resztą poza tym co widać nie ma nic)

0

Przesuń okno na obszar widoczny, pobierz kolor i przywróć poprzednią pozycję.

0

No wiem Łukaszu, że tak się da, ale chodziło o to żeby to okienko sobie tam było z boku i nie przeszkadzało
Bo jak mi będzie jakieś "G" wylatywać na ekran z częstotliwością 4Hz to choroby nerwowej dostanę :PP

1 użytkowników online, w tym zalogowanych: 0, gości: 1