Accueil > > > MODIFIER ICONE REPERTOIRE [C][WIN32]
MODIFIER ICONE REPERTOIRE [C][WIN32]
Information sur la source
Description
Bonjour, Ce code liste toutes les icones des fichiers *.exe et *.dll présents dans un répertoire, les affiche a l'aide d'une ListView et applique l'icone désirée au répertoire parent.
Source
- #include <windows.h>
- #include <shlobj.h>
- #include <commctrl.h>
- #include "resource.h"
-
- #pragma comment(lib, "comctl32.lib")
-
- #define WM_ENDTHR WM_USER + 1
- #define SZCLASSDESKTOP "[.ShellClassInfo]\r\nIconFile="
- #define SZICONINDEX "\r\nIconIndex="
-
- HWND hDlg, hlist, hpb;
- HANDLE hthread;
- DWORD dwthread;
- char szpath[260];
- char szwrite[512];
- char *szptr;
-
- //Fonction BruNews
- __declspec (naked) char* __stdcall bnultoa(unsigned int dwnum, char* szdst)
- {
- __asm {
- mov eax, [esp+4]
- mov ecx, [esp+8]
- or eax, eax
- jnz short L1
- lea eax, [ecx+1]
- mov byte ptr[ecx], 48
- mov byte ptr[eax], 0
- ret 8
- L1:
- mov [esp-4], edi
- mov [esp-8], ecx
- mov edi, ecx
- mov ecx, eax
- L2:
- mov eax, -858993459
- mul ecx
- mov eax, edx
- shr eax, 3
- mov edx, ecx
- lea ecx, [eax+eax*8]
- add ecx, eax
- sub edx, ecx
- add dl, 48
- mov [edi], dl
- mov ecx, eax
- inc edi
- test eax, eax
- jnz short L2
- mov [esp-12], edi
- mov eax, [esp-8]
- mov byte ptr[edi], 0
- L3:
- dec edi
- mov dl, [eax]
- mov cl, [edi]
- mov [edi], dl
- mov [eax], cl
- inc eax
- cmp eax, edi
- jb short L3
- mov edi, [esp-4]
- mov eax, [esp-12]
- ret 8
- }
- }
-
- __inline char* bnstrcpy(char *dst, char *src) // return ptr sur NULL final
- {
- __asm {
- mov eax, dst
- mov ecx, src
- dec eax
- LcpyLoop:
- mov dl, [ecx]
- inc eax
- inc ecx
- mov [eax], dl
- or dl, dl
- jz short LcpyOut
- mov dl, [ecx]
- inc eax
- inc ecx
- mov [eax], dl
- or dl, dl
- jz short LcpyOut
- mov dl, [ecx]
- inc eax
- inc ecx
- mov [eax], dl
- or dl, dl
- jnz short LcpyLoop
- LcpyOut:
- }
- }
-
- DWORD __stdcall ThreadProc(LPVOID lp)
- {
- WIN32_FIND_DATA wfd;
- LV_ITEM lvi;
- HIMAGELIST himglist;
- HICON *hbig;
- HANDLE hrep, hheap = GetProcessHeap();
- DWORD dwnumbericon = 0, i, dwdeb, dwtot = 0;
- char *c, *s, buf[128];
-
- strcpy(szptr, "\\*.*"); s = ++szptr; //on sauve s pour la suite du prog.
- hrep = FindFirstFile(szpath, &wfd);
- if (INVALID_HANDLE_VALUE == hrep) return 0;
- dwdeb = GetTickCount();
- SendMessage(hlist, LVM_DELETEALLITEMS, 0, 0);
- lvi.mask = LVIF_TEXT | LVIF_IMAGE;
- lvi.iSubItem = 0;
- himglist = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLORDDB | ILC_MASK, dwnumbericon, 1);
- SendMessage(hlist, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himglist);
- while (FindNextFile(hrep, &wfd)) {
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; //si c'est un repertoire, on ignore
- SetDlgItemText(hDlg, IDST_FILE, wfd.cFileName);
- c = wfd.cFileName; while (*c && *c++ != '.');
- if (strcmp(c, "exe") && strcmp(c, "dll")) continue; //si c'est pas un exe ou dll, on ignore
- strcpy(s, wfd.cFileName);
- dwnumbericon = ExtractIconEx(szpath, -1, 0, 0, 0);
- if (!dwnumbericon) continue; //si pas d'icones, on ignore
- SendMessage(hpb, PBM_SETPOS, 0, 0);
- SendMessage(hpb, PBM_SETRANGE, 0, MAKELPARAM(0, dwnumbericon));
- hbig = (HICON *) HeapAlloc(hheap, 0, dwnumbericon * 4);
- ExtractIconEx(szpath, 0, hbig, 0, dwnumbericon);
- c += 3; *c++ = ' ';
- lvi.pszText = wfd.cFileName;
- for (i = 0; i < dwnumbericon; ++i) {
- lvi.iImage = ImageList_AddIcon(himglist, hbig[i]);
- lvi.iItem = i;
- strcpy(c, itoa(i, buf, 10)); //ajoute l'index de l'icone a la suite du texte
- SendMessage(hlist, LVM_INSERTITEM, 0, (LPARAM)&lvi);
- SendMessage(hpb, PBM_STEPIT, 0, 0);
- }
- dwtot += i;
- HeapFree(hheap, 0, hbig);
- }
-
- dwdeb = (GetTickCount() - dwdeb); //avoir le temps en secondes
- *((DWORD *)buf) = 0x706D6F43; // "Comp"
- *((DWORD *)(buf + 4)) = 0x2074656C; //"let "
- c = bnultoa(dwdeb, (buf + 8));
- *((DWORD *)c) = 0x2D20736D; //"ms -"
- c = bnultoa(dwtot, (c + 4));
- *((DWORD *)c) = 0x6F636920; //" ico"
- *((DWORD *)(c + 4)) = 0x0073656E; //"nes "
- SetDlgItemText(hDlg, IDST_FILE, buf);
- DeleteObject(himglist);
- FindClose(hrep);
- PostMessage(hDlg, WM_ENDTHR, 0, 0);
- return 1;
- }
-
- void ApplicIcone(int iItem)
- {
- LVITEM lvi;
- LRESULT lresult;
- HANDLE hfile;
- DWORD dwWritten = 0;
- char buf[300], *b = buf, *c;
-
- lvi.cchTextMax = 300;
- lvi.pszText = buf;
- lvi.iSubItem = 0;
- lresult = SendMessage(hlist, LVM_GETITEMTEXT, iItem, (LPARAM)&lvi);
- if (!lresult) return;
- SetFileAttributes(szpath, FILE_ATTRIBUTE_SYSTEM);
- strcpy(szptr, "desktop.ini");
- hfile = CreateFile(szpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 0);
- if (INVALID_HANDLE_VALUE == hfile) return;
- while (*b) b++;
- while (*b != ' ') b--;
- *b = 0; b++;
- c = bnstrcpy(szwrite, SZCLASSDESKTOP);
- c = bnstrcpy(c, buf);
- c = bnstrcpy(c, SZICONINDEX);
- bnstrcpy(c, b);
- WriteFile(hfile, szwrite, strlen(szwrite), &dwWritten, 0);
- MessageBox(0, "Fichier créé, icone appliquée.", "OK", 0);
- CloseHandle(hfile);
- }
-
- int ObtDirectory()
- {
- BROWSEINFO bi;
- ITEMIDLIST *il;
- char buff[300];
-
- bi.hwndOwner = hDlg;
- bi.pidlRoot = NULL;
- bi.pszDisplayName = buff;
- bi.lpszTitle = "Choisissez un répertoire :";
- bi.ulFlags = 0;
- bi.lpfn = NULL;
- if (NULL == (il = SHBrowseForFolder(&bi))) return 0;
-
- return SHGetPathFromIDList(il, szpath);
- }
-
- BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
- {
- static int iItem = -1;
-
- switch (message) {
- case WM_INITDIALOG:
- SetClassLong(hwnd, GCL_HICON, (long)LoadIcon(0, IDI_APPLICATION));
- hDlg = hwnd;
- hlist = GetDlgItem(hwnd, IDLV_ICON);
- hpb = GetDlgItem(hwnd, IDPB_ICON);
- SendMessage(hpb, PBM_SETSTEP, 1, 0);
- return 1;
- case WM_ENDTHR:
- CloseHandle(hthread);
- dwthread = 0;
- return 0;
- case WM_COMMAND:
- switch (wparam) {
- case IDOK:
- if (!szpath[0]) { MessageBox(hwnd, "Choisissez un répertoire.", 0, 0x40); return 0; }
- hthread = CreateThread(0, 0, ThreadProc, 0, 0, &dwthread);
- return 0;
- case IDCANCEL:
- if (dwthread) {
- TerminateThread(hthread, 0);
- CloseHandle(hthread);
- }
- EndDialog(hwnd, 0);
- return 0;
- case IDBT_STOP:
- if (dwthread) {
- SuspendThread(hthread);
- if (IDNO == MessageBox(hwnd, "Etes-vous sur de vouloir stopper la recherche ?", "Fin prématurée", MB_YESNO)) {
- ResumeThread(hthread);
- return 0;
- }
- TerminateThread(hthread, 0);
- }
- return 0;
- case IDBT_APPLIC:
- if (iItem == -1) { MessageBox(hwnd, "Sélectionnez un item", 0, 0x40); return 0; }
- ApplicIcone(iItem);
- return 0;
- case IDBT_FIND:
- SetDlgItemText(hwnd, IDST_FILE, 0);
- SendMessage(hpb, PBM_SETPOS, 0, 0);
- if (!ObtDirectory()) { iItem = -1; *szpath = 0; }
- else { szptr = szpath; while (*szptr) szptr++; }
- SendMessage(hlist, LVM_DELETEALLITEMS, 0, 0);
- SetDlgItemText(hwnd, IDEC_PATH, szpath);
- return 0;
- }
- case WM_NOTIFY:
- if (wparam == IDLV_ICON)
- if (((LPNMITEMACTIVATE)lparam)->hdr.code == NM_CLICK)
- iItem = ((LPNMITEMACTIVATE)lparam)->iItem;
- default:
- return 0;
- }
- }
-
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE p, LPSTR q, int r)
- {
- InitCommonControls();
- DialogBoxParam(hInstance, (LPCTSTR)IDD_ICON, 0, DlgProc, 0);
-
- return 0;
- }
#include <windows.h>
#include <shlobj.h>
#include <commctrl.h>
#include "resource.h"
#pragma comment(lib, "comctl32.lib")
#define WM_ENDTHR WM_USER + 1
#define SZCLASSDESKTOP "[.ShellClassInfo]\r\nIconFile="
#define SZICONINDEX "\r\nIconIndex="
HWND hDlg, hlist, hpb;
HANDLE hthread;
DWORD dwthread;
char szpath[260];
char szwrite[512];
char *szptr;
//Fonction BruNews
__declspec (naked) char* __stdcall bnultoa(unsigned int dwnum, char* szdst)
{
__asm {
mov eax, [esp+4]
mov ecx, [esp+8]
or eax, eax
jnz short L1
lea eax, [ecx+1]
mov byte ptr[ecx], 48
mov byte ptr[eax], 0
ret 8
L1:
mov [esp-4], edi
mov [esp-8], ecx
mov edi, ecx
mov ecx, eax
L2:
mov eax, -858993459
mul ecx
mov eax, edx
shr eax, 3
mov edx, ecx
lea ecx, [eax+eax*8]
add ecx, eax
sub edx, ecx
add dl, 48
mov [edi], dl
mov ecx, eax
inc edi
test eax, eax
jnz short L2
mov [esp-12], edi
mov eax, [esp-8]
mov byte ptr[edi], 0
L3:
dec edi
mov dl, [eax]
mov cl, [edi]
mov [edi], dl
mov [eax], cl
inc eax
cmp eax, edi
jb short L3
mov edi, [esp-4]
mov eax, [esp-12]
ret 8
}
}
__inline char* bnstrcpy(char *dst, char *src) // return ptr sur NULL final
{
__asm {
mov eax, dst
mov ecx, src
dec eax
LcpyLoop:
mov dl, [ecx]
inc eax
inc ecx
mov [eax], dl
or dl, dl
jz short LcpyOut
mov dl, [ecx]
inc eax
inc ecx
mov [eax], dl
or dl, dl
jz short LcpyOut
mov dl, [ecx]
inc eax
inc ecx
mov [eax], dl
or dl, dl
jnz short LcpyLoop
LcpyOut:
}
}
DWORD __stdcall ThreadProc(LPVOID lp)
{
WIN32_FIND_DATA wfd;
LV_ITEM lvi;
HIMAGELIST himglist;
HICON *hbig;
HANDLE hrep, hheap = GetProcessHeap();
DWORD dwnumbericon = 0, i, dwdeb, dwtot = 0;
char *c, *s, buf[128];
strcpy(szptr, "\\*.*"); s = ++szptr; //on sauve s pour la suite du prog.
hrep = FindFirstFile(szpath, &wfd);
if (INVALID_HANDLE_VALUE == hrep) return 0;
dwdeb = GetTickCount();
SendMessage(hlist, LVM_DELETEALLITEMS, 0, 0);
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
lvi.iSubItem = 0;
himglist = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLORDDB | ILC_MASK, dwnumbericon, 1);
SendMessage(hlist, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himglist);
while (FindNextFile(hrep, &wfd)) {
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; //si c'est un repertoire, on ignore
SetDlgItemText(hDlg, IDST_FILE, wfd.cFileName);
c = wfd.cFileName; while (*c && *c++ != '.');
if (strcmp(c, "exe") && strcmp(c, "dll")) continue; //si c'est pas un exe ou dll, on ignore
strcpy(s, wfd.cFileName);
dwnumbericon = ExtractIconEx(szpath, -1, 0, 0, 0);
if (!dwnumbericon) continue; //si pas d'icones, on ignore
SendMessage(hpb, PBM_SETPOS, 0, 0);
SendMessage(hpb, PBM_SETRANGE, 0, MAKELPARAM(0, dwnumbericon));
hbig = (HICON *) HeapAlloc(hheap, 0, dwnumbericon * 4);
ExtractIconEx(szpath, 0, hbig, 0, dwnumbericon);
c += 3; *c++ = ' ';
lvi.pszText = wfd.cFileName;
for (i = 0; i < dwnumbericon; ++i) {
lvi.iImage = ImageList_AddIcon(himglist, hbig[i]);
lvi.iItem = i;
strcpy(c, itoa(i, buf, 10)); //ajoute l'index de l'icone a la suite du texte
SendMessage(hlist, LVM_INSERTITEM, 0, (LPARAM)&lvi);
SendMessage(hpb, PBM_STEPIT, 0, 0);
}
dwtot += i;
HeapFree(hheap, 0, hbig);
}
dwdeb = (GetTickCount() - dwdeb); //avoir le temps en secondes
*((DWORD *)buf) = 0x706D6F43; // "Comp"
*((DWORD *)(buf + 4)) = 0x2074656C; //"let "
c = bnultoa(dwdeb, (buf + 8));
*((DWORD *)c) = 0x2D20736D; //"ms -"
c = bnultoa(dwtot, (c + 4));
*((DWORD *)c) = 0x6F636920; //" ico"
*((DWORD *)(c + 4)) = 0x0073656E; //"nes "
SetDlgItemText(hDlg, IDST_FILE, buf);
DeleteObject(himglist);
FindClose(hrep);
PostMessage(hDlg, WM_ENDTHR, 0, 0);
return 1;
}
void ApplicIcone(int iItem)
{
LVITEM lvi;
LRESULT lresult;
HANDLE hfile;
DWORD dwWritten = 0;
char buf[300], *b = buf, *c;
lvi.cchTextMax = 300;
lvi.pszText = buf;
lvi.iSubItem = 0;
lresult = SendMessage(hlist, LVM_GETITEMTEXT, iItem, (LPARAM)&lvi);
if (!lresult) return;
SetFileAttributes(szpath, FILE_ATTRIBUTE_SYSTEM);
strcpy(szptr, "desktop.ini");
hfile = CreateFile(szpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 0);
if (INVALID_HANDLE_VALUE == hfile) return;
while (*b) b++;
while (*b != ' ') b--;
*b = 0; b++;
c = bnstrcpy(szwrite, SZCLASSDESKTOP);
c = bnstrcpy(c, buf);
c = bnstrcpy(c, SZICONINDEX);
bnstrcpy(c, b);
WriteFile(hfile, szwrite, strlen(szwrite), &dwWritten, 0);
MessageBox(0, "Fichier créé, icone appliquée.", "OK", 0);
CloseHandle(hfile);
}
int ObtDirectory()
{
BROWSEINFO bi;
ITEMIDLIST *il;
char buff[300];
bi.hwndOwner = hDlg;
bi.pidlRoot = NULL;
bi.pszDisplayName = buff;
bi.lpszTitle = "Choisissez un répertoire :";
bi.ulFlags = 0;
bi.lpfn = NULL;
if (NULL == (il = SHBrowseForFolder(&bi))) return 0;
return SHGetPathFromIDList(il, szpath);
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
static int iItem = -1;
switch (message) {
case WM_INITDIALOG:
SetClassLong(hwnd, GCL_HICON, (long)LoadIcon(0, IDI_APPLICATION));
hDlg = hwnd;
hlist = GetDlgItem(hwnd, IDLV_ICON);
hpb = GetDlgItem(hwnd, IDPB_ICON);
SendMessage(hpb, PBM_SETSTEP, 1, 0);
return 1;
case WM_ENDTHR:
CloseHandle(hthread);
dwthread = 0;
return 0;
case WM_COMMAND:
switch (wparam) {
case IDOK:
if (!szpath[0]) { MessageBox(hwnd, "Choisissez un répertoire.", 0, 0x40); return 0; }
hthread = CreateThread(0, 0, ThreadProc, 0, 0, &dwthread);
return 0;
case IDCANCEL:
if (dwthread) {
TerminateThread(hthread, 0);
CloseHandle(hthread);
}
EndDialog(hwnd, 0);
return 0;
case IDBT_STOP:
if (dwthread) {
SuspendThread(hthread);
if (IDNO == MessageBox(hwnd, "Etes-vous sur de vouloir stopper la recherche ?", "Fin prématurée", MB_YESNO)) {
ResumeThread(hthread);
return 0;
}
TerminateThread(hthread, 0);
}
return 0;
case IDBT_APPLIC:
if (iItem == -1) { MessageBox(hwnd, "Sélectionnez un item", 0, 0x40); return 0; }
ApplicIcone(iItem);
return 0;
case IDBT_FIND:
SetDlgItemText(hwnd, IDST_FILE, 0);
SendMessage(hpb, PBM_SETPOS, 0, 0);
if (!ObtDirectory()) { iItem = -1; *szpath = 0; }
else { szptr = szpath; while (*szptr) szptr++; }
SendMessage(hlist, LVM_DELETEALLITEMS, 0, 0);
SetDlgItemText(hwnd, IDEC_PATH, szpath);
return 0;
}
case WM_NOTIFY:
if (wparam == IDLV_ICON)
if (((LPNMITEMACTIVATE)lparam)->hdr.code == NM_CLICK)
iItem = ((LPNMITEMACTIVATE)lparam)->iItem;
default:
return 0;
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE p, LPSTR q, int r)
{
InitCommonControls();
DialogBoxParam(hInstance, (LPCTSTR)IDD_ICON, 0, DlgProc, 0);
return 0;
}
Conclusion
Voila, je remercie Arnotic pour sa relecture du code et des changements qu'il y a apporté.
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3 par ROMELARD Fabrice
Speaker: Bernard Ourghanlian Cette session est comme chaque jour transmise en live par BrainSonic, et j'ai donc suivi cette troisième pleinière par ce moyen sur mon iPad . Elle est dédiée comme chaque année à la mise en perspective de l'é...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE !MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE ! par Vko
Hier durant une session dédiée aux Techdays 2012, j'ai eu le plaisir d'annoncer la sortie de la Béta 2 de Mishra Reader. C'est quoi ? Pour les utilisateurs, c'est une vraie expérience de lecture de flux RSS sur Windows. Rien à voir avec les produit...
Cliquez pour lire la suite de l'article par Vko [FRAMEWORK 4] LES TASKS ET LE THREAD UI[FRAMEWORK 4] LES TASKS ET LE THREAD UI par fathi
Je viens de passer quelques temps au TechDay's et j'ai pu voir pas mal de session intéressante. Par contre une chose m'a un peu étonné lors de certaines de ces sessions qui abordaient les améliorations du framework .NET (donc le 4.5) : en gros, bea...
Cliquez pour lire la suite de l'article par fathi WORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBEWORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBE par JeremyJeanson
Depuis déjà un an, je conseille vivement les utilisateurs de Workflow Foundation 3 à migrer vers la version 4. L'information qui va suivre ne devrait donc pas trop prendre au dépourvu les personnes qui m'ont suivi. Je profite de ce poste, pour faire le re...
Cliquez pour lire la suite de l'article par JeremyJeanson TECHDAYS PARIS 2012 : NOUVELLES TENDANCES DU POSTE DE TRAVAIL - BRING YOUR OWN PCTECHDAYS PARIS 2012 : NOUVELLES TENDANCES DU POSTE DE TRAVAIL - BRING YOUR OWN PC par ROMELARD Fabrice
Speakers: Thierry Rapatout, Antoine Petit et Xavier Trebbia Cette session entre dans le cadre des RDV Décideurs des TechDays 2012, elle est liée à la consumérisation de l'IT et la mise en place du "DeskTop as a Service" dans de plus en ...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Forum
RE : CXIMAGERE : CXIMAGE par rt15
Cliquez pour lire la suite par rt15
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|