TTXStringGrid组件 - 扩展delphi的标准TStringGrid组件

本文介绍了一个Delphi组件TXStringGrid,它允许在TStringGrid中添加内置下拉列表,类似于TDBGrid的功能。该组件开源免费,支持列设置、事件监听等功能。

    1.1.64版本已发布,有兴趣请到 http://blog.youkuaiyun.com/boythl/archive/2008/11/25/3372110.aspx 下载。

 

     因为项目中有需求需要在TStringGrid的单元格中生成内置的下拉列表,如同TDBGrid里面的一样;貌似有个什么东西能做,但是是收费的, 本人口袋空空,只好自己实现该组件, 开源所有实现代码.

  

     1. 组件化,支持可视化设计;

     2. 支持列设置,包括字体,颜色,居中,列宽,visible,readonly, 内置下拉列表, 右键菜单等; 

     3. 增加一系列事件,如CellClick等.

     4. 对单元格的个性化设置的支持尚在开发中. 

 

      不好意思的说,因为头次写delphi组件, 所以所有代码都是从TCustDBGrid扒拉过来的, 简单嘛, 改吧改吧就能用了;  但TStringGrid的父类和TCustDBGrid做过部分类似的工作, ,所以有部分代码可能是冗余的, 不过应该不碍事.

 

    鉴于首次写组件的技术不成熟性,组件里肯定会有bug;  若发现bug,欢迎及时反馈,本人有时间会及时更新!

     本组件可自由转载,复制,使用,但请保留作者和版权信息! 若有源代码修改, 希望方便时能回增本人一份,boythl#163.com 谢谢!

 

     RAR格式的 完整的组件安装包下载链接请点这儿( B4 优快云,都不提供博客上传附件功能.) 

     ( https://p-blog.youkuaiyun.com/images/p_blog_youkuaiyun.com/boythl/EntryImages/20081007/TXStringGridV1.0.38.jpg  这是随文章上传的完整组件安装包, 请用右键另存为下载并将jpg扩展名改成rar, 就可以解压缩了.)

 

核心的 TXStringGrid.pas 完整代码如下: 

  1. {*******************************************************}
  2. {                                                       }
  3. {       Lonefox Visual Component Library                }
  4. {                                                       }
  5. {       Copyright (c) 2008 All Rights Reserved          }
  6. {                                                       }
  7. {       http://lonefox.blogcn.com                       }
  8. {       http://blog.youkuaiyun.com/boythl                 }
  9. {                                                       }
  10. {*******************************************************}
  11. unit TXStringGrid;
  12. interface
  13. uses
  14.   SysUtils, Classes, Windows, Controls, Grids, Graphics, Menus, Messages,
  15.   Types, stdCtrls;
  16. type
  17.   TTXColButtonStyle = (tcbsNone, tcbsAutoSelect, tcbsEllipse);//列类型:普通,下拉菜单,按钮
  18.   TTXColumnValue = (cvColor, cvWidth, cvFont, cvAlignment, cvReadOnly, cvTitleColor,
  19.     cvTitleCaption, cvTitleAlignment, cvTitleFont);
  20.   TTXColumnValues = set of TTXColumnValue;
  21.      
  22. const
  23.     ColumnTitleValues = [cvTitleColor..cvTitleFont];
  24.   cm_DeferLayout = WM_USER + 100;
  25. type
  26.     TTXStringGrid = class;
  27.   TTXColumn = class;
  28.   TTXColumnClass = class of TTXColumn;
  29.   TTXColumnTitle = class(TPersistent)
  30.   private
  31.     FColumn: TTXColumn;
  32.     FCaption: string;
  33.     FFont: TFont;
  34.     FColor: TColor;
  35.     FAlignment: TAlignment;
  36.     procedure FontChanged(Sender: TObject);
  37.     function GetAlignment: TAlignment;
  38.     function GetColor: TColor;
  39.     function GetCaption: string;
  40.     function GetFont: TFont;
  41.     function IsAlignmentStored: Boolean;
  42.     function IsColorStored: Boolean;
  43.     function IsFontStored: Boolean;
  44.     function IsCaptionStored: Boolean;
  45.     procedure SetAlignment(Value: TAlignment);
  46.     procedure SetColor(Value: TColor);
  47.     procedure SetFont(Value: TFont);
  48.     procedure SetCaption(const Value: string); virtual;
  49.   protected
  50.     procedure RefreshDefaultFont;
  51.   public
  52.     constructor Create(Column: TTXColumn);
  53.     destructor Destroy; override;
  54.     function DefaultAlignment: TAlignment;
  55.     function DefaultColor: TColor;
  56.     function DefaultFont: TFont;
  57.     procedure RestoreDefaults; virtual;
  58.     property Column: TTXColumn read FColumn;
  59.   published
  60.     property Alignment: TAlignment read GetAlignment write SetAlignment
  61.       stored IsAlignmentStored;
  62.     property Caption: string read GetCaption write SetCaption stored IsCaptionStored;
  63.     property Color: TColor read GetColor write SetColor stored IsColorStored;
  64.     property Font: TFont read GetFont write SetFont stored IsFontStored;
  65.   end;
  66.   TTXColumn = class(TCollectionItem)
  67.   private
  68.     FAssignedValues: TTXColumnValues;
  69.     FColor: TColor;
  70.     FTitle: TTXColumnTitle;
  71.     FFont: TFont;
  72.     FPickList: TStrings;
  73.     FPopupMenu: TPopupMenu;
  74.     FDropDownRows: Cardinal;
  75.     FButtonStyle: TTXColButtonStyle;
  76.     FAlignment: TAlignment;
  77.     FReadonly: Boolean;
  78.     FVisible: Boolean;
  79.     FStored: Boolean;
  80.     FWidth: Integer;
  81.     procedure FontChanged(Sender: TObject);
  82.     function  GetAlignment: TAlignment;
  83.     function  GetColor: TColor;
  84.     function  GetFont: TFont;
  85.     function  GetPickList: TStrings;
  86.     function  GetReadOnly: Boolean;
  87.     function  IsAlignmentStored: Boolean;
  88.     function  IsColorStored: Boolean;
  89.     function  IsFontStored: Boolean;
  90.     function  IsReadOnlyStored: Boolean;
  91.     procedure SetAlignment(Value: TAlignment); virtual;
  92.     procedure SetButtonStyle(Value: TTXColButtonStyle);
  93.     procedure SetColor(Value: TColor);
  94.     procedure SetFont(Value: TFont);
  95.     procedure SetPickList(Value: TStrings);
  96.     procedure SetPopupMenu(Value: TPopupMenu);
  97.     procedure SetReadOnly(Value: Boolean); virtual;
  98.     procedure SetTitle(Value: TTXColumnTitle);
  99.     procedure SetVisible(const Value: Boolean);
  100.     function GetWidth: Integer;
  101.     function IsWidthStored: Boolean;
  102.     procedure SetWidth(const Value: Integer);
  103.   protected
  104.     function  CreateTitle: TTXColumnTitle; virtual;
  105.     function  GetGrid: TTXStringGrid;
  106.     procedure RefreshDefaultFont;
  107.     property IsStored: Boolean read FStored write FStored default True;
  108.     function DefaultWidth: integer;
  109.   public
  110.     constructor Create(Collection: TCollection); override;
  111.     destructor Destroy; override;
  112.     procedure Assign(Source: TPersistent); override;
  113.     function  DefaultAlignment: TAlignment;
  114.     function  DefaultColor: TColor;
  115.     function  DefaultFont: TFont;
  116.     procedure RestoreDefaults; virtual;
  117.     property  Grid: TTXStringGrid read GetGrid;
  118.     property  AssignedValues: TTXColumnValues read FAssignedValues;
  119.   published
  120.     property  Alignment: TAlignment read GetAlignment write SetAlignment
  121.       stored IsAlignmentStored;
  122.     property  ButtonStyle: TTXColButtonStyle read FButtonStyle write SetButtonStyle
  123.       default tcbsNone;
  124.     property  Color: TColor read GetColor write SetColor stored IsColorStored;
  125.     property  DropDownRows: Cardinal read FDropDownRows write FDropDownRows default 7;
  126.     property  Font: TFont read GetFont write SetFont stored IsFontStored;
  127.     property  PickList: TStrings read GetPickList write SetPickList;
  128.     property  PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
  129.     property  ReadOnly: Boolean read GetReadOnly write SetReadOnly
  130.       stored IsReadOnlyStored;
  131.     property  Title: TTXColumnTitle read FTitle write SetTitle;
  132.     property  Visible: Boolean read FVisible write SetVisible default true;
  133.     property  Width: Integer read GetWidth write SetWidth stored IsWidthStored;
  134.   end;
  135.   TTXColumns = class(TCollection)
  136.   private
  137.     FGrid: TTXStringGrid;
  138.     function GetTXColumn(Index: Integer): TTXColumn;
  139.     procedure SetTXColumn(Index: Integer; Value: TTXColumn);
  140.   protected
  141.     function GetOwner: TPersistent; override;
  142.     procedure Update(Item: TCollectionItem); override;
  143.   public
  144.     constructor Create(Grid: TTXStringGrid; ColumnClass: TTXColumnClass);
  145.     function  Add: TTXColumn;
  146.     procedure RestoreDefaults;
  147.     property Grid: TTXStringGrid read FGrid;
  148.     property Items[Index: Integer]: TTXColumn read GetTXColumn write SetTXColumn; default;
  149.   end;
  150.   TTXStringGridInplaceEdit = class(TInplaceEditList)
  151.   private
  152.     FDataList: TListBox;
  153.     FUseDataList: Boolean;
  154.   protected
  155.     procedure CloseUp(Accept: Boolean); override;
  156.     procedure DoEditButtonClick; override;
  157.     procedure DropDown; override;
  158.     procedure UpdateContents; override;
  159.   public
  160.     constructor Create(Owner: TComponent); override;
  161.     property  DataList: TListBox read FDataList;
  162.   end;
  163.   TTXStringGridClickEvent = procedure (Column: TTXColumn; ARow:integerof object;
  164.   TTXStringGrid = class(TStringGrid)
  165.   private
  166.     FColumns : TTXColumns;
  167.     FTitleOffset: Byte;
  168.     FUpdateLock: Byte;
  169.     FLayoutLock: Byte; 
  170.     FDefaultDrawing: Boolean;
  171.     FSelfChangingTitleFont: Boolean;
  172.     FOnColEnter: TNotifyEvent;
  173.     FOnColExit: TNotifyEvent;
  174.     FVisibleColumns: TList;
  175.     FOnEditButtonClick: TNotifyEvent;
  176.     FOnColumnMoved: TMovedEvent;
  177.     FOnCellClick    : TTXStringGridClickEvent;
  178.     FOnTitleClick   : TTXStringGridClickEvent;
  179.     function GetTXColumns() : TTXColumns;
  180.     procedure SetTXColumns(value : TTXColumns);
  181.     function AcquireFocus: Boolean;
  182.     procedure InternalLayout;
  183.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  184.     procedure CMParentFontChanged(var Message: TMessage); message CM_PARENTFONTCHANGED;
  185.     procedure CMDeferLayout(var Message); message cm_DeferLayout;
  186.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  187.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SetFOCUS;
  188.     procedure WMKillFocus(var Message: TMessage); message WM_KillFocus;
  189.   protected
  190.     FAcquireFocus: Boolean;
  191.     function  AcquireLayoutLock: Boolean;
  192.     procedure ColWidthsChanged; override;
  193.     procedure BeginLayout;
  194.     procedure BeginUpdate; 
  195.     procedure CancelLayout;
  196.     function  CanEditModify: Boolean; override;
  197.     function  CanEditShow: Boolean; override;
  198.     procedure CellClick(Column: TTXColumn; ARow:integer); dynamic;
  199.     procedure ColumnMoved(FromIndex, ToIndex: Longint); override;
  200.     function CalcTitleRect(Col: TTXColumn; ARow: Integer;
  201.       var MasterCol: TTXColumn): TRect;
  202.     procedure ColEnter; dynamic;
  203.     procedure ColExit; dynamic;
  204.     function  CreateEditor: TInplaceEdit; override;
  205.     procedure CreateWnd; override;
  206.     procedure DeferLayout;
  207.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
  208.     procedure EditButtonClick; dynamic;
  209.     procedure EndLayout;
  210.     procedure EndUpdate;
  211.     function  GetEditStyle(ACol, ARow: Longint): TEditStyle; override;
  212.     function  HighlightCell(DataCol, DataRow: Integer; const Value: string;
  213.       AState: TGridDrawState): Boolean; virtual;
  214.     procedure InvalidateTitles;
  215.     procedure LayoutChanged; virtual;
  216.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  217.       X, Y: Integer); override;
  218.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  219.       X, Y: Integer); override;
  220.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  221.     procedure Scroll(Distance: Integer); virtual;
  222.     procedure SetColumnAttributes; virtual;
  223.     function  StoreColumns: Boolean;
  224.     procedure TitleClick(Column: TTXColumn; ARow:integer); dynamic;
  225.     procedure TopLeftChanged; override;  
  226.     property DefaultDrawing: Boolean read FDefaultDrawing write FDefaultDrawing default True;
  227.     property LayoutLock: Byte read FLayoutLock;
  228.     property ParentColor default False;
  229.     property UpdateLock: Byte read FUpdateLock;
  230.   public
  231.     constructor Create(AOwner: TComponent); override;
  232.     destructor Destroy; override;
  233.     procedure DefaultHandler(var Msg); override;
  234.     procedure ShowPopupEditor(Column: TTXColumn; X: Integer = Low(Integer);
  235.       Y: Integer = Low(Integer)); dynamic;
  236.     property EditorMode;
  237.   published
  238.     property Columns : TTXColumns read GetTXColumns write SetTXColumns;
  239.     property OnColEnter: TNotifyEvent read FOnColEnter write FOnColEnter;
  240.     property OnColExit: TNotifyEvent read FOnColExit write FOnColExit;
  241.     property OnEditButtonClick: TNotifyEvent read FOnEditButtonClick
  242.       write FOnEditButtonClick;
  243.     property OnColumnMoved: TMovedEvent read FOnColumnMoved write FOnColumnMoved;
  244.     property OnCellClick: TTXStringGridClickEvent read FOnCellClick write FOnCellClick;
  245.     property OnTitleClick: TTXStringGridClickEvent read FOnTitleClick write FOnTitleClick;
  246.   end;
  247. procedure Register;
  248. implementation
  249. uses Math, Forms;
  250. procedure Register;
  251. begin
  252.   RegisterComponents('Sample', [TTXStringGrid]);
  253. end;
  254. var
  255.   DrawBitmap: TBitmap;
  256.   UserCount: Integer;
  257. {    public function   }
  258. procedure KillMessage(Wnd: HWnd; Msg: Integer);
  259. // Delete the requested message from the queue, but throw back
  260. // any WM_QUIT msgs that PeekMessage may also return
  261. var
  262.   M: TMsg;
  263. begin
  264.   M.Message := 0;
  265.   if PeekMessage(M, Wnd, Msg, Msg, pm_Remove) and (M.Message = WM_QUIT) then
  266.     PostQuitMessage(M.wparam);
  267. end;
  268. procedure RaiseGridError(const S: string);
  269. begin
  270.   raise EInvalidGridOperation.Create(S);
  271. end;
  272. procedure UsesBitmap;
  273. begin
  274.   if UserCount = 0 then
  275.     DrawBitmap := TBitmap.Create();
  276.   Inc(UserCount);
  277. end;
  278. procedure ReleaseBitmap;
  279. begin
  280.   Dec(UserCount);
  281.   if UserCount = 0 then DrawBitmap.Free;
  282. end;
  283. procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer;
  284.   const Text: string; Alignment: TAlignment; ARightToLeft: Boolean);
  285. const
  286.   AlignFlags : array [TAlignment] of Integer =
  287.     ( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
  288.       DT_RIGHT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
  289.       DT_CENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX );
  290.   RTL: array [Boolean] of Integer = (0, DT_RTLREADING);
  291. var
  292.   B, R: TRect;
  293.   Hold, Left: Integer;
  294.   I: TColorRef;
  295. begin
  296.   I := ColorToRGB(ACanvas.Brush.Color);
  297.   if GetNearestColor(ACanvas.Handle, I) = I then
  298.   begin                       { Use ExtTextOut for solid colors }
  299.     { In BiDi, because we changed the window origin, the text that does not
  300.       change alignment, actually gets its alignment changed. }
  301.     if (ACanvas.CanvasOrientation = coRightToLeft) and (not ARightToLeft) then
  302.       ChangeBiDiModeAlignment(Alignment);
  303.     case Alignment of
  304.       taLeftJustify:
  305.         Left := ARect.Left + DX;
  306.       taRightJustify:
  307.         Left := ARect.Right - ACanvas.TextWidth(Text) - 3;
  308.     else { taCenter }
  309.       Left := ARect.Left + (ARect.Right - ARect.Left) shr 1
  310.         - (ACanvas.TextWidth(Text) shr 1);
  311.     end;
  312.     ACanvas.TextRect(ARect, Left, ARect.Top + DY, Text);
  313.   end
  314.   else begin                  { Use FillRect and Drawtext for dithered colors }
  315.     DrawBitmap.Canvas.Lock;
  316.     try
  317.       with DrawBitmap, ARect do { Use offscreen bitmap to eliminate flicker and }
  318.       begin                     { brush origin tics in painting / scrolling.    }
  319.         Width := Max(Width, Right - Left);
  320.         Height := Max(Height, Bottom - Top);
  321.         R := Rect(DX, DY, Right - Left - 1, Bottom - Top - 1);
  322.         B := Rect(00, Right - Left, Bottom - Top);
  323.       end;
  324.       with DrawBitmap.Canvas do
  325.       begin
  326.         Font := ACanvas.Font;
  327.         Font.Color := ACanvas.Font.Color;
  328.         Brush := ACanvas.Brush;
  329.         Brush.Style := bsSolid;
  330.         FillRect(B);
  331.         SetBkMode(Handle, TRANSPARENT);
  332.         if (ACanvas.CanvasOrientation = coRightToLeft) then
  333.           ChangeBiDiModeAlignment(Alignment);
  334.         DrawText(Handle, PChar(Text), Length(Text), R,
  335.           AlignFlags[Alignment] or RTL[ARightToLeft]);
  336.       end;
  337.       if (ACanvas.CanvasOrientation = coRightToLeft) then  
  338.       begin
  339.         Hold := ARect.Left;
  340.         ARect.Left := ARect.Right;
  341.         ARect.Right := Hold;
  342.       end;
  343.       ACanvas.CopyRect(ARect, DrawBitmap.Canvas, B);
  344.     finally
  345.       DrawBitmap.Canvas.Unlock;
  346.     end;
  347.   end;
  348. end;
  349. { TTXColumnTitle }
  350. constructor TTXColumnTitle.Create(Column: TTXColumn);
  351. begin
  352.   inherited Create;
  353.   FColumn := Column;
  354.   FFont := TFont.Create;
  355.   FFont.Assign(DefaultFont);
  356.   FFont.OnChange := FontChanged;
  357. end;
  358. destructor TTXColumnTitle.Destroy;
  359. begin
  360.   FFont.Free;
  361.   inherited Destroy;
  362. end;
  363. function TTXColumnTitle.DefaultAlignment: TAlignment;
  364. begin
  365.   Result := taLeftJustify;
  366. end;
  367. function TTXColumnTitle.DefaultColor: TColor;
  368. var
  369.   Grid: TTXStringGrid;
  370. begin
  371.   Grid := FColumn.GetGrid;
  372.   if Assigned(Grid) then
  373.     Result := Grid.FixedColor
  374.   else
  375.     Result := clBtnFace;
  376. end;
  377. function TTXColumnTitle.DefaultFont: TFont;
  378. var
  379.   Grid: TTXStringGrid;
  380. begin
  381.   Grid := FColumn.GetGrid;
  382.   if Assigned(Grid) then
  383.     Result := Grid.Font
  384.   else
  385.     Result := FColumn.Font;
  386. end;
  387. procedure TTXColumnTitle.FontChanged(Sender: TObject);
  388. begin
  389.   Include(FColumn.FAssignedValues, cvTitleFont);
  390.   FColumn.Changed(True);
  391. end;
  392. function TTXColumnTitle.GetAlignment: TAlignment;
  393. begin
  394.   if cvTitleAlignment in FColumn.FAssignedValues then
  395.     Result := FAlignment
  396.   else
  397.     Result := DefaultAlignment;
  398. end;
  399. function TTXColumnTitle.GetColor: TColor;
  400. begin
  401.   if cvTitleColor in FColumn.FAssignedValues then
  402.     Result := FColor
  403.   else
  404.     Result := DefaultColor;
  405. end;
  406. function TTXColumnTitle.GetCaption: string;
  407. begin
  408.   if cvTitleCaption in FColumn.FAssignedValues then
  409.     Result := FCaption;
  410. end;
  411. function TTXColumnTitle.GetFont: TFont;
  412. var
  413.   Save: TNotifyEvent;
  414.   Def: TFont;
  415. begin
  416.   if not (cvTitleFont in FColumn.FAssignedValues) then
  417.   begin
  418.     Def := DefaultFont;
  419.     if (FFont.Handle <> Def.Handle) or (FFont.Color <> Def.Color) then
  420.     begin
  421.       Save := FFont.OnChange;
  422.       FFont.OnChange := nil;
  423.       FFont.Assign(DefaultFont);
  424.       FFont.OnChange := Save;
  425.     end;
  426.   end;
  427.   Result := FFont;
  428. end;
  429. function TTXColumnTitle.IsAlignmentStored: Boolean;
  430. begin
  431.   Result := (cvTitleAlignment in FColumn.FAssignedValues) and
  432.     (FAlignment <> DefaultAlignment);
  433. end;
  434. function TTXColumnTitle.IsColorStored: Boolean;
  435. begin
  436.   Result := (cvTitleColor in FColumn.FAssignedValues) and
  437.     (FColor <> DefaultColor);
  438. end;
  439. function TTXColumnTitle.IsFontStored: Boolean;
  440. begin
  441.   Result := (cvTitleFont in FColumn.FAssignedValues);
  442. end;
  443. function TTXColumnTitle.IsCaptionStored: Boolean;
  444. begin
  445.   Result := (cvTitleCaption in FColumn.FAssignedValues);
  446. end;
  447. procedure TTXColumnTitle.RefreshDefaultFont;
  448. var
  449.   Save: TNotifyEvent;
  450. begin
  451.   if (cvTitleFont in FColumn.FAssignedValues) then Exit;
  452.   Save := FFont.OnChange;
  453.   FFont.OnChange := nil;
  454.   try
  455.     FFont.Assign(DefaultFont);
  456.   finally
  457.     FFont.OnChange := Save;
  458.   end;
  459. end;
  460. procedure TTXColumnTitle.RestoreDefaults;
  461. var
  462.   FontAssigned: Boolean;
  463. begin
  464.   FontAssigned := cvTitleFont in FColumn.FAssignedValues;
  465.   FColumn.FAssignedValues := FColumn.FAssignedValues - ColumnTitleValues;
  466.   FCaption := '';
  467.   RefreshDefaultFont;
  468.   { If font was assigned, changing it back to default may affect grid title
  469.     height, and title height changes require layout and redraw of the grid. }
  470.   FColumn.Changed(FontAssigned);
  471. end;
  472. procedure TTXColumnTitle.SetAlignment(Value: TAlignment);
  473. begin
  474.   if (cvTitleAlignment in FColumn.FAssignedValues) and (Value = FAlignment) then Exit;
  475.   FAlignment := Value;
  476.   Include(FColumn.FAssignedValues, cvTitleAlignment);
  477.   FColumn.Changed(False);
  478. end;
  479. procedure TTXColumnTitle.SetColor(Value: TColor);
  480. begin
  481.   if (cvTitleColor in FColumn.FAssignedValues) and (Value = FColor) then Exit;
  482.   FColor := Value;
  483.   Include(FColumn.FAssignedValues, cvTitleColor);
  484.   FColumn.Changed(False);
  485. end;
  486. procedure TTXColumnTitle.SetFont(Value: TFont);
  487. begin
  488.   FFont.Assign(Value);
  489. end;
  490. procedure TTXColumnTitle.SetCaption(const Value: string);
  491. begin
  492.   if Column.IsStored then
  493.   begin
  494.     if (cvTitleCaption in FColumn.FAssignedValues) and (Value = FCaption) then Exit;
  495.     FCaption := Value;
  496.     Include(Column.FAssignedValues, cvTitleCaption);
  497.     Column.Changed(False);
  498.   end;
  499. end;
  500. { TTXColumn }
  501. constructor TTXColumn.Create(Collection: TCollection);
  502. begin
  503.     FDropDownRows := 7;
  504.   FButtonStyle := tcbsNone;
  505.   FFont := TFont.Create;
  506.   FFont.Assign(DefaultFont);
  507.   FFont.OnChange := FontChanged;
  508.   FTitle := CreateTitle;
  509.   FVisible := True;
  510.   FWidth := self.DefaultWidth;
  511.   inherited Create(Collection);
  512.   FStored := True;
  513. end;
  514. destructor TTXColumn.Destroy;
  515. begin
  516.   FTitle.Free;
  517.   FFont.Free;
  518.   FPickList.Free;
  519.   inherited Destroy;
  520. end;
  521. procedure TTXColumn.Assign(Source: TPersistent);
  522. begin
  523.   if Source is TTXColumn then
  524.   begin
  525.     if Assigned(Collection) then Collection.BeginUpdate;
  526.     try
  527.       RestoreDefaults;
  528.       if cvColor in TTXColumn(Source).AssignedValues then
  529.         Color := TTXColumn(Source).Color;
  530.       if cvWidth in TTXColumn(Source).AssignedValues then
  531.         Width := TTXColumn(Source).Width;
  532.       if cvFont in TTXColumn(Source).AssignedValues then
  533.         Font := TTXColumn(Source).Font;
  534.       if cvAlignment in TTXColumn(Source).AssignedValues then
  535.         Alignment := TTXColumn(Source).Alignment;
  536.       if cvReadOnly in TTXColumn(Source).AssignedValues then
  537.         ReadOnly := TTXColumn(Source).ReadOnly;
  538.       Title := TTXColumn(Source).Title;
  539.       DropDownRows := TTXColumn(Source).DropDownRows;
  540.       ButtonStyle := TTXColumn(Source).ButtonStyle;
  541.       PickList := TTXColumn(Source).PickList;
  542.       PopupMenu := TTXColumn(Source).PopupMenu;
  543.     finally
  544.       if Assigned(Collection) then Collection.EndUpdate;
  545.     end;
  546.   end
  547.   else
  548.     inherited Assign(Source);
  549. end;
  550. function TTXColumn.CreateTitle: TTXColumnTitle;
  551. begin
  552.   Result := TTXColumnTitle.Create(Self);
  553. end;
  554. function TTXColumn.DefaultAlignment: TAlignment;
  555. begin
  556.   Result := taLeftJustify;
  557. end;
  558. function TTXColumn.DefaultColor: TColor;
  559. var
  560.   Grid: TTXStringGrid;
  561. begin
  562.   Grid := GetGrid;
  563.   if Assigned(Grid) then
  564.     Result := Grid.Color
  565.   else
  566.     Result := clWindow;
  567. end;
  568. function TTXColumn.DefaultFont: TFont;
  569. var
  570.   Grid: TTXStringGrid;
  571. begin
  572.   Grid := GetGrid;
  573.   if Assigned(Grid) then
  574.     Result := Grid.Font
  575.   else
  576.     Result := FFont;
  577. end;
  578. procedure TTXColumn.FontChanged;
  579. begin
  580.   Include(FAssignedValues, cvFont);
  581.   Title.RefreshDefaultFont;
  582.   Changed(False);
  583. end;
  584. function TTXColumn.GetAlignment: TAlignment;
  585. begin
  586.   if cvAlignment in FAssignedValues then
  587.     Result := FAlignment
  588.   else
  589.     Result := DefaultAlignment;
  590. end;
  591. function TTXColumn.GetColor: TColor;
  592. begin
  593.   if cvColor in FAssignedValues then
  594.     Result := FColor
  595.   else
  596.     Result := DefaultColor;
  597. end;
  598. function TTXColumn.GetFont: TFont;
  599. var
  600.   Save: TNotifyEvent;
  601. begin
  602.   if not (cvFont in FAssignedValues) and (FFont.Handle <> DefaultFont.Handle) then
  603.   begin
  604.     Save := FFont.OnChange;
  605.     FFont.OnChange := nil;
  606.     FFont.Assign(DefaultFont);
  607.     FFont.OnChange := Save;
  608.   end;
  609.   Result := FFont;
  610. end;
  611. function TTXColumn.GetGrid: TTXStringGrid;
  612. begin
  613.   if Assigned(Collection) and (Collection is TTXColumns) then
  614.     Result := TTXColumns(Collection).Grid
  615.   else
  616.     Result := nil;
  617. end;
  618. function TTXColumn.GetPickList: TStrings;
  619. begin
  620.   if FPickList = nil then
  621.     FPickList := TStringList.Create;
  622.   Result := FPickList;
  623. end;
  624. function TTXColumn.GetReadOnly: Boolean;
  625. begin
  626.   if cvReadOnly in FAssignedValues then
  627.     Result := FReadOnly
  628.   else
  629.     Result := False;  //default "can write"
  630. end;
  631. function TTXColumn.IsAlignmentStored: Boolean;
  632. begin
  633.   Result := (cvAlignment in FAssignedValues) and (FAlignment <> DefaultAlignment);
  634. end;
  635. function TTXColumn.IsColorStored: Boolean;
  636. begin
  637.   Result := (cvColor in FAssignedValues) and (FColor <> DefaultColor);
  638. end;
  639. function TTXColumn.IsFontStored: Boolean;
  640. begin
  641.   Result := (cvFont in FAssignedValues);
  642. end;
  643. function TTXColumn.IsReadOnlyStored: Boolean;
  644. begin
  645.   Result := (cvReadOnly in FAssignedValues) and (FReadOnly <> false);
  646. end;
  647. procedure TTXColumn.RefreshDefaultFont;
  648. var
  649.   Save: TNotifyEvent;
  650. begin
  651.   if cvFont in FAssignedValues then Exit;
  652.   Save := FFont.OnChange;
  653.   FFont.OnChange := nil;
  654.   try
  655.     FFont.Assign(DefaultFont);
  656.   finally
  657.     FFont.OnChange := Save;
  658.   end;
  659. end;
  660. procedure TTXColumn.RestoreDefaults;
  661. var
  662.   FontAssigned: Boolean;
  663. begin
  664.   FontAssigned := cvFont in FAssignedValues;
  665.   FTitle.RestoreDefaults;
  666.   FAssignedValues := [];
  667.   RefreshDefaultFont;
  668.   FPickList.Free;
  669.   FPickList := nil;
  670.   ButtonStyle := tcbsNone;
  671.   Changed(FontAssigned);
  672. end;
  673. procedure TTXColumn.SetAlignment(Value: TAlignment);
  674. begin
  675.   if IsStored then
  676.   begin
  677.     if (cvAlignment in FAssignedValues) and (Value = FAlignment) then Exit;
  678.     FAlignment := Value;
  679.     Include(FAssignedValues, cvAlignment);
  680.     Changed(False);
  681.   end;
  682. end;
  683. procedure TTXColumn.SetButtonStyle(Value: TTXColButtonStyle);
  684. begin
  685.   if Value = FButtonStyle then Exit;
  686.   FButtonStyle := Value;
  687.   Changed(False);
  688. end;
  689. procedure TTXColumn.SetColor(Value: TColor);
  690. begin
  691.   if (cvColor in FAssignedValues) and (Value = FColor) then Exit;
  692.   FColor := Value;
  693.   Include(FAssignedValues, cvColor);
  694.   Changed(False);
  695. end;
  696. procedure TTXColumn.SetFont(Value: TFont);
  697. begin
  698.   FFont.Assign(Value);
  699.   Include(FAssignedValues, cvFont);
  700.   Changed(False);
  701. end;
  702. procedure TTXColumn.SetPickList(Value: TStrings);
  703. begin
  704.   if Value = nil then
  705.   begin
  706.     FPickList.Free;
  707.     FPickList := nil;
  708.     Exit;
  709.   end;
  710.   PickList.Assign(Value);
  711. end;
  712. procedure TTXColumn.SetPopupMenu(Value: TPopupMenu);
  713. begin
  714.   FPopupMenu := Value;
  715.   if Value <> nil then Value.FreeNotification(GetGrid);
  716. end;
  717. procedure TTXColumn.SetReadOnly(Value: Boolean);
  718. begin
  719.   if IsStored then
  720.   begin
  721.     if (cvReadOnly in FAssignedValues) and (Value = FReadOnly) then Exit;
  722.     FReadOnly := Value;
  723.     Include(FAssignedValues, cvReadOnly);
  724.     Changed(False);
  725.   end;
  726. end;
  727. procedure TTXColumn.SetTitle(Value: TTXColumnTitle);
  728. begin
  729.   FTitle.Assign(Value);
  730. end;
  731. procedure TTXColumn.SetVisible(const Value: Boolean);
  732. begin
  733.   if Value <> FVisible then
  734.   begin
  735.     FVisible := Value;
  736.     Changed(True);
  737.   end;
  738. end;
  739. function TTXColumn.GetWidth: Integer;
  740. begin
  741.   if not Visible then
  742.     Result := -1
  743.   else if cvWidth in FAssignedValues then
  744.     Result := FWidth
  745.   else
  746.     Result := DefaultWidth;
  747. end;
  748. function TTXColumn.IsWidthStored: Boolean;
  749. begin
  750.     Result := (cvWidth in FAssignedValues) and
  751.                     (FWidth <> DefaultWidth);
  752. end;
  753. procedure TTXColumn.SetWidth(const Value: Integer);
  754. var
  755.   Grid: TTXStringGrid;
  756.   TM: TTextMetric;
  757.   DoSetWidth: Boolean;
  758. begin
  759.   DoSetWidth := IsStored;
  760.   if not DoSetWidth then
  761.   begin
  762.     Grid := GetGrid;
  763.     if Assigned(Grid) then
  764.     begin
  765.       if Grid.HandleAllocated then
  766.       with Grid do
  767.       begin
  768.         Canvas.Font := Self.Font;
  769.         GetTextMetrics(Canvas.Handle, TM);
  770.       end;
  771.       if (cvWidth in FAssignedValues) then
  772.         DoSetWidth := True;
  773.     end
  774.     else
  775.       DoSetWidth := True;
  776.   end;
  777.   if DoSetWidth then
  778.   begin
  779.     if ((cvWidth in FAssignedValues) or (Value <> DefaultWidth))
  780.       and (Value <> -1then
  781.     begin
  782.       FWidth := Value;
  783.       Include(FAssignedValues, cvWidth);
  784.     end;
  785.     Changed(False);
  786.   end;
  787. end;
  788. function TTXColumn.DefaultWidth: integer;
  789. begin
  790.     if  Assigned(self.Collection) and Assigned(TTXColumns(self.Collection).FGrid) then
  791.         Result := TTXColumns(self.Collection).FGrid.DefaultColWidth
  792.   else
  793.     Result := 60;
  794. end;
  795. { TTXColumns }
  796. constructor TTXColumns.Create(Grid: TTXStringGrid; ColumnClass: TTXColumnClass);
  797. begin
  798.   inherited Create(ColumnClass);
  799.   FGrid := Grid;
  800. end;
  801. function TTXColumns.Add: TTXColumn;
  802. begin
  803.   Result := TTXColumn(inherited Add);
  804. end;
  805. function TTXColumns.GetTXColumn(Index: Integer): TTXColumn;
  806. begin
  807.   Result := TTXColumn(inherited Items[Index]);
  808. end;
  809. function TTXColumns.GetOwner: TPersistent;
  810. begin
  811.   Result := FGrid;
  812. end;
  813. type
  814.   TTXColumnsWrapper = class(TComponent)
  815.   private
  816.     FColumns: TTXColumns;
  817.   published
  818.     property Columns: TTXColumns read FColumns write FColumns;
  819.   end;
  820. procedure TTXColumns.RestoreDefaults;
  821. var
  822.   I: Integer;
  823. begin
  824.   BeginUpdate;
  825.   try
  826.     for I := 0 to Count - 1 do
  827.       Items[I].RestoreDefaults;
  828.   finally
  829.     EndUpdate;
  830.   end;
  831. end;
  832. procedure TTXColumns.SetTXColumn(Index: Integer; Value: TTXColumn);
  833. begin
  834.   Items[Index].Assign(Value);
  835. end;
  836. procedure TTXColumns.Update(Item: TCollectionItem);
  837. var
  838.   Raw: Integer;
  839. begin
  840.   if (FGrid = nilor (csLoading in FGrid.ComponentState) then Exit;
  841.   inherited;
  842.   if Item = nil then
  843.   begin
  844.     self.FGrid.ColCount := self.Count;
  845.     FGrid.LayoutChanged;
  846.   end
  847.   else
  848.   begin
  849.     Raw := Item.Index;
  850.     FGrid.InvalidateCol(Raw);
  851.     FGrid.ColWidths[Raw] := TTXColumn(Item).Width;
  852.   end;
  853. end;
  854. function TTXStringGrid.GetTXColumns: TTXColumns;
  855. begin
  856.     Result := self.FColumns;
  857. end;
  858. procedure TTXStringGrid.SetTXColumns(value: TTXColumns);
  859. begin
  860.     self.Columns.Assign(value);
  861. end;
  862. {   Class TTXStringGridInplaceEdit    }
  863. constructor TTXStringGridInplaceEdit.Create(Owner: TComponent);
  864. begin
  865.   inherited Create(Owner);
  866. end;
  867. procedure TTXStringGridInplaceEdit.CloseUp(Accept: Boolean);
  868. var
  869.   ListValue: string;
  870. begin
  871.   if ListVisible then
  872.   begin
  873.     if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 00);
  874.     if ActiveList = DataList then
  875.     begin
  876.         if DataList.ItemIndex >= 0 then
  877.         ListValue := DataList.Items[DataList.ItemIndex];
  878.     end
  879.     else
  880.       if PickList.ItemIndex <> -1 then
  881.         ListValue := PickList.Items[Picklist.ItemIndex];
  882.     SetWindowPos(ActiveList.Handle, 00000, SWP_NOZORDER or
  883.       SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
  884.     ListVisible := False;
  885.     Invalidate;
  886.     if Accept then
  887.         with TTXStringGrid(Grid) do
  888.       begin
  889.         if ActiveList = DataList then
  890.           Cells[Col, Row] := ListValue
  891.         else
  892.           if EditCanModify then
  893.             Cells[Col, Row] := ListValue;
  894.       end;
  895.   end;
  896. end;
  897. procedure TTXStringGridInplaceEdit.DoEditButtonClick;
  898. begin
  899.   TTXStringGrid(Grid).EditButtonClick;
  900. end;
  901. procedure TTXStringGridInplaceEdit.DropDown;
  902. var
  903.   Column: TTXColumn;
  904. begin
  905.   if not ListVisible then
  906.   begin
  907.     with TTXStringGrid(Grid) do
  908.       Column := Columns[Col];
  909.     with Column do begin
  910.       if ActiveList = FDataList then
  911.       begin
  912.         FDataList.Color := Color;
  913.         FDataList.Font := Font;
  914.       end
  915.       else if ActiveList = self.PickList then
  916.       begin
  917.         self.PickList.Items.Assign(PickList);
  918.         self.DropDownRows := Column.DropDownRows;
  919.       end;
  920.     end;
  921.   end;
  922.   inherited DropDown;
  923. end;
  924. procedure TTXStringGridInplaceEdit.UpdateContents;
  925. var
  926.   Column: TTXColumn;
  927. begin
  928.   inherited UpdateContents;
  929.   if FUseDataList then
  930.   begin
  931.     if FDataList = nil then
  932.     begin
  933.       FDataList := TListBox.Create(Self);
  934.       FDataList.Visible := False;
  935.       FDataList.Parent := Self;
  936.       FDataList.OnMouseUp := ListMouseUp;
  937.     end;
  938.     ActiveList := FDataList;
  939.   end;
  940.   with TTXStringGrid(Grid) do
  941.     Column := Columns[Col];
  942.   Self.ReadOnly := Column.ReadOnly;
  943.   Font.Assign(Column.Font);
  944. end;
  945. { TTXStringGrid }
  946. constructor TTXStringGrid.Create(AOwner: TComponent);
  947. var
  948.   i : integer;
  949. begin
  950.   inherited Create(AOwner);
  951.   inherited DefaultDrawing := False;
  952.   FAcquireFocus := True;
  953.   FTitleOffset := 1;
  954.   DesignOptionsBoost := [goColSizing, goRowSizing, goAlwaysShowEditor];
  955.   VirtualView := True;
  956.   UsesBitmap;
  957.   FVisibleColumns := TList.Create;
  958.   Color := clWindow;
  959.   ParentColor := False;
  960.   FDefaultDrawing := True;
  961.   HideEditor;
  962.   self.FColumns := TTXColumns.Create(self, TTXColumn);
  963.   for i := 0 to self.ColCount - 1 do //create default columns
  964.   Begin
  965.       self.FColumns.Add();
  966.     //self.ColWidths[i] := self.DefaultColWidth;
  967.   end;
  968. end;
  969. destructor TTXStringGrid.Destroy;
  970. begin
  971.     FColumns.Clear();
  972.   FColumns.Free;
  973.   FColumns := nil;
  974.   FVisibleColumns.Free;
  975.   FVisibleColumns := nil;
  976.   
  977.   inherited Destroy;
  978.   ReleaseBitmap;
  979. end;
  980. function TTXStringGrid.AcquireLayoutLock: Boolean;
  981. begin
  982.   Result := (FUpdateLock = 0and (FLayoutLock = 0);
  983.   if Result then BeginLayout;
  984. end;
  985. procedure TTXStringGrid.BeginLayout;
  986. begin
  987.   BeginUpdate;
  988.   if (FLayoutLock = 0and (Assigned(Columns)) then Columns.BeginUpdate;
  989.   Inc(FLayoutLock);
  990. end;
  991. procedure TTXStringGrid.BeginUpdate;
  992. begin
  993.   Inc(FUpdateLock);
  994. end;
  995. procedure TTXStringGrid.CancelLayout;
  996. begin
  997.   if FLayoutLock > 0 then
  998.   begin
  999.     if FLayoutLock = 1 then
  1000.       Columns.EndUpdate;
  1001.     Dec(FLayoutLock);
  1002.     EndUpdate;
  1003.   end;
  1004. end;
  1005. function TTXStringGrid.CanEditModify: Boolean;
  1006. begin
  1007.   Result := not Columns[Col].ReadOnly;
  1008. end;
  1009. function TTXStringGrid.CanEditShow: Boolean;
  1010. begin
  1011.   Result := (LayoutLock = 0and inherited CanEditShow;
  1012. end;
  1013. procedure TTXStringGrid.CellClick(Column: TTXColumn; ARow:integer);
  1014. begin
  1015.   if Assigned(FOnCellClick) then FOnCellClick(Column, ARow);
  1016. end;
  1017. procedure TTXStringGrid.ColEnter;
  1018. begin
  1019.   if Assigned(FOnColEnter) then FOnColEnter(Self);
  1020. end;
  1021. procedure TTXStringGrid.ColExit;
  1022. begin
  1023.   if Assigned(FOnColExit) then FOnColExit(Self);
  1024. end;
  1025. procedure TTXStringGrid.ColumnMoved(FromIndex, ToIndex: Longint);
  1026. begin
  1027.   Columns[FromIndex].Index := ToIndex;
  1028.   inherited ColumnMoved(FromIndex, ToIndex);
  1029.   if Assigned(FOnColumnMoved) then FOnColumnMoved(Self, FromIndex, ToIndex);
  1030. end;
  1031. function TTXStringGrid.CreateEditor: TInplaceEdit;
  1032. begin
  1033.   Result := TTXStringGridInplaceEdit.Create(Self);
  1034. end;
  1035. procedure TTXStringGrid.CreateWnd;
  1036. begin
  1037.   BeginUpdate;   { prevent updates in WMSize message that follows WMCreate }
  1038.   try
  1039.     inherited CreateWnd;
  1040.   finally
  1041.     EndUpdate;
  1042.   end;
  1043. end;
  1044. procedure TTXStringGrid.DefaultHandler(var Msg);
  1045. var
  1046.   P: TPopupMenu;
  1047.   Cell: TGridCoord;
  1048. begin
  1049.   inherited DefaultHandler(Msg);
  1050.   if TMessage(Msg).Msg = wm_RButtonUp then
  1051.     with TWMRButtonUp(Msg) do
  1052.     begin
  1053.       Cell := MouseCoord(XPos, YPos);
  1054.       if (Cell.X < 0or (Cell.Y < 0then Exit;
  1055.       P := Columns[Cell.X].PopupMenu;
  1056.       if (P <> niland P.AutoPopup then
  1057.       begin
  1058.         SendCancelMode(nil);
  1059.         P.PopupComponent := Self;
  1060.         with ClientToScreen(SmallPointToPoint(Pos)) do
  1061.           P.Popup(X, Y);
  1062.         Result := 1;
  1063.       end;
  1064.     end;
  1065. end;
  1066. procedure TTXStringGrid.DeferLayout;
  1067. var
  1068.   M: TMsg;
  1069. begin
  1070.   if HandleAllocated and
  1071.     not PeekMessage(M, Handle, cm_DeferLayout, cm_DeferLayout, pm_NoRemove) then
  1072.     PostMessage(Handle, cm_DeferLayout, 00);
  1073.   CancelLayout;
  1074. end;
  1075. function TTXStringGrid.CalcTitleRect(Col: TTXColumn; ARow: Integer;
  1076.   var MasterCol: TTXColumn): TRect;
  1077. var
  1078.   I,J, W: Integer;
  1079.   DrawInfo: TGridDrawInfo;
  1080. begin
  1081.     MasterCol := Col;  //we don't surpport Parent column
  1082.   I := Col.Index;
  1083.     J := ARow;
  1084.   Result := CellRect(I, J);
  1085.   W := self.ColWidths[I];
  1086.   Result.Right := Min(Result.Right, W + Result.Left);
  1087.   if (J < FixedRows-1then
  1088.   begin
  1089.     CalcFixedInfo(DrawInfo);
  1090.     Result.Bottom := DrawInfo.Vert.FixedBoundary - DrawInfo.Vert.EffectiveLineWidth;
  1091.   end;
  1092. end;
  1093. procedure TTXStringGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
  1094. var
  1095.   FrameOffs: Byte;
  1096.   procedure DrawTitleCell(ACol, ARow: Integer; Column: TTXColumn; var AState: TGridDrawState);
  1097.   const
  1098.     ScrollArrows: array [Boolean, Boolean] of Integer =
  1099.       ((DFCS_SCROLLRIGHT, DFCS_SCROLLLEFT), (DFCS_SCROLLLEFT, DFCS_SCROLLRIGHT));
  1100.   var
  1101.     MasterCol: TTXColumn;
  1102.     TitleRect, TextRect: TRect;
  1103.   begin
  1104.     TitleRect := CalcTitleRect(Column, ARow, MasterCol);
  1105.     if MasterCol = nil then
  1106.     begin
  1107.       Canvas.FillRect(ARect);
  1108.       Exit;
  1109.     end;
  1110.     Canvas.Font := MasterCol.Title.Font;
  1111.     Canvas.Brush.Color := MasterCol.Title.Color;
  1112.     if [goVertLine, goHorzLine] * Options = [goVertLine, goHorzLine] then
  1113.       InflateRect(TitleRect, -1, -1);
  1114.     TextRect := TitleRect;
  1115.     with MasterCol.Title do
  1116.       WriteText(Canvas, TextRect, FrameOffs, FrameOffs, Caption, Alignment,
  1117.         IsRightToLeft);
  1118.     if [goVertLine, goHorzLine] * Options = [goVertLine, goHorzLine] then
  1119.     begin
  1120.       InflateRect(TitleRect, 11);
  1121.       DrawEdge(Canvas.Handle, TitleRect, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
  1122.       DrawEdge(Canvas.Handle, TitleRect, BDR_RAISEDINNER, BF_TOPLEFT);
  1123.     end;
  1124.     AState := AState - [gdFixed];  // prevent box drawing later
  1125.   end;
  1126. var
  1127.   Highlight: Boolean;
  1128.   Value: string;
  1129.   DrawColumn: TTXColumn;
  1130. begin
  1131.   if csLoading in ComponentState then
  1132.   begin
  1133.     Canvas.Brush.Color := Color;
  1134.     Canvas.FillRect(ARect);
  1135.     Exit;
  1136.   end;
  1137.   Dec(ARow, FTitleOffset);
  1138.   if (gdFixed in AState) and ([goVertLine, goHorzLine] * Options =
  1139.     [goVertLine, goHorzLine]) then
  1140.   begin
  1141.     InflateRect(ARect, -1, -1);
  1142.     FrameOffs := 1;
  1143.   end
  1144.   else
  1145.     FrameOffs := 2;
  1146.   if (gdFixed in AState) and (ACol < 0then
  1147.   begin
  1148.     Canvas.Brush.Color := FixedColor;
  1149.     Canvas.FillRect(ARect);
  1150.   end
  1151.   else with Canvas do
  1152.   begin
  1153.     DrawColumn := Columns[ACol];
  1154.     if (not DrawColumn.Visible) then Exit;    //don't draw hidden column
  1155.     
  1156.     if not (gdFixed in AState) then
  1157.     begin
  1158.       Font := DrawColumn.Font;
  1159.       Brush.Color := DrawColumn.Color;
  1160.     end;
  1161.     if ARow < 0 then
  1162.       DrawTitleCell(ACol, ARow + FTitleOffset, DrawColumn, AState)
  1163.     else
  1164.     begin
  1165.         inc(ARow, FTitleOffset);
  1166.       
  1167.       Value := self.Cells[ACol, ARow];
  1168.       Highlight := HighlightCell(ACol, ARow, Value, AState);
  1169.       if Highlight then
  1170.       begin
  1171.         Brush.Color := clHighlight;
  1172.         Font.Color := clHighlightText;
  1173.       end;
  1174.       if not Enabled then
  1175.         Font.Color := clGrayText;
  1176.       if FDefaultDrawing then
  1177.         WriteText(Canvas, ARect, 22, Value, DrawColumn.Alignment, False);
  1178.       if FDefaultDrawing and (gdSelected in AState)
  1179.         and ((goDrawFocusSelected in Options) or Focused)
  1180.         and not (csDesigning in ComponentState)
  1181.         and not (goRowSelect in Options)
  1182.         and (UpdateLock = 0)
  1183.         and (ValidParentForm(Self).ActiveControl = Self) then
  1184.         Windows.DrawFocusRect(Handle, ARect);
  1185.     end;
  1186.   end;
  1187.   if (gdFixed in AState) and ([goVertLine, goHorzLine] * Options =
  1188.     [goVertLine, goHorzLine]) then
  1189.   begin
  1190.     InflateRect(ARect, 11);
  1191.     DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
  1192.     DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_TOPLEFT);
  1193.   end;
  1194. end;
  1195. procedure TTXStringGrid.EditButtonClick;
  1196. begin
  1197.   if Assigned(FOnEditButtonClick) then
  1198.     FOnEditButtonClick(Self)
  1199.   else
  1200.     ShowPopupEditor(Columns[Col]);
  1201. end;
  1202. procedure TTXStringGrid.EndLayout;
  1203. begin
  1204.   if FLayoutLock > 0 then
  1205.   begin
  1206.     try
  1207.       try
  1208.         if FLayoutLock = 1 then
  1209.           InternalLayout;
  1210.       finally
  1211.         if FLayoutLock = 1 then
  1212.           FColumns.EndUpdate;
  1213.       end;
  1214.     finally
  1215.       Dec(FLayoutLock);
  1216.       EndUpdate;
  1217.     end;
  1218.   end;
  1219. end;
  1220. procedure TTXStringGrid.EndUpdate;
  1221. begin
  1222.   if FUpdateLock > 0 then
  1223.     Dec(FUpdateLock);
  1224. end;
  1225. function TTXStringGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
  1226. var
  1227.   Column: TTXColumn;
  1228. begin
  1229.   TTXStringGridInplaceEdit(InplaceEditor).FUseDataList := False;
  1230.   Column := Columns[Col];
  1231.   Result := esSimple;
  1232.   case Column.ButtonStyle of
  1233.    tcbsEllipse:
  1234.      Result := esEllipsis;
  1235.    tcbsAutoSelect:
  1236.      Result := esPickList;
  1237.   end;
  1238. end;
  1239. function TTXStringGrid.HighlightCell(DataCol, DataRow: Integer;
  1240.   const Value: string; AState: TGridDrawState): Boolean;
  1241. begin
  1242.   Result := (gdSelected in AState)
  1243.       and ((goDrawFocusSelected in Options) or Focused)
  1244.         { updatelock eliminates flicker when tabbing between rows }
  1245.       and ((UpdateLock = 0or (goRowSelect in Options));
  1246. end;
  1247. { InternalLayout is called with layout locks and column locks in effect }
  1248. procedure TTXStringGrid.InternalLayout;
  1249.   procedure CheckForPassthroughs;  // check for Columns.State flip-flop
  1250.   var
  1251.     SeenPassthrough: Boolean;
  1252.     I, J: Integer;
  1253.     Column: TTXColumn;
  1254.   begin
  1255.     SeenPassthrough := False;
  1256.     for I := 0 to FColumns.Count-1 do
  1257.       if not FColumns[I].IsStored then
  1258.         SeenPassthrough := True
  1259.       else if SeenPassthrough then
  1260.       begin  // we have both persistent and non-persistent columns.  Kill the latter
  1261.         for J := FColumns.Count-1 downto 0 do
  1262.         begin
  1263.           Column := FColumns[J];
  1264.           if not Column.IsStored then
  1265.             Column.Free;
  1266.         end;
  1267.         Exit;
  1268.       end;
  1269.   end;
  1270.   procedure MeasureTitleHeights;    //get the max height of the title
  1271.   var
  1272.     I, J, K: Integer;
  1273.     RestoreCanvas: Boolean;
  1274.     Heights: Integer;
  1275.   begin
  1276.     Heights := 0;
  1277.     RestoreCanvas := not HandleAllocated;
  1278.     if RestoreCanvas then
  1279.       Canvas.Handle := GetDC(0);
  1280.     try
  1281.       Canvas.Font := Font;
  1282.       K := Canvas.TextHeight('Wg') + 3;
  1283.       if goHorzLine in Options then
  1284.         Inc(K, GridLineWidth);
  1285.       DefaultRowHeight := K;
  1286.       if goFixedHorzLine in Options then
  1287.       begin
  1288.         for I := 0 to FColumns.Count-1 do
  1289.         begin
  1290.           if FColumns[I].Title <> nil then
  1291.               Canvas.Font := FColumns[I].Title.Font
  1292.           else
  1293.             Canvas.Font := FColumns[I].DefaultFont();
  1294.           J := Canvas.TextHeight('Wg') + 4;
  1295.           Heights := Max(J, Heights);
  1296.         end;
  1297.         if Heights = 0 then
  1298.         begin
  1299.           Canvas.Font := self.Font;
  1300.           Heights := Canvas.TextHeight('Wg') + 4;
  1301.         end;
  1302.         RowHeights[0] := Heights;
  1303.       end;
  1304.     finally
  1305.       if RestoreCanvas then
  1306.       begin
  1307.         ReleaseDC(0,Canvas.Handle);
  1308.         Canvas.Handle := 0;
  1309.       end;
  1310.     end;
  1311.   end;
  1312. var
  1313.   I: Integer;
  1314. begin
  1315.   if ([csLoading, csDestroying] * ComponentState) <> [] then Exit;
  1316.   if HandleAllocated then KillMessage(Handle, cm_DeferLayout);
  1317.   CheckForPassthroughs;
  1318.   FVisibleColumns.Clear;
  1319.   for I := 0 to FColumns.Count-1 do
  1320.     if (FColumns[I].Visible) then
  1321.         FVisibleColumns.Add(FColumns[I]);
  1322.   ColCount := FColumns.Count;
  1323.   FTitleOffset := 0;
  1324.   if goFixedHorzLine in Options then
  1325.   begin
  1326.     FTitleOffset := 1;
  1327.   end;
  1328.   MeasureTitleHeights;
  1329.   SetColumnAttributes;
  1330.   Invalidate;
  1331. end;
  1332. procedure TTXStringGrid.LayoutChanged;
  1333. begin
  1334.   if AcquireLayoutLock then
  1335.     EndLayout;
  1336. end;
  1337. function TTXStringGrid.AcquireFocus: Boolean;
  1338. begin
  1339.   Result := True;
  1340.   if FAcquireFocus and CanFocus and not (csDesigning in ComponentState) then
  1341.   begin
  1342.     SetFocus;
  1343.     Result := Focused or (InplaceEditor <> niland InplaceEditor.Focused;
  1344.   end;
  1345. end;
  1346. procedure TTXStringGrid.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1347.   X, Y: Integer);
  1348. var
  1349.   Cell: TGridCoord;
  1350. begin
  1351.   if not AcquireFocus then Exit;
  1352.   if (ssDouble in Shift) and (Button = mbLeft) then
  1353.   begin
  1354.     DblClick;
  1355.     Exit;
  1356.   end;
  1357.   if Sizing(X, Y) then
  1358.   begin
  1359.     inherited MouseDown(Button, Shift, X, Y);
  1360.     Exit;
  1361.   end;
  1362.   Cell := MouseCoord(X, Y);
  1363.   if (Cell.X < 0and (Cell.Y < 0then
  1364.   begin
  1365.     inherited MouseDown(Button, Shift, X, Y);
  1366.     Exit;
  1367.   end;
  1368.   if (DragKind = dkDock) and
  1369.     (Cell.Y < FTitleOffset) and (not (csDesigning in ComponentState)) then
  1370.   begin
  1371.     BeginDrag(false);
  1372.     Exit;
  1373.   end;
  1374.   if ((csDesigning in self.ComponentState) or (goColSizing in self.Options)) and
  1375.     (Cell.Y < FTitleOffset) then
  1376.   begin
  1377.     inherited MouseDown(Button, Shift, X, Y);
  1378.     Exit;
  1379.   end;
  1380.   inherited MouseDown(Button, Shift, X, Y);
  1381. end;
  1382. procedure TTXStringGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1383.   X, Y: Integer);
  1384. var
  1385.   Cell: TGridCoord;
  1386.   SaveState: TGridState;
  1387. begin
  1388.   SaveState := FGridState;
  1389.   inherited MouseUp(Button, Shift, X, Y);
  1390.   if (SaveState = gsRowSizing) or (SaveState = gsColSizing) or
  1391.     ((InplaceEditor <> niland (InplaceEditor.Visible) and
  1392.      (PtInRect(InplaceEditor.BoundsRect, Point(X,Y)))) then Exit;
  1393.   Cell := MouseCoord(X,Y);
  1394.   if (Button = mbLeft) and (Cell.Y >= 0then
  1395.     if Cell.Y < FTitleOffset then
  1396.       TitleClick(Columns[Cell.X], Cell.Y)
  1397.     else
  1398.       CellClick(Columns[Cell.X], Cell.Y);
  1399. end;
  1400. procedure TTXStringGrid.Notification(AComponent: TComponent;
  1401.   Operation: TOperation);
  1402. var
  1403.   I: Integer;
  1404. begin
  1405.   inherited Notification(AComponent, Operation);
  1406.   if (Operation = opRemove) then
  1407.   begin
  1408.     if (AComponent is TPopupMenu) then
  1409.     begin
  1410.       for I := 0 to Columns.Count-1 do
  1411.         if Columns[I].PopupMenu = AComponent then
  1412.           Columns[I].PopupMenu := nil;
  1413.     end ;
  1414.   end;
  1415. end;
  1416. procedure TTXStringGrid.Scroll(Distance: Integer);
  1417. var
  1418.   OldRect, NewRect: TRect;
  1419.   RowHeight: Integer;
  1420. begin
  1421.   if not HandleAllocated then Exit;
  1422.   OldRect := BoxRect(0, Row, ColCount - 1, Row);
  1423.   NewRect := BoxRect(0, Row, ColCount - 1, Row);
  1424.   ValidateRect(Handle, @OldRect);
  1425.   InvalidateRect(Handle, @OldRect, False);
  1426.   InvalidateRect(Handle, @NewRect, False);
  1427.   if Distance <> 0 then
  1428.   begin
  1429.     HideEditor;
  1430.     try
  1431.       if Abs(Distance) > VisibleRowCount then
  1432.       begin
  1433.         Invalidate;
  1434.         Exit;
  1435.       end
  1436.       else
  1437.       begin
  1438.         RowHeight := DefaultRowHeight;
  1439.         if goHorzLine in Options then Inc(RowHeight, GridLineWidth);
  1440.         NewRect := BoxRect(0, FTitleOffset, ColCount - 11000);
  1441.         ScrollWindowEx(Handle, 0, -RowHeight * Distance, @NewRect, @NewRect,
  1442.           0nil, SW_Invalidate);
  1443.       end;
  1444.     finally
  1445.       if goAlwaysShowEditor in Options then ShowEditor;
  1446.     end;
  1447.   end;
  1448.   if UpdateLock = 0 then Update;
  1449. end;
  1450. procedure TTXStringGrid.SetColumnAttributes;
  1451. var
  1452.   I: Integer;
  1453. begin
  1454.   for I := 0 to FColumns.Count-1 do
  1455.   with FColumns[I] do
  1456.   begin
  1457.     TabStops[I] := Visible and not ReadOnly ;
  1458.     ColWidths[I] := Width;
  1459.   end;
  1460. end;
  1461. function TTXStringGrid.StoreColumns: Boolean;
  1462. begin
  1463.   Result := true;
  1464. end;
  1465. procedure TTXStringGrid.TitleClick(Column: TTXColumn; ARow:integer);
  1466. begin
  1467.   if Assigned(FOnTitleClick) then FOnTitleClick(Column, ARow);
  1468. end;
  1469. procedure TTXStringGrid.CMParentFontChanged(var Message: TMessage);
  1470. begin
  1471.   inherited;
  1472.   if ParentFont then
  1473.   begin
  1474.     FSelfChangingTitleFont := True;
  1475.     FSelfChangingTitleFont := False;
  1476.     LayoutChanged;
  1477.   end;
  1478. end;
  1479. procedure TTXStringGrid.CMFontChanged(var Message: TMessage);
  1480. var
  1481.   I: Integer;
  1482. begin
  1483.   inherited;
  1484.   BeginLayout;
  1485.   try
  1486.     for I := 0 to Columns.Count-1 do
  1487.       Columns[I].RefreshDefaultFont;
  1488.   finally
  1489.     EndLayout;
  1490.   end;
  1491. end;
  1492. procedure TTXStringGrid.CMDeferLayout(var Message);
  1493. begin
  1494.   if AcquireLayoutLock then
  1495.     EndLayout
  1496.   else
  1497.     DeferLayout;
  1498. end;
  1499. procedure TTXStringGrid.WMSize(var Message: TWMSize);
  1500. begin
  1501.   inherited;
  1502.   InvalidateTitles;
  1503. end;
  1504. procedure TTXStringGrid.WMSetFocus(var Message: TWMSetFocus);
  1505. begin
  1506.   if not ((InplaceEditor <> niland
  1507.     (Message.FocusedWnd = InplaceEditor.Handle)) then SetIme;
  1508.   inherited;
  1509. end;
  1510. procedure TTXStringGrid.WMKillFocus(var Message: TMessage);
  1511. begin
  1512.   if not SysLocale.FarEast then inherited
  1513.   else
  1514.   begin
  1515.     ImeName := Screen.DefaultIme;
  1516.     ImeMode := imDontCare;
  1517.     inherited;
  1518.     if not ((InplaceEditor <> niland
  1519.       (HWND(Message.WParam) = InplaceEditor.Handle)) then
  1520.       ActivateKeyboardLayout(Screen.DefaultKbLayout, KLF_ACTIVATE);
  1521.   end;
  1522. end;
  1523. { Defer action processing to datalink }
  1524. procedure TTXStringGrid.ShowPopupEditor(Column: TTXColumn; X, Y: Integer);
  1525. var
  1526.   SubGrid: TTXStringGrid;
  1527.   I: Integer;
  1528.   FloatRect: TRect;
  1529.   Cmp: TControl;
  1530. begin
  1531.   // find existing popup for this column field, if any, and show it
  1532.   for I := 0 to ComponentCount-1 do
  1533.     if Components[I] is TTXStringGrid then
  1534.     begin
  1535.       SubGrid := TTXStringGrid(Components[I]);
  1536.       begin
  1537.         SubGrid.Parent.Show;
  1538.         SubGrid.SetFocus;
  1539.         Exit;
  1540.       end;
  1541.     end;
  1542.   // create another instance of this kind of grid
  1543.   SubGrid := TTXStringGrid(TComponentClass(Self.ClassType).Create(Self));
  1544.   try
  1545.     SubGrid.Visible := False;
  1546.     SubGrid.FloatingDockSiteClass := TCustomDockForm;
  1547.     FloatRect.TopLeft := ClientToScreen(CellRect(Col, Row).BottomRight);
  1548.     if X > Low(Integer) then FloatRect.Left := X;
  1549.     if Y > Low(Integer) then FloatRect.Top := Y;
  1550.     FloatRect.Right := FloatRect.Left + Width;
  1551.     FloatRect.Bottom := FloatRect.Top + Height;
  1552.     SubGrid.ManualFloat(FloatRect);
  1553. //    SubGrid.ManualDock(nil,nil,alClient);
  1554.     SubGrid.Parent.BiDiMode := Self.BiDiMode; { This carries the BiDi setting }
  1555.     I := SubGrid.CellRect(SubGrid.ColCount-10).Right;
  1556.     if (I > 0and (I < Screen.Width div 2then
  1557.       SubGrid.Parent.ClientWidth := I
  1558.     else
  1559.       SubGrid.Parent.Width := Screen.Width div 4;
  1560.     SubGrid.Parent.Height := Screen.Height div 4;
  1561.     SubGrid.Align := alClient;
  1562.     SubGrid.DragKind := dkDock;
  1563.     SubGrid.Color := Color;
  1564.     SubGrid.Ctl3D := Ctl3D;
  1565.     SubGrid.Cursor := Cursor;
  1566.     SubGrid.Enabled := Enabled;
  1567.     SubGrid.FixedColor := FixedColor;
  1568.     SubGrid.Font := Font;
  1569.     SubGrid.HelpContext := HelpContext;
  1570.     SubGrid.IMEMode := IMEMode;
  1571.     SubGrid.IMEName := IMEName;
  1572.     SubGrid.Options := Options;
  1573.     Cmp := Self;
  1574.     while (Cmp <> niland (TTXStringGrid(Cmp).PopupMenu = nildo
  1575.       Cmp := Cmp.Parent;
  1576.     if Cmp <> nil then
  1577.       SubGrid.PopupMenu := TTXStringGrid(Cmp).PopupMenu;
  1578.     SubGrid.Visible := True;
  1579.     SubGrid.Parent.Show;
  1580.   except
  1581.     SubGrid.Free;
  1582.     raise;
  1583.   end;
  1584. end;
  1585. procedure TTXStringGrid.InvalidateTitles;
  1586. var
  1587.   R: TRect;
  1588.   DrawInfo: TGridDrawInfo;
  1589. begin
  1590.   if HandleAllocated then
  1591.   begin
  1592.     CalcFixedInfo(DrawInfo);
  1593.     R := Rect(00, Width, DrawInfo.Vert.FixedBoundary);
  1594.     InvalidateRect(Handle, @R, False);
  1595.   end;
  1596. end;
  1597. procedure TTXStringGrid.TopLeftChanged;
  1598. begin
  1599.   InvalidateTitles;
  1600.   inherited TopLeftChanged;
  1601. end;
  1602. procedure TTXStringGrid.ColWidthsChanged;
  1603. var
  1604.   I: Integer;
  1605. begin
  1606.   inherited ColWidthsChanged;
  1607.   if FColumns <> nil then
  1608.   begin
  1609.       if AcquireLayoutLock then
  1610.       try
  1611.           for I := 0 to ColCount - 1 do
  1612.           FColumns[I].Width := ColWidths[I];
  1613.         finally
  1614.         EndLayout;
  1615.         end;
  1616.   end;
  1617. end;
  1618. end.

===================================

非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,
原创文章版权本人(lonefox)所有;转载文章版权归原作者所有;

http://blog.youkuaiyun.com/boythl

欢迎转载,但请注明出处,保留作者和版权信息。

===================================

评论 20
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值