unit
dipsdef;
interface
uses
Windows, CommCtrl;
const
RegSubKeyName =
'Software\LVT\Desktop Item Position Saver'
;
procedure
RestoreDesktopItemPositions;
procedure
SaveDesktopItemPositions;
implementation
uses
uvirtalloc, registry;
procedure
SaveListItemPosition(LVH : THandle; RemoteAddr :
Pointer
);
var
lvi : TLVITEM;
lenlvi :
integer
;
nb :
integer
;
buffer :
array
[
0..
MAX_PATH]
of
char
;
Base :
Pointer
;
Base2 : PByte;
i, ItemsCount :
integer
;
Apoint : TPoint;
key : HKEY;
Dummy :
integer
;
begin
ItemsCount := SendMessage(LVH, LVM_GETITEMCOUNT,
0
,
0
);
Base := RemoteAddr;
lenlvi := SizeOf(lvi);
FillChar(lvi, lenlvi,
0
);
lvi
.
cchTextMax :=
255
;
lvi
.
pszText := Base;
inc(lvi
.
pszText, lenlvi);
WriteToRemoteBuffer(@lvi, Base,
255
);
Base2 := Base;
inc(Base2, Lenlvi);
RegDeleteKey(HKEY_CURRENT_USER, RegSubKeyName);
RegCreateKeyEx(HKEY_CURRENT_USER,
PChar
(RegSUbKeyName),
0
,
nil
,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
nil
, key,
nil
);
for
i :=
0
to
ItemsCount -
1
do
begin
nb := SendMessage(LVH, LVM_GETITEMTEXT, i, LParam(Base));
ReadRemoteBuffer(Base2, @buffer, nb +
1
);
FillChar(Apoint, SizeOf(Apoint),
0
);
WriteToRemoteBuffer(@APoint, Base2, SizeOf(Apoint));
SendMessage(LVH, LVM_GETITEMPOSITION, i, LParam(Base) + lenlvi);
ReadRemoteBuffer(Base2, @Apoint, SizeOf(Apoint));
RegSetValueEx(key, @buffer,
0
, REG_BINARY, @Apoint, SizeOf(APoint));
end
;
RegCloseKey(key);
end
;
procedure
RestoreListItemPosition(LVH : THandle; RemoteAddr :
Pointer
);
type
TInfo =
packed
record
lvfi : TLVFindInfo;
Name :
array
[
0..
MAX_PATH]
of
char
;
end
;
var
SaveStyle : Dword;
Base :
Pointer
;
Apoint : TPoint;
key : HKey;
idx : DWord;
info : TInfo;
atype : Dword;
cbname, cbData : Dword;
itemidx : DWord;
begin
SaveStyle := GetWindowLong(LVH, GWL_STYLE);
if
(SaveStyle
and
LVS_AUTOARRANGE) = LVS_AUTOARRANGE
then
SetWindowLong(LVH, GWL_STYLE, SaveStyle
xor
LVS_AUTOARRANGE);
RegOpenKeyEx(HKEY_CURRENT_USER, RegSubKeyName,
0
, KEY_QUERY_VALUE, key);
FillChar(info, SizeOf(info),
0
);
Base := RemoteAddr;
idx :=
0
;
cbname := MAX_PATH;
cbdata := SizeOf(APoint);
while
(RegEnumValue(key, idx, info
.
Name, cbname,
nil
, @atype, @Apoint, @cbData) <> ERROR_NO_MORE_ITEMS)
do
begin
if
(atype = REG_BINARY)
and
(cbData = SizeOf(Apoint))
then
begin
info
.
lvfi
.
flags := LVFI_STRING;
info
.
lvfi
.
psz := Base;
inc(info
.
lvfi
.
psz, SizeOf(info
.
lvfi));
WriteToRemoteBuffer(@info, Base, SizeOf(info
.
lvfi) + cbname +
1
);
itemidx := SendMessage(LVH, LVM_FINDITEM, -
1
, LParam(Base));
if
itemidx > -
1
then
SendMessage(LVH, LVM_SETITEMPOSITION, itemidx, MakeLong(Apoint
.
x, Apoint
.
y));
end
;
inc(idx);
cbname := MAX_PATH;
cbdata := SizeOf(APoint);
end
;
RegCloseKey(key);
SetWindowLong(LVH, GWL_STYLE, SaveStyle);
end
;
function
GetSysListView32: THandle;
begin
Result := FindWindow(
'Progman'
,
nil
);
Result := FindWindowEx(Result,
0
,
nil
,
nil
);
Result := FindWindowEx(Result,
0
,
nil
,
nil
);
end
;
procedure
SaveDesktopItemPositions;
var
pid :
integer
;
rembuffer : PByte;
hTarget : THandle;
begin
hTarget := GetSysListView32;
GetWindowThreadProcessId(hTarget, @pid);
if
(hTarget =
0
)
or
(pid =
0
)
then
Exit;
rembuffer := CreateRemoteBuffer(pid,
$FFF
);
if
Assigned(rembuffer)
then
begin
SaveListItemPosition(hTarget, rembuffer);
DestroyRemoteBuffer;
end
;
end
;
procedure
RestoreDesktopItemPositions;
var
hTarget : THandle;
pid : DWord;
rembuffer : PByte;
begin
hTarget := GetSysListView32;
GetWindowThreadProcessId(hTarget, @pid);
if
(hTarget =
0
)
or
(pid =
0
)
then
Exit;
rembuffer := CreateRemoteBuffer(pid,
$FFF
);
if
Assigned(rembuffer)
then
begin
RestoreListItemPosition(hTarget, rembuffer);
DestroyRemoteBuffer;
end
;
end
;
end
.