MiConfigBasic.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. {Unidad con definiciones básicas para las clases MiConfigINI y MiConfigXML.
  2. Aquí se define la clase TMiConfigBasic, que incluye los métodos para crear las
  3. asociaciones entre las variables (propiedades) y los controles.
  4. También incluye las rutinas para mover datos entre los controles y las variables.
  5. En teoría, se podría usar esta clase, si no fuera necesario guardar datos a disco,
  6. solamente entre controles y variables:
  7. +------------+ +------------+
  8. | | <----PropertiesToWindow---- | |
  9. | Controles | | Variables |
  10. | | ----WindowToProperties----> | |
  11. +------------+ +------------+
  12. Pero como es común salvar los datos a disco, se le debe agregar las funcionalidades
  13. de accesos a disco, como se hace en las unidades MiConfigINI y MiConfigXML.
  14. Las asociaciones entre variables y controles, se hacen con los métodos:
  15. Asoc_Int, Asoc_Dbl, Asoc_Str, ... que están sobrecargados para manejar diversos controles
  16. o crear la asociación sin control.
  17. Solo se han creado asociaciones entre tipos comunes y controles comunes.
  18. Para agregar un nuevo tipo de asociación, en esta unidad se debe:
  19. 1. Crear el identificador de la nueva asociación en el tipo TTipPar.
  20. 2. Crear el nuevo método de asociación (Asoc_XXX) o sobrecargar uno existente.
  21. 3. Actualizar el método TMiConfigBasic.PropertyWindow(), con el nuevo tipo.
  22. Luego también debe implementarse el acceso a disco, para esta nueva asociación, en las
  23. unidades MiConfigINI y MiConfigXML.
  24. Por Tito Hinostroza 29/07/2016
  25. }
  26. unit MiConfigBasic;
  27. {$mode objfpc}{$H+}
  28. interface
  29. uses
  30. Classes, SysUtils, StdCtrls, Spin, Graphics, EditBtn, Dialogs,
  31. ExtCtrls, Grids, ColorBox, fgl;
  32. type
  33. //Tipos de asociaciones
  34. TTipPar = (
  35. tp_Int //Entero sin asociación
  36. ,tp_Int_TEdit //entero asociado a TEdit
  37. ,tp_Int_TSpinEdit //entero asociado a TSpinEdit
  38. ,tp_Int_TRadioGroup //entero asociado a TRadioGroup
  39. ,tp_Dbl //Double sin asociación
  40. ,tp_Dbl_TEdit //Double asociado a TEdit
  41. ,tp_Dbl_TFloatSpinEdit //Double asociado a TFloatSpinEdit
  42. ,tp_Str //String sin asociación
  43. ,tp_Str_TEdit //string asociado a TEdit
  44. ,tp_Str_TEditButton //string asociado a TEditButton (ancestro de TFileNameEdit, TDirectoryEdit, ...)
  45. ,tp_Str_TCmbBox //string asociado a TComboBox
  46. ,tp_Bol //Boleano sin asociación
  47. ,tp_Bol_TCheckBox //booleano asociado a CheckBox
  48. ,tp_Bol_TRadBut //Booleano asociado a TRadioButton
  49. ,tp_Enum //Enumerado sin asociación
  50. ,tp_Enum_TRadBut //Enumerado asociado a TRadioButton
  51. ,tp_Enum_TRadGroup //Enumerado asociado a TRadioGroup
  52. ,tp_TCol_TColBut //TColor asociado a TColorButton
  53. ,tp_TCol_TColBox //TColor asociado a TColorBox
  54. ,tp_StrList //TStringList sin asociación
  55. ,tp_StrList_TListBox //StringList asociado a TListBox
  56. ,tp_StrList_TStringGrid //StringList asociado a TStringGrid
  57. );
  58. //Objeto de asociación variable-control
  59. { TParElem }
  60. TParElem = class
  61. private //Getters and setters
  62. pCtl: TComponent; //referencia al control
  63. radButs: array of TRadioButton; //referencia a controles TRadioButton (se usan en conjunto)
  64. minEnt, maxEnt: integer; //valores máximos y mínimos para variables enteras
  65. minDbl, maxDbl: Double; //valores máximos y mínimos para variables Double
  66. function GetAsBoolean: Boolean;
  67. function GetAsInteger: integer;
  68. procedure SetAsBoolean(AValue: Boolean);
  69. procedure SetAsInteger(AValue: integer);
  70. function GetAsDouble: double;
  71. procedure SetAsDouble(AValue: double);
  72. function GetAsString: string;
  73. procedure SetAsString(AValue: string);
  74. function GetAsInt32: Int32;
  75. procedure SetAsInt32(AValue: Int32);
  76. function GetAsTColor: TColor;
  77. procedure SetAsTColor(AValue: TColor);
  78. public
  79. pVar : pointer; //referencia a la variable
  80. lVar : integer; //tamaño de variable. (Cuando no sea conocido)
  81. tipPar : TTipPar; //tipo de par agregado
  82. etiqVar: string; //etiqueta usada para grabar la variable en archivo INI o XML
  83. categ : integer; //Categoría. Usada para leer selectivamente con
  84. //Campos para configurar la grilla, cuando se use
  85. HasHeader : boolean; //Si incluye encabezado
  86. HasFixedCol: boolean; //Si tiene una columna fija
  87. ColCount : byte; //Cantidad de columnas para la grilla
  88. OnPropertyToWindow: procedure of object;
  89. OnWindowToProperty: procedure of object;
  90. OnFileToProperty: procedure of object; //Después de guardar el elemento a disco
  91. OnPropertyToFile: procedure of object; //Antes de guardar el elemento a disco
  92. public //Valores por defecto
  93. defInt: integer; //Valor entero por defecto al leer de archivo
  94. defDbl: Double; //Valor double por defecto al leer de archivo
  95. defStr: string; //Valor string por defecto al leer de archivo
  96. defBol: boolean; //Valor booleano por defecto al leer de archivo
  97. defCol: TColor; //Valor TColor por defecto al leer de archivo
  98. public //Propiedades para facilitar el acceso a pVar^, usando diversos tipos
  99. property AsInteger: integer read GetAsInteger write SetAsInteger;
  100. property AsDouble: double read GetAsDouble write SetAsDouble;
  101. property AsString: string read GetAsString write SetAsString;
  102. property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
  103. property AsInt32: Int32 read GetAsInt32 write SetAsInt32;
  104. property AsTColor: TColor read GetAsTColor write SetAsTColor;
  105. end;
  106. TParElem_list = specialize TFPGObjectList<TParElem>;
  107. { TMiConfigBasic }
  108. TMiConfigBasic = class
  109. private
  110. procedure SetFocusEd(ed: TEdit);
  111. protected
  112. valInt: integer; //valor entero de salida
  113. valDbl: Double; //valor double de salida
  114. listParElem : TParElem_list;
  115. procedure PropertyWindow(r: TParElem; PropToWindow: boolean);
  116. public //Rutinas de movimientos entre: Controles <-> Propiedades <-> Archivo
  117. OnPropertiesChanges: procedure of object; //Cuando se actualizan las propiedades
  118. function PropertiesToWindow: boolean; virtual;
  119. function WindowToProperties: boolean; virtual;
  120. protected //Rutinas de validación
  121. function EditValidateInt(edit: TEdit; min: integer=MaxInt; max: integer=-MaxInt): boolean;
  122. function EditValidateDbl(edit: TEdit; min: Double=0; max: Double=1e6): boolean;
  123. public //Métodos para asociar pares: variable-control
  124. function Asoc_Int(etiq: string; ptrInt: pointer; defVal: integer): TParElem;
  125. function Asoc_Int(etiq: string; ptrInt: pointer; edit: TEdit;
  126. defVal: integer; minVal, maxVal: integer): TParElem;
  127. function Asoc_Int(etiq: string; ptrInt: pointer; spEdit: TSpinEdit;
  128. defVal: integer): TParElem;
  129. function Asoc_Int(etiq: string; ptrInt: pointer; radGroup: TRadioGroup;
  130. defVal: integer): TParElem;
  131. //---------------------------------------------------------------------
  132. function Asoc_Dbl(etiq: string; ptrDbl: PDouble; defVal: double): TParElem;
  133. function Asoc_Dbl(etiq: string; ptrDbl: PDouble; edit: TEdit;
  134. defVal: double; minVal, maxVal: double): TParElem;
  135. function Asoc_Dbl(etiq: string; ptrDbl: PDouble; spEdit: TFloatSpinEdit;
  136. defVal: double): TParElem;
  137. //---------------------------------------------------------------------
  138. function Asoc_Str(etiq: string; ptrStr: pointer; defVal: string): TParElem;
  139. function Asoc_Str(etiq: string; ptrStr: pointer; edit: TCustomEdit;
  140. defVal: string): TParElem;
  141. function Asoc_Str(etiq: string; ptrStr: pointer; edit: TCustomEditButton;
  142. defVal: string): TParElem;
  143. function Asoc_Str(etiq: string; ptrStr: pointer; cmbBox: TComboBox;
  144. defVal: string): TParElem;
  145. //---------------------------------------------------------------------
  146. function Asoc_Bol(etiq: string; ptrBol: pointer; defVal: boolean): TParElem;
  147. function Asoc_Bol(etiq: string; ptrBol: pointer; chk: TCheckBox;
  148. defVal: boolean): TParElem;
  149. function Asoc_Bol(etiq: string; ptrBol: pointer;
  150. radButs: array of TRadioButton; defVal: boolean): TParElem;
  151. //---------------------------------------------------------------------
  152. function Asoc_Enum(etiq: string; ptrEnum: pointer; EnumSize: integer; defVal: integer): TParElem;
  153. function Asoc_Enum(etiq: string; ptrEnum: pointer; EnumSize: integer;
  154. radButs: array of TRadioButton; defVal: integer): TParElem;
  155. function Asoc_Enum(etiq: string; ptrEnum: pointer; EnumSize: integer;
  156. radGroup: TRadioGroup; defVal: integer): TParElem;
  157. //---------------------------------------------------------------------
  158. function Asoc_TCol(etiq: string; ptrTCol: pointer; colBut: TColorButton;
  159. defVal: TColor): TParElem;
  160. function Asoc_TCol(etiq: string; ptrTCol: pointer; colBut: TColorBox;
  161. defVal: TColor): TParElem;
  162. //---------------------------------------------------------------------
  163. function Asoc_StrList(etiq: string; ptrStrList: pointer): TParElem;
  164. function Asoc_StrList_TListBox(etiq: string; ptrStrList: pointer; lstBox: TlistBox): TParElem;
  165. public
  166. MsjErr: string; //mensaje de error
  167. ctlErr: TParElem; //elemento con error
  168. constructor Create;
  169. destructor Destroy; override;
  170. end;
  171. implementation
  172. { TParElem }
  173. function TParElem.GetAsInteger: integer;
  174. begin
  175. Result := Integer(Pvar^);
  176. end;
  177. procedure TParElem.SetAsInteger(AValue: integer);
  178. begin
  179. //if FAsInteger=AValue then Exit;
  180. Integer(Pvar^) := AValue;
  181. end;
  182. function TParElem.GetAsDouble: double;
  183. begin
  184. Result := Double(Pvar^);
  185. end;
  186. procedure TParElem.SetAsDouble(AValue: double);
  187. begin
  188. Double(Pvar^) := AValue;
  189. end;
  190. function TParElem.GetAsString: string;
  191. begin
  192. Result := string(Pvar^);
  193. end;
  194. procedure TParElem.SetAsString(AValue: string);
  195. begin
  196. string(Pvar^) := AValue;
  197. end;
  198. function TParElem.GetAsTColor: TColor;
  199. begin
  200. Result := TColor(Pvar^);
  201. end;
  202. procedure TParElem.SetAsTColor(AValue: TColor);
  203. begin
  204. TColor(Pvar^) := AValue;
  205. end;
  206. function TParElem.GetAsBoolean: Boolean;
  207. begin
  208. Result := boolean(Pvar^);
  209. end;
  210. procedure TParElem.SetAsBoolean(AValue: Boolean);
  211. begin
  212. boolean(Pvar^) := AValue;
  213. end;
  214. function TParElem.GetAsInt32: Int32;
  215. begin
  216. Result := Int32(Pvar^);
  217. end;
  218. procedure TParElem.SetAsInt32(AValue: Int32);
  219. begin
  220. Int32(pVar^) := AValue;
  221. end;
  222. { TMiConfigBasic }
  223. procedure TMiConfigBasic.PropertyWindow(r: TParElem; PropToWindow: boolean);
  224. {Implementa el movimiento de datos entre las propiedades y los controles de la ventana
  225. Permite leer o escribir una propiedad, desde o hacia un comtrol}
  226. var
  227. n, j: Integer;
  228. list: TStringList;
  229. gr: TStringGrid;
  230. spEd: TSpinEdit;
  231. spFloatEd: TFloatSpinEdit;
  232. rdGr: TRadioGroup;
  233. begin
  234. if r.pVar = nil then exit; //se inició con NIL
  235. case r.tipPar of
  236. tp_Int:; //no tiene control asociado
  237. tp_Int_TEdit:
  238. if PropToWindow then begin //entero en TEdit
  239. //carga entero
  240. TEdit(r.pCtl).Text:=IntToStr(r.AsInteger);
  241. end else begin
  242. if not EditValidateInt(TEdit(r.pCtl),r.minEnt, r.MaxEnt) then
  243. exit; //hubo error. con mensaje en "msjErr"
  244. r.AsInteger := valInt; //guarda
  245. end;
  246. tp_Int_TSpinEdit:
  247. if PropToWindow then begin //entero en TSpinEdit
  248. //carga entero
  249. TSpinEdit(r.pCtl).Value:= r.AsInteger;
  250. end else begin
  251. spEd := TSpinEdit(r.pCtl);
  252. r.AsInteger := spEd.Value;
  253. end;
  254. tp_Int_TRadioGroup:
  255. if PropToWindow then begin //entero en TSpinEdit
  256. //carga entero
  257. TRadioGroup(r.pCtl).ItemIndex := r.AsInteger;
  258. end else begin
  259. rdGr := TRadioGroup(r.pCtl);
  260. r.AsInteger := rdGr.ItemIndex;
  261. end;
  262. //---------------------------------------------------------------------
  263. tp_Dbl:;
  264. tp_Dbl_TEdit:
  265. if PropToWindow then begin
  266. //carga double
  267. TEdit(r.pCtl).Text:=FloatToStr(r.AsDouble);
  268. end else begin
  269. if not EditValidateDbl(TEdit(r.pCtl),r.minDbl, r.MaxDbl) then
  270. exit; //hubo error. con mensaje en "msjErr"
  271. r.AsDouble := valDbl; //guarda
  272. end;
  273. tp_Dbl_TFloatSpinEdit:
  274. if PropToWindow then begin
  275. //carga double
  276. TFloatSpinEdit(r.pCtl).Value := r.AsDouble;
  277. end else begin
  278. spFloatEd := TFloatSpinEdit(r.pCtl);
  279. //las validaciones de rango las hace el mismo control
  280. r.AsDouble := spFloatEd.Value;
  281. end;
  282. //---------------------------------------------------------------------
  283. tp_Str:; //no tiene control asociado
  284. tp_Str_TEdit:
  285. if PropToWindow then begin //cadena en TEdit
  286. //carga cadena
  287. TEdit(r.pCtl).Text := r.AsString;
  288. end else begin
  289. r.AsString := TEdit(r.pCtl).Text;
  290. end;
  291. tp_Str_TEditButton:
  292. if PropToWindow then begin
  293. //carga cadena
  294. TEditButton(r.pCtl).Text := r.AsString;
  295. end else begin
  296. r.AsString := TEditButton(r.pCtl).Text;
  297. end;
  298. tp_Str_TCmbBox:
  299. if PropToWindow then begin //cadena en TComboBox
  300. //carga cadena
  301. TComboBox(r.pCtl).Text := r.AsString;
  302. end else begin
  303. r.AsString := TComboBox(r.pCtl).Text;
  304. end;
  305. //---------------------------------------------------------------------
  306. tp_Bol:; //no tiene control asociado
  307. tp_Bol_TCheckBox:
  308. if PropToWindow then begin //boolean a TCheckBox
  309. TCheckBox(r.pCtl).Checked := r.AsBoolean;
  310. end else begin
  311. r.AsBoolean := TCheckBox(r.pCtl).Checked;
  312. end;
  313. tp_Bol_TRadBut:
  314. if PropToWindow then begin //Enumerado a TRadioButtons
  315. if 1<=High(r.radButs) then begin
  316. if r.AsBoolean then r.radButs[1].checked := true //activa primero
  317. else r.radButs[0].checked := true //activa segundo
  318. end;
  319. end else begin
  320. //busca el que está marcado
  321. if high(r.radButs)>=1 then begin
  322. if r.radButs[1].checked then r.AsBoolean := true
  323. else r.AsBoolean := false;
  324. end;
  325. end;
  326. //---------------------------------------------------------------------
  327. tp_Enum:; //no tiene control asociado
  328. tp_Enum_TRadBut:
  329. if PropToWindow then begin //Enumerado a TRadioButtons
  330. if r.lVar = 4 then begin //enumerado de 4 bytes
  331. n := r.AsInt32; //convierte a entero
  332. if n<=High(r.radButs) then
  333. r.radButs[n].checked := true; //lo activa
  334. end else begin //tamño no implementado
  335. msjErr := 'Enumerated type no handled.';
  336. exit;
  337. end;
  338. end else begin
  339. //busca el que está marcado
  340. for j:=0 to high(r.radButs) do begin
  341. if r.radButs[j].checked then begin
  342. //debe fijar el valor del enumerado
  343. if r.lVar = 4 then begin //se puede manejar como entero
  344. r.AsInt32 := j; //guarda
  345. break;
  346. end else begin //tamaño no implementado
  347. msjErr := 'Enumerated type no handled.';
  348. exit;
  349. end;
  350. end;
  351. end;
  352. end;
  353. tp_Enum_TRadGroup:
  354. if PropToWindow then begin
  355. if r.lVar = 4 then begin //enumerado de 4 bytes
  356. n := r.AsInt32; //convierte a entero
  357. if n<TRadioGroup(r.pCtl).Items.Count then
  358. TRadioGroup(r.pCtl).ItemIndex:=n; //activa
  359. end else begin //tamño no implementado
  360. msjErr := 'Enumerated type no handled.';
  361. exit;
  362. end;
  363. end else begin
  364. //debe fijar el valor del enumerado
  365. if r.lVar = 4 then begin //se puede manejar como entero
  366. r.AsInt32 := TRadioGroup(r.pCtl).ItemIndex; //lee
  367. end else begin //tamaño no implementado
  368. msjErr := 'Enumerated type no handled.';
  369. exit;
  370. end;
  371. end;
  372. //---------------------------------------------------------------------
  373. tp_TCol_TColBut:
  374. if PropToWindow then begin //Tcolor a TColorButton
  375. TColorButton(r.pCtl).ButtonColor := r.AsTColor;
  376. end else begin
  377. r.AsTColor := TColorButton(r.pCtl).ButtonColor;
  378. end;
  379. tp_TCol_TColBox:
  380. if PropToWindow then begin //Tcolor a TColorButton
  381. TColorBox(r.pCtl).Selected := r.AsTColor;
  382. end else begin
  383. r.AsTColor := TColorBox(r.pCtl).Selected;
  384. end;
  385. //---------------------------------------------------------------------
  386. tp_StrList:; //no tiene control asociado
  387. tp_StrList_TListBox:
  388. if PropToWindow then begin //lista en TlistBox
  389. //carga lista
  390. list := TStringList(r.Pvar^);
  391. TListBox(r.pCtl).Clear;
  392. for j:=0 to list.Count-1 do
  393. TListBox(r.pCtl).AddItem(list[j],nil);
  394. end else begin
  395. list := TStringList(r.Pvar^);
  396. list.Clear;
  397. for j:= 0 to TListBox(r.pCtl).Count-1 do
  398. list.Add(TListBox(r.pCtl).Items[j]);
  399. end;
  400. tp_StrList_TStringGrid:
  401. if PropToWindow then begin //lista en TStringGrid
  402. //carga lista
  403. list := TStringList(r.Pvar^);
  404. gr := TStringGrid(r.pCtl);
  405. gr.Clear;
  406. gr.BeginUpdate;
  407. if r.HasFixedCol then gr.FixedCols:=1 else gr.FixedCols:=0;
  408. gr.ColCount:=r.ColCount; //fija número de columnas
  409. if r.HasHeader then begin
  410. //Hay encabezado
  411. gr.RowCount:=list.Count+1; //deja espacio para encabezado
  412. for j:=0 to list.Count-1 do begin
  413. gr.Cells[0,j+1] := list[j];
  414. end;
  415. end else begin
  416. //No hay encabezado
  417. gr.RowCount:=list.Count;
  418. for j:=0 to list.Count-1 do begin
  419. gr.Cells[0,j] := list[j];
  420. end;
  421. end;
  422. gr.EndUpdate();
  423. end else begin
  424. //????????
  425. end;
  426. else //no se ha implementado bien
  427. msjErr := 'Design error.';
  428. exit;
  429. end;
  430. end;
  431. function TMiConfigBasic.PropertiesToWindow: boolean;
  432. {Muestra en los controles, las variables asociadas
  433. Si encuentra error devuelve FALSE, y el mensaje de error en "MsjErr", y el elemento
  434. con error en "ctlErr".}
  435. var
  436. r: TParElem;
  437. begin
  438. msjErr := '';
  439. for r in listParElem do begin
  440. PropertyWindow(r, true);
  441. if msjErr<>'' then begin
  442. ctlErr := r; //guarda la referencia al elemento, en caso de que haya error
  443. end;
  444. if r.OnPropertyToWindow<>nil then r.OnPropertyToWindow;
  445. end;
  446. Result := (msjErr='');
  447. end;
  448. function TMiConfigBasic.WindowToProperties: boolean;
  449. {Lee en las variables asociadas, los valores de los controles
  450. Si encuentra error devuelve FALSE, y el mensaje de error en "MsjErr", y el elemento
  451. con error en "ctlErr".}
  452. var
  453. r: TParElem;
  454. begin
  455. msjErr := '';
  456. for r in listParElem do begin
  457. PropertyWindow(r, false);
  458. if msjErr<>'' then begin
  459. ctlErr := r; //guarda la referencia al elemento, en caso de que haya error
  460. end;
  461. if r.OnWindowToProperty<>nil then r.OnWindowToProperty;
  462. end;
  463. //Terminó con éxito. Actualiza los cambios
  464. if OnPropertiesChanges<>nil then OnPropertiesChanges;
  465. Result := (msjErr=''); //si hubo error, se habrá actualizado "ctlErr"
  466. end;
  467. procedure TMiConfigBasic.SetFocusEd(ed: TEdit);
  468. {Pone el enfoque en un TEdit, si es posible.}
  469. begin
  470. try
  471. if ed.visible and ed.enabled and ed.CanFocus then begin //Valida condiciones.
  472. ed.SetFocus; //Pone enfoque.
  473. end;
  474. //Ya si todo falla, solo confiamos en el "try"
  475. finally
  476. end;
  477. end;
  478. //Rutinas de validación
  479. function TMiConfigBasic.EditValidateInt(edit: TEdit; min: integer; max: integer): boolean;
  480. {Valida el contenido de un TEdit, para ver si se puede convertir a un valor entero.
  481. Si no se puede convertir, devuelve FALSE, devuelve el mensaje de error en "MsjErr", y
  482. pone el TEdit con enfoque.
  483. Si se puede convertir, devuelve TRUE, y el valor convertido en "valInt".}
  484. var
  485. tmp : string;
  486. c : char;
  487. signo: string;
  488. larMaxInt: Integer;
  489. n: Int64;
  490. begin
  491. Result := false;
  492. //validaciones previas
  493. larMaxInt := length(IntToStr(MaxInt));
  494. tmp := trim(edit.Text);
  495. if tmp = '' then begin
  496. MsjErr:= 'Field must contain a value.';
  497. SetFocusEd(edit);
  498. exit;
  499. end;
  500. if tmp[1] = '-' then begin //es negativo
  501. signo := '-'; //guarda signo
  502. tmp := copy(tmp, 2, length(tmp)); //quita signo
  503. end;
  504. for c in tmp do begin
  505. if not (c in ['0'..'9']) then begin
  506. MsjErr:= 'Only numeric values are allowed.';
  507. SetFocusEd(edit);
  508. exit;
  509. end;
  510. end;
  511. if length(tmp) > larMaxInt then begin
  512. MsjErr:= 'Numeric value is too large.';
  513. SetFocusEd(edit);
  514. exit;
  515. end;
  516. //lo leemos en Int64 por seguridad y validamos
  517. n := StrToInt64(signo + tmp);
  518. if n>max then begin
  519. MsjErr:= Format('The maximun allowed value is: %d', [max]);
  520. SetFocusEd(edit);
  521. exit;
  522. end;
  523. if n<min then begin
  524. MsjErr:= Format('The minimun allowed value is: %d', [min]);
  525. SetFocusEd(edit);
  526. exit;
  527. end;
  528. //pasó las validaciones
  529. valInt:=n; //actualiza valor
  530. Result := true; //tuvo éxito
  531. end;
  532. function TMiConfigBasic.EditValidateDbl(edit: TEdit; min: Double; max: Double): boolean;
  533. {Valida el contenido de un TEdit, para ver si se puede convertir a un valor Double.
  534. Si no se puede convertir, devuelve FALSE, devuelve el mensaje de error en "MsjErr", y
  535. pone el TEdit con enfoque.
  536. Si se puede convertir, devuelve TRUE, y el valor convertido en "valDbl".}
  537. var
  538. d: double;
  539. begin
  540. Result := false;
  541. //intenta convertir
  542. if not TryStrToFloat(edit.Text, d) then begin
  543. MsjErr:= 'Wrong float number.';
  544. SetFocusEd(edit);
  545. exit;
  546. end;
  547. //validamos
  548. if d>max then begin
  549. MsjErr:= Format('The maximun allowed value is: %f', [max]);
  550. SetFocusEd(edit);
  551. exit;
  552. end;
  553. if d<min then begin
  554. MsjErr:= Format('The minimun allowed value is: %f', [min]);
  555. SetFocusEd(edit);
  556. exit;
  557. end;
  558. //pasó las validaciones
  559. valDbl:=d; //actualiza valor
  560. Result := true; //tuvo éxito
  561. end;
  562. //Métodos de asociación
  563. function TMiConfigBasic.Asoc_Int(etiq: string; ptrInt: pointer; defVal: integer
  564. ): TParElem;
  565. //Agrega una variable Entera para guardarla en el archivo.
  566. var
  567. r: TParElem;
  568. begin
  569. r := TParElem.Create;
  570. r.pVar := ptrInt; //toma referencia
  571. r.tipPar := tp_Int; //tipo de par
  572. r.etiqVar:= etiq;
  573. r.defInt := defVal;
  574. listParElem.Add(r);
  575. Result := r;
  576. end;
  577. function TMiConfigBasic.Asoc_Int(etiq: string; ptrInt: pointer; edit: TEdit;
  578. defVal: integer; minVal, maxVal: integer): TParElem;
  579. //Agrega un par variable entera - Control TEdit
  580. begin
  581. Result := Asoc_Int(etiq, ptrInt, defVal);
  582. Result.pCtl := edit; //toma referencia
  583. Result.tipPar := tp_Int_TEdit; //tipo de par
  584. Result.minEnt := minVal; //protección de rango
  585. Result.maxEnt := maxVal; //protección de rango
  586. end;
  587. function TMiConfigBasic.Asoc_Int(etiq: string; ptrInt: pointer;
  588. spEdit: TSpinEdit; defVal: integer): TParElem;
  589. //Agrega un par variable entera - Control TSpinEdit
  590. begin
  591. Result := Asoc_Int(etiq, ptrInt, defVal);
  592. Result.pCtl := spEdit; //toma referencia
  593. Result.tipPar := tp_Int_TSpinEdit; //tipo de par
  594. end;
  595. function TMiConfigBasic.Asoc_Int(etiq: string; ptrInt: pointer;
  596. radGroup: TRadioGroup; defVal: integer): TParElem;
  597. //Agrega un par variable entera - Control TRadioGroup
  598. begin
  599. Result := Asoc_Int(etiq, ptrInt, defVal);
  600. Result.pCtl := radGroup; //toma referencia
  601. Result.tipPar := tp_Int_TRadioGroup; //tipo de par
  602. end;
  603. //---------------------------------------------------------------------
  604. function TMiConfigBasic.Asoc_Dbl(etiq: string; ptrDbl: PDouble; defVal: double
  605. ): TParElem;
  606. var
  607. r: TParElem;
  608. begin
  609. r := TParElem.Create;
  610. r.pVar := ptrDbl; //toma referencia
  611. r.tipPar := tp_Dbl; //tipo de par
  612. r.etiqVar:= etiq;
  613. r.defDbl := defVal;
  614. listParElem.Add(r);
  615. Result := r;
  616. end;
  617. function TMiConfigBasic.Asoc_Dbl(etiq: string; ptrDbl: PDouble; edit: TEdit;
  618. defVal: double; minVal, maxVal: double): TParElem;
  619. //Agrega un par variable double - Control TEdit
  620. begin
  621. Result := Asoc_Dbl(etiq, ptrDbl, defVal);
  622. Result.pCtl := edit; //toma referencia
  623. Result.tipPar := tp_Dbl_TEdit; //tipo de par
  624. Result.minDbl := minVal; //protección de rango
  625. Result.maxDbl := maxVal; //protección de rango
  626. end;
  627. function TMiConfigBasic.Asoc_Dbl(etiq: string; ptrDbl: PDouble;
  628. spEdit: TFloatSpinEdit; defVal: double): TParElem;
  629. begin
  630. Result := Asoc_Dbl(etiq, ptrDbl, defVal);
  631. Result.pCtl := spEdit; //toma referencia
  632. Result.tipPar := tp_Dbl_TFloatSpinEdit; //tipo de par
  633. end;
  634. //---------------------------------------------------------------------
  635. function TMiConfigBasic.Asoc_Str(etiq: string; ptrStr: pointer; defVal: string
  636. ): TParElem;
  637. //Agrega una variable String para guardarla en el archivo.
  638. var
  639. r: TParElem;
  640. begin
  641. r := TParElem.Create;
  642. r.pVar := ptrStr; //toma referencia
  643. r.tipPar := tp_Str; //tipo de par
  644. r.etiqVar:= etiq;
  645. r.defStr := defVal;
  646. listParElem.Add(r);
  647. Result := r;
  648. end;
  649. function TMiConfigBasic.Asoc_Str(etiq: string; ptrStr: pointer;
  650. edit: TCustomEdit; defVal: string): TParElem;
  651. //Agrega un par variable string - Control TEdit
  652. begin
  653. Result := Asoc_Str(etiq, ptrStr, defVal);
  654. Result.pCtl := edit; //toma referencia
  655. Result.tipPar := tp_Str_TEdit; //tipo de par
  656. end;
  657. function TMiConfigBasic.Asoc_Str(etiq: string; ptrStr: pointer;
  658. edit: TCustomEditButton; defVal: string): TParElem;
  659. //Agrega un par variable string - Control TEditButton
  660. begin
  661. Result := Asoc_Str(etiq, ptrStr, defVal);
  662. Result.pCtl := edit; //toma referencia
  663. Result.tipPar := tp_Str_TEditButton; //tipo de par
  664. end;
  665. function TMiConfigBasic.Asoc_Str(etiq: string; ptrStr: pointer;
  666. cmbBox: TComboBox; defVal: string): TParElem;
  667. //Agrega un par variable string - Control TEdit
  668. begin
  669. Result := Asoc_Str(etiq, ptrStr, defVal);
  670. Result.pCtl := cmbBox; //toma referencia
  671. Result.tipPar := tp_Str_TCmbBox; //tipo de par
  672. end;
  673. //---------------------------------------------------------------------
  674. function TMiConfigBasic.Asoc_Bol(etiq: string; ptrBol: pointer; defVal: boolean
  675. ): TParElem;
  676. var
  677. r: TParElem;
  678. begin
  679. r := TParElem.Create;
  680. r.pVar := ptrBol; //toma referencia
  681. r.tipPar := tp_Bol; //tipo de par
  682. r.etiqVar:= etiq;
  683. r.defBol := defVal;
  684. listParElem.Add(r);
  685. Result := r;
  686. end;
  687. function TMiConfigBasic.Asoc_Bol(etiq: string; ptrBol: pointer; chk: TCheckBox;
  688. defVal: boolean): TParElem;
  689. //Agrega un para variable booleana - Control TCheckBox
  690. begin
  691. Result := Asoc_Bol(etiq, ptrBol, defVal);
  692. Result.pCtl := chk; //toma referencia
  693. Result.tipPar := tp_Bol_TCheckBox; //tipo de par
  694. end;
  695. function TMiConfigBasic.Asoc_Bol(etiq: string; ptrBol: pointer;
  696. radButs: array of TRadioButton; defVal: boolean): TParElem;
  697. //Agrega un par variable Enumerated - Controles TRadioButton
  698. //Solo se permiten enumerados de hasta 32 bits de tamaño
  699. var
  700. i: Integer;
  701. begin
  702. Result := Asoc_Bol(etiq, ptrBol, defVal);
  703. // Result.pCtl := ; //toma referencia
  704. Result.tipPar := tp_Bol_TRadBut; //tipo de par
  705. //guarda lista de controles
  706. setlength(Result.radButs, high(radButs)+1); //hace espacio
  707. for i:=0 to high(radButs) do
  708. Result.radButs[i]:= radButs[i];
  709. end;
  710. //---------------------------------------------------------------------
  711. function TMiConfigBasic.Asoc_Enum(etiq: string; ptrEnum: pointer;
  712. EnumSize: integer; defVal: integer): TParElem;
  713. var
  714. r: TParElem;
  715. begin
  716. r := TParElem.Create;
  717. r.pVar := ptrEnum; //toma referencia
  718. r.lVar := EnumSize; //necesita el tamaño para modificarlo luego
  719. r.tipPar := tp_Enum; //tipo de par
  720. r.etiqVar:= etiq;
  721. r.defInt := defVal; //se maneja como entero
  722. listParElem.Add(r);
  723. Result := r;
  724. end;
  725. function TMiConfigBasic.Asoc_Enum(etiq: string; ptrEnum: pointer;
  726. EnumSize: integer; radButs: array of TRadioButton; defVal: integer): TParElem;
  727. //Agrega un par variable Enumerated - Controles TRadioButton
  728. //Solo se permiten enumerados de hasta 32 bits de tamaño
  729. var
  730. i: Integer;
  731. begin
  732. Result := Asoc_Enum(etiq, ptrEnum, EnumSize, defVal);
  733. // Result.pCtl := ; //toma referencia
  734. Result.tipPar := tp_Enum_TRadBut; //tipo de par
  735. //guarda lista de controles
  736. setlength(Result.radButs, high(radButs)+1); //hace espacio
  737. for i:=0 to high(radButs) do
  738. Result.radButs[i]:= radButs[i];
  739. end;
  740. function TMiConfigBasic.Asoc_Enum(etiq: string; ptrEnum: pointer; EnumSize: integer;
  741. radGroup: TRadioGroup; defVal: integer): TParElem;
  742. //Agrega un par variable Enumerated - Control TRadioGroup
  743. //Solo se permiten enumerados de hasta 32 bits de tamaño
  744. begin
  745. Result := Asoc_Enum(etiq, ptrEnum, EnumSize, defVal);
  746. Result.pCtl := radGroup; //toma referencia a control
  747. Result.tipPar := tp_Enum_TRadGroup; //tipo de par
  748. end;
  749. //---------------------------------------------------------------------
  750. function TMiConfigBasic.Asoc_TCol(etiq: string; ptrTCol: pointer;
  751. colBut: TColorButton; defVal: TColor): TParElem;
  752. //Agrega un par variable TColor - Control TColorButton
  753. var
  754. r: TParElem;
  755. begin
  756. r := TParElem.Create;
  757. r.pVar := ptrTCol; //toma referencia
  758. r.pCtl := colBut; //toma referencia a control
  759. r.tipPar := tp_TCol_TColBut; //tipo de par
  760. r.etiqVar:= etiq;
  761. r.defCol := defVal;
  762. listParElem.Add(r);
  763. Result := r;
  764. end;
  765. function TMiConfigBasic.Asoc_TCol(etiq: string; ptrTCol: pointer; colBut: TColorBox;
  766. defVal: TColor): TParElem;
  767. //Agrega un par variable TColor - Control TColorButton
  768. var
  769. r: TParElem;
  770. begin
  771. r := TParElem.Create;
  772. r.pVar := ptrTCol; //toma referencia
  773. r.pCtl := colBut; //toma referencia a control
  774. r.tipPar := tp_TCol_TColBox; //tipo de par
  775. r.etiqVar:= etiq;
  776. r.defCol := defVal;
  777. listParElem.Add(r);
  778. Result := r;
  779. end;
  780. //---------------------------------------------------------------------
  781. function TMiConfigBasic.Asoc_StrList(etiq: string; ptrStrList: pointer
  782. ): TParElem;
  783. //Agrega una variable TStringList para guardarla en el archivo. El StrinList, debe estar
  784. //ya creado, sino dará error.
  785. var
  786. r: TParElem;
  787. begin
  788. r := TParElem.Create;
  789. r.pVar := ptrStrList; //toma referencia
  790. // r.pCtl := colBut; //toma referencia
  791. r.tipPar := tp_StrList; //tipo de par
  792. r.etiqVar:= etiq;
  793. // r.defCol := defVal;
  794. listParElem.Add(r);
  795. Result := r;
  796. end;
  797. function TMiConfigBasic.Asoc_StrList_TListBox(etiq: string;
  798. ptrStrList: pointer; lstBox: TlistBox): TParElem;
  799. var
  800. r: TParElem;
  801. begin
  802. r := TParElem.Create;
  803. r.pVar := ptrStrList; //toma referencia
  804. r.pCtl := lstBox; //toma referencia
  805. r.tipPar := tp_StrList_TlistBox; //tipo de par
  806. r.etiqVar:= etiq;
  807. // r.defCol := defVal;
  808. listParElem.Add(r);
  809. Result := r;
  810. end;
  811. constructor TMiConfigBasic.Create;
  812. begin
  813. listParElem := TParElem_list.Create(true);
  814. end;
  815. destructor TMiConfigBasic.Destroy;
  816. begin
  817. listParElem.Destroy;
  818. inherited Destroy;
  819. end;
  820. end.