Este componente permite para recuperar información diversa sobre los Discos existentes en el de sistema; Discos duros, diskettes, discos de red, discos RAM… Colóquelo en un formulario y defina la letra del disco.
Puede recuperar la información sobre:
- Volumem; Etiqueta, número…
- Serial number (no número de volumen)
- Espacio; Libre, total, ocupado.
- Icono del suistema
- Nombre en el Explorer y descripción
- Tipo de disco
- Sistema de ficheros
- Clusters, Sectores,…
- …

- Incluye código fuente
- Incluye EXE (demo)
Historial:
(version 1.2)
Corrected bug at retrive Serial number (not volume number) from various disks.
Descargar componente
(versión 1.1)
Este componente (en éste caso derivado de un TPanel) muestra cómo añadir a un componente una Cuadrícula o Grid similar a la que aparece en los formularios cuando los estamos diseñando desde el IDE de Delphi.
Se puede configurar en el componente el color y el espaciado entre puntos de la cuadrícula.
Basta con soltarlo en el formulario y activarlo.
- Incluye código fuente
- Incluye EXE (demo)
Descargar componente
Estos días he estado «trasteando» con Gesbit; De todo eso, además de conocimientos ha salido un tema nuevo que he subido a la web de Gesbit, por si a alguien más le gusta a parte de a mi (que ya se que viendo los colores va a ser difícil… ;-D )
Tema OrangeNight para Gesbit.
Uno más entre la lista de Temas y PlugIns que tiene este Gestor de Bitácoras, programado entéramente por David, gratuíto, ligero y de código libre.
Destacable por su rapidez y simplicidad. Ampliable mediante plugIns, y además con licencia Open Source.

(version 1.1)
Este componente permite definir un texto de ayuda en la parte interna del control de edición (TEdit).
El texto desaparace cuando el control contiene algun texto que el usuario ha introducido. Si el texto se borra vuelve a aparecer el texto de ayuda.
Se pueden definir el color que deseamos para el texto de la ayuda de forma independiente al color definido en la fuente (propiedad Font) del componente.

- Incluye código fuente
- Incluye EXE (demo)
Historial:
(Vers. 1.1)
Cambiada la propiedad InsideHelpColor por InsideHelpFont para permitir mayor flexibilidad (thanks Ariel Martín from Cuba).
Descargar componente
Ya están actualizados en la nueva web los trucos que tenía en la antigua; Tal vez las fechas y el orden no coincidan del todo, pero creo que es lo menos importante.
Están accesible por el Tag: Trucos o desde el acceso de la página principal donde hay creado un pequeño índice de todos los existentes.

Si detectáis algun error (que seguro los hay) os ruego que me lo comuniquéis.
Un saludo.
Pues eso. Que me he «liado la manta a la cabeza» (como se suele decir) y me he puesto a actualizar la Web.
La que tenía hasta ahora estaba hecha de forma «manual», y en su día me sirvió para aprender y practicar determinadas cosas (conceptos) de las cuales no tenía ni idea.
Actualmente la tenía un poco (mucho, porqué no decirlo) abandonada; No es que tenga mucho tiempo para actualizarla, pero además el modo en que estaba hecha no ayudaba, ya que el tiempo dedicado a realizar cambios era más elevado de lo deseable.
Esa es la razón por la que llevo un par de semanas probando cosas para poder actualizarla. Siempre pensando que a la larga me sea más fácil mantenerla. Por el camino he probado:
- Gesbit. El Gestor de bitácoras de David. El primero que probé y el más sencillo. Casi ningun problema para instalarlo (y los pocos debidos a mi torpeza). Finalmente lo hubiera instalado (incluído un tema «Orange» que creé mientras hacía las pruebas y que tengo pendiente subir a la web de Gebit), pero incompatibilidades con el Hosting actual, me hicieron desistir.
- Joomla. Esta fue mi segunda opción. La verdad es que salvo un pequeño problema en la instalación, esta fue sencilla. Mi primera impresión de Joomla y la que finalmente me ha quedado, es que es un sistema completísimo, pero también complejo. Esto de «complejo» hay que verlo desde mi punto de vista. Es decir, el de una persona que sabe poco de Web, que nunca ha instalado un CMS o similar y que lo hice sin mirar manual. Guiándome por la intuición. LLegué a instalarlo y a hacerlo funcionar; Pero su administración me sigue pareciendo «engorrosa/compleja/liosa» y poco clara.

