Impstringgrid.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  1. unit Impstringgrid;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5. Grids,Stdctrls,Variants;
  6. type
  7. TImpgridCellEvent = procedure (Sender: TObject; Col, Row: Longint) of object;
  8. TImpgriddropdownEvent = procedure (Sender: TObject; Col, Row: Longint;
  9. var Picklist:Tstrings) of object;
  10. TImpColumnValue = (cvColor, cvWidth, cvFont, cvAlignment, cvReadOnly, cvTitleColor,
  11. cvTitleCaption, cvTitleAlignment, cvTitleFont, cvImeMode, cvImeName);
  12. TImpColumnValues = set of TImpColumnValue;
  13. { TImpColumn defines internal storage for column attributes. Values assigned
  14. to properties are stored in this object, the grid- or field-based default
  15. sources are not modified. Values read from properties are the previously
  16. assigned value, if any, or the grid- or field-based default values if
  17. nothing has been assigned to that property. This class also publishes the
  18. column attribute properties for persistent storage. }
  19. TImpGridColumnsState = (csDefault, csCustomized);
  20. TImpColumn = class;
  21. TImpStringgrid = class;
  22. TImpColumnClass = class of TImpColumn;
  23. TImpColumnTitle = class(TPersistent)
  24. private
  25. FColumn: TImpColumn;
  26. FCaption: string;
  27. FFont: TFont;
  28. FColor: TColor;
  29. FAlignment: TAlignment;
  30. procedure FontChanged(Sender: TObject);
  31. function GetAlignment: TAlignment;
  32. function GetColor: TColor;
  33. function GetCaption: string;
  34. function GetFont: TFont;
  35. function IsAlignmentStored: Boolean;
  36. function IsColorStored: Boolean;
  37. function IsFontStored: Boolean;
  38. function IsCaptionStored: Boolean;
  39. procedure SetAlignment(Value: TAlignment);
  40. procedure SetColor(Value: TColor);
  41. procedure SetFont(Value: TFont);
  42. procedure SetCaption(const Value: string); virtual;
  43. protected
  44. procedure RefreshDefaultFont;
  45. public
  46. constructor Create(Column: TImpColumn);
  47. destructor Destroy; override;
  48. procedure Assign(Source: TPersistent); override;
  49. function DefaultAlignment: TAlignment;
  50. function DefaultColor: TColor;
  51. function DefaultFont: TFont;
  52. function DefaultCaption: string;
  53. procedure RestoreDefaults; virtual;
  54. published
  55. property Alignment: TAlignment read GetAlignment write SetAlignment
  56. stored IsAlignmentStored;
  57. property Caption: string read GetCaption write SetCaption stored IsCaptionStored;
  58. property Color: TColor read GetColor write SetColor stored IsColorStored;
  59. property Font: TFont read GetFont write SetFont stored IsFontStored;
  60. end;
  61. TImpColumnButtonStyle = (cbsPicklist, cbsEllipsis, cbsNone);
  62. TImpColumn = class(TCollectionItem)
  63. private
  64. FColor: TColor;
  65. FWidth: Integer;
  66. FTitle: TImpColumnTitle;
  67. FFont: TFont;
  68. FImeMode: TImeMode;
  69. FImeName: TImeName;
  70. FPickList: TStrings;
  71. // FPopupMenu: TPopupMenu;
  72. FDropDownRows: Cardinal;
  73. FButtonStyle: TImpColumnButtonStyle;
  74. FAlignment: TAlignment;
  75. FReadonly: Boolean;
  76. FAssignedValues: TImpColumnValues;
  77. procedure FontChanged(Sender: TObject);
  78. function GetAlignment: TAlignment;
  79. function GetColor: TColor;
  80. // function GetField: TField;
  81. function GetFont: TFont;
  82. function GetImeMode: TImeMode;
  83. function GetImeName: TImeName;
  84. function GetPickList: TStrings;
  85. function GetReadOnly: Boolean;
  86. function GetWidth: Integer;
  87. function IsAlignmentStored: Boolean;
  88. function IsColorStored: Boolean;
  89. function IsFontStored: Boolean;
  90. function IsImeModeStored: Boolean;
  91. function IsImeNameStored: Boolean;
  92. function IsReadOnlyStored: Boolean;
  93. function IsWidthStored: Boolean;
  94. procedure SetAlignment(Value: TAlignment); virtual;
  95. procedure SetButtonStyle(Value: TImpColumnButtonStyle);
  96. procedure SetColor(Value: TColor);
  97. // procedure SetField(Value: TField); virtual;
  98. // procedure SetFieldName(const Value: String);
  99. procedure SetFont(Value: TFont);
  100. procedure SetImeMode(Value: TImeMode); virtual;
  101. procedure SetImeName(Value: TImeName); virtual;
  102. procedure SetPickList(Value: TStrings);
  103. // procedure SetPopupMenu(Value: TPopupMenu);
  104. procedure SetReadOnly(Value: Boolean); virtual;
  105. procedure SetTitle(Value: TImpColumnTitle);
  106. procedure SetWidth(Value: Integer); virtual;
  107. protected
  108. function CreateTitle: TImpColumnTitle; virtual;
  109. function GetGrid: TImpStringGrid;
  110. function GetDisplayName: string; override;
  111. procedure RefreshDefaultFont;
  112. public
  113. constructor Create(Collection: TCollection); override;
  114. destructor Destroy; override;
  115. procedure Assign(Source: TPersistent); override;
  116. function DefaultAlignment: TAlignment;
  117. function DefaultColor: TColor;
  118. function DefaultFont: TFont;
  119. function DefaultImeMode: TImeMode;
  120. function DefaultImeName: TImeName;
  121. function DefaultReadOnly: Boolean;
  122. function DefaultWidth: Integer;
  123. procedure RestoreDefaults; virtual;
  124. property Grid: TImpStringGrid read GetGrid;
  125. property AssignedValues: TImpColumnValues read FAssignedValues;
  126. // property Field: TField read GetField write SetField;
  127. published
  128. property Alignment: TAlignment read GetAlignment write SetAlignment
  129. stored IsAlignmentStored;
  130. property ButtonStyle: TImpColumnButtonStyle read FButtonStyle write SetButtonStyle
  131. default cbsNone;
  132. property Color: TColor read GetColor write SetColor stored IsColorStored;
  133. property DropDownRows: Cardinal read FDropDownRows write FDropDownRows default 7;
  134. // property FieldName: String read FFieldName write SetFieldName;
  135. property Font: TFont read GetFont write SetFont stored IsFontStored;
  136. property ImeMode: TImeMode read GetImeMode write SetImeMode stored IsImeModeStored;
  137. property ImeName: TImeName read GetImeName write SetImeName stored IsImeNameStored;
  138. property PickList: TStrings read GetPickList write SetPickList;
  139. // property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
  140. property ReadOnly: Boolean read GetReadOnly write SetReadOnly
  141. stored IsReadOnlyStored;
  142. property Title: TImpColumnTitle read FTitle write SetTitle;
  143. property Width: Integer read GetWidth write SetWidth stored IsWidthStored;
  144. end;
  145. TImpGridColumns = class(TCollection)
  146. private
  147. FGrid: TImpStringGrid;
  148. function GetCount:Integer;
  149. function GetState: TImpGridColumnsState;
  150. function GeTImpColumn(Index: Integer): TImpColumn;
  151. procedure SeTImpColumn(Index: Integer; Value: TImpColumn);
  152. procedure SetState(NewState: TImpGridColumnsState);
  153. protected
  154. function GetOwner: TPersistent; override;
  155. procedure Update(Item: TCollectionItem); override;
  156. public
  157. constructor Create(Grid: TImpStringGrid; ColumnClass: TImpColumnClass);
  158. function Add: TImpColumn;
  159. procedure LoadFromFile(const Filename: string);
  160. procedure LoadFromStream(S: TStream);
  161. procedure RestoreDefaults;
  162. procedure RebuildColumns;
  163. procedure SaveToFile(const Filename: string);
  164. procedure SaveToStream(S: TStream);
  165. property State: TImpGridColumnsState read GetState write SetState;
  166. property Grid: TImpStringGrid read FGrid;
  167. property Items[Index: Integer]: TImpColumn read GeTImpColumn write SeTImpColumn; default;
  168. property Count: integer read GetCount;
  169. end;
  170. { TImpGridInplaceEdit }
  171. { TImpGridInplaceEdit adds support for a button on the in-place editor,
  172. which can be used to drop down a table-based lookup list, a stringlist-based
  173. pick list, or (if button style is esEllipsis) fire the grid event
  174. OnEditButtonClick. }
  175. TEditStyle = (esSimple, esEllipsis, esPickList, esDataList);
  176. TPopupListbox = class;
  177. TImpStringgrid = class(TStringGrid)
  178. private
  179. fOntoomuch:TnotifyEvent;
  180. fOnNewRow:TnotifyEvent;
  181. fOnElippsisclicked:TImpgridCellEvent;
  182. fOnPicklistDropdown:TImpgridDropDownEvent;
  183. fToomuch:boolean;
  184. function GetColCount: Integer;
  185. procedure SetColCount(Col: LongInt);
  186. procedure Editbuttonclick;
  187. { Private declarations }
  188. protected
  189. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  190. procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
  191. function CreateEditor: TInplaceEdit; override;
  192. { Protected declarations }
  193. public
  194. { Public declarations }
  195. Columns: TImpGridColumns;
  196. constructor Create(Owner: TComponent); override;
  197. published
  198. property OnTooMuchrows : TNotifyEvent read fOntoomuch write fOntoomuch;
  199. property OnNewRow : TNotifyEvent read fOnNewRow write fOnNewRow;
  200. property OnElippsisclicked : TImpGridCellEvent read fOnElippsisclicked write fOnElippsisclicked;
  201. property OnPicklistDropdown : TImpGridDropdownEvent read fOnPicklistDropdown write fOnPicklistDropdown;
  202. property ColCount: Longint read GetColCount write SetColCount default 5;
  203. { Published declarations }
  204. end;
  205. TImpGridInplaceEdit = class(TInplaceEdit)
  206. private
  207. FButtonWidth: Integer;
  208. //FDataList: TDBLookupListBox;
  209. FPickList: TPopupListbox;
  210. FActiveList: TWinControl;
  211. //FLookupSource: TDatasource;
  212. FEditStyle: TEditStyle;
  213. FListVisible: Boolean;
  214. FTracking: Boolean;
  215. FPressed: Boolean;
  216. procedure ListMouseUp(Sender: TObject; Button: TMouseButton;
  217. Shift: TShiftState; X, Y: Integer);
  218. procedure SetEditStyle(Value: TEditStyle);
  219. procedure StopTracking;
  220. procedure TrackButton(X,Y: Integer);
  221. procedure CMCancelMode(var Message: TCMCancelMode); message CM_CancelMode;
  222. procedure WMCancelMode(var Message: TMessage); message WM_CancelMode;
  223. procedure WMKillFocus(var Message: TMessage); message WM_KillFocus;
  224. procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message wm_LButtonDblClk;
  225. procedure WMPaint(var Message: TWMPaint); message wm_Paint;
  226. procedure WMSetCursor(var Message: TWMSetCursor); message WM_SetCursor;
  227. protected
  228. procedure BoundsChanged; override;
  229. procedure CloseUp(Accept: Boolean);
  230. procedure DoDropDownKeys(var Key: Word; Shift: TShiftState);
  231. procedure DropDown;
  232. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  233. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  234. X, Y: Integer); override;
  235. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  236. procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  237. X, Y: Integer); override;
  238. procedure PaintWindow(DC: HDC); override;
  239. procedure UpdateContents; override;
  240. procedure WndProc(var Message: TMessage); override;
  241. property EditStyle: TEditStyle read FEditStyle write SetEditStyle;
  242. property ActiveList: TWinControl read FActiveList write FActiveList;
  243. //property DataList: TDBLookupListBox read FDataList;
  244. property PickList: TPopupListbox read FPickList;
  245. public
  246. constructor Create(Owner: TComponent); override;
  247. end;
  248. { TPopupListbox }
  249. TPopupListbox = class(TCustomListbox)
  250. private
  251. FSearchText: String;
  252. FSearchTickCount: Longint;
  253. protected
  254. procedure CreateParams(var Params: TCreateParams); override;
  255. procedure CreateWnd; override;
  256. procedure KeyPress(var Key: Char); override;
  257. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  258. end;
  259. const
  260. ColumnTitleValues = [cvTitleColor..cvTitleFont];
  261. cm_DeferLayout = WM_USER + 100;
  262. procedure Register;
  263. implementation
  264. var
  265. DrawBitmap: TBitmap;
  266. UserCount: Integer;
  267. procedure UsesBitmap;
  268. begin
  269. if UserCount = 0 then
  270. DrawBitmap := TBitmap.Create;
  271. Inc(UserCount);
  272. end;
  273. procedure ReleaseBitmap;
  274. begin
  275. Dec(UserCount);
  276. if UserCount = 0 then DrawBitmap.Free;
  277. end;
  278. function Max(X, Y: Integer): Integer;
  279. begin
  280. Result := Y;
  281. if X > Y then Result := X;
  282. end;
  283. procedure KillMessage(Wnd: HWnd; Msg: Integer);
  284. // Delete the requested message from the queue, but throw back
  285. // any WM_QUIT msgs that PeekMessage may also return
  286. var
  287. M: TMsg;
  288. begin
  289. M.Message := 0;
  290. if PeekMessage(M, Wnd, Msg, Msg, pm_Remove) and (M.Message = WM_QUIT) then
  291. PostQuitMessage(M.wparam);
  292. end;
  293. procedure WriteText(ACanvas: TCanvas; ARect: TRect; DX, DY: Integer;
  294. const Text: string; Alignment: TAlignment);
  295. const
  296. AlignFlags : array [TAlignment] of Integer =
  297. ( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
  298. DT_RIGHT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
  299. DT_CENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX );
  300. var
  301. B, R: TRect;
  302. I, Left: Integer;
  303. begin
  304. I := ColorToRGB(ACanvas.Brush.Color);
  305. if GetNearestColor(ACanvas.Handle, I) = I then
  306. begin { Use ExtTextOut for solid colors }
  307. case Alignment of
  308. taLeftJustify:
  309. Left := ARect.Left + DX;
  310. taRightJustify:
  311. Left := ARect.Right - ACanvas.TextWidth(Text) - 3;
  312. else { taCenter }
  313. Left := ARect.Left + (ARect.Right - ARect.Left) shr 1
  314. - (ACanvas.TextWidth(Text) shr 1);
  315. end;
  316. ExtTextOut(ACanvas.Handle, Left, ARect.Top + DY, ETO_OPAQUE or
  317. ETO_CLIPPED, @ARect, PChar(Text), Length(Text), nil);
  318. end
  319. else begin { Use FillRect and Drawtext for dithered colors }
  320. DrawBitmap.Canvas.Lock;
  321. try
  322. with DrawBitmap, ARect do { Use offscreen bitmap to eliminate flicker and }
  323. begin { brush origin tics in painting / scrolling. }
  324. Width := Max(Width, Right - Left);
  325. Height := Max(Height, Bottom - Top);
  326. R := Rect(DX, DY, Right - Left - 1, Bottom - Top - 1);
  327. B := Rect(0, 0, Right - Left, Bottom - Top);
  328. end;
  329. with DrawBitmap.Canvas do
  330. begin
  331. Font := ACanvas.Font;
  332. Font.Color := ACanvas.Font.Color;
  333. Brush := ACanvas.Brush;
  334. Brush.Style := bsSolid;
  335. FillRect(B);
  336. SetBkMode(Handle, TRANSPARENT);
  337. DrawText(Handle, PChar(Text), Length(Text), R, AlignFlags[Alignment]);
  338. end;
  339. ACanvas.CopyRect(ARect, DrawBitmap.Canvas, B);
  340. finally
  341. DrawBitmap.Canvas.Unlock;
  342. end;
  343. end;
  344. end;
  345. procedure TPopupListBox.CreateParams(var Params: TCreateParams);
  346. begin
  347. inherited CreateParams(Params);
  348. with Params do
  349. begin
  350. Style := Style or WS_BORDER;
  351. ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST;
  352. WindowClass.Style := CS_SAVEBITS;
  353. end;
  354. end;
  355. procedure TPopupListbox.CreateWnd;
  356. begin
  357. inherited CreateWnd;
  358. Windows.SetParent(Handle, 0);
  359. CallWindowProc(DefWndProc, Handle, wm_SetFocus, 0, 0);
  360. end;
  361. procedure TPopupListbox.Keypress(var Key: Char);
  362. var
  363. TickCount: Integer;
  364. begin
  365. case Key of
  366. #8, #27: FSearchText := '';
  367. #32..#255:
  368. begin
  369. TickCount := GetTickCount;
  370. if TickCount - FSearchTickCount > 2000 then FSearchText := '';
  371. FSearchTickCount := TickCount;
  372. if Length(FSearchText) < 32 then FSearchText := FSearchText + Key;
  373. SendMessage(Handle, LB_SelectString, WORD(-1), Longint(PChar(FSearchText)));
  374. Key := #0;
  375. end;
  376. end;
  377. inherited Keypress(Key);
  378. end;
  379. procedure TPopupListbox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  380. X, Y: Integer);
  381. begin
  382. inherited MouseUp(Button, Shift, X, Y);
  383. TImpGridInplaceEdit(Owner).CloseUp((X >= 0) and (Y >= 0) and
  384. (X < Width) and (Y < Height));
  385. end;
  386. constructor TImpGridInplaceEdit.Create(Owner: TComponent);
  387. begin
  388. inherited Create(Owner);
  389. //FLookupSource := TDataSource.Create(Self);
  390. FButtonWidth := GetSystemMetrics(SM_CXVSCROLL);
  391. FEditStyle := esEllipsis;
  392. end;
  393. procedure TImpGridInplaceEdit.BoundsChanged;
  394. var
  395. R: TRect;
  396. begin
  397. SetRect(R, 2, 2, Width - 2, Height);
  398. if FEditStyle <> esSimple then Dec(R.Right, FButtonWidth);
  399. SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R));
  400. SendMessage(Handle, EM_SCROLLCARET, 0, 0);
  401. if SysLocale.Fareast then
  402. SetImeCompositionWindow(Font, R.Left, R.Top);
  403. end;
  404. procedure TImpGridInplaceEdit.CloseUp(Accept: Boolean);
  405. var
  406. //MasterField: TField;
  407. ListValue: Variant;
  408. begin
  409. if FListVisible then
  410. begin
  411. if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  412. { if FActiveList = FDataList then
  413. ListValue := FDataList.KeyValue
  414. else }
  415. if FPickList.ItemIndex <> -1 then
  416. ListValue := FPickList.Items[FPicklist.ItemIndex];
  417. SetWindowPos(FActiveList.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
  418. SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
  419. FListVisible := False;
  420. Invalidate;
  421. if Accept then
  422. if (not VarIsNull(ListValue)) and EditCanModify then
  423. {with TImpStringGrid(Grid) do}
  424. Text := ListValue;
  425. end;
  426. end;
  427. procedure TImpGridInplaceEdit.DoDropDownKeys(var Key: Word; Shift: TShiftState);
  428. var tempTstrings:Tstrings;
  429. begin
  430. case Key of
  431. VK_UP, VK_DOWN:
  432. if ssAlt in Shift then
  433. begin
  434. if FListVisible then CloseUp(True) else DropDown;
  435. Key := 0;
  436. end;
  437. VK_RETURN, VK_ESCAPE:
  438. if FListVisible and not (ssAlt in Shift) then
  439. begin
  440. CloseUp(Key = VK_RETURN);
  441. Key := 0;
  442. end;
  443. end;
  444. end;
  445. procedure TImpGridInplaceEdit.DropDown;
  446. var
  447. P: TPoint;
  448. I,J,Y: Integer;
  449. Column: TImpColumn;
  450. str : Tstrings;
  451. begin
  452. if not FListVisible and Assigned(FActiveList) then
  453. begin
  454. FActiveList.Width := Width;
  455. with TImpStringGrid(Grid) do
  456. Column := Columns[col];
  457. begin
  458. FPickList.Color := Color;
  459. FPickList.Font := Font;
  460. FPickList.Items := Column.Picklist;
  461. if assigned(TImpStringgrid(Grid).OnPickListDropDown) then begin
  462. str := Tstringlist.create;
  463. str.assign(fpicklist.items);
  464. TImpStringgrid(Grid).OnPickListDropDown(Self,TImpStringgrid(Grid).col,TImpStringgrid(Grid).row,
  465. str);
  466. fpicklist.items.Assign(str);
  467. end;
  468. if FPickList.Items.Count >= Column.DropDownRows then
  469. FPickList.Height := Column.DropDownRows * FPickList.ItemHeight + 4
  470. else
  471. FPickList.Height := FPickList.Items.Count * FPickList.ItemHeight + 4;
  472. // if Column.Field.IsNull then
  473. FPickList.ItemIndex := -1;
  474. // else
  475. // FPickList.ItemIndex := FPickList.Items.IndexOf(Column.Field.Value);
  476. J := FPickList.ClientWidth;
  477. for I := 0 to FPickList.Items.Count - 1 do
  478. begin
  479. Y := FPickList.Canvas.TextWidth(FPickList.Items[I]);
  480. if Y > J then J := Y+10;
  481. end;
  482. FPickList.ClientWidth := J;
  483. end;
  484. P := Parent.ClientToScreen(Point(Left, Top));
  485. Y := P.Y + Height;
  486. if Y + FActiveList.Height > Screen.Height then Y := P.Y - FActiveList.Height;
  487. SetWindowPos(FActiveList.Handle, HWND_TOP, P.X, Y, 0, 0,
  488. SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
  489. FListVisible := True;
  490. Invalidate;
  491. Windows.SetFocus(Handle);
  492. end;
  493. end;
  494. type
  495. TWinControlCracker = class(TWinControl) end;
  496. procedure TImpGridInplaceEdit.KeyDown(var Key: Word; Shift: TShiftState);
  497. begin
  498. if (EditStyle = esEllipsis) and (Key = VK_RETURN) and (Shift = [ssCtrl]) then
  499. begin
  500. TImpStringgrid(Grid).EditButtonClick;
  501. KillMessage(Handle, WM_CHAR);
  502. end
  503. else
  504. inherited KeyDown(Key, Shift);
  505. end;
  506. procedure TImpGridInplaceEdit.ListMouseUp(Sender: TObject; Button: TMouseButton;
  507. Shift: TShiftState; X, Y: Integer);
  508. begin
  509. if Button = mbLeft then
  510. CloseUp(PtInRect(FActiveList.ClientRect, Point(X, Y)));
  511. end;
  512. procedure TImpGridInplaceEdit.MouseDown(Button: TMouseButton; Shift: TShiftState;
  513. X, Y: Integer);
  514. var TempTstrings:TStrings;
  515. begin
  516. if (Button = mbLeft) and (FEditStyle <> esSimple) and
  517. PtInRect(Rect(Width - FButtonWidth, 0, Width, Height), Point(X,Y)) then
  518. begin
  519. if FListVisible then
  520. CloseUp(False)
  521. else
  522. begin
  523. MouseCapture := True;
  524. FTracking := True;
  525. TrackButton(X, Y);
  526. if Assigned(FActiveList) then DropDown;
  527. end;
  528. end;
  529. inherited MouseDown(Button, Shift, X, Y);
  530. end;
  531. procedure TImpGridInplaceEdit.MouseMove(Shift: TShiftState; X, Y: Integer);
  532. var
  533. ListPos: TPoint;
  534. MousePos: TSmallPoint;
  535. begin
  536. if FTracking then
  537. begin
  538. TrackButton(X, Y);
  539. if FListVisible then
  540. begin
  541. ListPos := FActiveList.ScreenToClient(ClientToScreen(Point(X, Y)));
  542. if PtInRect(FActiveList.ClientRect, ListPos) then
  543. begin
  544. StopTracking;
  545. MousePos := PointToSmallPoint(ListPos);
  546. SendMessage(FActiveList.Handle, WM_LBUTTONDOWN, 0, Integer(MousePos));
  547. Exit;
  548. end;
  549. end;
  550. end;
  551. inherited MouseMove(Shift, X, Y);
  552. end;
  553. procedure TImpGridInplaceEdit.MouseUp(Button: TMouseButton; Shift: TShiftState;
  554. X, Y: Integer);
  555. var
  556. WasPressed: Boolean;
  557. begin
  558. WasPressed := FPressed;
  559. StopTracking;
  560. if (Button = mbLeft) and (FEditStyle = esEllipsis) and WasPressed then
  561. TImpStringGrid(Grid).EditButtonClick;
  562. inherited MouseUp(Button, Shift, X, Y);
  563. end;
  564. procedure TImpGridInplaceEdit.PaintWindow(DC: HDC);
  565. var
  566. R: TRect;
  567. Flags: Integer;
  568. W: Integer;
  569. begin
  570. if FEditStyle <> esSimple then
  571. begin
  572. SetRect(R, Width - FButtonWidth, 0, Width, Height);
  573. Flags := 0;
  574. if FEditStyle in [esDataList, esPickList] then
  575. begin
  576. if FActiveList = nil then
  577. Flags := DFCS_INACTIVE
  578. else if FPressed then
  579. Flags := DFCS_FLAT or DFCS_PUSHED;
  580. DrawFrameControl(DC, R, DFC_SCROLL, Flags or DFCS_SCROLLCOMBOBOX);
  581. end
  582. else { esEllipsis }
  583. begin
  584. if FPressed then
  585. Flags := BF_FLAT;
  586. DrawEdge(DC, R, EDGE_RAISED, BF_RECT or BF_MIDDLE or Flags);
  587. Flags := ((R.Right - R.Left) shr 1) + Ord(FPressed);
  588. W := Height shr 3;
  589. if W = 0 then W := 1;
  590. PatBlt(DC, R.Left + Flags, R.Top + 10, 1, 1, BLACKNESS);
  591. PatBlt(DC, R.Left + Flags-3, R.Top + 10, 1, 1, BLACKNESS);
  592. PatBlt(DC, R.Left + Flags+3, R.Top + 10, 1, 1, BLACKNESS);
  593. end;
  594. ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
  595. end;
  596. inherited PaintWindow(DC);
  597. end;
  598. procedure TImpGridInplaceEdit.SetEditStyle(Value: TEditStyle);
  599. begin
  600. if Value = FEditStyle then Exit;
  601. FEditStyle := Value;
  602. case Value of
  603. esPickList:
  604. begin
  605. if FPickList = nil then
  606. begin
  607. FPickList := TPopupListbox.Create(Self);
  608. FPickList.Visible := False;
  609. FPickList.Parent := Self;
  610. FPickList.OnMouseUp := ListMouseUp;
  611. FPickList.IntegralHeight := True;
  612. FPickList.ItemHeight := 11;
  613. end;
  614. FActiveList := FPickList;
  615. end;
  616. { esDataList:
  617. begin
  618. if FDataList = nil then
  619. begin
  620. FDataList := TPopupDataList.Create(Self);
  621. FDataList.Visible := False;
  622. FDataList.Parent := Self;
  623. FDataList.OnMouseUp := ListMouseUp;
  624. end;
  625. FActiveList := FDataList;
  626. end;}
  627. else { cbsNone, cbsEllipsis, or read only field }
  628. FActiveList := nil;
  629. end;
  630. with TImpStringGrid(Grid) do
  631. Self.ReadOnly := Columns[col].ReadOnly;
  632. Repaint;
  633. end;
  634. procedure TImpGridInplaceEdit.StopTracking;
  635. begin
  636. if FTracking then
  637. begin
  638. TrackButton(-1, -1);
  639. FTracking := False;
  640. MouseCapture := False;
  641. end;
  642. end;
  643. procedure TImpGridInplaceEdit.TrackButton(X,Y: Integer);
  644. var
  645. NewState: Boolean;
  646. R: TRect;
  647. begin
  648. SetRect(R, ClientWidth - FButtonWidth, 0, ClientWidth, ClientHeight);
  649. NewState := PtInRect(R, Point(X, Y));
  650. if FPressed <> NewState then
  651. begin
  652. FPressed := NewState;
  653. InvalidateRect(Handle, @R, False);
  654. end;
  655. end;
  656. procedure TImpGridInplaceEdit.UpdateContents;
  657. var
  658. Column: TImpColumn;
  659. NewStyle: TEditStyle;
  660. {MasterField: TField; }
  661. begin
  662. with TImpStringgrid(Grid) do
  663. Column := Columns[col];
  664. NewStyle := esSimple;
  665. case Column.ButtonStyle of
  666. cbsEllipsis: NewStyle := esEllipsis;
  667. cbsPicklist: begin
  668. NewStyle := esPickList;
  669. { if Assigned(Column.Field) then
  670. with Column.Field do
  671. begin
  672. { Show the dropdown button only if the field is editable }
  673. { if FieldKind = fkLookup then
  674. begin
  675. MasterField := Dataset.FieldByName(KeyFields);
  676. { Column.DefaultReadonly will always be True for a lookup field.
  677. Test if Column.ReadOnly has been assigned a value of True }
  678. { if Assigned(MasterField) and MasterField.CanModify and
  679. not ((cvReadOnly in Column.AssignedValues) and Column.ReadOnly) then
  680. with TCustomDBGrid(Grid) do
  681. if not ReadOnly and DataLink.Active and not Datalink.ReadOnly then
  682. NewStyle := esDataList
  683. end
  684. else
  685. if Assigned(Column.Picklist) and (Column.PickList.Count > 0) and
  686. not Column.Readonly then
  687. NewStyle := esPickList;
  688. end;}
  689. end;
  690. end;
  691. EditStyle := NewStyle;
  692. inherited UpdateContents;
  693. end;
  694. procedure TImpGridInplaceEdit.CMCancelMode(var Message: TCMCancelMode);
  695. begin
  696. if (Message.Sender <> Self) and (Message.Sender <> FActiveList) then
  697. CloseUp(False);
  698. end;
  699. procedure TImpGridInplaceEdit.WMCancelMode(var Message: TMessage);
  700. begin
  701. StopTracking;
  702. inherited;
  703. end;
  704. procedure TImpGridInplaceEdit.WMKillFocus(var Message: TMessage);
  705. begin
  706. if SysLocale.FarEast then
  707. begin
  708. ImeName := Screen.DefaultIme;
  709. ImeMode := imDontCare;
  710. end;
  711. inherited;
  712. CloseUp(False);
  713. end;
  714. procedure TImpGridInplaceEdit.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  715. begin
  716. with Message do
  717. if (FEditStyle <> esSimple) and
  718. PtInRect(Rect(Width - FButtonWidth, 0, Width, Height), Point(XPos, YPos)) then
  719. Exit;
  720. inherited;
  721. end;
  722. procedure TImpGridInplaceEdit.WMPaint(var Message: TWMPaint);
  723. begin
  724. PaintHandler(Message);
  725. end;
  726. procedure TImpGridInplaceEdit.WMSetCursor(var Message: TWMSetCursor);
  727. var
  728. P: TPoint;
  729. begin
  730. GetCursorPos(P);
  731. if (FEditStyle <> esSimple) and
  732. PtInRect(Rect(Width - FButtonWidth, 0, Width, Height), ScreenToClient(P)) then
  733. Windows.SetCursor(LoadCursor(0, idc_Arrow))
  734. else
  735. inherited;
  736. end;
  737. procedure TImpGridInplaceEdit.WndProc(var Message: TMessage);
  738. begin
  739. case Message.Msg of
  740. wm_KeyDown, wm_SysKeyDown, wm_Char:
  741. if EditStyle in [esPickList, esDataList] then
  742. with TWMKey(Message) do
  743. begin
  744. //DoDropDownKeys(CharCode, KeyDataToShiftState(KeyData));
  745. if (CharCode <> 0) and FListVisible then
  746. begin
  747. with TMessage(Message) do
  748. SendMessage(FActiveList.Handle, Msg, WParam, LParam);
  749. Exit;
  750. end;
  751. end
  752. end;
  753. inherited;
  754. end;
  755. constructor Timpstringgrid.Create(Owner: TComponent);
  756. var i:integer;
  757. begin
  758. inherited;
  759. Columns := TImpGridColumns.Create(self,TImpColumn);
  760. For i := 1 to 5 do Columns.add;
  761. end;
  762. procedure Timpstringgrid.Editbuttonclick;
  763. begin
  764. if assigned(OnElippsisclicked) then OnElippsisclicked(self,col,row)
  765. end;
  766. function Timpstringgrid.GetColCount: Integer;
  767. begin
  768. result := inherited colcount
  769. end;
  770. procedure Timpstringgrid.SetColCount(Col: LongInt);
  771. var oldcol:Longint;
  772. begin
  773. oldcol := inherited Colcount;
  774. if oldcol <> col then begin
  775. if col > oldcol then begin
  776. while oldcol < col do begin
  777. columns.add;
  778. inc(oldcol);
  779. end;
  780. end
  781. else
  782. begin
  783. while oldcol > col do begin
  784. columns.items[columns.count-1].free;
  785. dec(oldcol);
  786. end;
  787. end;
  788. end;
  789. inherited colcount := col;
  790. end;
  791. function TImpStringGrid.CreateEditor: TInplaceEdit;
  792. begin
  793. Result := TImpGridInplaceEdit.Create(Self);
  794. end;
  795. procedure TImpstringgrid.KeyDown(var Key: Word; Shift: TShiftState);
  796. var coll,roww,i:integer;
  797. begin
  798. coll := col;
  799. roww := row;
  800. if key = vk_tab then begin
  801. if not (ssAlt in Shift) then
  802. if ssShift in Shift then
  803. begin
  804. Dec(coll);
  805. if coll < FixedCols then
  806. begin
  807. coll := ColCount - 1;
  808. Dec(roww);
  809. if roww < FixedRows then roww := RowCount - 1;
  810. end;
  811. Shift := [];
  812. end
  813. else
  814. begin
  815. Inc(coll);
  816. if coll >= ColCount then
  817. begin
  818. coll := FixedCols;
  819. Inc(roww);
  820. if roww >= RowCount then
  821. begin
  822. if (rowcount+1)*(Defaultrowheight+Gridlinewidth) > height then
  823. begin
  824. if not ftoomuch then if assigned(fOntoomuch) then fOntoomuch(self);
  825. ftoomuch := true;
  826. end else ftoomuch := false;
  827. rowcount := rowcount +1;
  828. if assigned(fOnNewRow) then fOnNewRow(self);
  829. if colcount <> 0 then for i := 0 to colcount-1 do begin
  830. cells[i,roww] := '';
  831. end;
  832. end;
  833. end;
  834. end;
  835. end;
  836. inherited keydown(Key,Shift);
  837. end;
  838. procedure TImpStringGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
  839. function RowIsMultiSelected: Boolean;
  840. var
  841. Index: Integer;
  842. begin
  843. Result :=false;
  844. {(dgMultiSelect in Options) and Datalink.Active and
  845. FBookmarks.Find(Datalink.Datasource.Dataset.Bookmark, Index);}
  846. end;
  847. var
  848. OldActive: Integer;
  849. Indicator: Integer;
  850. Highlight: Boolean;
  851. Value: string;
  852. DrawColumn: TImpColumn;
  853. FrameOffs: Byte;
  854. MultiSelected: Boolean;
  855. begin
  856. if csLoading in ComponentState then
  857. begin
  858. Canvas.Brush.Color := Color;
  859. Canvas.FillRect(ARect);
  860. Exit;
  861. end;
  862. { Dec(ARow, FTitleOffset);
  863. Dec(ACol, FIndicatorOffset); }
  864. if (gdFixed in AState) then
  865. begin
  866. InflateRect(ARect, -1, -1);
  867. FrameOffs := 1;
  868. end
  869. else
  870. FrameOffs := 2;
  871. with Canvas do
  872. begin
  873. DrawColumn := Columns[ACol];
  874. if gdFixed in AState then
  875. begin
  876. Font := DrawColumn.Title.Font;
  877. Brush.Color := DrawColumn.Title.Color;
  878. end
  879. else
  880. begin
  881. Font := DrawColumn.Font;
  882. Brush.Color := DrawColumn.Color;
  883. end;
  884. with DrawColumn do
  885. WriteText(Canvas, ARect, FrameOffs, FrameOffs, cells[Acol,Arow], Alignment)
  886. end;
  887. if (gdFixed in AState) then
  888. begin
  889. InflateRect(ARect, 1, 1);
  890. if ARow < 1 then with DrawColumn.Title do
  891. WriteText(Canvas, ARect, FrameOffs, FrameOffs, Caption, Alignment);
  892. DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
  893. DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_TOPLEFT);
  894. end;
  895. end;
  896. { TImpColumn }
  897. constructor TImpColumn.Create(Collection: TCollection);
  898. var
  899. Grid: TImpStringGrid;
  900. begin
  901. Grid := nil;
  902. if Assigned(Collection) and (Collection is TImpGridColumns) then
  903. Grid := TImpGridColumns(Collection).Grid;
  904. {if Assigned(Grid) then
  905. Grid.BeginLayout; }
  906. try
  907. inherited Create(Collection);
  908. FDropDownRows := 7;
  909. FButtonStyle := cbsNone;
  910. FFont := TFont.Create;
  911. FFont.Assign(DefaultFont);
  912. FFont.OnChange := FontChanged;
  913. FImeMode := imDontCare;
  914. FImeName := Screen.DefaultIme;
  915. FTitle := CreateTitle;
  916. //FPicklist := Tstrings.create;
  917. finally
  918. if Assigned(Grid) then
  919. // Grid.EndLayout;
  920. end;
  921. end;
  922. destructor TImpColumn.Destroy;
  923. begin
  924. FTitle.Free;
  925. FFont.Free;
  926. FPickList.Free;
  927. inherited Destroy;
  928. end;
  929. procedure TImpColumn.Assign(Source: TPersistent);
  930. begin
  931. if Source is TImpColumn then
  932. begin
  933. if Assigned(Collection) then Collection.BeginUpdate;
  934. try
  935. RestoreDefaults;
  936. //FieldName := TImpColumn(Source).FieldName;
  937. if cvColor in TImpColumn(Source).AssignedValues then
  938. Color := TImpColumn(Source).Color;
  939. if cvWidth in TImpColumn(Source).AssignedValues then
  940. Width := TImpColumn(Source).Width;
  941. if cvFont in TImpColumn(Source).AssignedValues then
  942. Font := TImpColumn(Source).Font;
  943. if cvImeMode in TImpColumn(Source).AssignedValues then
  944. ImeMode := TImpColumn(Source).ImeMode;
  945. if cvImeName in TImpColumn(Source).AssignedValues then
  946. ImeName := TImpColumn(Source).ImeName;
  947. if cvAlignment in TImpColumn(Source).AssignedValues then
  948. Alignment := TImpColumn(Source).Alignment;
  949. if cvReadOnly in TImpColumn(Source).AssignedValues then
  950. ReadOnly := TImpColumn(Source).ReadOnly;
  951. Title := TImpColumn(Source).Title;
  952. DropDownRows := TImpColumn(Source).DropDownRows;
  953. ButtonStyle := TImpColumn(Source).ButtonStyle;
  954. PickList := TImpColumn(Source).PickList;
  955. //PopupMenu := TImpColumn(Source).PopupMenu;
  956. finally
  957. if Assigned(Collection) then Collection.EndUpdate;
  958. end;
  959. end
  960. else
  961. inherited Assign(Source);
  962. end;
  963. function TImpColumn.CreateTitle: TImpColumnTitle;
  964. begin
  965. Result := TImpColumnTitle.Create(Self);
  966. end;
  967. function TImpColumn.DefaultAlignment: TAlignment;
  968. begin
  969. // if Assigned(Field) then
  970. // Result := FField.Alignment
  971. // else
  972. Result := taLeftJustify;
  973. end;
  974. function TImpColumn.DefaultColor: TColor;
  975. var
  976. Grid: TImpStringGrid;
  977. begin
  978. Grid := GetGrid;
  979. if Assigned(Grid) then
  980. Result := Grid.Color
  981. else
  982. Result := clWindow;
  983. end;
  984. function TImpColumn.DefaultFont: TFont;
  985. var
  986. Grid: TImpStringGrid;
  987. begin
  988. Grid := GetGrid;
  989. if Assigned(Grid) then
  990. Result := Grid.Font
  991. else
  992. Result := FFont;
  993. end;
  994. function TImpColumn.DefaultImeMode: TImeMode;
  995. var
  996. Grid: TImpStringGrid;
  997. begin
  998. Grid := GetGrid;
  999. if Assigned(Grid) then
  1000. Result := Grid.ImeMode
  1001. else
  1002. Result := FImeMode;
  1003. end;
  1004. function TImpColumn.DefaultImeName: TImeName;
  1005. var
  1006. Grid: TImpStringGrid;
  1007. begin
  1008. Grid := GetGrid;
  1009. if Assigned(Grid) then
  1010. Result := Grid.ImeName
  1011. else
  1012. Result := FImeName;
  1013. end;
  1014. function TImpColumn.DefaultReadOnly: Boolean;
  1015. //var
  1016. // Grid: TImpStringGrid;
  1017. begin
  1018. // Grid := GetGrid;
  1019. Result := false;
  1020. // Result := (Assigned(Grid) and Grid.ReadOnly) or (Assigned(Field) and FField.ReadOnly);
  1021. end;
  1022. function TImpColumn.DefaultWidth: Integer;
  1023. //var
  1024. //W: Integer;
  1025. // RestoreCanvas: Boolean;
  1026. // TM: TTextMetric;
  1027. begin
  1028. if GetGrid = nil then
  1029. begin
  1030. Result := 64;
  1031. Exit;
  1032. end;
  1033. with GetGrid do
  1034. begin
  1035. { if Assigned(Field) then
  1036. begin
  1037. RestoreCanvas := not HandleAllocated;
  1038. if RestoreCanvas then
  1039. Canvas.Handle := GetDC(0);
  1040. try
  1041. Canvas.Font := Self.Font;
  1042. GetTextMetrics(Canvas.Handle, TM);
  1043. Result := Field.DisplayWidth * (Canvas.TextWidth('0') - TM.tmOverhang)
  1044. + TM.tmOverhang + 4;
  1045. if dgTitles in Options then
  1046. begin
  1047. Canvas.Font := Title.Font;
  1048. W := Canvas.TextWidth(Title.Caption) + 4;
  1049. if Result < W then
  1050. Result := W;
  1051. end;
  1052. finally
  1053. if RestoreCanvas then
  1054. begin
  1055. ReleaseDC(0,Canvas.Handle);
  1056. Canvas.Handle := 0;
  1057. end;
  1058. end;
  1059. end
  1060. else}
  1061. Result := DefaultColWidth;
  1062. end;
  1063. end;
  1064. procedure TImpColumn.FontChanged;
  1065. begin
  1066. Include(FAssignedValues, cvFont);
  1067. Title.RefreshDefaultFont;
  1068. Changed(False);
  1069. end;
  1070. function TImpColumn.GetAlignment: TAlignment;
  1071. begin
  1072. if cvAlignment in FAssignedValues then
  1073. Result := FAlignment
  1074. else
  1075. Result := DefaultAlignment;
  1076. end;
  1077. function TImpColumn.GetColor: TColor;
  1078. begin
  1079. if cvColor in FAssignedValues then
  1080. Result := FColor
  1081. else
  1082. Result := DefaultColor;
  1083. end;
  1084. {function TImpColumn.GetField: TField;
  1085. var
  1086. Grid: TImpStringGrid;
  1087. begin { Returns Nil if FieldName can't be found in dataset }
  1088. { Grid := GetGrid;
  1089. if (FField = nil) and (Length(FFieldName) > 0) and Assigned(Grid) and
  1090. Assigned(Grid.DataLink.DataSet) then
  1091. with Grid.Datalink.Dataset do
  1092. if Active or (not DefaultFields) then
  1093. SetField(FindField(FieldName));
  1094. Result := FField;
  1095. end;}
  1096. function TImpColumn.GetFont: TFont;
  1097. var
  1098. Save: TNotifyEvent;
  1099. begin
  1100. if not (cvFont in FAssignedValues) and (FFont.Handle <> DefaultFont.Handle) then
  1101. begin
  1102. Save := FFont.OnChange;
  1103. FFont.OnChange := nil;
  1104. FFont.Assign(DefaultFont);
  1105. FFont.OnChange := Save;
  1106. end;
  1107. Result := FFont;
  1108. end;
  1109. function TImpColumn.GetGrid: TImpStringGrid;
  1110. begin
  1111. if Assigned(Collection) and (Collection is TImpGridColumns) then
  1112. Result := TImpGridColumns(Collection).Grid
  1113. else
  1114. Result := nil;
  1115. end;
  1116. function TImpColumn.GetDisplayName: string;
  1117. begin
  1118. { Result := FFieldName;
  1119. if Result = '' then }Result := inherited GetDisplayName;
  1120. end;
  1121. function TImpColumn.GetImeMode: TImeMode;
  1122. begin
  1123. if cvImeMode in FAssignedValues then
  1124. Result := FImeMode
  1125. else
  1126. Result := DefaultImeMode;
  1127. end;
  1128. function TImpColumn.GetImeName: TImeName;
  1129. begin
  1130. if cvImeName in FAssignedValues then
  1131. Result := FImeName
  1132. else
  1133. Result := DefaultImeName;
  1134. end;
  1135. function TImpColumn.GetPickList: TStrings;
  1136. begin
  1137. if FPickList = nil then
  1138. FPickList := TStringList.Create;
  1139. Result := FPickList;
  1140. end;
  1141. function TImpColumn.GetReadOnly: Boolean;
  1142. begin
  1143. if cvReadOnly in FAssignedValues then
  1144. Result := FReadOnly
  1145. else
  1146. Result := DefaultReadOnly;
  1147. end;
  1148. function TImpColumn.GetWidth: Integer;
  1149. begin
  1150. if cvWidth in FAssignedValues then
  1151. Result := FWidth
  1152. else
  1153. Result := DefaultWidth;
  1154. end;
  1155. function TImpColumn.IsAlignmentStored: Boolean;
  1156. begin
  1157. Result := (cvAlignment in FAssignedValues) and (FAlignment <> DefaultAlignment);
  1158. end;
  1159. function TImpColumn.IsColorStored: Boolean;
  1160. begin
  1161. Result := (cvColor in FAssignedValues) and (FColor <> DefaultColor);
  1162. end;
  1163. function TImpColumn.IsFontStored: Boolean;
  1164. begin
  1165. Result := (cvFont in FAssignedValues);
  1166. end;
  1167. function TImpColumn.IsImeModeStored: Boolean;
  1168. begin
  1169. Result := (cvImeMode in FAssignedValues) and (FImeMode <> DefaultImeMode);
  1170. end;
  1171. function TImpColumn.IsImeNameStored: Boolean;
  1172. begin
  1173. Result := (cvImeName in FAssignedValues) and (FImeName <> DefaultImeName);
  1174. end;
  1175. function TImpColumn.IsReadOnlyStored: Boolean;
  1176. begin
  1177. Result := (cvReadOnly in FAssignedValues) and (FReadOnly <> DefaultReadOnly);
  1178. end;
  1179. function TImpColumn.IsWidthStored: Boolean;
  1180. begin
  1181. Result := (cvWidth in FAssignedValues) and (FWidth <> DefaultWidth);
  1182. end;
  1183. procedure TImpColumn.RefreshDefaultFont;
  1184. var
  1185. Save: TNotifyEvent;
  1186. begin
  1187. if cvFont in FAssignedValues then Exit;
  1188. Save := FFont.OnChange;
  1189. FFont.OnChange := nil;
  1190. try
  1191. FFont.Assign(DefaultFont);
  1192. finally
  1193. FFont.OnChange := Save;
  1194. end;
  1195. end;
  1196. procedure TImpColumn.RestoreDefaults;
  1197. var
  1198. FontAssigned: Boolean;
  1199. begin
  1200. FontAssigned := cvFont in FAssignedValues;
  1201. FTitle.RestoreDefaults;
  1202. FAssignedValues := [];
  1203. RefreshDefaultFont;
  1204. FPickList.Free;
  1205. FPickList := nil;
  1206. ButtonStyle := cbsNone;
  1207. Changed(FontAssigned);
  1208. end;
  1209. procedure TImpColumn.SetAlignment(Value: TAlignment);
  1210. begin
  1211. if (cvAlignment in FAssignedValues) and (Value = FAlignment) then Exit;
  1212. FAlignment := Value;
  1213. Include(FAssignedValues, cvAlignment);
  1214. Changed(False);
  1215. end;
  1216. procedure TImpColumn.SetButtonStyle(Value: TImpColumnButtonStyle);
  1217. begin
  1218. if Value = FButtonStyle then Exit;
  1219. FButtonStyle := Value;
  1220. Changed(False);
  1221. end;
  1222. procedure TImpColumn.SetColor(Value: TColor);
  1223. begin
  1224. if (cvColor in FAssignedValues) and (Value = FColor) then Exit;
  1225. FColor := Value;
  1226. Include(FAssignedValues, cvColor);
  1227. Changed(False);
  1228. end;
  1229. {procedure TImpColumn.SetField(Value: TField);
  1230. begin
  1231. if FField = Value then Exit;
  1232. FField := Value;
  1233. if Assigned(Value) then
  1234. FFieldName := Value.FieldName;
  1235. Changed(False);
  1236. end; }
  1237. {procedure TImpColumn.SetFieldName(const Value: String);
  1238. var
  1239. AField: TField;
  1240. Grid: TImpStringGrid;
  1241. begin
  1242. AField := nil;
  1243. Grid := GetGrid;
  1244. if Assigned(Grid) and Assigned(Grid.DataLink.DataSet) and
  1245. not (csLoading in Grid.ComponentState) and (Length(Value) > 0) then
  1246. AField := Grid.DataLink.DataSet.FindField(Value); { no exceptions }
  1247. { FFieldName := Value;
  1248. SetField(AField);
  1249. Changed(False);
  1250. end;}
  1251. procedure TImpColumn.SetFont(Value: TFont);
  1252. begin
  1253. FFont.Assign(Value);
  1254. Include(FAssignedValues, cvFont);
  1255. Changed(False);
  1256. end;
  1257. procedure TImpColumn.SetImeMode(Value: TImeMode);
  1258. begin
  1259. if (cvImeMode in FAssignedValues) or (Value <> DefaultImeMode) then
  1260. begin
  1261. FImeMode := Value;
  1262. Include(FAssignedValues, cvImeMode);
  1263. end;
  1264. Changed(False);
  1265. end;
  1266. procedure TImpColumn.SetImeName(Value: TImeName);
  1267. begin
  1268. if (cvImeName in FAssignedValues) or (Value <> DefaultImeName) then
  1269. begin
  1270. FImeName := Value;
  1271. Include(FAssignedValues, cvImeName);
  1272. end;
  1273. Changed(False);
  1274. end;
  1275. procedure TImpColumn.SetPickList(Value: TStrings);
  1276. begin
  1277. if Value = nil then
  1278. begin
  1279. FPickList.Free;
  1280. FPickList := nil;
  1281. Exit;
  1282. end;
  1283. PickList.Assign(Value);
  1284. end;
  1285. {procedure TImpColumn.SetPopupMenu(Value: TPopupMenu);
  1286. begin
  1287. FPopupMenu := Value;
  1288. if Value <> nil then Value.FreeNotification(GetGrid);
  1289. end;}
  1290. procedure TImpColumn.SetReadOnly(Value: Boolean);
  1291. begin
  1292. if (cvReadOnly in FAssignedValues) and (Value = FReadOnly) then Exit;
  1293. FReadOnly := Value;
  1294. Include(FAssignedValues, cvReadOnly);
  1295. Changed(False);
  1296. end;
  1297. procedure TImpColumn.SetTitle(Value: TImpColumnTitle);
  1298. begin
  1299. FTitle.Assign(Value);
  1300. end;
  1301. procedure TImpColumn.SetWidth(Value: Integer);
  1302. begin
  1303. if (cvWidth in FAssignedValues) or (Value <> DefaultWidth) then
  1304. begin
  1305. FWidth := Value;
  1306. Include(FAssignedValues, cvWidth);
  1307. end;
  1308. Changed(False);
  1309. end;
  1310. procedure Register;
  1311. begin
  1312. RegisterComponents('Samples', [TImpStringgrid]);
  1313. end;
  1314. { TImpGridColumns }
  1315. constructor TImpGridColumns.Create(Grid: TImpStringGrid; ColumnClass: TImpColumnClass);
  1316. begin
  1317. inherited Create(ColumnClass);
  1318. FGrid := Grid;
  1319. end;
  1320. function TImpGridColumns.Add: TImpColumn;
  1321. begin
  1322. Result := TImpColumn(inherited Add);
  1323. end;
  1324. function TImpGridColumns.GeTImpColumn(Index: Integer): TImpColumn;
  1325. begin
  1326. Result := TImpColumn(inherited Items[Index]);
  1327. end;
  1328. function TImpGridColumns.GetCount: Integer;
  1329. begin
  1330. Result := inherited Count;
  1331. end;
  1332. function TImpGridColumns.GetOwner: TPersistent;
  1333. begin
  1334. Result := FGrid;
  1335. end;
  1336. function TImpGridColumns.GetState: TImpGridColumnsState;
  1337. begin
  1338. Result := TImpGridColumnsState((Count > 0)) ;//and not (Items[0] is TPassthroughColumn));
  1339. end;
  1340. procedure TImpGridColumns.LoadFromFile(const Filename: string);
  1341. var
  1342. S: TFileStream;
  1343. begin
  1344. S := TFileStream.Create(Filename, fmOpenRead);
  1345. try
  1346. LoadFromStream(S);
  1347. finally
  1348. S.Free;
  1349. end;
  1350. end;
  1351. type
  1352. TImpColumnsWrapper = class(TComponent)
  1353. private
  1354. FColumns: TImpGridColumns;
  1355. published
  1356. property Columns: TImpGridColumns read FColumns write FColumns;
  1357. end;
  1358. procedure TImpGridColumns.LoadFromStream(S: TStream);
  1359. var
  1360. Wrapper: TImpColumnsWrapper;
  1361. begin
  1362. { Wrapper := TImpColumnsWrapper.Create(nil);
  1363. try
  1364. Wrapper.Columns := FGrid.CreateColumns;
  1365. S.ReadComponent(Wrapper);
  1366. Assign(Wrapper.Columns);
  1367. finally
  1368. Wrapper.Columns.Free;
  1369. Wrapper.Free;
  1370. end;}
  1371. end;
  1372. procedure TImpGridColumns.RestoreDefaults;
  1373. var
  1374. I: Integer;
  1375. begin
  1376. BeginUpdate;
  1377. try
  1378. for I := 0 to Count-1 do
  1379. Items[I].RestoreDefaults;
  1380. finally
  1381. EndUpdate;
  1382. end;
  1383. end;
  1384. procedure TImpGridColumns.RebuildColumns;
  1385. var
  1386. I: Integer;
  1387. begin
  1388. {if Assigned(FGrid) and Assigned(FGrid.DataSource) and
  1389. Assigned(FGrid.Datasource.Dataset) then
  1390. begin
  1391. FGrid.BeginLayout;
  1392. try
  1393. Clear;
  1394. with FGrid.Datasource.Dataset do
  1395. for I := 0 to FieldCount-1 do
  1396. Add.FieldName := Fields[I].FieldName
  1397. finally
  1398. FGrid.EndLayout;
  1399. end
  1400. end
  1401. else
  1402. Clear;}
  1403. end;
  1404. procedure TImpGridColumns.SaveToFile(const Filename: string);
  1405. var
  1406. S: TStream;
  1407. begin
  1408. S := TFileStream.Create(Filename, fmCreate);
  1409. try
  1410. SaveToStream(S);
  1411. finally
  1412. S.Free;
  1413. end;
  1414. end;
  1415. procedure TImpGridColumns.SaveToStream(S: TStream);
  1416. var
  1417. Wrapper: TImpColumnsWrapper;
  1418. begin
  1419. Wrapper := TImpColumnsWrapper.Create(nil);
  1420. try
  1421. Wrapper.Columns := Self;
  1422. S.WriteComponent(Wrapper);
  1423. finally
  1424. Wrapper.Free;
  1425. end;
  1426. end;
  1427. procedure TImpGridColumns.SeTImpColumn(Index: Integer; Value: TImpColumn);
  1428. begin
  1429. Items[Index].Assign(Value);
  1430. end;
  1431. procedure TImpGridColumns.SetState(NewState: TImpGridColumnsState);
  1432. begin
  1433. if NewState = State then Exit;
  1434. if NewState = csDefault then
  1435. Clear
  1436. else
  1437. RebuildColumns;
  1438. end;
  1439. procedure TImpGridColumns.Update(Item: TCollectionItem);
  1440. var
  1441. Raw: Integer;
  1442. begin
  1443. { if (FGrid = nil) or (csLoading in FGrid.ComponentState) then Exit;
  1444. { if Item = nil then
  1445. begin
  1446. FGrid.LayoutChanged;
  1447. end
  1448. else }
  1449. { begin
  1450. Raw := FGrid.DataToRawColumn(Item.Index);
  1451. FGrid.InvalidateCol(Raw);
  1452. FGrid.ColWidths[Raw] := TImpColumn(Item).Width;
  1453. end; }
  1454. end;
  1455. { TImpColumnTitle }
  1456. constructor TImpColumnTitle.Create(Column: TImpColumn);
  1457. begin
  1458. inherited Create;
  1459. FColumn := Column;
  1460. FFont := TFont.Create;
  1461. FFont.Assign(DefaultFont);
  1462. FFont.OnChange := FontChanged;
  1463. end;
  1464. destructor TImpColumnTitle.Destroy;
  1465. begin
  1466. FFont.Free;
  1467. inherited Destroy;
  1468. end;
  1469. procedure TImpColumnTitle.Assign(Source: TPersistent);
  1470. begin
  1471. if Source is TImpColumnTitle then
  1472. begin
  1473. if cvTitleAlignment in TImpColumnTitle(Source).FColumn.FAssignedValues then
  1474. Alignment := TImpColumnTitle(Source).Alignment;
  1475. if cvTitleColor in TImpColumnTitle(Source).FColumn.FAssignedValues then
  1476. Color := TImpColumnTitle(Source).Color;
  1477. if cvTitleCaption in TImpColumnTitle(Source).FColumn.FAssignedValues then
  1478. Caption := TImpColumnTitle(Source).Caption;
  1479. if cvTitleFont in TImpColumnTitle(Source).FColumn.FAssignedValues then
  1480. Font := TImpColumnTitle(Source).Font;
  1481. end
  1482. else
  1483. inherited Assign(Source);
  1484. end;
  1485. function TImpColumnTitle.DefaultAlignment: TAlignment;
  1486. begin
  1487. Result := taLeftJustify;
  1488. end;
  1489. function TImpColumnTitle.DefaultColor: TColor;
  1490. var
  1491. Grid: TImpStringGrid;
  1492. begin
  1493. Grid := FColumn.GetGrid;
  1494. if Assigned(Grid) then
  1495. Result := Grid.FixedColor
  1496. else
  1497. Result := clBtnFace;
  1498. end;
  1499. function TImpColumnTitle.DefaultFont: TFont;
  1500. var
  1501. Grid: TImpStringGrid;
  1502. begin
  1503. Grid := FColumn.GetGrid;
  1504. {if Assigned(Grid) then
  1505. Result := Grid.TitleFont
  1506. else }
  1507. Result := FColumn.Font;
  1508. end;
  1509. function TImpColumnTitle.DefaultCaption: string;
  1510. //var
  1511. { Field: TField;}
  1512. begin
  1513. { Field := FColumn.Field;
  1514. if Assigned(Field) then
  1515. Result := Field.DisplayName
  1516. else }
  1517. { Result := FColumn.FieldName;}
  1518. end;
  1519. procedure TImpColumnTitle.FontChanged(Sender: TObject);
  1520. begin
  1521. Include(FColumn.FAssignedValues, cvTitleFont);
  1522. FColumn.Changed(True);
  1523. end;
  1524. function TImpColumnTitle.GetAlignment: TAlignment;
  1525. begin
  1526. if cvTitleAlignment in FColumn.FAssignedValues then
  1527. Result := FAlignment
  1528. else
  1529. Result := DefaultAlignment;
  1530. end;
  1531. function TImpColumnTitle.GetColor: TColor;
  1532. begin
  1533. if cvTitleColor in FColumn.FAssignedValues then
  1534. Result := FColor
  1535. else
  1536. Result := DefaultColor;
  1537. end;
  1538. function TImpColumnTitle.GetCaption: string;
  1539. begin
  1540. if cvTitleCaption in FColumn.FAssignedValues then
  1541. Result := FCaption
  1542. else
  1543. Result := DefaultCaption;
  1544. end;
  1545. function TImpColumnTitle.GetFont: TFont;
  1546. var
  1547. Save: TNotifyEvent;
  1548. Def: TFont;
  1549. begin
  1550. if not (cvTitleFont in FColumn.FAssignedValues) then
  1551. begin
  1552. Def := DefaultFont;
  1553. if (FFont.Handle <> Def.Handle) or (FFont.Color <> Def.Color) then
  1554. begin
  1555. Save := FFont.OnChange;
  1556. FFont.OnChange := nil;
  1557. FFont.Assign(DefaultFont);
  1558. FFont.OnChange := Save;
  1559. end;
  1560. end;
  1561. Result := FFont;
  1562. end;
  1563. function TImpColumnTitle.IsAlignmentStored: Boolean;
  1564. begin
  1565. Result := (cvTitleAlignment in FColumn.FAssignedValues) and
  1566. (FAlignment <> DefaultAlignment);
  1567. end;
  1568. function TImpColumnTitle.IsColorStored: Boolean;
  1569. begin
  1570. Result := (cvTitleColor in FColumn.FAssignedValues) and
  1571. (FColor <> DefaultColor);
  1572. end;
  1573. function TImpColumnTitle.IsFontStored: Boolean;
  1574. begin
  1575. Result := (cvTitleFont in FColumn.FAssignedValues);
  1576. end;
  1577. function TImpColumnTitle.IsCaptionStored: Boolean;
  1578. begin
  1579. Result := (cvTitleCaption in FColumn.FAssignedValues) and
  1580. (FCaption <> DefaultCaption);
  1581. end;
  1582. procedure TImpColumnTitle.RefreshDefaultFont;
  1583. var
  1584. Save: TNotifyEvent;
  1585. begin
  1586. if (cvTitleFont in FColumn.FAssignedValues) then Exit;
  1587. Save := FFont.OnChange;
  1588. FFont.OnChange := nil;
  1589. try
  1590. FFont.Assign(DefaultFont);
  1591. finally
  1592. FFont.OnChange := Save;
  1593. end;
  1594. end;
  1595. procedure TImpColumnTitle.RestoreDefaults;
  1596. var
  1597. FontAssigned: Boolean;
  1598. begin
  1599. FontAssigned := cvTitleFont in FColumn.FAssignedValues;
  1600. FColumn.FAssignedValues := FColumn.FAssignedValues - ColumnTitleValues;
  1601. FCaption := '';
  1602. RefreshDefaultFont;
  1603. { If font was assigned, changing it back to default may affect grid title
  1604. height, and title height changes require layout and redraw of the grid. }
  1605. FColumn.Changed(FontAssigned);
  1606. end;
  1607. procedure TImpColumnTitle.SetAlignment(Value: TAlignment);
  1608. begin
  1609. if (cvTitleAlignment in FColumn.FAssignedValues) and (Value = FAlignment) then Exit;
  1610. FAlignment := Value;
  1611. Include(FColumn.FAssignedValues, cvTitleAlignment);
  1612. FColumn.Changed(False);
  1613. end;
  1614. procedure TImpColumnTitle.SetColor(Value: TColor);
  1615. begin
  1616. if (cvTitleColor in FColumn.FAssignedValues) and (Value = FColor) then Exit;
  1617. FColor := Value;
  1618. Include(FColumn.FAssignedValues, cvTitleColor);
  1619. FColumn.Changed(False);
  1620. end;
  1621. procedure TImpColumnTitle.SetFont(Value: TFont);
  1622. begin
  1623. FFont.Assign(Value);
  1624. end;
  1625. procedure TImpColumnTitle.SetCaption(const Value: string);
  1626. begin
  1627. if (cvTitleCaption in FColumn.FAssignedValues) and (Value = FCaption) then Exit;
  1628. FCaption := Value;
  1629. Include(FColumn.FAssignedValues, cvTitleCaption);
  1630. FColumn.Changed(False);
  1631. end;
  1632. end.