Autor Beitrag
obbschtkuche
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mi 30.07.03 18:53 
Symbolleisten

Bei diesem Tutorial geht es darum, Symbolleisten zu erstellen, die der Windows-Taskleiste im Verhalten gleichen.
Die Symbolleiste soll verschiebbar sein und Maximierte Fenster sollen die Symbolleiste nicht verdecken. Wenn man jedoch das Fenster einfach per "Align"-Eigenschaft an eine Seite zwingt, überdeckt es eventuell Desktopsymbole. Deshalb muss der Arbeitsbereich angepasst werden. Beim beenden der Leiste soll der alte Bereich wiederhergestellt werden.

Um den Aktuellen Arbeitsbereich zu lesen verwenden wir die Funktion SystemParametersInfo:

Delphi Hilfe hat folgendes geschrieben:

BOOL SystemParametersInfo(
UINT uiAction, // system parameter to query or set
UINT uiParam, // depends on action to be taken
PVOID pvParam, // depends on action to be taken
UINT fWinIni // user profile update flag
);


Da wir den Arbeitsbereich lesen/schreiben wollen, ist für uns als Wert für uiAction nur "SPI_SetWorkArea" und "SPI_GetWorkArea" interessant.

Um den Arbeitsbereich in OnCreate zu lesen, deklarieren wir erst eine Variable "WorkArea" vom Typ "TRect" und schreiben anschließend folgendes in OnCreate:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.FormCreate(Sender: TObject);
begin
 // Workarea in Workarea speichern
 SystemParametersInfo(SPI_GETWorkArea, 0, @WorkArea, SPIF_SENDCHANGE);
 // Anfangs oben andocken
 DockAt(alBottom);
end;


Der dritte Parameter von SystemParametersInfo gibt in diesem Fall an, wo der Arbeitsbereich gespeichert werden soll.
Zu der Methode DockAt kommen wir gleich.
Zuerst müssen wir noch sicherstellen, dass auch wieder der alte Arbeitsbereich hergestellt wird. Dazu schreiben wir in OnDestroy:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.FormDestroy(Sender: TObject);
begin
 // Ursprüngliche Workarea wiederherstellen
 SystemParametersInfo(SPI_SetWorkArea, 0, @WorkArea, SPIF_SENDCHANGE);
end;


Hier gibt der dritte Parameter an, woraus der Arbeitsbereich gelesen werden soll.

Die Methode, die für das eigentliche Docken zuständig ist, heißt DockAt. Sie ist folgendermaßen implementiert:

ausblenden volle Höhe 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:
const
 defaultWidth = 28;
 defaultHeight = 28

var
 calign: TAlign = alnone;

procedure TForm1.DockAt(Align: TAlign);
var
 TempRect: TRect;
begin
 if calign = align then exit;
 calign := align;

 TempRect := WorkArea;
 // Fenster oben halten
 FormStyle := fsStayOnTop;
 // Kein Rand
 BorderStyle := bsNone;
 // Größe einstellen
 SetBounds(WorkArea.Left, WorkArea.Top, defaultWidth, defaultHeight);
 // Je nach Ausrichtung Workarea verkleinern und Fenster ausrichten
 case Align of
  alTop: begin
          // Breite anpassen, Höhe ist bereits auf defaultHeight.
          width := WorkArea.Right-WorkArea.Left;
          // Workarea verkleinern
          TempRect.Top := height+WorkArea.Top;
         end;
  alBottom: begin
             Width := WorkArea.right - WorkArea.left;
             Top := WorkArea.Bottom - height;
             TempRect.Bottom := WorkArea.Bottom-height;
            end;
  alLeft: begin
           height := WorkArea.Bottom-WorkArea.Top;
           TempRect.Left := width+Workarea.Left;
          end;
  alright: begin
            Height := WorkArea.bottom - WorkArea.top;
            Left := WorkArea.Right - width;
            TempRect.Right := WorkArea.Right-Width;
           end;
 end;
 // Die Workarea überschreiben
 SystemParametersInfo(SPI_SetWorkArea, 0, @TempRect, SPIF_SENDCHANGE);
end;


Zuerst überprüft DockAt, ob sich die Ausrichtung überhaupt ändert. Wenn nicht, wird sofot aus der Prozedur gesprungen.

Je nach neuer Ausrichtung wird der Arbeitsbereich verkleinert und die Position des Fensters angepasst.

Wenn das Programm jetzt ausgeführt wird, erscheint unten eine Symbolleiste. Maximierte Anwendungen sollten sie nicht überdecken.

Allerdings soll sich die Symbolleiste noch verschieben lassen. Dazu definieren wir eine Variable "MouseDown" vom Typ "Boolean", die anfangs False sein sollte, in MouseDown auf true und in MouseUp wieder auf false gesetzt wird. Da die Symbolleiste auch immer an die richtige Seite des Bildschirms gedockt werden soll, muss die Position des Mauscursors in Prozentwerte relativ zur Höhe und Breite der Blidschirmauflösung umgerechnet werden. Die Prozentwerte für die Position von links, rechts, oben und unten können dann verglichen werden, woraus sich die richtige Seite ergibt.

ausblenden volle Höhe 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:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
 oben, unten, links, rechts: real;
 mpos: TPoint;
begin
 if not fMouseDown then exit;
 // Mausposition holen
 GetCursorPos(mpos);
 with mpos do
 begin
  // Position der Maus in 100stel Prozent umrechnen
  unten := y/screen.height;
  oben := 1-unten;
  rechts := x/screen.width;
  links := 1-rechts;

  // Abhängig davon, welcher Prozentsatz der höchste ist,
  // wird die Leiste ausgerichtet.
  // Dadurch wird eine Ausrichtung wie bei der Windows-
  // Taskleiste erreicht.
  if (oben > unten) and (oben > links) and (oben > rechts) then
   DockAt(alTop)
  else if (unten > links) and (unten > rechts) then
   DockAt(alBottom)
  else if (rechts > links) then
   DockAt(alRight)
  else
   DockAt(alLeft);
 end;
end;


Ich hoffe es war nicht zu unverständlich und ich habe nichts vergessen.

Selbstverständlich sind alle Rechtschreibfehler beabsichtigt. :D
DerKladower
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Mi 04.08.04 11:13 
Bei mir funktioniert das soweit.

Wenn ich aber die Taskleiste an den Rand glatsche, bleiben einige Programme, obwohl sie maximiert sind, hinter der Leiste. Erst nachdem ich ein Programm normal und danach wieder maximiert habe, hat es die Korrekte maximal Größe.
Dennis[B]
Hält's aus hier
Beiträge: 1



BeitragVerfasst: So 03.04.05 12:29 
Hallo

Der Code selber geht sehr gut.

Es git nur zwei kleine Probleme

1) Wie kann ich auf das ändern der Workarea eingehen? Wie heißt die dann eingehende Message? Wenn ich z.B: ICQ andocke oder die Taskleiste vergrößere, dann wird mein Proggy wieder abgedockt... Wie kann ich das Problem unterbinden?
2) Einige Programme erkennen es nicht, daß die WorkArea verändert wurde. Welche Message müßte man denn an die Proggys senden?

Grüße
Dennis
Ist die Frage beantwortet? Das Problem gelöst?

Dann klicke hier, um das Thema entsprechend zu markieren!