Entwickler-Ecke

Windows API - GetSystemMetrics - Rahmen eines Fensters


Premaider - So 25.03.12 16:03
Titel: GetSystemMetrics - Rahmen eines Fensters
Hey Leute,
ich habe mir ein Programm geschrieben das mir ein gewünschtes Fenster in eine gewünschte Größe bringt.
Das Problem dabei ist das wenn man z.b. 1280x720 Pixel eingibt der Rahmen des Fensters mit dabei ist. Ich möchte das nur das Fenster 1280x720p hat und nicht Das Fenster+Rahmen. Wie stelle ich das mit GetSystemMetrics an ?


bummi - So 25.03.12 16:15

Dafür musst Du nur ClientWidth und Clientheight setzen ...


Premaider - So 25.03.12 16:19

Wie mache ich das ? Ich bin noch ein ziemlicher Anfänger :D


bummi - So 25.03.12 16:24

Das sind Propertys des Forms, entweder im Objektinspektor, oder per Code Form1.Clientwidth := ....


Premaider - So 25.03.12 16:27

Es ändert aber ja nicht die Größe von Form1 sondern von externen Programmen wie Minecraft oder so :D


jaenicke - So 25.03.12 18:32

Schau einfach mal in die Doku: ;-)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385.aspx
Nun musst du nur noch wissen (oder abfragen) was für ein Rand das Fenster hat, dann kannst du den entsprechenden Wert abfragen, z.B.:
Zitat:
SM_CXFIXEDFRAME
7
The thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels. SM_CXFIXEDFRAME is the height of the horizontal border, and SM_CYFIXEDFRAME is the width of the vertical border.
This value is the same as SM_CXDLGFRAME.


Premaider - So 25.03.12 20:26

Nur irgendwie muss ich die ja von einander abziehen.

Oder wäre das dann z.b. "SM_CYBORDER + 1280" und "SM_CYBORDER + 720" ?


jaenicke - So 25.03.12 20:33

user profile iconPremaider hat folgendes geschrieben Zum zitierten Posting springen:
Oder wäre das dann z.b. "SM_CYBORDER + 1280" und "SM_CYBORDER + 720" ?
Wenn du mit SM_CYBORDER das Ergebnis der Funktion GetSystemMetrics mit diesem Parameter meinst, dann fast ja.

Überlege dir zusätzlich einmal ganz genau wofür das Y stehen könnte. :zwinker:
Und wenn es dir nicht klar ist, schau in die Doku...


Premaider - So 25.03.12 21:22

Aber wenn man
GetSystemMetrics(SM_CYBORDER);
hat gibt es doch kein :=
In welcher Art und Weise hat man da ein Ergebnis ?


jaenicke - So 25.03.12 22:08

Hmm, vielleicht solltest du dir erst einmal anschauen wie Funktionsaufrufe überhaupt funktionieren...
http://www.delphi-treff.de/object-pascal/prozeduren-und-funktionen/

user profile iconPremaider hat folgendes geschrieben Zum zitierten Posting springen:
Aber wenn man
GetSystemMetrics(SM_CYBORDER);
hat gibt es doch kein :=
Wenn man das Ergebnis nirgends zuweisen will, braucht man das auch nicht. Irgendetwas musst du mit dem Wert aber machen. Ob du den nun in eine Variable packst oder direkt damit rechnest, musst du schon selbst schreiben.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  BorderHeight: Integer;
begin
  BorderHeight := GetSystemMetrics(SM_CYBORDER);
// oder direkt benutzen:
  ShowMessage('Höhe mit Rand: ' + IntToStr(720 + GetSystemMetrics(SM_CYBORDER)));
// ...


Premaider - Mo 26.03.12 17:06

Also bei mir sieht es jetzt so aus.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
var
 HWND:THandle;
 Width:Integer;
 Height:Integer;
begin
  Width:= 1280 + GetSystemMetrics(SM_CXBORDER);
  Height:= 720 + GetSystemMetrics(SM_CYBORDER);
  HWND := FindWindow(nil, PChar(Edit1.Text));
  SetWindowPos(HWND,HWND_TOPMOST,0,0,Width,Height,SWP_NOMOVE);
