Entwickler-Ecke
Open Source Units - Desktopverwaltungsunit
Dezipaitor - Fr 02.02.07 21:40
Titel: Desktopverwaltungsunit
hi,
ich habe eine Unit geschrieben, die es ermöglicht eigene Windows Desktops zu verwalten.
Die Units sind von mir (bis auf compilers.inc) und in ANSI und Unicode aufgeteilt.
So ziemlich alles ist in Englisch kommentiert und auch mit Beispielen versehen.
Die verwendete Lizenz ist
Creative Commons [
http://creativecommons.org/licenses/by-nc-sa/2.0/de]
# Namensnennung. Sie müssen den Namen des Autors/Rechtsinhabers nennen.
# Keine kommerzielle Nutzung. Dieser Inhalt darf nicht für kommerzielle Zwecke verwendet werden.
# Weitergabe unter gleichen Bedingungen. Wenn Sie diesen Inhalt bearbeiten oder in anderer Weise umgestalten, verändern oder als Grundlage für einen anderen Inhalt verwenden, dann dürfen Sie den neu entstandenen Inhalt nur unter Verwendung identischer Lizenzbedingungen weitergeben.
1. Achtung!
Die aktuelle Version ist noch im Betastatus, da ich noch nicht lange Testen konnte.
2. Achtung!
Teste deine Desktopverwaltung auf einem zweiten PC oder in einer VM (auch über Remotedebugging). Sollte dein Programm unter Delphi eine Exception werfen, so zeigt Delphi die Quellcodezeile an. Da jedoch der Desktop in diesem Moment nicht zurückgesetzt wird, kommst du nicht zu Delphi und kannst daher auch nicht fortsetzen.
Der Desktop wird automatisch geschlossen, sobald deine Anwendung beendet wird.
Man kann daher auch über Telnet (o.Ä.) die Anwendung abschießen.
Bekannte Bugs :
In einigen Fällen bekomme ich bei der Erstellung eines neuen Desktops die Ausnahmen, dass nicht genügend Speicher zur Verfügung steht.
Ein Auszug aus
CreateDesktop [
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createdesktop.asp] beschreibt vermutlich die Ursache.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| The number of desktops that can be created is limited by the size of the system desktop heap, which is 48 MB. Desktop objects use the heap to store resources. You can increase the number of desktops that can be created by reducing the default heap reserved for each desktop in the interactive window station. This value is specified in the SharedSection substring of the following registry value: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\Windows. The default data for this registry value is as follows:
%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16
The first SharedSection value is the size of the shared heap common to all desktops, in kilobytes. The second SharedSection value is the size of the desktop heap needed for each desktop that is created in the interactive window station, WinSta0, in kilobytes. The third SharedSection value is the size of the desktop heap needed for each desktop that is created in a noninteractive window station, in kilobytes. |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163:
| TDesktop = class(TPersistent) public constructor Create(const aParent : TDesktops; const aFlag : TCreationFlag; const aCloseOnDestroy : Boolean; const aName : WideString; const DesktopFlags : TDesktopFlags; const doInherit : Boolean; const aDesiredAccess : ACCESS_MASK; const aSecurityDescriptor : PSECURITYATTRIBUTES);
constructor CreateUnInitialized(const aParent : TDesktops; const aName : WideString);
destructor Destroy; override;
function OpenDesktopByName(const DesktopFlags : TDesktopFlags; const doInherit : Boolean; const aDesiredAccess : ACCESS_MASK) : HDESK; overload; virtual;
function DesktopFlagsToInt(DesktopFlags : TDesktopFlags) : Cardinal;
function GetDesktopWindowHandles : TList; virtual;
function OpenInputDesktop(const DesktopFlags : TDesktopFlags; const doInherit : Boolean; const aDesiredAccess : ACCESS_MASK) : HDESK; virtual;
procedure Close; procedure SetThreadDesktop; procedure SwitchDesktop; procedure SwitchDesktopBack;
published property Name : WideString read GetName; property DesiredAccess : ACCESS_MASK read fDesiredAccess; property SecurityDescriptor : TSECURITYATTRIBUTES read RetrieveSD; property Handle : HDESK read fHandle; property DesktopFlags : TDesktopFlags read GetDesktopFlags write SetDesktopFlags; property IsInputDesktop : Boolean read fIsInputDesktop;
property Parent : TDesktops read fParent; property CloseOnDestroy : Boolean read fCloseOnDestroy write fCloseOnDestroy;
property Opened : Boolean read GetOpened; property OnDestroyDesktop : TOnDestroyDesktop read fOnDestroyDesktop write fOnDestroyDesktop; end; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164:
| TDesktops = class(TComponent) public constructor Create(AOwner: TComponent); override; destructor Destroy; override;
procedure Clear; virtual;
function FindDesktopByName(const Name : WideString) : TDesktop; virtual; function FindDesktopByHandle(const Handle : HDESK) : TDesktop; virtual; function FindInputDesktop : TDesktop; virtual;
procedure Update; function CreateDesktop(const Name : WideString; const DesktopFlags : TDesktopFlags; const aDesiredAccess : ACCESS_MASK; const aSecurityDescriptor : PSECURITYATTRIBUTES) : TDesktop; virtual;
function OpenDesktop(const Name : WideString; const DesktopFlags : TDesktopFlags; const aDesiredAccess : ACCESS_MASK; const doInherit : Boolean) : TDesktop; virtual; function OpenInputDesktop(const DesktopFlags : TDesktopFlags; const aDesiredAccess : ACCESS_MASK; const doInherit : Boolean) : TDesktop; virtual;
function GetThreadDesktop(ThreadID : Cardinal = 0) : TDesktop;
class function GetDesktopName(const desk : HDESK) : WideString;
class function GetDesktops(WindowStation : HWINSTA) : TTntStringList; overload; virtual;
class function GetDesktopHeapSize : Cardinal; virtual; published property Desktops : tObjectlist read fDesktops; property OnDestroyDesktop : TOnDestroyDesktop read fOnDestroyDesktop write fOnDestroyDesktop;
end; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| var Desktops : TDesktops; MyDesktop : TDesktop; begin Desktops := TDesktops.Create(nil); MyDesktop := Desktops.CreateDesktop() MyDesktop := Desktops.CreateDesktop('MyDesktop1' ,[], GENERIC_ALL,nil);
if Assigned(MyDesktop) then try MyDesktop.SwitchDesktop; MyDesktop.SetThreadDesktop; ...do you stuff here... finally MyDesktop.SwitchDesktopBack; MyDesktop.SetThreadDesktop; end; Desktops.Free; Desktops := nil; end; |
Demo
Angehängt habe ich ein Beispielprogram mit VCL und KOL (
http://kolmck.net/).
Das Programm zeigt auf dem Hauptdesktop ein VCL Formular an mit dem man einen Desktop erstellen kann.
Auf dem neuen Desktop wird dann mit KOL ein neues Fenster in einem neuen Thread erstellt. Im Hintegrund wird ein eingegrautes Bild des alten Desktops dargestellt, so dass der Benutzer sich nicht wundert, warum alle seine Anwendungen verschwunden sind.
Dieses Verhalten sieht man auch in Vista.
matze - Fr 02.02.07 23:58
Hallo,
könntest du evtl. ein kleines Demo-Projekt mit anhängen, damit man auch weiß wie man die Unit zu benutzen hat.
Danke.
Karlson - Sa 17.02.07 03:31
In Zukunft würde ich eine kompilierte Exe mit ins Demoprojekt legen.
Dann kann man nämlich gleich sehen ob es sich lohnt die Unit zu installieren.
Weil allgemein hört sich das ganz intressant an ;)
matze - Sa 17.02.07 11:48
ja da muss ich dir Recht geben.
@Dezipaitor: Bitte hänge doch noch eine kompilierte Exe an, damit man sich nicht zum testen extra noch KOL installieren muss.
Dezipaitor - Sa 31.03.07 22:21
KOL muss nicht installiert werden. Runterladen und in den Suchpfad einfügen - fertig.
Eine EXE Datei habe ich deshalb nicht beigelegt, weil die DEMO sinnlos wäre. Desktop wechseln,Nachrichtenbox anzeigen und dann wieder zurück.
BenBE - So 01.04.07 14:17
Ich würde mich auch über eine compilierte Version der Demo freuen.
Selbst wenn die Demo nur kurz den Desktop wechselt, so reicht das aus, dass man damit ein wenig spielen kann. ...
Ansonsten ein paar Ideen, was die Demo noch machen könnte:
- Verfügbare Desktops auslesen
- auf diese Wechseln
- Neue anlegen \ vorhandene löschen
- Fenster zwischen Desktops verschieben ...
Dezipaitor - So 01.04.07 21:10
Anbei die ausführbare DEMO zum Desktopwechseln.
Ich muss jedoch ausdrüchklich darauf hinweisen, dass vor dem Starten der Anwendung, alle Daten gespeichert werden müssen.
BenBE hat folgendes geschrieben: |
Ansonsten ein paar Ideen, was die Demo noch machen könnte:
- Verfügbare Desktops auslesen
- auf diese Wechseln
- Neue anlegen \ vorhandene löschen
- Fenster zwischen Desktops verschieben ... |
+ Verfügbare Desktops auslesen
> Auslesen der Desktops der aktuellen Winstation ist drin
+ auf diese Wechseln
> Wechseln hier nicht möglich, da die Standarddesktops geschützt sind (man kann auch eigene Desktops so schützen)
Andere Desktops würden natürlich funkzen.
+ Neue anlegen \ vorhandene löschen
> Eine Desktopverwaltung kann jeder selbst schreiben :D. Der Witz an der Sache ist, dass man in einem neuen Desktop einfach den Explorer aufrufen muss, um die Startleiste zu erhalten.
Ein Programm (in Delphi) dazu findet man dort :
http://sourceforge.net/projects/virtual-desktop
+ Fenster zwischen Desktops verschieben
> Das ist nicht möglich, weil sobald ein Prozess (oder Thread) auf einen Desktop ersteinmal ein Fenster erstellt hat, dieses nicht mehr auf einen anderen Desktop gebracht werden kann.
D.h. jeder Thread (auch der Prozessthread) kann nur dann ein Fenster auf einen Desktop erstellen, wenn er nicht bereits auf einem anderen Desktop Fenster erstellt hat. Also pro Desktop braucht ein Programm einen Thread mit der Ausgabe. Und da die VCL völlig Thread inkompatibel ist (auch mit Syncronize!!!!), muss man nonVCL programmieren (habs mit KOL gemacht).
\\BBG// - Mo 09.04.07 21:50
Könnte man nicht die gesamte Anwendung mittels Codeinjection dazu "überreden", auf einen anderen Desktop zu wandern?
Dezipaitor - Di 10.04.07 09:49
Naja, wenn du es schaffst damit die Fensterhandles zu schließen, und dann auf dem neuen Desktop erneut die Fenster zu erstellen und darzustellen, dann würde das wohl schon gehen.
Aber selbst das Schließen von Fenstern in der VCL bringt nichts, weil da immernoch irgendwas an Handles geöffnet ist. Das erstmal rauszufinden ist schon zu aufwendig.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!