- WordPress. Esta fue la definitiva. La instalación al igual que las otras, sencilla (muy sencilla en este caso). Y su utilización y administración es realmente intuitiva. Así que esta ha sido mi selección.

Posiblemente ahora la mayoría de opciones de la web no funcionen, pero espero poco a poco ir poniendola «al día» de paso que me voy enterando de cómo funciona. ;-D
Para los que leáis esta primera entrada y tengáis configurados los Feeds(RSS) a mi anterior página podéis ir actualizándolos al nuevo link.
./?feed=rss2
Un saludo.
Utilizando ADO se puede acceder a casi toda la información de la Base de Datos, Tablas y Columnas, pero no a toda. En el caso de las Bases de datos de Access, por ejemplo, la propiedad descripción, que utilizamos para añadir un texto descriptivo a las columnas de las tablas, no es accesible.
Para obtenerla, hace falta acceder directamente a la información del «catálogo» utiliando ADOX. Para poder utilizar ADOX, lo primero que debemos hacer es importar la librería a en Delphi;
Esto se puede hacer desde el menú de: Proyect/Import Type Library.
La librería en concreto es la llamada «Microsoft ADO Ext. for DDL and Security» y proceso paso a paso, podéis verlo es esta página de Zarko Gajic.
Una vez importada la librería, basta con abrir la Base de Datos, acceder a una tabla y a un columna; A partir de ahí ya tenemos todos los datos(propiedades) referentes a esa columna.
El código es sencillo (basta con tener un formulario con un memo (Memo1) y un botón (button1)):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| procedure TForm1.Button2Click(Sender: TObject);
const
DB_CONNECTION='Provider=Microsoft.Jet.OLEDB.4.0;' +
'Data Source=%s';
DATABASENAME = 'c:\Archivos de ' +
'programa\Archivos comunes\Borland Shared\Data' +
'\dbdemos.mdb';
var
i, j:Integer;
Con:OleVariant;
fCatalog:Catalog;
Column: _Column;
Table:_Table;
Str1, Str2:string;
begin
// Limpiar la salida
Memo1.Lines.Clear;
// Conectar con la Base de Datos
Con := CreateOleObject('ADODB.Connection');
// Abrir
Con.Open(Format(DB_CONNECTION,[DATABASENAME]));
// proteccion
try
// Acceder a la Base de Datos
fCatalog := CoCatalog.Create;
fCatalog._Set_ActiveConnection(Con);
// Acceder a la tabla de empleados
Table := fCatalog.Tables['employee'];
// recorrer las columnas
for i := 0 to (Table.Columns.Count - 1) do begin
// Acceder a la columna
Column := Table.Columns[i];
// Datos de columna
Memo1.Lines.Add(' ');
Memo1.Lines.Add(Format('Columna: %s',[Column.Name]));
Memo1.Lines.Add('---------------------------------');
Memo1.Lines.Add(Format(' Tamaño: %d',[Column.DefinedSize]));
Memo1.Lines.Add(Format(' Precisión: %d',[Column.Precision]));
// recorrer las propiedades de la columna
for j := 0 to (Column.Properties.Count - 1) do begin
// Cada propiedad, Nombre y valor
Str1 := Column.Properties[j].Name;
Str2 := Column.Properties[j].Value;
// Saltamos las propiedades Jet...
if (Length(Str1) > 0) then begin
// Saltar las Jet
if (Str1[1] <> 'J') then begin
Memo1.Lines.Add(Format(' %s: %s',[Str1, Str2]))
end; //if
end; //if
end; // for
end; // for
finally
// Liberar y cerrar
Column := nil;
Table := nil;
fCatalog := nil;
Con.Close;
end;
end; |
procedure TForm1.Button2Click(Sender: TObject);
const
DB_CONNECTION='Provider=Microsoft.Jet.OLEDB.4.0;' +
'Data Source=%s';
DATABASENAME = 'c:\Archivos de ' +
'programa\Archivos comunes\Borland Shared\Data' +
'\dbdemos.mdb';
var
i, j:Integer;
Con:OleVariant;
fCatalog:Catalog;
Column: _Column;
Table:_Table;
Str1, Str2:string;
begin
// Limpiar la salida
Memo1.Lines.Clear;
// Conectar con la Base de Datos
Con := CreateOleObject('ADODB.Connection');
// Abrir
Con.Open(Format(DB_CONNECTION,[DATABASENAME]));
// proteccion
try
// Acceder a la Base de Datos
fCatalog := CoCatalog.Create;
fCatalog._Set_ActiveConnection(Con);
// Acceder a la tabla de empleados
Table := fCatalog.Tables['employee'];
// recorrer las columnas
for i := 0 to (Table.Columns.Count - 1) do begin
// Acceder a la columna
Column := Table.Columns[i];
// Datos de columna
Memo1.Lines.Add(' ');
Memo1.Lines.Add(Format('Columna: %s',[Column.Name]));
Memo1.Lines.Add('---------------------------------');
Memo1.Lines.Add(Format(' Tamaño: %d',[Column.DefinedSize]));
Memo1.Lines.Add(Format(' Precisión: %d',[Column.Precision]));
// recorrer las propiedades de la columna
for j := 0 to (Column.Properties.Count - 1) do begin
// Cada propiedad, Nombre y valor
Str1 := Column.Properties[j].Name;
Str2 := Column.Properties[j].Value;
// Saltamos las propiedades Jet...
if (Length(Str1) > 0) then begin
// Saltar las Jet
if (Str1[1] <> 'J') then begin
Memo1.Lines.Add(Format(' %s: %s',[Str1, Str2]))
end; //if
end; //if
end; // for
end; // for
finally
// Liberar y cerrar
Column := nil;
Table := nil;
fCatalog := nil;
Con.Close;
end;
end;
Procedimiento que muestra cómo ordenar un TStringGrid a partir de los datos de una columna. El texto está basado en esta página Web donde hay un algoritmo de ordenación. El problema es que sólo es para datos numéricos. En este truco he añadido un par de parámetros para poder definir columnas de otro tipo (u ordenación de otro tipo) y además marcar si que quiere de forma Ascendente o Descendente (que tampoco está en el truco original).
Yo he añadido métodos para ordenar por enteros y Float, aunque ampliando se pueden añadir para alguno más.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| // Ordena un TStringGrid.
procedure SortStringGrid(var GenStrGrid: TStringGrid;
ThatCol: Integer;
ColData:TGridData=gdString;
SortOrder:TSortOrder=soASC);
const
TheSeparator = '@';
var
CountItem, I, J, K, ThePosition: integer;
MyList: TStringList;
MyString, TempString: string;
str:string;
vali:Integer;
valf:Double;
begin
CountItem := GenStrGrid.RowCount;
MyList := TStringList.Create;
MyList.Sorted := False;
try
begin
for I := 1 to (CountItem - 1) do begin
Str := GenStrGrid.Rows[I].Strings[ThatCol];
if (ColData = gdInteger) then begin
vali := StrToIntDef(Str, 0);
Str := Format('%*d', [15,vali]);
end;
if (ColData = gdFloat) then begin
valf := StrToFloat(Str);
Str := Format('%15.2f',[valf]);
end;
MyList.Add(Str + TheSeparator + GenStrGrid.Rows[I].Text);
end;
Mylist.Sort;
for K := 1 to Mylist.Count do begin
MyString := MyList.Strings[(K - 1)];
ThePosition := Pos(TheSeparator, MyString);
TempString := '';
{Eliminate the Text of the column on which we have
sorted the StringGrid}
TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
MyList.Strings[(K - 1)] := '';
MyList.Strings[(K - 1)] := TempString;
end;
if (SortOrder = soASC) then begin
for J := 1 to (CountItem - 1) do begin
GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];
end;
end
else begin
for J := 1 to (CountItem - 1) do begin
I := (CountItem - J);
GenStrGrid.Rows[I].Text := MyList.Strings[(J - 1)];
end;
end;
end;
finally
MyList.Free;
end;
end; |
// Ordena un TStringGrid.
procedure SortStringGrid(var GenStrGrid: TStringGrid;
ThatCol: Integer;
ColData:TGridData=gdString;
SortOrder:TSortOrder=soASC);
const
TheSeparator = '@';
var
CountItem, I, J, K, ThePosition: integer;
MyList: TStringList;
MyString, TempString: string;
str:string;
vali:Integer;
valf:Double;
begin
CountItem := GenStrGrid.RowCount;
MyList := TStringList.Create;
MyList.Sorted := False;
try
begin
for I := 1 to (CountItem - 1) do begin
Str := GenStrGrid.Rows[I].Strings[ThatCol];
if (ColData = gdInteger) then begin
vali := StrToIntDef(Str, 0);
Str := Format('%*d', [15,vali]);
end;
if (ColData = gdFloat) then begin
valf := StrToFloat(Str);
Str := Format('%15.2f',[valf]);
end;
MyList.Add(Str + TheSeparator + GenStrGrid.Rows[I].Text);
end;
Mylist.Sort;
for K := 1 to Mylist.Count do begin
MyString := MyList.Strings[(K - 1)];
ThePosition := Pos(TheSeparator, MyString);
TempString := '';
{Eliminate the Text of the column on which we have
sorted the StringGrid}
TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
MyList.Strings[(K - 1)] := '';
MyList.Strings[(K - 1)] := TempString;
end;
if (SortOrder = soASC) then begin
for J := 1 to (CountItem - 1) do begin
GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];
end;
end
else begin
for J := 1 to (CountItem - 1) do begin
I := (CountItem - J);
GenStrGrid.Rows[I].Text := MyList.Strings[(J - 1)];
end;
end;
end;
finally
MyList.Free;
end;
end;
AÑADO: Me falta una cosa.
Además habrá que definir en la unit los dos tipos que se utilizan para la ordenación:
1
2
3
4
5
| Type
//: Tipo de Dat de la columna por la que queremos ordenar.
TGridData = (gdString, gdInteger, gdFloat);
//: Tipos de ordenación.
TSortOrder = (soASC, soDESC); |
Type
//: Tipo de Dat de la columna por la que queremos ordenar.
TGridData = (gdString, gdInteger, gdFloat);
//: Tipos de ordenación.
TSortOrder = (soASC, soDESC);
Función para buscar ficheros en un directorio de forma recursiva.
Devuelve una lista de nombres de fichero encontrados a partir de la carpeta inicial StartDir, que cumplen el patrón especificado por FileMask.
Mediante recursively se indica si se desea
hacer la busqueda en los subdirectorios.
El resultado se devuelve en FilesList (TStringList), que es la lista que se rellena con los nombres de fichero encontrados.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| {: Devuelve una lista de nombres de fichero encontrados a partir
de la carpeta inicial StartDir, que cumplen el patrón especificado
por FileMask.Mediante recursively se indica si se desea hacer la
busqueda en los subdirectorios.
StartDir Carpeta desde la que empezar a buscar.
FileMask Patrón que han de cumplir los ficheros.
Recursively Si hay que continuar la búsqueda en los subdirectorios.
FilesList Lista con los nombres de fichero encontrados.
}
procedure FindFiles(StartDir, FileMask: string;
recursively: boolean; var FilesList: TStringList);
const
MASK_ALL_FILES = '*.*';
CHAR_POINT = '.';
var
SR: TSearchRec;
DirList: TStringList;
IsFound: Boolean;
i: integer;
begin
if (StartDir[length(StartDir)] <> '\') then begin
StartDir := StartDir + '\';
end;
// Crear la lista de ficheos en el dir. StartDir (no directorios!)
IsFound := FindFirst(StartDir + FileMask,
faAnyFile - faDirectory, SR) = 0;
// MIentras encuentre
while IsFound do begin
FilesList.Add(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end;
FindClose(SR);
// Recursivo?
if (recursively) then begin
// Build a list of subdirectories
DirList := TStringList.Create;
// proteccion
try
IsFound := FindFirst(StartDir + MASK_ALL_FILES,
faAnyFile, SR) = 0;
while IsFound do begin
if ((SR.Attr and faDirectory) <> 0) and
(SR.Name[1] <> CHAR_POINT) then begin
DirList.Add(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end; // if
end; // while
FindClose(SR);
// Scan the list of subdirectories
for i := 0 to DirList.Count - 1 do begin
FindFiles(DirList[i], FileMask, recursively, FilesList);
end;
finally
DirList.Free;
end;
end;
end; |
{: Devuelve una lista de nombres de fichero encontrados a partir
de la carpeta inicial StartDir, que cumplen el patrón especificado
por FileMask.Mediante recursively se indica si se desea hacer la
busqueda en los subdirectorios.
StartDir Carpeta desde la que empezar a buscar.
FileMask Patrón que han de cumplir los ficheros.
Recursively Si hay que continuar la búsqueda en los subdirectorios.
FilesList Lista con los nombres de fichero encontrados.
}
procedure FindFiles(StartDir, FileMask: string;
recursively: boolean; var FilesList: TStringList);
const
MASK_ALL_FILES = '*.*';
CHAR_POINT = '.';
var
SR: TSearchRec;
DirList: TStringList;
IsFound: Boolean;
i: integer;
begin
if (StartDir[length(StartDir)] <> '\') then begin
StartDir := StartDir + '\';
end;
// Crear la lista de ficheos en el dir. StartDir (no directorios!)
IsFound := FindFirst(StartDir + FileMask,
faAnyFile - faDirectory, SR) = 0;
// MIentras encuentre
while IsFound do begin
FilesList.Add(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end;
FindClose(SR);
// Recursivo?
if (recursively) then begin
// Build a list of subdirectories
DirList := TStringList.Create;
// proteccion
try
IsFound := FindFirst(StartDir + MASK_ALL_FILES,
faAnyFile, SR) = 0;
while IsFound do begin
if ((SR.Attr and faDirectory) <> 0) and
(SR.Name[1] <> CHAR_POINT) then begin
DirList.Add(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end; // if
end; // while
FindClose(SR);
// Scan the list of subdirectories
for i := 0 to DirList.Count - 1 do begin
FindFiles(DirList[i], FileMask, recursively, FilesList);
end;
finally
DirList.Free;
end;
end;
end;
Muestra como utilizar un BITMAP (en este caso extraído de un TImage) para modificar el cursor activo. Modificando un poco el Tip/Truco es fácil obtener la imagen de disco o desde un recurso.
Se utiliza la API CreateIconIndirect para generar el cursor que posteriormente se activará.
Se puede usar un color de fondo como transparente para obtener un cursos «opaco» o un segundo BITMAP para combinarlo con el primero y así obtener también efectos de transparencia en el cursor generado.

// Crear los bitmaps
BitmapMask := TBitmap.Create;
Bitmap := TBitmap.Create;
// proteccion
try
// Cargar las imágenes
BitmapMask.Assign(Image2.Picture.Bitmap);
Bitmap.Assign(Image1.Picture.Bitmap);
// Crear el icono del cursor
with iconInfo do begin
fIcon := false;
xHotspot := (Bitmap.Width div 4);
yHotspot := (Bitmap.Height div 3);
hbmMask := BitmapMask.Handle;
hbmColor := Bitmap.Handle;
end;
// Asignar el icono
Screen.Cursors[1] := CreateIconIndirect(iconInfo);
Self.Cursor := 1;
finally
// Liberar
BitmapMask.Free;
Bitmap.Free;
end; |
// Crear los bitmaps
BitmapMask := TBitmap.Create;
Bitmap := TBitmap.Create;
// proteccion
try
// Cargar las imágenes
BitmapMask.Assign(Image2.Picture.Bitmap);
Bitmap.Assign(Image1.Picture.Bitmap);
// Crear el icono del cursor
with iconInfo do begin
fIcon := false;
xHotspot := (Bitmap.Width div 4);
yHotspot := (Bitmap.Height div 3);
hbmMask := BitmapMask.Handle;
hbmColor := Bitmap.Handle;
end;
// Asignar el icono
Screen.Cursors[1] := CreateIconIndirect(iconInfo);
Self.Cursor := 1;
finally
// Liberar
BitmapMask.Free;
Bitmap.Free;
end;
Es ejemplo completo se puede descargar <AQUÍ>.
Descargar.