Cet utilitaire permet donc de sauvegarder le nom et la position des icones dans un fichier pour pouvoir les restaurer si besoin (après un plantage ou une réorganisation automatique non désirée, ou bien un changement de résolution.)
Ce programme est basé sur le code donné dans le bouquin de Richter:
http://brunews.free.fr/brunews/download/JR4.zip
http://brunews.free.fr/brunews/download/JR4Sources.zip
Part IV, Chapter 22 : "Injecting a DLL Using Windows Hooks"
Ce code utililise un hook dans une Dll et mon prog ReadProcessMemory et WriteProcessMemory.
Le point sensible est le passage de données entre 2 processus différents (cet utilitaire et le Program Manager).
Source / Exemple :
//***************************************************************************************
// DesktopUtility.cpp :
//
//---------------------------------------------------------------------------------------
// Auteur : Y.M. Morgan.
// Date : 19/05:2004.
// Projet : "DesktopUtility.exe", utilitaire de sauvegarde et de restauration
// de la position des icones sur le bureau.
//
//---------------------------------------------------------------------------------------
//
// - Les icones du bureau sont regroupées dans un contrôle ListView. Ce contrôle est le
// premier "petit-fils" de la fenêtre "ProgMan" (Program manager).
// - Pour récupérer le nom et la position de ces icones il suffit donc d'envoyer le
// message LV_GETITEMTEXT ou LV_GETITEMPOSITION.
// - Cependant, ces messages nécessitent l'emploi d'un pointeur, et étant donné que cet
// utilitaire et le contrôle ListView cible ne sont pas dans le même processus, un
// pointeur dans un des processus n'est pas valide dans l'autre.
// - Pour remédier à ce problème, il faut un moyen d'allouer de la mémoire dans le
// processus de la ListView et de pouvoir y lire et écrire.
// - Sous Windows 98/ME, la zone au dessus de l'adresse 0x80000000 est partagée par tous
// les processus, il suffit donc d'y allouer une zone. La fonction CreateFileMapping
// et MapViewOfFile permet cela.
// - Sous Windows 2000/NT/XP, il suffit d'utiliser la fonction VirtualQueryEx en lui
// passant un handle du processus cible.
// - Une fois la zone allouée, les fonctions ReadProcessMemory et WriteProcessMemory
// sont utilisées pour accéder à cette zone.
// - Finalement, les données récupérées sont stockées dans un fichier "*.ini" sous le
// format : ItemXX="nom de l'icon" x y.
//
//***************************************************************************************
#include <windows.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <stdio.h>
#include <tchar.h>
#include "Resource.h"
//=======================================================================================
// Variables globales.
//=======================================================================================
HINSTANCE g_hAppInstance = NULL; // instance de l'application
HWND g_hWndMainDialog = NULL; // boîte de dialogue principale
//=======================================================================================
// Déclarations des fonctions du module.
//=======================================================================================
static int CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
static int MsgInitDialog (HWND, WPARAM, LPARAM);
static int MsgCommand (WPARAM, LPARAM);
static void CmdBtnSave ();
static void CmdBtnRestore ();
//***************************************************************************************
// WinMain : point d'entrée de l'application.
// entrée : hInstance : instance de l'application.
// hPrevInstance : instance précédente de l'application (NULL sous Win32).
// lpCmdLine : ligne de commande associée au programme.
// nCmdShow : indique comment doît être affichée la fenêtre principale.
// retour : code de retour de PostQuitMessage.
//***************************************************************************************
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
// sauvegarde instance de l'application, ouverture de la boîte de dialogue
g_hAppInstance = hInstance;
DialogBox(g_hAppInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, DlgProc);
return 0;
}
//=======================================================================================
// Traitement des messages.
//=======================================================================================
//***************************************************************************************
// DlgProc : procédure de traitement des messages de la boîte de dialogue principale.
// entrée : hDlg : handle de la boîte de dialogue.
// uMsg : message à traiter.
// wParam : premier paramètre du message.
// lParam : second paramètre du message.
// retour : dépend du message à traiter.
//***************************************************************************************
int CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// en fonction du message
switch(uMsg)
{
case WM_INITDIALOG : return MsgInitDialog (hDlg, wParam, lParam);
case WM_COMMAND : return MsgCommand (wParam, lParam);
default : return 0;
}
}
//***************************************************************************************
// MsgInitDialog : traitement du message WM_INITDIALOG. Initialisation de la boîte de
// dialogue.
// entrée : hDlg : handle de la boîte de dialogue.
// wParam : premier paramètre du message.
// lParam : second paramètre du message.
// retour : vrai.
//***************************************************************************************
int MsgInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
// sauvegarde handle de la boîte de dialogue
g_hWndMainDialog = hDlg;
// affectation icones
HICON hIcon = LoadIcon(g_hAppInstance, MAKEINTRESOURCE(IDI_APPICON));
SendMessage(g_hWndMainDialog, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
SendMessage(g_hWndMainDialog, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
// centrage au milieu du bureau
RECT rcDlg;
GetWindowRect(g_hWndMainDialog, &rcDlg);
RECT rcDesktop;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0);
int x = ((rcDesktop.right-rcDesktop.left)-(rcDlg.right-rcDlg.left))/2;
int y = ((rcDesktop.bottom-rcDesktop.top)-(rcDlg.bottom-rcDlg.top))/2;
x += rcDesktop.left;
y += rcDesktop.top;
SetWindowPos(g_hWndMainDialog, NULL, x, y, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
return TRUE;
}
//***************************************************************************************
// MsgCommand : traitement du message WM_COMMAND. Action sur un des contrôles de la
// boîte de dialogue.
// entrée : wParam : premier paramètre du message.
// lParam : second paramètre du message.
// retour : vrai si la commande a été traitée, faux sinon.
//***************************************************************************************
int MsgCommand(WPARAM wParam, LPARAM lParam)
{
// récupération des paramètres
int nIDCtl = LOWORD(wParam);
// en fonction de la commande
switch(nIDCtl)
{
case IDC_BTN_SAVE : CmdBtnSave (); break;
case IDC_BTN_RESTORE : CmdBtnRestore (); break;
case IDOK : EndDialog(g_hWndMainDialog, IDOK); break;
case IDCANCEL : EndDialog(g_hWndMainDialog, IDCANCEL); break;
default : return FALSE;
}
// la commande a été traitée
return TRUE;
}
//***************************************************************************************
// CmdBtnSave : action sur le bouton [Sauvegarder], sauvegarde la position des icones
// sur le bureau.
//***************************************************************************************
void CmdBtnSave()
{
//-----------------------------------------------------------------------------------
// récupération plateforme d'exécution
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if(osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS &&
osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
return;
}
//-----------------------------------------------------------------------------------
// récupération ListView avec les icones du bureau, récupération de son processus
HWND hWnd = FindWindow(_T("ProgMan"), NULL);
HWND hListView = GetTopWindow(GetTopWindow(hWnd));
DWORD dwProcessId;
GetWindowThreadProcessId(hListView, &dwProcessId);
DWORD dwAccess = PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE;
HANDLE hProcess = OpenProcess(dwAccess, FALSE, dwProcessId);
if(hProcess == NULL)
return;
// allocation d'une chaînes de caractères, d'une stucture LVITEM et d'une structure
// POINT dans le processus de la listview ou dans la zone partagée (Windows 98)
DWORD dwSize = sizeof(POINT) + sizeof(LVITEM) + 256*sizeof(TCHAR);
HANDLE hFileMapping = NULL;
LPVOID lpData = NULL;
// Windows 98 : création FileMapping
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
hFileMapping = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL,
PAGE_READWRITE|SEC_COMMIT, 0, dwSize, NULL);
if(hFileMapping != NULL)
lpData = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwSize);
}
// Windows NT : VirtualAllocEx
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
lpData = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
}
// en cas d'erreur
if(lpData == NULL)
{
if(hFileMapping != NULL)
CloseHandle(hFileMapping);
CloseHandle(hProcess);
return;
}
// affectation des pointeurs
LPVOID lpPosition = lpData;
LPVOID lpItem = ((LPBYTE) lpData) + sizeof(POINT);
LPVOID lpText = ((LPBYTE) lpData) + sizeof(POINT) + sizeof(LVITEM);
//-----------------------------------------------------------------------------------
// création nom du fichier d'initialisation
TCHAR szIniFileName[_MAX_PATH];
GetModuleFileName(NULL, szIniFileName, _MAX_PATH);
GetLongPathName(szIniFileName, szIniFileName, _MAX_PATH);
PathRenameExtension(szIniFileName, _T(".ini"));
// boucle sur les items de la ListView
int nItemCount = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0);
TCHAR szCount[32];
wsprintf(szCount, _T("%d"), nItemCount);
WritePrivateProfileString(_T("Icons"), _T("ItemCount"), szCount, szIniFileName);
for(int i = 0; i < nItemCount; i++)
{
// init structure LVITEM dans une variable locale et recopie dans la zone de
// mémoire allouée
LVITEM lvi;
ZeroMemory(&lvi, sizeof(LVITEM));
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.mask = LVIF_TEXT;
lvi.pszText = (LPTSTR) lpText;
lvi.cchTextMax = 256;
WriteProcessMemory(hProcess, lpItem, &lvi, sizeof(LVITEM), NULL);
// récupération nom et position
SendMessage(hListView, LVM_GETITEMTEXT, i, (LPARAM) lpItem);
SendMessage(hListView, LVM_GETITEMPOSITION, i, (LPARAM) lpPosition);
// recopie dans variables locales
TCHAR szText[256];
ReadProcessMemory(hProcess, lpText, szText, 256*sizeof(TCHAR), NULL);
POINT ptPosition;
ReadProcessMemory(hProcess, lpPosition, &ptPosition, sizeof(POINT), NULL);
// ajout de la position et du nom
TCHAR szKey[256];
wsprintf(szKey, _T("Item%02d"), i);
TCHAR szValue[256];
wsprintf(szValue, _T("\"%s\" %d %d"), szText, ptPosition.x, ptPosition.y);
WritePrivateProfileString(_T("Icons"), szKey, szValue, szIniFileName);
}
//-----------------------------------------------------------------------------------
// libération mémoire
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
UnmapViewOfFile(lpData);
CloseHandle(hFileMapping);
}
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
VirtualFreeEx(hProcess, lpData, 0, MEM_RELEASE);
}
// fermeture processus
CloseHandle(hProcess);
MessageBox(g_hWndMainDialog, _T("Position des icones sauvegardée"),
_T("DektopUtility"), MB_ICONINFORMATION);
}
//***************************************************************************************
// CmdBtnRestore : action sur le bouton [Restaurer], resaure la position des icones sur
// le bureau.
//***************************************************************************************
void CmdBtnRestore()
{
//-----------------------------------------------------------------------------------
// récupération plateforme d'exécution
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if(osvi.dwPlatformId!=VER_PLATFORM_WIN32_WINDOWS &&
osvi.dwPlatformId!=VER_PLATFORM_WIN32_NT)
{
return;
}
//-----------------------------------------------------------------------------------
// récupération ListView avec les icones du bureau, récupération de son processus
HWND hWnd = FindWindow(_T("ProgMan"), NULL);
HWND hListView = GetTopWindow(GetTopWindow(hWnd));
DWORD dwProcessId;
GetWindowThreadProcessId(hListView, &dwProcessId);
DWORD dwAccess = PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE;
HANDLE hProcess = OpenProcess(dwAccess, FALSE, dwProcessId);
if(hProcess == NULL)
return;
// allocation d'une chaînes de caractères, d'une stucture LVFINDINFO dans le
// processus de la listview ou dans la zone partagée (Windows 98)
DWORD dwSize = sizeof(LVFINDINFO) + 256*sizeof(TCHAR);
HANDLE hFileMapping = NULL;
LPVOID lpData = NULL;
// Windows 98 : création FileMapping
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
hFileMapping = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL,
PAGE_READWRITE|SEC_COMMIT, 0, dwSize, NULL);
if(hFileMapping != NULL)
lpData = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwSize);
}
// Windows NT : VirtualAllocEx
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
lpData = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
}
// en cas d'erreur
if(lpData == NULL)
{
if(hFileMapping != NULL)
CloseHandle(hFileMapping);
CloseHandle(hProcess);
return;
}
// affectation des pointeurs
LPVOID lpItem = lpData;
LPVOID lpText = ((LPBYTE) lpData) + sizeof(LVITEM);
//-----------------------------------------------------------------------------------
// création nom du fichier d'initialisation
TCHAR szIniFileName[_MAX_PATH];
GetModuleFileName(NULL, szIniFileName, _MAX_PATH);
GetLongPathName(szIniFileName, szIniFileName, _MAX_PATH);
PathRenameExtension(szIniFileName, _T(".ini"));
// si la liste a le style AUTO_ARRANGE, on le vire pendant le positionnement
DWORD dwStyle = GetWindowLong(hListView, GWL_STYLE);
if(dwStyle & LVS_AUTOARRANGE)
SetWindowLong(hListView, GWL_STYLE, dwStyle & ~LVS_AUTOARRANGE);
// boucle sur les items sauvegardés
int nItemCount = GetPrivateProfileInt(_T("Icons"), _T("ItemCount"), 0, szIniFileName);
for(int i = 0; i < nItemCount; i++)
{
// récupération données de l'item
TCHAR szKey[256];
wsprintf(szKey, _T("Item%02d"), i);
TCHAR szValue[256];
GetPrivateProfileString(_T("Icons"), szKey, _T(""), szValue, 256, szIniFileName);
// récherche nom de l'item entre ""
TCHAR szText[256];
if(szValue[0] != '\"')
continue;
TCHAR* pEnd = _tcsrchr(szValue, '\"');
if(pEnd == NULL)
continue;
_tcscpy(szText, szValue + 1);
WriteProcessMemory(hProcess, lpText, szText, 256 * sizeof(TCHAR), NULL);
// recherche de l'item dans la ListView
LVFINDINFO lvfi;
ZeroMemory(&lvfi, sizeof(LVFINDINFO));
lvfi.flags = LVFI_STRING;
lvfi.psz = (LPTSTR) lpText;
WriteProcessMemory(hProcess, lpItem, &lvfi, sizeof(LVFINDINFO), NULL);
int index = SendMessage(hListView, LVM_FINDITEM, -1, (LPARAM) lpItem);
if(index == -1)
continue;
// position
TCHAR* pStart = pEnd+1;
while(*pStart == ' ')
pStart++;
int x = _ttoi(pStart);
while(*pStart != ' ' && *pStart != '\0')
pStart++;
while(*pStart == ' ')
pStart++;
int y = _ttoi(pStart);
SendMessage(hListView, LVM_SETITEMPOSITION, index, MAKELPARAM(x, y));
}
// on remet l'ancien style
SetWindowLong(hListView, GWL_STYLE, dwStyle);
//-----------------------------------------------------------------------------------
// libération mémoire
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
UnmapViewOfFile(lpData);
CloseHandle(hFileMapping);
}
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
VirtualFreeEx(hProcess, lpData, 0, MEM_RELEASE);
}
// fermeture processus
CloseHandle(hProcess);
MessageBox(g_hWndMainDialog, _T("Position des icones restaurée"),
_T("DektopUtility"), MB_ICONINFORMATION);
}
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.