home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 1999 February / DPPCPRO0299.ISO / February / Delphi / Install / DATA.Z / COLORGRD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-06-11  |  16.0 KB  |  527 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,96 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ColorGrd;
  11.  
  12. {$R-}
  13.  
  14. interface
  15.  
  16. uses Windows, Messages, Classes, Graphics, Forms, Controls, ExtCtrls;
  17.  
  18. const
  19.   NumPaletteEntries = 20;
  20.  
  21. type
  22.   TGridOrdering = (go16x1, go8x2, go4x4, go2x8, go1x16);
  23.  
  24.   TColorGrid = class(TCustomControl)
  25.   private
  26.     FPaletteEntries: array[0..NumPaletteEntries - 1] of TPaletteEntry;
  27.     FClickEnablesColor: Boolean;
  28.     FForegroundIndex: Integer;
  29.     FBackgroundIndex: Integer;
  30.     FForegroundEnabled: Boolean;
  31.     FBackgroundEnabled: Boolean;
  32.     FSelection: Integer;
  33.     FCellXSize, FCellYSize: Integer;
  34.     FNumXSquares, FNumYSquares: Integer;
  35.     FGridOrdering: TGridOrdering;
  36.     FHasFocus: Boolean;
  37.     FOnChange: TNotifyEvent;
  38.     FButton: TMouseButton;
  39.     FButtonDown: Boolean;
  40.     procedure DrawSquare(Which: Integer; ShowSelector: Boolean);
  41.     procedure DrawFgBg;
  42.     procedure UpdateCellSizes(DoRepaint: Boolean);
  43.     procedure SetGridOrdering(Value: TGridOrdering);
  44.     function GetForegroundColor: TColor;
  45.     function GetBackgroundColor: TColor;
  46.     procedure SetForegroundIndex(Value: Integer);
  47.     procedure SetBackgroundIndex(Value: Integer);
  48.     procedure SetSelection(Value: Integer);
  49.     procedure EnableForeground(Value: Boolean);
  50.     procedure EnableBackground(Value: Boolean);
  51.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  52.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  53.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  54.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  55.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  56.   protected
  57.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  58.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  59.       X, Y: Integer); override;
  60.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  61.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  62.       X, Y: Integer); override;
  63.     procedure CreateWnd; override;
  64.     procedure Paint; override;
  65.     procedure Change; dynamic;
  66.     function SquareFromPos(X, Y: Integer): Integer;
  67.   public
  68.     constructor Create(AOwner: TComponent); override;
  69.     property ForegroundColor: TColor read GetForegroundColor;
  70.     property BackgroundColor: TColor read GetBackgroundColor;
  71.   published
  72.     property ClickEnablesColor: Boolean read FClickEnablesColor write FClickEnablesColor default False;
  73.     property Ctl3D;
  74.     property DragCursor;
  75.     property DragMode;
  76.     property Enabled;
  77.     property GridOrdering: TGridOrdering read FGridOrdering write SetGridOrdering default go4x4;
  78.     property ForegroundIndex: Integer read FForegroundIndex write SetForegroundIndex default 0;
  79.     property BackgroundIndex: Integer read FBackgroundIndex write SetBackgroundIndex default 0;
  80.     property ForegroundEnabled: Boolean read FForegroundEnabled write EnableForeground default True;
  81.     property BackgroundEnabled: Boolean read FBackgroundEnabled write EnableBackground default True;
  82.     property Font;
  83.     property ParentCtl3D;
  84.     property ParentFont;
  85.     property ParentShowHint;
  86.     property PopUpMenu;
  87.     property Selection: Integer read FSelection write SetSelection default 0;
  88.     property ShowHint;
  89.     property TabOrder;
  90.     property TabStop;
  91.     property Visible;
  92.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  93.     property OnClick;
  94.     property OnDragDrop;
  95.     property OnDragOver;
  96.     property OnEndDrag;
  97.     property OnEnter;
  98.     property OnExit;
  99.     property OnKeyDown;
  100.     property OnKeyPress;
  101.     property OnKeyUp;
  102.     property OnMouseDown;
  103.     property OnMouseMove;
  104.     property OnMouseUp;
  105.   end;
  106.  
  107. implementation
  108.  
  109. uses SysUtils, Consts, StdCtrls;
  110.  
  111. constructor TColorGrid.Create(AOwner: TComponent);
  112. begin
  113.   inherited Create(AOwner);
  114.   ControlStyle := ControlStyle + [csOpaque];
  115.   FGridOrdering := go4x4;
  116.   FNumXSquares := 4;
  117.   FNumYSquares := 4;
  118.   FForegroundEnabled := True;
  119.   FBackgroundEnabled := True;
  120.   Color := clBtnFace;
  121.   Canvas.Brush.Style := bsSolid;
  122.   Canvas.Pen.Color := clBlack;
  123.   SetBounds(0, 0, 100, 100);
  124.   GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, NumPaletteEntries,
  125.     FPaletteEntries);
  126. end;
  127.  
  128. procedure TColorGrid.CreateWnd;
  129. begin
  130.   inherited CreateWnd;
  131.   SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE)
  132.     or WS_CLIPSIBLINGS);
  133. end;
  134.  
  135. procedure TColorGrid.DrawSquare(Which: Integer; ShowSelector: Boolean);
  136. var
  137.   WinTop, WinLeft: Integer;
  138.   PalIndex: Integer;
  139.   CellRect: TRect;
  140. begin
  141.   if (Which >=0) and (Which <= 15) then
  142.   begin
  143.     if Which < 8 then
  144.       PalIndex := Which else PalIndex := Which + 4;
  145.     WinTop := (Which div FNumXSquares) * FCellYSize;
  146.     WinLeft := (Which mod FNumXSquares) * FCellXSize;
  147.     CellRect := Bounds(WinLeft, WinTop, FCellXSize, FCellYSize);
  148.     if Ctl3D then
  149.     begin
  150.       Canvas.Pen.Color := clBtnFace;
  151.       with CellRect do Canvas.Rectangle(Left, Top, Right, Bottom);
  152.       InflateRect(CellRect, -1, -1);
  153.       Frame3D(Canvas, CellRect, clBtnShadow, clBtnHighlight, 2);
  154.     end else Canvas.Pen.Color := clBlack;
  155.     with FPaletteEntries[PalIndex] do
  156.     begin
  157.       Canvas.Brush.Color := TColor(RGB(peRed, peGreen, peBlue));
  158.       if Ctl3D then Canvas.Pen.Color := TColor(RGB(peRed, peGreen, peBlue));
  159.     end;
  160.     if not ShowSelector then with CellRect do
  161.       Canvas.Rectangle(Left, Top, Right, Bottom)
  162.     else with CellRect do
  163.     begin
  164.       if Ctl3D then
  165.       begin
  166.         Canvas.Rectangle(Left, Top, Right, Bottom);
  167.         InflateRect(CellRect, -1, -1);
  168.         DrawFocusRect(Canvas.Handle, CellRect);
  169.       end else with Canvas do
  170.       begin
  171.         Pen.Color := clBlack;
  172.         Pen.Mode := pmNot;
  173.         Rectangle(Left, Top, Right, Bottom);
  174.         Pen.Mode := pmCopy;
  175.         Rectangle(Left + 2, Top + 2, Right - 2, Bottom - 2);
  176.       end;
  177.     end;
  178.   end;
  179. end;
  180.  
  181. procedure TColorGrid.DrawFgBg;
  182. var
  183.   TextColor: TPaletteEntry;
  184.   PalIndex: Integer;
  185.   TheText: string;
  186.   OldBkMode: Integer;
  187.   R: TRect;
  188.  
  189.   function TernaryOp(Test: Boolean; ResultTrue, ResultFalse: Integer): Integer;
  190.   begin
  191.     if Test then
  192.       Result := ResultTrue
  193.     else Result := ResultFalse;
  194.   end;
  195.  
  196. begin
  197.   OldBkMode := SetBkMode(Canvas.Handle, TRANSPARENT);
  198.   if FForegroundEnabled then
  199.   begin
  200.     if (FForegroundIndex = FBackgroundIndex) and FBackgroundEnabled then
  201.       TheText := LoadStr(SFB) else TheText := LoadStr(SFG);
  202.     if FForegroundIndex < 8 then
  203.       PalIndex := FForegroundIndex else PalIndex := FForegroundIndex + 4;
  204.     TextColor := FPaletteEntries[PalIndex];
  205.     with TextColor do
  206.     begin
  207.       peRed := TernaryOp(peRed >= $80, 0, $FF);
  208.       peGreen := TernaryOp(peGreen >= $80, 0, $FF);
  209.       peBlue := TernaryOp(peBlue >= $80, 0, $FF);
  210.       Canvas.Font.Color := TColor(RGB(peRed, peGreen, peBlue));
  211.     end;
  212.     with R do
  213.     begin
  214.       left := (FForegroundIndex mod FNumXSquares) * FCellXSize;
  215.       right := left + FCellXSize;
  216.       top := (FForegroundIndex div FNumXSquares) * FCellYSize;
  217.       bottom := top + FCellYSize;
  218.     end;
  219.     DrawText(Canvas.Handle, PChar(TheText), -1, R,
  220.        DT_NOCLIP or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
  221.   end;
  222.   if FBackgroundEnabled then
  223.   begin
  224.     if (FForegroundIndex = FBackgroundIndex) and FForegroundEnabled then
  225.       TheText := LoadStr(SFB) else TheText := LoadStr(SBG);
  226.     if FBackgroundIndex < 8 then
  227.       PalIndex := FBackgroundIndex else PalIndex := FBackgroundIndex + 4;
  228.     TextColor := FPaletteEntries[PalIndex];
  229.     with TextColor do
  230.     begin
  231.       peRed := TernaryOp(peRed >= $80, 0, $FF);
  232.       peGreen := TernaryOp(peGreen >= $80, 0, $FF);
  233.       peBlue := TernaryOp(peBlue >= $80, 0, $FF);
  234.       Canvas.Font.Color := TColor(RGB(peRed, peGreen, peBlue));
  235.     end;
  236.     with R do
  237.     begin
  238.       left := (FBackgroundIndex mod FNumXSquares) * FCellXSize;
  239.       right := left + FCellXSize;
  240.       top := (FBackgroundIndex div FNumXSquares) * FCellYSize;
  241.       bottom := top + FCellYSize;
  242.     end;
  243.     DrawText(Canvas.Handle, PChar(TheText), -1, R,
  244.       DT_NOCLIP or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
  245.   end;
  246.   SetBkMode(Canvas.Handle, OldBkMode);
  247. end;
  248.  
  249. procedure TColorGrid.EnableForeground(Value: Boolean);
  250. begin
  251.   if FForegroundEnabled = Value then Exit;
  252.   FForegroundEnabled := Value;
  253.   DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  254.   DrawFgBg;
  255. end;
  256.  
  257. procedure TColorGrid.EnableBackground(Value: Boolean);
  258. begin
  259.   if FBackgroundEnabled = Value then Exit;
  260.   FBackgroundEnabled := Value;
  261.   DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  262.   DrawFgBg;
  263. end;
  264.  
  265. function TColorGrid.GetForegroundColor: TColor;
  266. var
  267.   PalIndex: Integer;
  268. begin
  269.   if FForegroundIndex < 8 then
  270.     PalIndex := FForegroundIndex else PalIndex := FForegroundIndex + 4;
  271.   with FPaletteEntries[PalIndex] do
  272.     Result := TColor(RGB(peRed, peGreen, peBlue));
  273. end;
  274.  
  275. function TColorGrid.GetBackgroundColor: TColor;
  276. var
  277.   PalIndex: Integer;
  278. begin
  279.   if FBackgroundIndex < 8 then
  280.     PalIndex := FBackgroundIndex else PalIndex := FBackgroundIndex + 4;
  281.   with FPaletteEntries[PalIndex] do
  282.     Result := TColor(RGB(peRed, peGreen, peBlue));
  283. end;
  284.  
  285. procedure TColorGrid.WMSetFocus(var Message: TWMSetFocus);
  286. begin
  287.   FHasFocus := True;
  288.   DrawSquare(FSelection, True);
  289.   DrawFgBg;
  290.   inherited;
  291. end;
  292.  
  293. procedure TColorGrid.WMKillFocus(var Message: TWMKillFocus);
  294. begin
  295.   FHasFocus := False;
  296.   DrawSquare(FSelection, False);
  297.   DrawFgBg;
  298.   inherited;
  299. end;
  300.  
  301. procedure TColorGrid.KeyDown(var Key: Word; Shift: TShiftState);
  302. var
  303.   NewSelection: Integer;
  304.   Range: Integer;
  305. begin
  306.   inherited KeyDown(Key, Shift);
  307.   NewSelection := FSelection;
  308.   Range := FNumXSquares * FNumYSquares;
  309.   case Key of
  310.     $46, $66:
  311.       begin
  312.         if not FForegroundEnabled and FClickEnablesColor then
  313.         begin
  314.           FForegroundEnabled := True;
  315.           DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  316.           FForegroundIndex := -1;
  317.         end;
  318.         SetForegroundIndex(NewSelection);
  319.         SetSelection(NewSelection);
  320.         Click;
  321.       end;
  322.     $42, $62:
  323.       begin
  324.         if not FBackgroundEnabled and FClickEnablesColor then
  325.         begin
  326.           FBackgroundEnabled := True;
  327.           DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  328.           FBackgroundIndex := -1;
  329.         end;
  330.         SetBackgroundIndex(NewSelection);
  331.         SetSelection(NewSelection);
  332.         Click;
  333.       end;
  334.     VK_HOME: NewSelection := 0;
  335.     VK_UP:
  336.       if FSelection >= FNumXSquares then
  337.         NewSelection := FSelection - FNumXSquares
  338.       else if FSelection <> 0 then
  339.         NewSelection := Range - FNumXSquares + FSelection - 1
  340.       else NewSelection := Range - 1;
  341.     VK_LEFT:
  342.       if FSelection <> 0 then
  343.         NewSelection := FSelection - 1
  344.       else NewSelection := Range - 1;
  345.     VK_DOWN:
  346.       if FSelection + FNumXSquares < Range then
  347.         NewSelection := FSelection + FNumXSquares
  348.       else if FSelection <> Range - 1 then
  349.         NewSelection := FSelection mod FNumXSquares + 1
  350.       else NewSelection := 0;
  351.     VK_SPACE,
  352.     VK_RIGHT:
  353.       if FSelection <> Range - 1 then
  354.         NewSelection := FSelection + 1
  355.       else NewSelection := 0;
  356.     VK_END: NewSelection := Range - 1;
  357.   else
  358.     inherited KeyDown(Key, Shift);
  359.     Exit;
  360.   end;
  361.   Key := 0;
  362.   if FSelection <> NewSelection then
  363.     SetSelection(NewSelection);
  364. end;
  365.  
  366. procedure TColorGrid.WMGetDlgCode(var Message: TWMGetDlgCode);
  367. begin
  368.   Message.Result := DLGC_WANTARROWS + DLGC_WANTCHARS;
  369. end;
  370.  
  371. procedure TColorGrid.WMSize(var Message: TWMSize);
  372. begin
  373.   inherited;
  374.   UpdateCellSizes(False);
  375. end;
  376.  
  377. procedure TColorGrid.CMCtl3DChanged(var Message: TMessage);
  378. begin
  379.   inherited;
  380.   Invalidate;
  381. end;
  382.  
  383. procedure TColorGrid.MouseDown(Button: TMouseButton; Shift: TShiftState;
  384.   X, Y: Integer);
  385. var
  386.   Square: Integer;
  387. begin
  388.   inherited MouseDown(Button, Shift, X, Y);
  389.   FButton := Button;
  390.   FButtonDown := True;
  391.   Square := SquareFromPos(X, Y);
  392.   if Button = mbLeft then
  393.   begin
  394.     if not FForegroundEnabled and FClickEnablesColor then
  395.     begin
  396.       FForegroundEnabled := True;
  397.       DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  398.       FForegroundIndex := -1;
  399.     end;
  400.     SetForegroundIndex(Square);
  401.   end
  402.   else begin
  403.     MouseCapture := True;
  404.     if not FBackgroundEnabled and FClickEnablesColor then
  405.     begin
  406.       FBackgroundEnabled := True;
  407.       DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  408.       FBackgroundIndex := -1;
  409.     end;
  410.     SetBackgroundIndex(Square);
  411.   end;
  412.   SetSelection(Square);
  413.   if TabStop then SetFocus;
  414. end;
  415.  
  416. procedure TColorGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
  417. var
  418.   Square: Integer;
  419. begin
  420.   inherited MouseMove(Shift, X, Y);
  421.   if FButtonDown then
  422.   begin
  423.     Square := SquareFromPos(X, Y);
  424.     if FButton = mbLeft then
  425.       SetForegroundIndex(Square)
  426.     else SetBackgroundIndex(Square);
  427.     SetSelection(Square);
  428.   end;
  429. end;
  430.  
  431. procedure TColorGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
  432.   X, Y: Integer);
  433. begin
  434.   inherited MouseUp(Button, Shift, X, Y);
  435.   FButtonDown := False;
  436.   if FButton = mbRight then MouseCapture := False;
  437. end;
  438.  
  439. procedure TColorGrid.Paint;
  440. var
  441.   Row, Col, wEntryIndex: Integer;
  442. begin
  443.   Canvas.Font := Font;
  444.   for Row := 0 to FNumYSquares do
  445.     for Col := 0 to FNumXSquares do
  446.     begin
  447.       wEntryIndex := Row * FNumXSquares + Col;
  448.       DrawSquare(wEntryIndex, False);
  449.     end;
  450.   DrawSquare(FSelection, FHasFocus);
  451.   DrawFgBg;
  452. end;
  453.  
  454. procedure TColorGrid.SetBackgroundIndex(Value: Integer);
  455. begin
  456.   if (FBackgroundIndex <> Value) and FBackgroundEnabled then
  457.   begin
  458.     DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  459.     FBackgroundIndex := Value;
  460.     if FBackgroundIndex = FForegroundIndex then
  461.       DrawSquare(FBackgroundIndex, (FBackgroundIndex = FSelection) and FHasFocus);
  462.     DrawFgBg;
  463.     Change;
  464.   end;
  465. end;
  466.  
  467. procedure TColorGrid.SetForegroundIndex(Value: Integer);
  468. begin
  469.   if (FForegroundIndex <> Value) and FForegroundEnabled then
  470.   begin
  471.     DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  472.     FForegroundIndex := Value;
  473.     if FForegroundIndex = FBackgroundIndex then
  474.       DrawSquare(FForegroundIndex, (FForegroundIndex = FSelection) and FHasFocus);
  475.     DrawFgBg;
  476.     Change;
  477.   end;
  478. end;
  479.  
  480. procedure TColorGrid.SetGridOrdering(Value: TGridOrdering);
  481. begin
  482.   if FGridOrdering = Value then Exit;
  483.   FGridOrdering := Value;
  484.   FNumXSquares := 16 shr Ord(FGridOrdering);
  485.   FNumYSquares := 1 shl Ord(FGridOrdering);
  486.   UpdateCellSizes(True);
  487. end;
  488.  
  489. procedure TColorGrid.SetSelection(Value: Integer);
  490. begin
  491.   if FSelection = Value then Exit;
  492.   DrawSquare(FSelection, False);
  493.   FSelection := Value;
  494.   DrawSquare(FSelection, FHasFocus);
  495.   DrawFgBg;
  496. end;
  497.  
  498. function TColorGrid.SquareFromPos(X, Y: Integer): Integer;
  499. begin
  500.   if X > Width - 1 then X := Width - 1
  501.   else if X < 0 then X := 0;
  502.   if Y > Height - 1 then Y := Height - 1
  503.   else if Y < 0 then Y := 0;
  504.   Result := (Y div FCellYSize) * FNumXSquares + (X div FCellXSize);
  505. end;
  506.  
  507. procedure TColorGrid.UpdateCellSizes(DoRepaint: Boolean);
  508. var
  509.   NewWidth, NewHeight: Integer;
  510. begin
  511.   NewWidth := (Width div FNumXSquares) * FNumXSquares;
  512.   NewHeight := (Height div FNumYSquares) * FNumYSquares;
  513.   BoundsRect := Bounds(Left, Top, NewWidth, NewHeight);
  514.   FCellXSize := Width div FNumXSquares;
  515.   FCellYSize := Height div FNumYSquares;
  516.   if DoRepaint then Invalidate;
  517. end;
  518.  
  519. procedure TColorGrid.Change;
  520. begin
  521.   if Assigned(FOnChange) then FOnChange(Self);
  522. end;
  523.  
  524. end.
  525.  
  526. 
  527.