{ This file is part of the Mufasa Macro Library (MML) Copyright (c) 2009 by Raymond van Venetiƫ and Merlijn Wajer MML is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. MML is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with MML. If not, see . See the file COPYING, included in this distribution, for details about the copyright. Colourpicker for the Mufasa Macro Library } unit colourpicker; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LCLIntf,LCLType,InterfaceBase,Forms,Controls,ExtCtrls, Graphics, {$IFDEF MSWINDOWS} os_windows, {$ENDIF} {$IFDEF LINUX} os_linux, {$ENDIF} MufasaTypes, colourhistory,bitmaps {$IFNDEF PICKER_CLIENT} {$IFDEF LINUX} ,x {$ENDIF} {$ENDIF} ; type TMColorPicker = class(TObject) constructor Create(manager: TIOManager); destructor Destroy; override; procedure Pick(Out C, X, Y: Integer); procedure ImageMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure ImageInfoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure ColorPickUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer); private { Are we currently picking? } FPicking: Boolean; public manager: TIOManager; { Form components } ScreenForm, InfoForm : TForm; ImageMain, ImageInfo: TImage; Text : string; FPickEvent : TColourPickEvent; { Some temp vars } oldx, oldy, Color, colorx, colory: Integer; // targetleft,targettop : integer; TheChangedEvent,TheChangingEvent : TNotifyEvent; { Handles } InfoHandle, ImageHandle : HDC; public property Picking: Boolean read FPicking; property OnPick: TColourPickEvent read FPickEvent write FPickEvent; end; implementation constructor TMColorPicker.Create(manager: TIOManager); begin inherited Create; Self.manager := manager; Self.FPicking := False; end; destructor TMColorPicker.Destroy; begin inherited Destroy; end; var closed: Boolean; procedure TMColorPicker.Pick(Out C, X, Y: Integer); var w, h: integer; SS : TShiftState; p : TPoint; bmp2 : Graphics.TBitmap; bmp: TMufasaBitmap; Desktop : TIOManager; begin if self.FPicking then raise Exception.Create('Pick() has not yet returned, but has been called' + 'again'); Self.FPicking := True; { Disable both of the color pick buttons } w := 0; h := 0; { If the target window isn't valid (closed etc), make the destkop the new window} if not Self.Manager.TargetValid then Self.Manager.SetDesktop; {Desktop is needed for the whole picture} Desktop := TIOManager.Create; Desktop.SetDesktop; Desktop.GetDimensions(w, h); { Application.MainForm.Enabled := False; ColourHistoryForm.Enabled := False;} { Create a form that will hold the client image and a form that will show cursor and color data } ScreenForm := TForm.Create(Application.MainForm); InfoForm := TForm.Create(ScreenForm); { Initialize the form that will hold the client image } ScreenForm.Caption := 'SimbaColourPicker'; { Set the form's dimensions to match that of the screen } ScreenForm.Width := w; ScreenForm.Height := h; ScreenForm.Top := 0; ScreenForm.left := 0; //ScreenForm.WindowState := wsmaximized; {Dual screen problems} ScreenForm.BorderStyle:= bsNone; // ScreenForm.FormStyle := fsStayOnTop; {Runescape generates new handle ;-)} { Initialize the form that will hold the cursor and color info } InfoForm.Width := 173; InfoForm.Height := 33; InfoForm.BorderStyle := bsNone; // InfoForm.FormStyle := fsStayOnTop; InfoForm.Left := Mouse.CursorPos.X + 5; InfoForm.Top := Mouse.CursorPos.Y - 15; { Initialize the image that will hold the cursor and color info } ImageInfo := TImage.Create(InfoForm); ImageInfo.Parent := InfoForm; ImageInfo.Left := 0; ImageInfo.Top := 0; ImageInfo.Width := 173; ImageInfo.Height := 33; ImageInfo.Cursor := crCross; ImageInfo.OnMouseMove := @ImageInfoMouseMove; ImageInfo.Canvas.Brush.Color := 14811135; ImageInfo.Canvas.Rectangle(0, 0, 173, 33); ImageInfo.Canvas.Rectangle(114, 3, 140, 29); ImageInfo.Canvas.Rectangle(142, 3, 168, 29); ImageInfo.Canvas.Pen.Style := psClear; { Initialize the image that will hold the client image } ImageMain := TImage.Create(ScreenForm); ImageMain.Parent := ScreenForm; ImageMain.left := 0; ImageMain.top := 0; ImageMain.width := ScreenForm.Width; ImageMain.Height := ScreenForm.Height; ImageMain.Cursor:= crCross; ImageMain.OnMouseUp:= @ColorPickUp; ImageMain.OnMouseMove:=@ImageMainMouseMove; { Copy the client to ImageMain } bmp:=TMufasaBitmap.Create; bmp.CopyClientToBitmap(Desktop, true, 0, 0, w-1, h-1); Bmp2 := Bmp.ToTBitmap; ImageMain.Picture.Assign(bmp2); bmp2.free; bmp.Free; { Set up handles and events } ImageHandle:= ImageMain.Canvas.Handle; InfoHandle:= ImageInfo.Canvas.Handle; TheChangedEvent := ImageMain.Canvas.OnChange; TheChangingEvent := ImageMain.Canvas.OnChanging; { Show the forms } ScreenForm.Show; InfoForm.Show; { Display the data on the info form } p := ImageMain.ScreenToClient(Mouse.CursorPos); ImageMainMouseMove(nil, SS, p.x, p.y); closed := False; { Wait while the forms are still open } while not Closed do begin sleep(1); Application.ProcessMessages; end; { Close the forms } InfoForm.Hide; ScreenForm.Hide; // add x to history here. c := Color; x := Colorx; y := Colory; { Free forms and images } ImageMain.Free; ImageInfo.Free; InfoForm.Free; ScreenForm.Free; Desktop.free; self.FPicking := False; { Re-enable the color pick buttons } // Application.MainForm.Enabled := True; // ColourHistoryForm.Enabled := True; end; procedure TMColorPicker.ImageMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var TempPoint : TPoint; R : TRect; px, py : Integer; MouseX, MouseY: Integer; begin { Move the info form } manager.GetMousePos(MouseX, MouseY); InfoForm.Left := Mouse.CursorPos.X + 5; InfoForm.Top := Mouse.CursorPos.Y - 15; TempPoint := Point(x, y); { If a form cannot be fully set to 0,0 } TempPoint.X := TempPoint.X - ScreenForm.Left; TempPoint.Y := TempPoint.Y - ScreenForm.Top; { Get the pixel that the cursor is currently on } Color := WidgetSet.DCGetPixel(ImageHandle, X, Y); { Draw the current pixel to the right color box } ImageInfo.Canvas.Brush.Color := Color; ImageInfo.Canvas.Rectangle(143, 4, 168, 29); { Draw the cursor and color info } SetBkColor(InfoHandle, 14811135); Text := Format('Pos: %d, %d', [MouseX, MouseY]); R := Rect(5, 6, 114, 18); ExtTextOut(InfoHandle, 5, 3, ETO_OPAQUE, @R, pchar(text), length(text), nil); Text := Format('Color: %d', [Color]); R := Rect(5, 18, 114, 28); ExtTextOut(InfoHandle, 5, 15, ETO_OPAQUE, @R, pchar(text), length(text), nil); { Draw the left, slightly zoomed out, color box } for px := -1 to 1 do for py := -1 to 1 do begin ImageInfo.Canvas.Brush.Color := WidgetSet.DCGetPixel(ImageHandle, x + px, y + py); ImageInfo.Canvas.Rectangle((px + 1) * 8 + 115, (py + 1) * 8 + 4, (px + 1) * 8 + 124, (py + 1) * 8 + 13); end; Oldx := TempPoint.x; Oldy := TempPoint.y; end; procedure TMColorPicker.ImageInfoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin { Move the info form } InfoForm.Top := Mouse.CursorPos.Y - 15; InfoForm.Left := Mouse.CursorPos.X + 5; end; procedure TMColorPicker.ColorPickUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin; { Set the coordinates and color that the user cliked on } Color:= WidgetSet.DCGetPixel(ImageMain.Canvas.Handle,x,y); Manager.GetMousePos(ColorX, ColorY); if Assigned(OnPick) then Onpick(Sender,Color,Colorx,Colory); { Tell Pick() that we are done } closed := True; end; end.