Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   ¿Cómo obtener información de un "bit set"? (https://www.clubdelphi.com/foros/showthread.php?t=77967)

dec 09-03-2012 12:04:19

¿Cómo obtener información de un "bit set"?
 
Hola a todos,

Tengo una pregunta para vosotros, a ver si podéis ayudarme, puesto que tengo ninguna o muy poca idea sobre cómo hacerlo en este caso. Se trata de que, siguiendo la ayuda de Turbo Power ShellShock, podemos leer lo siguiente

Cita:

Defines an event handler that is called when the amount of free space on a drive changes. The OnDriveSpaceChange event is fired when the amount of free space on a drive changes. Drives is a bit set that indicates which drives have changed. Bits 0 through 25 represent drives A: through Z:. If, for example, the free space on drive C: changes, Drive will be equal to 4. If the free space on both the C: and D: drives changed, Drive will be equal to 12. An OnFolderChange event also occurs when the drive space changes.
En efecto, el evento "OnDriveSpaceChange" existe y es utilizado en determinado componente, ahora bien, no tengo ni idea de cómo hacer para extraer la información de su argumento "Drive".

Dicho argumento es un "Cardinal", me parece recordar ahora mismo, y, en todo caso, no resulta complicado cuando contiene sólo una unidad: "If, for example, the free space on drive C: changes, Drive will be equal to 4.".

El problema me surge para el caso de que dicho argumento contenga más de una unidad. Por ejemplo, dice la ayuda: "If the free space on both the C: and D: drives changed, Drive will be equal to 12.".

De acuerdo, pero, ¿qué pasa si las unidades son distintas? Y, en cualquier caso, ¿cómo demonios hago para obtener del "Cardinal" las unidades? A ver si, por favor, puede alguien echarme una mano.

Si necesitáis más información, cualquiera que sea, no dudéis en decírmelo y yo trataré de proporcionárosla lo antes posible.

¡Muchísimas gracias de antemano a todos! :)

P.D. Dedico este tema a Casimiro. ;)

roman 09-03-2012 16:38:32

Cada bit corresponde a una potencia de dos: bit 0 a 2^0 = 1, bit 1 a 2^1 = 2, bit 2 a 2^2 = 4, bit 3 a 2^3 = 8, etc. Si quieres saber que pasa en específico con un bit (un drive) tienes que aislarlo operando el cardinal con AND y la potencia de 2 que corresponda:

Si C and 4 <> 0 quiere decir que el bit 2 está "prendido".

Me parece que en Delphi hay una clase TBits que facilita el uso de bits.

// Saludos

ecfisa 09-03-2012 16:58:48

Hola Dec.

Y si quisieras saber el valor de un bit en particular, o reccorrer el número para ver los valores de los diferentes bits:
Código Delphi [-]
function BitOn(const N:Cardinal; const bitN: Byte): Boolean;
begin
  Result:= N shr bitN and 1 = 1;
end;

Un saludo.

dec 09-03-2012 18:05:15

Hola,

Gracias por vuestras respuestas, aunque, no sé si podré yo sacar algo en limpio. En cuanto pueda haré pruebas y pondré aquí qué he hecho y preguntaré porqué no funciona. :D :D

¡Gracias a ambos! ;)

dec 09-03-2012 20:35:17

Hola,

Como funcionar... parece que funciona. Sin embargo, me queda la espinita de no saberme quitar de encima el "mapa de unidades" que conformo "directamente" y que creo que puede hacerse de otra forma más elegante. Por lo demás, lo mío, lamentablemente, no son las matemáticas, así que sigo son comprender muy bien qué ocurre a nivel de "bits", quizá algún día... sea como sea, el código podría quedar más o menos así, a modo de ejemplo:

Código Delphi [-]
procedure TForm2.StShellNotification1DriveSpaceChange(
 Sender: TObject; Drive: Cardinal);

const
  DRIVES : array[ 0..25 ] of char =
  (
    'A', 'B', 'C', 'D', 'E', 'F',
    'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R',
    'S', 'T', 'U', 'V', 'W', 'X',
    'Y', 'Z'
  );

var
  i : byte;
  s : string;

begin
  s := '';

  for i := Low( DRIVES ) to High( DRIVES ) do
  begin
    if Drive shr i and 1 = 1 then
    begin
      if s = '' then
        s := DRIVES[ i ]
      else
        s := s +' # '+ DRIVES[ i ];
    end;
  end;

  ShowMessage( 'Drive Space Change in : ' + s );
