Première version de MultiBureau.
Je n'en suis pas fier du tout. Le code est assez brouillon. ça part dans tout les sens. Et surtout il y trop de thread. Et de la découle des erreurs possibles et parfois non débuggable.
Normalement cette version est à peu près stable. Tout les tests que j'ai réalisé (sous Vista) n'ont pas buggés.
Lorsque le programme se lance, la fenêtre de paramètre apparait, elle ne permet pour l'instant que de rajouter des bureaux. (Ajouter, mettre un nom, puis créer). J'ai tester jusqu'à 6 bureaux, je n'ai pas fait de contrôle sur le nombre de bureau, mais on ne peux en accéder que 10 de toute façon.
Le programme créé les dossiers : Bureau_1, bureau_2, etc.. dans le répertoire racine de l'utilisateur pour lancer les différentes fenêtres des Shell (explorer.exe)
Raccourcis : Ctrl + 1, Ctrl + 2, ...., Ctrl + 9, Ctrl + 0 pour switcher entre les bureaux, Ctrl + F3 pour ouvrir la fenetre de paramètrage
Il y a aussi Ctrl + F12 pour fermer l'application, cependant, comme les bureaux ne se ferment pas, ainsi que les applications lancées, ce raccourci n'est là que pour le développement de l'application.
Code : Tout sélectionner
;######################################
; programme : MultiBureau
#VERSION = "1.00alpha0"
; description : - Permet de créer plusieurs bureaux réels sur window et de changer entre eux rapidement
;
; détails : - Fenetre de parametre pour regler les différents bureaux ( Ctrl + F3 )
; - raccourcis Ctrl + 1 ~ 9 et 0 pour switcher entre les bureaux
; - fermer le programme : Ctrl + F12 (ne ferme pas les desktops, ni les applications lancées, il faut fermer la session pour cela)
; ajouts prévus : - modification de l'interface
; - eradication des bugs possibles
; - changement réels des bureaux pour l'explorateur windows
; - changement du système de raccourcis
;
; auteur : graph100 alias Kriek106
;######################################
;{ Structure, variables globales et constantes
Structure Bureau
nom.s
hd_bureau.l
numero.l
hd_miniature.l
nom_utilisateur.s
dossier_bureau.s
programme.s
wallpaper.s
thread.l
EndStructure
Global currentdirectory$ = GetCurrentDirectory()
Global USER.s, InitFile$ = "Multibureau.init"
Global Bureau_ACTUEL.s = "Default", IS_PARAMETRE_BEING_SET.b = #False
Global taille_max_snapshot.l = 140, EXIT_PROGRAM.b = #False
Global NewMap Desktop.Bureau()
#WHEEL_DELTA = 120
;}
;{ procedure
Declare ThreadRaccourcisClavier(*adresse.String)
Procedure.s GetUserName()
_user_.s = Space(255)
size = 255
While GetUserName_(@_user_, @size) = #False
_user_ + Space(255)
size + 255
Wend
ProcedureReturn Left(_user_, size)
EndProcedure
Procedure.s GetWindowsDirectory()
_dir_.s = Space(255)
size = 255
While GetWindowsDirectory_(@_dir_, @size) = #False
_dir_ + Space(255)
size + 255
Wend
ProcedureReturn Left(_dir_, size)
EndProcedure
Procedure.s GetUserProfileDirectory()
_dir_.s = Space(255)
size = 255
If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY, @usertoken) = #False
ProcedureReturn ""
EndIf
If GetUserProfileDirectory_(usertoken, @_dir_, @size) = #False
_dir_ = Space(size)
If GetUserProfileDirectory_(usertoken, @_dir_, @size) = #False
ProcedureReturn ""
EndIf
EndIf
ProcedureReturn Left(_dir_, size) + "\"
EndProcedure
Procedure DesktopSnapShot(w, h, img = #PB_Any)
Ecran_Largeur = GetSystemMetrics_(#SM_CXSCREEN)
Ecran_Hauteur = GetSystemMetrics_(#SM_CYSCREEN)
coef.d = Ecran_Largeur / w
coef2.d = Ecran_Hauteur / h
If coef < coef2
Swap coef, coef2
EndIf
DC = GetDC_(0)
If img = #PB_Any
img = CreateImage(#PB_Any, Ecran_Largeur, Ecran_Hauteur)
Else
If IsImage(img)
FreeImage(img)
EndIf
CreateImage(img, Ecran_Largeur, Ecran_Hauteur)
EndIf
Dessin = StartDrawing(ImageOutput(img))
If Dessin
BitBlt_(Dessin, 0, 0, Ecran_Largeur, Ecran_Hauteur, DC, 0, 0, #SRCPAINT | $40000000)
StopDrawing()
EndIf
ReleaseDC_(0, DC)
ResizeImage(img, Ecran_Largeur / coef, Ecran_Hauteur / coef, #PB_Image_Smooth)
; w.l = Ecran_Largeur / coef
; h.l = Ecran_Hauteur / coef
;
; CreateImage(snap, w, h)
;
; If StartDrawing(ImageOutput(snap))
; DrawImage(ImageID(img), 0, 0, w, h)
;
; StopDrawing()
; EndIf
;
; FreeImage(img)
ProcedureReturn img
EndProcedure
;--------------------------------------
Procedure.l CreateDesktop(nom.s)
Define.SECURITY_ATTRIBUTES lpsa
lpsa\nLength = SizeOf(SECURITY_ATTRIBUTES)
lpsa\lpSecurityDescriptor = 0
lpsa\bInheritHandle = #True
desktop_hd.l = CreateDesktop_(nom, #NULL$, #Null, 0, #GENERIC_ALL, @lpsa)
ProcedureReturn desktop_hd
EndProcedure
Procedure.l OpenDesktop(nom.s, *desktophd.Long) ; ouvre un bureau existant, ou le créé si il n'existait pas
*desktophd\l = OpenDesktop_(nom, 0, #True, #GENERIC_ALL)
res = 2 ; le bureau spécifié existe déjà
If *desktophd\l = 0
; Debug "Le bureau : " + nom + " n'existe pas. On va le recréer."
*desktophd\l = CreateDesktop(nom)
If *desktophd\l = 0
; Debug "Création du bureau : " + FormatMessage(GetLastError_())
ProcedureReturn 0 ; on retourne une erreur
EndIf
res = 1 ; on crée le bureau, car il n'existait pas
EndIf
ProcedureReturn res
EndProcedure
;--------------------------------------
;--------------------------------------
Procedure CreateProcess(application.s, dossier_courant.s, desktop_name.s, *lpProcessInformation.PROCESS_INFORMATION)
Define.SECURITY_ATTRIBUTES lpProcessAttributes
With lpProcessAttributes
\nLength = SizeOf(SECURITY_ATTRIBUTES)
\lpSecurityDescriptor = 0
\bInheritHandle = #True
EndWith
Define.STARTUPINFO lpStartupInfo
With lpStartupInfo
\cb = SizeOf(STARTUPINFO)
\lpDesktop = @desktop_name
EndWith
res = CreateProcess_(#Null, #DQUOTE$ + application + #DQUOTE$, lpProcessAttributes, #Null, #True, #NORMAL_PRIORITY_CLASS, #Null, dossier_courant, lpStartupInfo, *lpProcessInformation)
If res = 0
Debug "Failed"
; Debug "CreateProcess : " + FormatMessage(GetLastError_())
Else
; Debug "Created"
EndIf
ProcedureReturn res
EndProcedure
;--------------------------------------
;{ Parametre
Global _desktop_affiche_actuellement.l, _exit_thread_affichage_serie.b
Macro FindSpecificMapElement(_map, _element)
fin.b = #True
ForEach _map
If _map\numero = _element
fin = #False
Break
EndIf
Next
EndMacro
Procedure Affiche_miniature_deroulante(img.l)
affiche_x = 1
; w = ImageWidth(img) ; pour adaptivité
; h = ImageHeight(img)
w = 410 ; comme on a fixé la taille de la fenêtre
h = 140
nb_image_affiche = Round(2 + w / h, #PB_Round_Up) - 2 ; 1ere image partielle + images entre + 2eme image partielle
taille_affichage = 130
Repeat
Delay(25)
If affiche_x <> h * _desktop_affiche_actuellement ; on arrete de bouger
dif = _desktop_affiche_actuellement * h - affiche_x
adif = Abs(dif)
If adif > 100 : vitesse = 40
ElseIf adif <= 100 And adif > 50 : vitesse = 20
ElseIf adif <= 50 And adif > 10 : vitesse = 10
ElseIf adif <= 10 And adif > 5 : vitesse = 5
ElseIf adif <= 5 : vitesse = 1
EndIf
affiche_x = affiche_x + vitesse * Sign(dif)
; Debug nb_image_affiche
premiere_image_affiche = Round(affiche_x / h - nb_image_affiche / 2, #PB_Round_Down)
; Debug premiere_image_affiche
derniere_image_affiche = premiere_image_affiche + nb_image_affiche
; Debug derniere_image_affiche
If premiere_image_affiche < 0 : premiere_image_affiche = 0 : EndIf
If derniere_image_affiche > MapSize(Desktop()) - 1 : derniere_image_affiche = MapSize(Desktop()) - 1 : EndIf
; SelectElement(Serie_Choix(), premiere_image_affiche)
If StartDrawing(ImageOutput(img))
Box(0, 0, w, h, 0)
For a = premiere_image_affiche To derniere_image_affiche
; FindMapElement(mini_vignette(), Serie_Choix())
FindSpecificMapElement(Desktop(), a)
If fin = #True
Break
EndIf
If a = _desktop_affiche_actuellement
Box(- affiche_x + a * h + (w - taille_affichage) / 2, 0, h, h, #Red)
EndIf
ratio.d = ImageWidth(Desktop()\hd_miniature) / ImageHeight(Desktop()\hd_miniature)
h1 = taille_affichage / ratio
w1 = taille_affichage * ratio
If h1 <= taille_affichage
DrawImage(ImageID(Desktop()\hd_miniature), - affiche_x + a * h + (w + h) / 2 - taille_affichage, (h - h1) / 2, taille_affichage, h1)
; If x >= a * wr And x <= a * wr + wr And y >= b * hr + hr / 2 - h1 / 2 And y <= b * hr + hr / 2 + h1 / 2
; index_sous_la_sourie = MapKey(mini_vignette())
; EndIf
Else
; DrawImage(ImageID(Desktop()\hd_miniature), - affiche_x + ((a + nb_image_affiche / 2) * 80) + (h - w1) / 2, (h - taille_affichage) / 2, w1, taille_affichage)
DrawImage(ImageID(Desktop()\hd_miniature), - affiche_x + a * h + (w - taille_affichage + h - w1) / 2, (h - taille_affichage) / 2, w1, taille_affichage)
; If x >= a * wr + wr / 2 - w1 / 2 And x <= a * wr + wr / 2 + w1 / 2 And y >= b * hr And y <= b * hr + hr
; index_sous_la_sourie = MapKey(mini_vignette())
; EndIf
EndIf
Next
StopDrawing()
EndIf
SetGadgetState(7, ImageID(img))
EndIf
Until _exit_thread_affichage_serie = #True
EndProcedure
Procedure.i WindowCallBack_molette_souris(hWnd,uMsg,wParam,lParam)
Define.i ValeurRetour
; Static compteur.l = 0
ValeurRetour = #PB_ProcessPureBasicEvents
If uMsg = #WM_MOUSEWHEEL
; If compteur < 2
; compteur = compteur + 1
; ProcedureReturn ValeurRetour
; EndIf
;
; compteur = 0
Molette.l= -(wParam >> 16) / #WHEEL_DELTA
tmp = _desktop_affiche_actuellement + Molette
If tmp < 0 : tmp = 0 : EndIf
If tmp > MapSize(Desktop()) - 1 : tmp = MapSize(Desktop()) - 1 : EndIf
_desktop_affiche_actuellement = tmp
EndIf
ProcedureReturn ValeurRetour
EndProcedure
Procedure Fenetre_Parametre(bla.l)
;{ on associe le thread au bureau actuel
If SetThreadDesktop_(Desktop(Bureau_ACTUEL)\hd_bureau) = #False
ProcedureReturn 0
EndIf
_desktop_affiche_actuellement = Desktop(Bureau_ACTUEL)\numero
;}
;{ ouverture de la fenetre
If OpenWindow(0, 0, 0, 430, 300, "MultiBureau - Paramètres", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(0, 10, 10, 100, 20, "Ajouter un Bureau")
ButtonGadget(8, 120, 10, 150, 20, "Créer le nouveau Bureau")
DisableGadget(8, #True)
TextGadget(1, 10, 40, 100, 20, "Nom du bureau")
StringGadget(2, 120, 40, 100, 20, Desktop()\nom_utilisateur)
TextGadget(3, 10, 70, 100, 20, "Shell :")
StringGadget(4, 120, 70, 300, 20, Desktop()\programme)
TextGadget(5, 10, 100, 100, 20, "Wallpaper :")
StringGadget(6, 120, 100, 300, 20, Desktop()\wallpaper)
ImageGadget(7, 10, 150, 410, 140, 0)
image_defilante = CreateImage(#PB_Any, 410, 140)
Else
ProcedureReturn 0
EndIf
SetWindowCallback(@WindowCallBack_molette_souris(), 0)
;}
;{ lancement du dessin des miniatures
_exit_thread_affichage_serie = #False
thread_dessin_miniature = CreateThread(@Affiche_miniature_deroulante(), image_defilante)
;}
StickyWindow(0, #True)
SetForegroundWindow_(WindowID(0))
;{ boucle principale des evenements
Repeat
event = WaitWindowEvent(100)
If event = #PB_Event_Gadget
Select EventGadget()
;{ nouvelle page de bureau
Case 0
SetGadgetText(2, "")
SetGadgetText(4, GetWindowsDirectory() + "\explorer.exe")
SetGadgetText(6, Desktop(Bureau_ACTUEL)\wallpaper)
DisableGadget(8, #False)
;}
;{ création effective d'un nouveau bureau
Case 8
nom$ = GetGadgetText(2)
If nom$ = ""
MessageRequester("Erreur", "Spécifiez un nom de bureau")
Else
ok_1.b = #True
ForEach Desktop()
If Desktop()\nom_utilisateur = nom$
ok_1 = #False
Break
EndIf
Next
If ok_1 = #False
MessageRequester("Erreur", "Spécifiez un nom de bureau différent, celui-ci existe déjà")
Else
If FileSize(GetGadgetText(4)) <= 0
MessageRequester("Erreur", "Le Shell n'existe pas")
Else
nombredesktopmax.l = 0
For a = 1 To MapSize(Desktop())
ok.b = #True
ForEach Desktop()
If Desktop()\numero = a
ok = #False
Break
EndIf
Next
If ok = #True
nombredesktopmax = a
Break
EndIf
Next
nom_bureau$ = "bureau_" + Str(nombredesktopmax)
;{ on arrete de mettre à jour la defilante pour eviter les bug
; _exit_thread_affichage_serie = #True
; WaitThread(thread_dessin_miniature)
PauseThread(thread_dessin_miniature)
;}
AddMapElement(Desktop(), nom_bureau$)
Debug "---"
Debug nom_bureau$
Debug "AddMapElement(Desktop(), nom_bureau$)"
With Desktop(nom_bureau$)
\nom = nom_bureau$
\nom_utilisateur = nom$
\numero = nombredesktopmax
\programme = GetGadgetText(4)
\dossier_bureau = GetUserProfileDirectory() + nom_bureau$ + "\" ; pour le moment
\wallpaper = GetGadgetText(6)
Debug "\wallpaper = GetGadgetText(6)"
\hd_miniature = DesktopSnapShot(taille_max_snapshot, taille_max_snapshot, 100 + \numero)
If StartDrawing(ImageOutput(\hd_miniature))
Box(0, 0, ImageWidth(\hd_miniature), ImageHeight(\hd_miniature), #White)
StopDrawing()
EndIf
Debug "StopDrawing()"
handle.Long\l = 0
OpenDesktop(\nom, @handle)
Debug "OpenDesktop(\nom, @handle)"
\hd_bureau = handle\l
If \hd_bureau = 0
MessageRequester("Erreur Fatale", "Impossible de créer le Bureau " + nom$ + "." + "Essayez de changer les permissions du programme.")
FreeImage(\hd_miniature)
DeleteMapElement(Desktop())
EndIf
CreateDirectory(GetUserProfileDirectory() + nom_bureau$)
Debug "CreateDirectory(GetUserProfileDirectory() + nom_bureau$) : " + GetUserProfileDirectory() + nom_bureau$
res = CreateProcess(\programme, GetUserProfileDirectory() + nom_bureau$, nom_bureau$, @information_process.PROCESS_INFORMATION)
Debug "CreateProcess " + Str(res)
Delay(1000)
Debug "fin delay"
\thread = CreateThread(@ThreadRaccourcisClavier(), @nom_bureau$)
Debug "Thread créer : " + Str(\thread)
EndWith
;{ on reprend l'affichage des miniatures
; _exit_thread_affichage_serie = #False
; thread_dessin_miniature = CreateThread(@Affiche_miniature_deroulante(), image_defilante)
ResumeThread(thread_dessin_miniature)
_desktop_affiche_actuellement = nombredesktopmax
;}
EndIf
EndIf
EndIf
;}
EndSelect
EndIf
Until event = #PB_Event_CloseWindow
Debug "on sort de la fenetre de parametre"
;}
;{ clean up
_exit_thread_affichage_serie = #True
If IsThread(thread_dessin_miniature)
WaitThread(thread_dessin_miniature)
EndIf
FreeImage(image_defilante)
CloseWindow(0)
;}
IS_PARAMETRE_BEING_SET = #False
ProcedureReturn 1
EndProcedure
Macro Parametre()
If IS_PARAMETRE_BEING_SET = #False
IS_PARAMETRE_BEING_SET = #True
thread_parametre = CreateThread(@Fenetre_Parametre(), 0)
EndIf
EndMacro
;}
Procedure SwitchDesktop(num.l)
If IS_PARAMETRE_BEING_SET = #False
DesktopSnapShot(taille_max_snapshot, taille_max_snapshot, Desktop(Bureau_ACTUEL)\hd_miniature)
ok.b = #False
ForEach Desktop()
If Desktop()\numero = num
ok = #True
Break
EndIf
Next
If ok = #False : ProcedureReturn 0 : EndIf
Bureau_ACTUEL = Desktop()\nom
SwitchDesktop_(Desktop(Bureau_ACTUEL)\hd_bureau)
EndIf
EndProcedure
Procedure ThreadRaccourcisClavier(*adresse)
SetThreadDesktop_(Desktop(PeekS(*adresse))\hd_bureau)
Debug PeekS(*adresse)
Define desktop_in_thread.Bureau
CopyStructure(@Desktop(PeekS(*adresse)), @desktop_in_thread, Bureau)
; key = #VK_1
; Select desktop_in_thread\numero
; Case 1 : key = #VK_2
; Case 2 : key = #VK_3
; Case 3 : key = #VK_4
; Case 4 : key = #VK_5
; Case 5 : key = #VK_6
; Case 6 : key = #VK_7
; Case 7 : key = #VK_8
; Case 8 : key = #VK_9
; Case 9 : key = #VK_0
; EndSelect
Repeat
Delay(25)
If Bureau_ACTUEL = desktop_in_thread\nom
num = -1
If GetAsyncKeyState_(#VK_1) <> 0 : num = 0
ElseIf GetAsyncKeyState_(#VK_2) <> 0 : num = 1
ElseIf GetAsyncKeyState_(#VK_3) <> 0 : num = 2
ElseIf GetAsyncKeyState_(#VK_4) <> 0 : num = 3
ElseIf GetAsyncKeyState_(#VK_5) <> 0 : num = 4
ElseIf GetAsyncKeyState_(#VK_6) <> 0 : num = 5
ElseIf GetAsyncKeyState_(#VK_7) <> 0 : num = 6
ElseIf GetAsyncKeyState_(#VK_8) <> 0 : num = 7
ElseIf GetAsyncKeyState_(#VK_9) <> 0 : num = 8
ElseIf GetAsyncKeyState_(#VK_0) <> 0 : num = 9
EndIf
If GetAsyncKeyState_(#VK_CONTROL) <> 0
If num <> -1
SwitchDesktop(num)
Debug desktop_in_thread\nom + " switch to : " + Str(num)
Else
If GetAsyncKeyState_(#VK_F3) <> 0
Parametre()
Debug desktop_in_thread\nom + " Show parameter"
EndIf
If GetAsyncKeyState_(#VK_F12) <> 0 : EXIT_PROGRAM = #True : EndIf ; à virer ensuite
EndIf
EndIf
EndIf
Until EXIT_PROGRAM = #True
EndProcedure
;}
;{ on récupère le nom de l'utilisateur qui a lancé le programme
USER = GetUserName()
; à chaque changement de bureau, on va tester l'utilisateur.
; Si l'utilisateur courant n'est pas celui qui a lancé l'application,
; alors on ne fait rien.
; il faut fonctionner comme cela, pour éviter que les différentes sessions
; ne crée de problème avec tout les desktops. (hypothèque)
; c'est peut-être inutile, cependant, tant que je n'ai pas fait de test,
; c'est l'inconnu.
;}
;{ initialisation de la liste
thread_parametre.l = 0
If ReadFile(0, currentdirectory$ + InitFile$)
Else ; le fichier d'init n'existe pas, il faut montrer la fenêtre des paramètres à l'utilisateur
; on initialise le bureau par defaut
AddMapElement(Desktop(), Bureau_ACTUEL)
With Desktop()
\nom = Bureau_ACTUEL
\nom_utilisateur = "Bureau par Défaut"
\numero = 0
\programme = GetWindowsDirectory() + "\explorer.exe"
\dossier_bureau = GetUserProfileDirectory() + "Bureau\"
\wallpaper = ""
\hd_miniature = DesktopSnapShot(taille_max_snapshot, taille_max_snapshot, 100 + \numero)
\hd_bureau = OpenDesktop_(\nom, 0, #True, #GENERIC_ALL)
If \hd_bureau = 0
MessageRequester("Erreur Fatale", "Impossible d'accéder au Bureau par Défaut." + "Essayez de changer les permissions du programme.")
End
EndIf
\thread = CreateThread(@ThreadRaccourcisClavier(), @Bureau_ACTUEL)
EndWith
Parametre()
EndIf
;}
;{ boucle principale d'attente
is_one_thread_active.b = #True
EXIT.b = #False
Repeat
If is_one_thread_active = #False ; on tourne 2 fois pour être sur que les threads sont tous finis
EXIT = #True
Else
EXIT = #False
EndIf
is_one_thread_active.b = #False
If IsThread(thread_parametre)
WaitThread(thread_parametre)
is_one_thread_active = #True
EndIf
ForEach Desktop()
If IsThread(Desktop()\thread)
WaitThread(Desktop()\thread)
is_one_thread_active = #True
EndIf
Next
Until EXIT = #True And is_one_thread_active = #False
;}
End