home *** CD-ROM | disk | FTP | other *** search
/ PC Format Collection 48 / SENT14D.ISO / tech / delphi / disk15 / sampsrc.pak / COLORGRD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-08-24  |  16.2 KB  |  531 lines

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