end;


Aber es ist immernoch 1862x682 Pixel :(


jaenicke - Mo 26.03.12 17:46

Width und Height sind relativ ungünstige Bezeichner, da es die schon als Eigenschaften des Formulars gibt.

Davon abgesehen:
Was sagt denn der Debugger? Stimmen Breite und Höhe? Bekommst du ein Handle (wird das Fenster also gefunden)?
Zudem:
Wie wäre es mit Fehlerbehandlung? Abfragen, ob das Handle gültig ist (ungleich INVALID_HANDLE_VALUE), Rückgabewert von SetWindowPos nicht einfach wegwerfen, ...


Premaider - Mo 26.03.12 17:51

Das Fenster wird gefunden alles funktioniert auch, nur es wird in 1262x682 Pixel anstatt 1280x720 Pixel gesetzt. Also der Rand des Fensters wurde nicht dazugezählt.


jaenicke - Mo 26.03.12 18:15

Was gibt SetWindowPos denn zurück und welchen Wert hatte das Handle z.B.?


Premaider - Mo 26.03.12 18:41

Wie kann ich das herrausfinden ? Meine eben mit meiner "Aussage" das, dass das Fenster sich in der Größe ändert :D


bummi - Mo 26.03.12 19:08

Kannst Du das Zielfenster manuell größer ziehen, wenn da Constraints definiert sind ist es Essig.


Premaider - Mo 26.03.12 19:10

Ja kann man manuell größer machen. Ist Minecraft :D


jaenicke - Mo 26.03.12 19:11

Wie wäre es mit Haltepunkte setzen? Dann noch die Maus über die Variable mit dem Handle halten, wenn das Programm dort ankommt. Oder Strg + F7 drücken und direkt den Namen der Variablen zur Auswertung eingeben. Hier steht ein wenig dazu:
http://www.delphi-treff.de/ueber-delphi/entwicklungsumgebung-bis-delphi-7/debugger/

Und den Rückgabewert kannst du ja auch direkt abfragen und z.B. mit ShowMessage und BoolToStr ausgeben.


Martok - Mo 26.03.12 19:18

Überleg doch mal, was du hier tust :zwinker: Nehmen wir mal dieses Bild.
aerowin

Rot markiert ist der Teil, dessen Größe du auf 1280x720 setzen möchtest.
"Außen" ist das, dessen Größe SetWindowPos ändert. Da ist also was übrig, nämlich:

Quelltext
1:
2:
3:
4:
- Rahmen links   = GetSystemMetrics(SM_CXBORDER)
- Rahmen rechts  = GetSystemMetrics(SM_CXBORDER)
- Rahmen unten   = GetSystemMetrics(SM_CYBORDER)
- Fenstertitel   = GetSystemMetrics(SM_CYCAPTION)


Wie groß ist also dein Fenster außen?


Delphi-Quelltext
1:
2:
Breite:= 1280 + 2 * GetSystemMetrics(SM_CXBORDER);
Höhe:= 720 + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION);


Eventuell kommt auf die Höhe noch ein SM_CYBORDER drauf, bin mir aber nicht sicher ob das nicht vielleicht schon in SM_CYCAPTION mitgezählt wird.


Premaider - Mo 26.03.12 19:27

Sorry, das funktioniert auch nicht. Ich habe euch mal die Projektdatein hochgeladen. Vielleicht habe ich einfach einen Fehler den ich nicht finde.

P.S. Ist es möglich, dass mein Programm nicht diesen Windows 98 Stil hat sondern so wie es vom Betriebssystem vorgesehen ist ?
(Habs hinbekommen :D) Liegt es vllt an Delphi 7 ??


Martok - Mo 26.03.12 19:51

Wichtige Lektion für Programmierer: RTFM - Read The F*ing Manual.

Wenn man mal den MSDN-Artikel zu GetSystemMetrics liest, findet man noch ein paar Abstände, die man addieren muss. Namentlich die DialogFrames, also der Teil "ganz außen", der den 3D-Eindruck erzeugt. Und die auf jeder Seite.

Damit das hier nicht nur Copy&Paste wird, Aufgabe für dich: selber finden und einbauen ;)


