Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 04-11-2004
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Y tampoco sé a qué te refieres con la hora del hwClock pero a fin de cuentas Windows toma la hora del hardware de la máquina. Quizá te refieras a algo como GetTickCount que te devuelve el número de milisegundos que han pasado desde que se inició el sistema, independientemente de si el usuario cambia o no la hora, con lo que puedes fabricarte tu propio "reloj" al iniciar el sistema para no tener que depender de la hora del sistema. La única limitante es que el TickCount se reinicia a cero después de 49.7 días de uso continuo.

// Saludos
Responder Con Cita
  #2  
Antiguo 05-11-2004
Nil Nil is offline
Registrado
 
Registrado: oct 2004
Posts: 8
Poder: 0
Nil Va por buen camino
Iconos de escritorio

Hola Roman, yo pensaba que la hora del relog de la bios era independiente de la hora de Windows, es posible que esté equivocado.

Lo que mas me urge es el tema de mover mediante código la posición de los iconos del escritorio.

Un saludo, y gracias por vuestro interés.
Responder Con Cita
  #3  
Antiguo 08-11-2004
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Nil
Lo que mas me urge es el tema de mover mediante código la posición de los iconos del escritorio.
Luego de una búsqueda en los grupos de noticias de Borland me he percatado de que esto es más difícil de lo que en principio hubiera pensado.

La situación es la siguiente:

Visualmente, el escritorio no es más que un ListView cuyo identificador puedes obtner fácilmente con:

Código Delphi [-]
function SysListView: HWnd;
begin
  Result := FindWindow('Progman', nil);
  Result := FindWindowEx(Result, 0, 'SHELLDLL_DefView', nil);
  Result := FindWindowEx(Result, 0, 'SysListView32', nil);
end;

con lo que en pricipio podrías mandarle el mensaje LVM_SETITEMPOSITION:

Código Delphi [-]
var
  ItemPos: TPoint;
 
begin
  ItemPos.X := 200;
  ItemPos.Y := 300;
 
  SendMessage(SysListView, LVM_SETITEMPOSITION, Index, Cardinal(@ItemPos));
end;

El problema es que ItemPos se localiza en el espacio de memoria asignado a tu aplicación y el ListView del escritorio espera los datos en su propio espacio de memoria. Dicho de otra forma, no puedes acceder a datos de la memoria de otra aplicación.

Para resolver esto he visto que usan varias técnicas dependiendo del sistema operativo. En Windows 9x parece que puedes usar Memory Mapped Files pero no en Windows NT (XP, 2000) en donde o bien usan una DLL o bien funciones especiales de la API para obtener memoria en el espacio de otra aplicación.

Michael Winters, en un hilo de los grupos de noticias de Borland, proporciona un ejemplo muy completo para interactuar con el ListView del escritorio.

La unidad que a continuación te pongo es una versión sumamente simplificada de su código que sirve únicamente para el caso de Windows NT (XP, 2000).

Código Delphi [-]
unit VMem;
 
interface
 
uses
  Windows, SysUtils;
 
type
  TVMemory = class
  private
    FProcess: Cardinal;
 
  public
    constructor Create(Pid: Cardinal);
    destructor Destroy; override;
    function AllocMem(Size: Cardinal): Pointer;
    procedure FreeMem(P: Pointer);
    procedure Read(Source: Pointer; var Dest; Size: Cardinal);
    procedure Write(const Source; Dest: Pointer; Size: Cardinal);
  end;
 
implementation
 
{ TVMemory }
constructor TVMemory.Create(Pid: Cardinal);
const
  Flags = PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE;
 
begin
  FProcess := OpenProcess(Flags, false, Pid);
  if FProcess = 0 then RaiseLastOSError;
end;
 
destructor TVMemory.Destroy;
begin
  CloseHandle(FProcess);
  inherited;
end;
 
function TVMemory.AllocMem(Size: Cardinal): Pointer;
begin
  Result := VirtualAllocEx(FProcess, nil, Size, MEM_COMMIT, PAGE_READWRITE);
end;
 
procedure TVMemory.FreeMem(P: Pointer);
begin
  VirtualFreeEx(FProcess, P, 0, MEM_RELEASE);
end;
 
procedure TVMemory.Write(const Source; Dest: Pointer; Size: Cardinal);
var
  BytesWritten: Cardinal;
 
begin
  if not WriteProcessMemory(FProcess, Dest, @Source, Size, BytesWritten) then
    RaiseLastOSError;
end;
 
procedure TVMemory.Read(Source: Pointer; var Dest; Size: Cardinal);
var
  BytesRead: Cardinal;
 
begin
  if not ReadProcessMemory(FProcess, Source, @Dest, Size, BytesRead) then
    RaiseLastOSError;
end;
 
end.

Para usarla tienes que crear una instancia de TVMemory pasándole el identificador del proceso de la aplicación que contiene al ListView:

Código Delphi [-]
var
  Pid: Cardinal;
 
begin
  GetWindowThreadProcessId(SysListView, @Result);
  VMemory := TVMemory.Create(Pid);
end;

Para establecer la posición de un icono harías algo así:

Código Delphi [-]
var
  ItemPos: TPoint;
  PItemPos: PPoint;
 
begin
  ItemPos.X := 200;
  ItemPos.Y := 300;
 
  PItemPos := VMemory.AllocMem(SizeOf(ItemPos));
  VMemory.Write(ItemPos, PItemPos, SizeOf(ItemPos));
  SendMessage(SysListView, LVM_SETITEMPOSITION, Index, Cardinal(PItemPos));
  VMemory.FreeMem(PItemPos);
end;

donde Index será el índice del icono que desees cambiar. Cómo obtienes este índice dependerá de cómo pretendas manipular los iconos pero quizá podrías obtener de entrada la posición e índice de todos ellos usando LVM_GETNEXTITEM y LVM_GETITEMPOSITION. Para el útlimo tendrías que usar VMemory con Read en lugar de Write.

// Saludos
Responder Con Cita
  #4  
Antiguo 09-11-2004
Nil Nil is offline
Registrado
 
Registrado: oct 2004
Posts: 8
Poder: 0
Nil Va por buen camino
Thumbs up

Hola Roman, una explicación magistral.

Muchas gracias lo probaré.

Un saludo.
Responder Con Cita
  #5  
Antiguo 22-10-2007
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 24
mlara Va por buen camino
De verdad que es excelente la explicación, pero me pregunto: cuando apago mi equipo todas las propiedades del ListView se almacenan en algún lugar del disco duro, en dónde? Y si sé cuál es el archivo no podría modificarlo de tal manera que al actualizar el escritorio se tomen los valores del archivo?

Como siempre, de antemano muchas gracias.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
  #6  
Antiguo 22-10-2007
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.025
Poder: 28
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Se me ocurren dos posibilidades, a saber:

1.- En un archivo oculto dentro del directorio que contiene los iconos, que en el caso del escritorio sería algo así como "C:/Documents and settings/<usuario>/desktop".

2.- En el registro de Windows: escondido en alguna parte de HKEY_CURRENT_USER o de HKEY_CURRENT_CONFIG.

Que conste que ni lo he comprobado, pero a mi me parece lo más lógico.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 14:06:07.


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
Copyright 1996-2007 Club Delphi