PDA

Ver la Versión Completa : Iconos de escritorio


Nil
31-10-2004, 18:48:25
Hola a todos, dos preguntas :

1-. Me podrían indicar con que función puedo acceder a los iconos del escritorio y cambiarles la posición.

2-. Con que función puedo obtener la hora del hwClock.

Muchas gracias de antemano.

Nil
02-11-2004, 17:13:39
¿Alguien sabría decirme algo de esto?

Gracias.

Durbed
04-11-2004, 11:26:26
No se que es la hora HWclock, pero para obtener la hora puedes usar la funcion time.

Edit1.text := TimeToStr(time);


Y si quieres que la hora se actualize, tiemes que poner un control Timer y en el evento OnTimer (el unico que tienen) pones la linea anterior. Luego en la propiedad interval le indicas la frecuencia con la que quieres que ejecute el codigo (1seg = 1000 mseg)

Espero que te sirva (que me da que no). Respecto a los iconos no tengo ni idea.

Nil
04-11-2004, 17:06:08
Hola Durbed, gracias por responder, pero la solución que me das devuelve la hora de Windows, no la hora interna de la máquina, y si al usuario se le ocurre cambiarla, será una distinta a la real.

roman
04-11-2004, 17:43:30
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

Nil
05-11-2004, 22:31:05
:confused: 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.

roman
08-11-2004, 02:57:43
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:


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:


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 (http://groups.google.com.mx/groups?hl=es&lr=&threadm=3B13105A.6E15D8CF%40borland.newsgroups&rnum=1&prev=/groups%3Fhl%3Des%26lr%3D%26q%3DDesktop%2Bicons%26meta%3Dgroup%253Dborland.public.delphi.*) de los grupos de noticias de Borland, proporciona un ejemplo (http://home.foni.net/~winter/download/PrcMemMgrTest.zip) 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).


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:


var
Pid: Cardinal;

begin
GetWindowThreadProcessId(SysListView, @Result);
VMemory := TVMemory.Create(Pid);
end;


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


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

Nil
09-11-2004, 09:37:47
:p Hola Roman, una explicación magistral.

Muchas gracias lo probaré.

Un saludo.

mlara
22-10-2007, 17:22:50
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.

Ñuño Martínez
22-10-2007, 20:12:14
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.