Premaider - Mo 26.03.12 21:21

Habe das ganze jetzt nochmal neu geschrieben, doch dann kommt immer ein Fehler.

Das Neue:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
var
 HWND:THandle;
 Breite:Integer;
 Hoehe:Integer;
 BorderWidth:Integer;
 BorderHeight:Integer;
begin
  BorderHeight:= 2 * GetSystemMetrics(SM_CXBORDER);
  BorderWidth:= GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION);
  Hoehe:= BorderHeight + SpinEdit1.Value;
  Breite:= BorderWidth + SpinEdit2.Value;
  HWND := FindWindow(nil, PChar(Edit1.Text));
  SetWindowPos(HWND,HWND_TOPMOST,0,0,Breite,Hoehe,SWP_NOMOVE);
end;


Der Fehler:

Delphi-Quelltext
1:
[Fataler Fehler] Ausgabedatei 'C:\Users\Daniel\Desktop\Delphi Projekte\HelpTool\Project1.exe' kann nicht erstellt werden                    


Was ist da los ?


jaenicke - Mo 26.03.12 21:28

Wahrscheinlich läuft die Exe noch? :gruebel: Schau mal im Taskmanager.


Premaider - Mo 26.03.12 21:31

Es läuft auf jeden Fall nicht mehr. Im Taskmanager seh ich nichts :(


jaenicke - Mo 26.03.12 21:44

Hast du den PC schon einmal neu gestartet?


Premaider - Mo 26.03.12 21:58

Werd ich. Wenn ich morgen um 5 von der Schule da bin :( wäre schön wenn bis dahin eine Lösung für das andere Problem gefunden wäre :D


Premaider - Di 27.03.12 11:26

Da ich gerade eine Freistunde habe, habe ich es nochmal neu geschrieben. Doch es bleibt wie es war. Er rechnet die Ränder nicht mit dazu :(


jaenicke - Di 27.03.12 11:37

Naja, wie sieht denn dein Quelltext aus?


Premaider - Di 27.03.12 12:01

So

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
 HWND:THandle;
 Width:Integer;
 Height:Integer;
begin
  Width:= 1280 + 2 * GetSystemMetrics(SM_CXBORDER);
  Height:= 720 + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION);
  HWND := FindWindow(nil, PChar(Edit1.Text));
  SetWindowPos(HWND,HWND_TOPMOST,0,0,Width,Height,SWP_NOMOVE);
end;


Und danke das du mir so konstant hilfst :D


jaenicke - Di 27.03.12 13:36

Womit wir wieder am Anfang dieser Seite der Diskussion angekommen wären...
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Wichtige Lektion für Programmierer: RTFM - Read The F*ing Manual.

Wenn man mal den MSDN-Artikel zu GetSystemMetrics liest, findet man noch ein paar Abstände, die man addieren muss. Namentlich die DialogFrames, also der Teil "ganz außen", der den 3D-Eindruck erzeugt. Und die auf jeder Seite.


Premaider - Di 27.03.12 13:51

Also ist der Aero Look von Win7 3D ?


jaenicke - Di 27.03.12 14:00

Ist es, ja, und vor allem handelt es sich um ein Fenster, das in der Größe verändert werden kann, [zaunpfahl=Baumstamm]also sizeable ist[/zaunpfahl].


Premaider - Di 27.03.12 14:20

Aber was ist wenn mein Programm jetzt auf einem OS ohne Aero ausgeführt wird wie WinXP dann geht das doch nicht mehr ?
€: Sieht jetzt so aus und geht auch nicht :(

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
var
 HWND:THandle;
 Width:Integer;
 Height:Integer;
begin
  Width:= 1280 + 2 * GetSystemMetrics(SM_CXEDGE);
  Height:= 720 + 2 * GetSystemMetrics(SM_CYEDGE);
  HWND := FindWindow(nil, PChar(Edit1.Text));
  SetWindowPos(HWND,HWND_TOPMOST,0,0,Width,Height,SWP_NOMOVE);
end;


Premaider - Di 27.03.12 20:23

Hat einer eine Idee warum das nicht funktioniert ? :(