end;

Por supuesto, cualquier sugerencia será bienvenida. ;)

roman 09-03-2012 20:49:14

En realidad, el arreglo DRIVES te lo puedes ahorrar. A partir de I en la iteración puedes obtener la letra así:

Código Delphi [-]
Chr(I + Ord('A'))

// Saludos

dec 09-03-2012 21:02:17

Hola,

No entiendo, Román. ¿De dónde saco yo esa "A"?

marcoszorrilla 09-03-2012 21:26:07

Se trata del viejo truco de sumarle 65 al 0 que es la unidad A (ASCII), 1 + 65 = 66 =B etc.

Recuerdo que yo lo usaba en ensamblador.

Un Saludo.

dec 09-03-2012 21:50:19

Hola,

Ese truco no me le sabía yo, Marcos, se agradece. ;)

Aunque me parece a mí que Román no va por ahí... :rolleyes:

Entonces el código ya podría quedar, como poco, de esta manera:

Código Delphi [-]
for i := 0 to 25 do // From A to Z
begin
  if Drive shr i and 1 = 1 then
  begin
    if s = '' then
      s := Chr( Ord( i + TRICK_ASCII_NUMBER ) )
    else
      s := s +'#'+ Chr( Ord( i + TRICK_ASCII_NUMBER ) );
  end;
end;

Siendo "TRICK_ASCII_NUMBER" igual a 65. Prescindiendo ya del arreglo "DRIVES". ;)

ecfisa 09-03-2012 22:14:12

Hola Dec.

Creo que se puede reducir un poco mas:
Código Delphi [-]
begin
  for i:= 0 to 25 do
    if Drive shr i and 1 = 1 then
      s:= s + Chr(TRICK_ASCII_NUMBER + i) + '#';
  SetLength(s, Length(s)-1);
end;

Saludos.

dec 10-03-2012 00:32:45

Hola,

Muy chula esa ecfisa. Bueno, y la otra. Muchas gracias. ;)

roman 10-03-2012 01:19:27

Cita:

Empezado por dec (Mensaje 427270)
Siendo "TRICK_ASCII_NUMBER" igual a 65. Prescindiendo ya del arreglo "DRIVES". ;)

En un sentido excesivamente purista, no debes usar una constante para ese 65, sino, como puse, Ord('A'). No vaya a ser que algún día cambie el número asignado a la A ;).

// Saludos

dec 10-03-2012 02:01:36

Hola,

Hombre, Román, pero, como no me digas de dónde saco yo esa "A"... es que no me aclaro. ;)

Acaso esa constante no está del todo bien y llevas razón. Al fin y al cabo se trata de prescindir del arreglo, pero, ¿por qué, exactamente?... A mí es que se me ha metido en la cabeza porque intuyo (¡Cuidado!) otra forma de hacerlo (tal vez la que tú no dices... :D), pero, lo cierto es que el arreglo tampoco pide pan, como se suele decir. ¿No? Por lo demás, el viejo truco del joven Marcos sigue siendo un buen truco. :)

roman 10-03-2012 02:14:52

Cita:

Empezado por dec (Mensaje 427303)
(tal vez la que tú no dices... :D)

Hey! No hay nada escondido. Ya no había puesto nada porque tanto Marcos como ecfisa contestaron lo que yo pensaba :)

// Saludos

dec 10-03-2012 03:03:58

Cita:

Empezado por roman (Mensaje 427304)
Hey! No hay nada escondido. Ya no había puesto nada porque tanto Marcos como ecfisa contestaron lo que yo pensaba :)

// Saludos

Este Román es una esfinge para mí. ¡¿Serán así todos los matemáticos?! :D :D

ecfisa 10-03-2012 04:08:58

¿ Un código salomónico ?

Código Delphi [-]
const
   TRICK_ASCII_NUMBER = Ord('A');

:D:D:D

dec 10-03-2012 12:30:13

¡Buenas!

Hombre, ecfisa, ¡así es como se explican las cosas! :)

Nota mental: ir el alergólogo, que, algo sabrá de lo que me pase. :D

dec 10-03-2012 16:07:56

Hola,

Bueno. De nuevo muchas gracias a todos, puesto que el problema está resuelto, es decir, "funcionando". ;)

dec 10-03-2012 20:30:02

Cita:

Empezado por Román
¡Qué paciencia, señor!

:D :D :D :D :D


La franja horaria es GMT +2. Ahora son las 20:06:53.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi