2013-03-01 2 views
4

마우스 커서 아래에서 픽셀 색상을 실제로 얻는 방법은 있습니까? 마우스 훅이 있는데 마우스를 움직이는 동안 픽셀 색을 읽으려고합니다. ColorPicker의 종류마우스 커서 아래에서 픽셀 색상 가져 오기 - 빠른 방법

getPixel 및 BitBlt를 사용한 모든 시도는 대단히 느립니다.

UPDATE - ADDED 코드

unit Unit1; 

{$mode delphi}{$H+} 

interface 

uses 
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, lclintf, Windows; 

type 

    { TForm1 } 

    TForm1 = class(TForm) 
    pnColor: TPanel; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure ms(var message: tmessage); message WM_USER+1234; 
    private 
    { private declarations } 
    public 
    { public declarations } 
    end; 

var 
    Form1: TForm1; 
    DC:HDC; 

    const WH_MOUSE_LL = 14; //for Lazarus 

implementation 

{$R *.lfm} 

{ TForm1 } 

procedure HookMouse(Handle:HWND); stdcall; external 'mhook.dll'; 
procedure UnHookMouse; stdcall; external 'mhook.dll'; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    //Self.Caption := IntToStr(Self.Height); 
    Self.Left:= Screen.Monitors[0].WorkareaRect.Right - Self.Width - 18; 
    Self.Top := Screen.Monitors[0].WorkareaRect.Bottom - Self.Height - 18 - 25; //35 LAZARUS BUG 

    DC := getDC(0); 

    HookMouse(Self.Handle); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    UnHookMouse; 
end; 

procedure TForm1.ms(var message: tmessage); 
var color:TColor; 
begin 
    color := GetPixel(DC, message.WParam, message.LParam); //<-- Extremly slow 
    //format('%d - %d',[message.LParam, message.WParam]); // Edited 

    pnColor.Color:=color; 
end; 

end. 

그리고 DLL

library project1; 

{$mode delphi}{$H+} 

uses 
    Windows, 
    Messages; 

var Hook: HHOOK; 
    hParent:HWND; 

function HookProc(nCode: Integer; MsgID: WParam; Data: LParam): LResult; stdcall; 
var 
    mousePoint: TPoint; 
begin 
    //if nCode = HC_ACTION then 
    //begin 
     mousePoint := PMouseHookStruct(Data)^.pt; 
     PostMessage(hParent, WM_USER+1234, mousePoint.X, mousePoint.Y); 
    //end; 
    Result := CallNextHookEx(Hook,nCode,MsgID,Data); 
end; 

procedure HookMouse(Parent: Hwnd); stdcall; 
begin 
    hParent := parent; 
    if Hook = 0 then Hook:=SetWindowsHookEx(WH_MOUSE_LL,@HookProc,HInstance,0); 
end; 

procedure UnHookMouse; stdcall; 
begin 
    UnhookWindowsHookEx(Hook); 
    Hook:=0; 
end; 

exports 
    HookMouse, UnHookMouse; 

begin 

end. 

업데이트 2 - 하나의 단위 업데이트

unit Unit1; 

{$mode delphi}{$H+} 

interface 

uses 
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, lclintf, Windows; 

type 

    { TForm1 } 

    TForm1 = class(TForm) 
    pnColor: TPanel; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    private 
    { private declarations } 
    public 
    { public declarations } 
    end; 

var 
    Form1: TForm1; 
    HookHandle: Cardinal; 
    DC:HDC; 
    timer:Long; 

const WH_HOOK_LL = 14; //for Lazarus 

implementation 

{$R *.lfm} 

{ TForm1 } 

function LowLevelMouseProc(nCode: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall; 
var 
    point:TPoint; 
begin 
    if (nCode >= 0) then 
    begin 
    if(GetTickCount - timer >= 100) then 
    begin 
     point:=PMouseHookStruct(lParam)^.pt; 
     Form1.pnColor.Color := GetPixel(DC,point.X,point.Y); 
     timer := GetTickCount; 
    end; 
    end; 
    Result := CallNextHookEx(HookHandle, nCode, wParam, lParam); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    //Self.Caption := IntToStr(Self.Height); 
    Self.Left:= Screen.Monitors[0].WorkareaRect.Right - Self.Width - 18; 
    Self.Top := Screen.Monitors[0].WorkareaRect.Bottom - Self.Height - 18 - 25; //35 LAZARUS BUG 

    DC := GetWindowDC(GetDesktopWindow); 
    if HookHandle = 0 then 
    begin 
    HookHandle := SetWindowsHookEx(WH_HOOK_LL, @LowLevelMouseProc, hInstance, 0); 
    end; 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    if HookHandle <> 0 then 
    UnhookWindowsHookEx(HookHandle); 

    ReleaseDC(GetDesktopWindow(), DC); 
end; 

end. 
+0

이 메시지는 Delphi 질문 또는 나사로 질문이 아니며 둘 다 어쨌든 태그 지정에 이상합니다. 이것은 winapi 질문입니다. 그 방법으로 태그를 지정하는 것이 좋습니다. 또한 자신의 앱이 아닌 화면에서 픽셀을 읽으 려한다는 의미라고 설명합니다. –

+0

감사합니다. 태그가 추가되었습니다. –

+0

그게 Lazarus 태그를 추가 한 바로 그 이유입니다. –

답변

4

간격이 100ms와 나는 개인적 않을 것 이것에 후크를 사용하십시오. 예 : 예를 들어 간격이 30ms 인 타이머를 사용하고 다음 코드를 사용하여 마우스 커서 아래의 현재 픽셀의 위치와 색상을 결정합니다 (이 코드는 원래 코드 에서처럼 Windows 플랫폼에서만 작동합니다). 나는 당신의 애플리케이션이 WM_TIMER 메시지를 처리 ​​할 수 ​​없기 때문에 (낮은 레벨의 유휴 우선 순위) 메시지를 처리 ​​할 수 ​​없기 때문에 사용자 인터페이스 책임을 지키는 훅의 빈번한 콜백을 처리 할 수 ​​있다고 생각하지 않는다. (자신의 주 스레드 메시지를 처리하기 위해) :

unit Unit1; 

{$mode objfpc}{$H+} 

interface 

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

type 

    { TForm1 } 

    TForm1 = class(TForm) 
    Label1: TLabel; 
    Panel1: TPanel; 
    UpdateTimer: TTimer; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure UpdateTimerTimer(Sender: TObject); 
    private 
    DesktopDC: HDC; 
    public 
    { public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.lfm} 

{ TForm1 } 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    DesktopDC := GetDC(0); 
    if (DesktopDC <> 0) then 
    UpdateTimer.Enabled := True; 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    ReleaseDC(GetDesktopWindow, DesktopDC); 
end; 

procedure TForm1.UpdateTimerTimer(Sender: TObject); 
var 
    CursorPos: TPoint; 
begin 
    if GetCursorPos(CursorPos) then 
    begin 
    Label1.Caption := 'Cursor pos: [' + IntToStr(CursorPos.x) + '; ' + 
     IntToStr(CursorPos.y) + ']'; 
    Panel1.Color := GetPixel(DesktopDC, CursorPos.x, CursorPos.y); 
    end; 
end; 

end. 
+0

감사합니다, 타이머를 사용하여 내 첫 시도했다. 그것은 시스템 성능에 상당한 영향을 미치므로 내가 후크에왔다. 그러나이 설정으로 나는 최선의 결과 (업데이트 시간 대 글로벌 성능)를 얻을 수 있습니다. 나의 목표는 Litschi-soft의 ColGet과 같은 것을 달성하는 것이 었습니다.그래서 GetPixel보다 빠른 것이 없다면 이것은 답이 될 것입니다. –

+0

그래픽 어댑터로 직접 작업하는 방법이 있다고 생각합니다. 그러나 작업이 지나치게 복잡 할 것입니다 (프로젝트에 얼마나 많은 시간을 쓰느냐에 달려 있음). 'GetPixel' 함수는 꽤 느리지 만 마우스 후크가 어떻게 든 도움이된다는 것을 의미하지는 않습니다. 반대로 커서 위치와 색상 정보를 훨씬 더 자주 업데이트했기 때문에 더욱 나 빠졌다고 느낄 수 있습니다. 인간의 눈은 너무 자주 (모든 단일 커서 이동) 읽을 수 없으며 좋은 모양과 느낌은 IMHO만큼 30ms 타이머입니다. – TLama

+0

나는 또한 글로벌 마우스 클릭에 액션을 추가하려고했다. 하지만 최선의 결과를 얻으려는 시도는 30ms 타이머로만 이루어졌습니다. –

관련 문제