Unit Unit1;
//
// Sujet : Position des icônes sur le bureau
//
// Par Nono40 : http://nono40.developpez.com http://nono40.fr.st
// mailTo:nono40@fr.st
//
// Le 18/05/2003
//
Interface
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Spin, StdCtrls;
Type
TForm1 = Class(TForm)
Button1: TButton;
Button2: TButton;
Liste: TListBox;
SpinX: TSpinEdit;
SpinY: TSpinEdit;
Label1: TLabel;
Label2: TLabel;
Procedure Button1Click(Sender: TObject);
Procedure ListeClick(Sender: TObject);
Procedure Button2Click(Sender: TObject);
Private
{ Déclarations privées }
Public
{ Déclarations publiques }
End;
Var
Form1: TForm1;
Implementation
{$R *.dfm}
Const
// Définition des messages Windows pour les TListView
LVM_FIRST =$1000;
LVM_GETITEMCOUNT = LVM_FIRST+4;
LVM_GETITEM = LVM_FIRST+5;
LVM_SETITEM = LVM_FIRST+6;
LVM_SETITEMPOSITION = LVM_FIRST+15;
LVM_GETITEMPOSITION = LVM_FIRST+16;
LVM_SETITEMPOSITION32 = LVM_FIRST+49;
// Définition des constante de masque des champs de TLV_ITEM
LVIF_TEXT = $0001;
LVIF_IMAGE = $0002;
LVIF_PARAM = $0004;
LVIF_STATE = $0008;
LVIF_INDENT = $0010;
LVIF_GROUPID = $0100;
LVIF_COLUMNS = $0200;
LVIF_NORECOMPUTE = $0800;
LVIF_DI_SETITEM = $1000;
Type
// Type utilisé pour les messages Windows sur les items d'un TListView
TLV_ITEM = Record
mask : Cardinal;
iItem : Integer;
iSubItem : Integer;
state : Cardinal;
stateMask : Cardinal;
pszText : Pointer;
cchTextMax : Integer;
iImage : Integer;
_lParam : LPARAM;
End;
// Définition d'unestructure pouvant contenir tout ce qui est utile
// sur un Item. C'est ce type de structure qui est allouée en partage
// sous Win9x ou allouée dans la mémoire de EXPLORER.EXE dans le cas
// de WinNT.
PDatas = ^TDatas;
TDatas = Record
LV_ITEM : TLV_ITEM;
LV_TEXTE : Array[0..255] Of Char;
LV_POS : TPoint;
End;
// Définition des prototype d'allocation étendue.
// Les liens sont ici dynamiques afin de ne pas faire d'erreur
// dans les applications Win9x
TVirtualAllocEx = Function (hProcess : THandle;
lpAddress : Pointer; dwSize, flAllocationType : DWORD;
flProtect : DWORD) : Pointer; stdcall;
TVirtualFreeEx = Function (hProcess : THandle;
lpAddress : Pointer; dwSize, dwFreeType : DWORD) : Pointer;
stdcall;
Const
TailleMap=SizeOf(TDatas);
Var
HandleMAP :THandle; // Handle du mapping pour les système Win9x
HandleLV :THandle; // Handle de la ListView contenant les icône
ProcessLV :Cardinal; // Handle du process propriétaire de la ListView
DatasLV :PDatas; // Pointeur sur la mémoire allouée
Datas :TDatas; // Données locales sur l'item
WindowsNT :Boolean;
VirtualAllocEx :TVirtualAllocEx;
VirtualFreeEx :TVirtualFreeEx;
// Procédure de copie de la mémoire allouée dans le process
// ou le memory-mapping vers la mémoire locale
Procedure LecturePartage;
Var N:Cardinal;
Begin
If WindowsNT
Then ReadProcessMemory(ProcessLV, DatasLV, @Datas, SizeOf(Datas), N)
Else Datas:=DatasLV^;
End;
// Procédure de copie de la mémoire locale vers la mémoire allouée
// dans le process ou le memory-mapping
Procedure EcriturePartage;
Var N:Cardinal;
Begin
If WindowsNT
Then WriteProcessMemory(ProcessLV, DatasLV, @Datas, SizeOf(Datas), N)
Else DatasLV^:=Datas;
End;
// Allocation de la mémoire pour les échanges des données sur les items
// Win9x : création d'un MemoryMapping
// WinNT : allocation dans la mémoire de Explorer.exe
Procedure CreationPartage;
Var ProcessID :Cardinal;
Begin
If WindowsNT
Then Begin
// Obtention de l'identificateur de process de la ListView
GetWindowThreadProcessId(HandleLV,ProcessID);
// Obtention d'un Handle de process à partir de l'identificateur
ProcessLV := OpenProcess(PROCESS_ALL_ACCESS,False,ProcessID);
// Allocation d'une zone dans le Process obtenu
DatasLV := VirtualAllocEx(ProcessLV
, Nil
, TailleMAP
, MEM_COMMIT
, PAGE_READWRITE);
End
Else Begin
// Création d'un mapping mémoire
HandleMAP:=CreateFileMapping(
$FFFFFFFF // Handle mémoire
,Nil // Sécurité par défaut
,PAGE_READWRITE // Accès en lecture/écriture
,0 // Taille de la zone partagée HIGH
,TailleMAP // Taille de la zone partagée LOW
,'LISTVIEWINFO'); // Nom du partage
DatasLV:=MapViewOfFile(
HandleMAP // Handle du partage mémoire
,FILE_MAP_WRITE // Accès en lecture/écriture
,0 // Début de la zone HIGH
,0 // Début de la zone LOW
,0); // Zone entière
End;
// L'adresse contenu dans pszText est mise à jour en fonction
// de l'adresse du membre LV_TEXTE
Datas.LV_ITEM.pszText := @(DatasLV^.LV_TEXTE);
Datas.LV_ITEM.cchTextMax := SizeOf(Datas.LV_TEXTE);
EcriturePartage;
End;
// Libération de ce qui à été alloué précédemment
Procedure FinPartage;
Begin
If WindowsNT
Then Begin
VirtualFreeEx(ProcessLV, DatasLV, 0, MEM_RELEASE);
End
Else Begin
UnMapViewOfFile(DatasLV);
CloseHandle (HandleMAP);
End;
End;
// Mise à jour de la liste des icônes
Procedure TForm1.Button1Click(Sender: TObject);
Var i:Integer;
Begin
Liste.Clear;
// Pour chaque icône, il faut en demander les infos
For i:=0 To SendMessage(HandleLV,LVM_GETITEMCOUNT,0,0)-1 Do
Begin
// Seule le champ pszText doit être rempli
Datas.LV_ITEM.mask := LVIF_TEXT;
// et ceci pour l'item numéro i
Datas.LV_ITEM.iItem := i;
// Ecriture dans la partage afin que Explorer puisse
// lire ce qui est demandé
EcriturePartage;
// Et on lui demande d'écrire les infos sur l'item
SendMessage(HandleLV,LVM_GETITEM,0,Integer(DatasLV));
// Puis on copie ces informations là ou on peut les lire
LecturePartage;
// Ajout du texte de l'icpône dans la liste
Liste.Items.Add(Datas.LV_TEXTE);
End;
End;
Procedure TForm1.ListeClick(Sender: TObject);
Begin
If Liste.ItemIndex>=0 Then
Begin
// Lors d'un click sur un item de la liste
// on demande la position de l'icône correspondante
SendMessage(HandleLV,LVM_GETITEMPOSITION
,Liste.ItemIndex,Integer(@DatasLV.LV_POS));
// Copie en local des info
LecturePartage;
// et affichage
SpinX.Value := Datas.LV_POS.X;
SpinY.Value := Datas.LV_POS.Y;
End;
End;
Procedure TForm1.Button2Click(Sender: TObject);
Begin
If Liste.ItemIndex>=0 Then
Begin
// demande de modification de la position
Datas.LV_POS.X := SpinX.Value;
Datas.LV_POS.Y := SpinY.Value;
// Il faut copier la position dans une zone
// accessible par Explorer.exe
EcriturePartage;
// Et ensuite lui demander de changer la position
SendMessage(HandleLV,LVM_SETITEMPOSITION32
,Liste.ItemIndex,Integer(@DatasLV.LV_POS));
End;
End;
Initialization
// Obtention du Handle de la ListView du bureau
HandleLV := FindWindowEx(GetDesktopWindow, 0, 'Progman' , Nil);
HandleLV := FindWindowEx(HandleLV , 0, 'SHELLDLL_DefView' , Nil);
HandleLV := FindWindowEx(HandleLV , 0, 'SysListView32' , Nil);
// Obtention des routines utilisées sous WinNT
WindowsNT:= Win32Platform = VER_PLATFORM_WIN32_NT;
If WindowsNT Then
Begin
@VirtualAllocEx := GetProcAddress(
GetModuleHandle('KERNEL32.DLL'),'VirtualAllocEx');
@VirtualFreeEx := GetProcAddress(
GetModuleHandle('KERNEL32.DLL'),'VirtualFreeEx');
End;
CreationPartage;
Finalization
FinPartage;
end.
|