Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

spiderX

Frischling

  • »spiderX« ist der Autor dieses Themas

Beiträge: 4

Wohnort: München

  • Private Nachricht senden

1

06.11.2006, 12:02

(Verständnis-) Problem mit GetClientRect() unter Win32

Hallo Leute,


Die Situation:
Modeless Dialog mit einer Textbox (EDITTEXT) mit dem Resourceneditor erstellt und als Win32 Anwendung kompiliert.

Wie kann ich im Programm die X/Y-Position der Textbox feststellen, so wie sie auch im Resource File angegeben ist?
Zur Kontrolle möchte ich einfach nur Koodinaten und Größe der Textbox lesen und unverändert wieder mittels MoveWindow() oder SetWindowPos() setzen. Dabei soll sich die Textbox nicht verschieben - tut sie aber doch!

Versuche wie das Client Rectangle und Windows Rectangle zu holen und X/Y zu addieren wie ...

Quellcode

1
2
3
4
5
6
7
8
...
GetClientRect(hCtl, &rectCli);
GetWindowRect(hCtl, &rectWin);
...
leftCtl=rectCli.left+rectWin.left;  // X-Pos des Controls, relativ z. Dialog,
                                    // oder doch nicht?
topCtl=rectCli.top+rectWin.top;     // Y-Pos des Controls
...


schlagen fehl. Zusätzliche Versuche mit ClientToScreen(...) bringt auch nichts. Mit "Augenmaß" habe ich bemerkt, dass u. a. die Höhe der Titelleiste des Dialoges eine Rolle spielt (ist aber nur unbestätigtes Halbwissen).
Ich bin mit meinem Latein langsam am Ende, hat jemand einen Tipp?
Danke schon mal vorab.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

06.11.2006, 16:17

Ich glaube GetClientRect reicht. GetWindowRect brauchst du nicht.
Also einfach die Koordinaten, die du von GetClientRect bekommst, wieder für SetWindowPos/MoveWindow benutzen.

spiderX

Frischling

  • »spiderX« ist der Autor dieses Themas

Beiträge: 4

Wohnort: München

  • Private Nachricht senden

3

06.11.2006, 17:27

danke für dein schnelles Feedback.

GetClientRect() leifert als Ursprung leider immer (0, 0), da es das/den? Handle des zu bestimmenden Controls erwartet und in rect.right und rect.bottom dessen Breite und Höhe zurückgibt. Naja, und diese Koordinaten in MoveWindow() eingesetzt bewegen das Control halt in die Ecke ganz links oben.

Zum Hintergrund: Als Ergänzung zu deinem tbWriteToLog(..) baue ich ein Fensterchen, um Loggingdaten in Echtzeit zu sehen. Speziell beim Loggen von sehr vielen Einträgen wie sie z. B. tbResult Render(..) produziert, wird Ruck Zuck das Logfile (zwar schön formatiert, aber) riesengroß. Und in diesem Fensterchen sollen beim Resizen eben alle EDIT-Controls mit ge-resized werden. Genug der Prosa - sorry!


Danke, Peter
Die Wahrheit ist die Geschichte des besseren Lügners.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

4

06.11.2006, 17:42

GetWindowRect(hCtl, &rectWin); liefert sowohl die obere linke und die untere rechte Ecke in Bildschirmkoords. GetWindowRect ist also das was du suchst. Die Breite und Höhe des Fenster rechnet man einfach per right - left bzw. bottom - top aus.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

5

06.11.2006, 17:49

Nachtrag(Pseudocode):

C-/C++-Quelltext

1
2
GetWindowRect(hMain, &rectWin); 
SetWindowPos(hChild, HWND_TOP, rectWin.left + relPosX, rectWin.top + relPosY, (rectWin.right - rectWin.left) * ProzentGroesseX, (rectWin.bottom - rectWin.top) * ProzentGroesseY, 0); 


viell. hilft es dir ja ein bisschen weiter ;)
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

6

06.11.2006, 17:58

Du musst halt nur beachten das das Window-Rect noch die Menübar, den Rand und die Titelleite usw mitberechnet ... Client-Rect ist nur der Bereich innerhalb deines Fensters. Zum Zeichnen wirdnormalerweise die pos innerhalb des Controls genutzt. gib doch bei GetClientRect einfach die Pos des Parent Wnds an und Move dann das Childwindow ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

spiderX

Frischling

  • »spiderX« ist der Autor dieses Themas

Beiträge: 4

Wohnort: München

  • Private Nachricht senden

7

06.11.2006, 18:15

danke für deinen engagierten Einsatz.

GetWindowRect(hCtl, &rectWin); war auch meinGedanke, wenn ich allerdings

C-/C++-Quelltext

1
2
3
4
5
6
7
8
GetWindowRect(hCtl, &rectWin);
MoveWindow(hCtl,
           rWin.left,
           rWin.top,
           rWin.right-rWin.left,
           rWin.bottom-rWin.top,
           TRUE
          );


wiederholt Aufrufe wandert die Textbox bei jedem Mal ein Stück weiter nach rechts unten (mit rWin.right-rWin.left und rWin.bottom-rWin.top bleibt wenigstens die Breite und Höhe unverändert). Genau relPosX und relPosY, die du elegant reingeschummelt hast ;) scheint des Pudels Kern zu sein - wie bekommst du denn die Linke obere Ecke des Dialoges raus?

Mit...

C-/C++-Quelltext

1
2
3
4
5
RECT relPos;

GetWindowRect(m_hDlg, &relPos);  // dialog pos

// oder

GetClientRect(m_hDlg, &relPos);  // dialog pos


...klappt es leider nicht. Darüber hinaus liefern diese beiden Aufrufe verschiedene Koordinaten, auch, wenn er gesamte Dialog auf Screenposition (0, 0) steht, was meine Verwirrung nur weiter steigert.
Die Wahrheit ist die Geschichte des besseren Lügners.

8

06.11.2006, 19:32

Warte mal dein Code ist doch Quatsch... du verschiebst mit MoveWindow ja ein Client Window im parent Window ... d.h. brauchst du die Client Koordinaten des Parent Wnds ...

C-/C++-Quelltext

1
2
3
4
5
::RECT rcClient; // Client Rect

::RECT rcControl; // Control Rect - wird für die Breite/Höhe des Controls gebraucht...

::GetClientRect(hWndParent, &rcClient); // Client Rect des Parent Wnds

::GetWindowRect(hWndControl, &rcControl); // Rect des Controls

::MoveWindow(hWndControl, rcClient.left + 20, rcClient.top + 10, rcControl.right - rcControl.left, rcControl.bottom - rcControl.top, TRUE);
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

spiderX

Frischling

  • »spiderX« ist der Autor dieses Themas

Beiträge: 4

Wohnort: München

  • Private Nachricht senden

9

08.11.2006, 11:34

deine Anregung, Deviloper, hat mich auf die richtige Fährte gebracht, du bist ziemlich nah' dran. Habe noch etwas Grundlagenforschung betrieben und fasse für jeden, den's interessiert zusammen (das Parent Window ist, wie gesagt, ein nicht modaler Dialog, auf dem ein EDIT-Control sitzt, alles zusammen in einem RSC-File definiert).

Es gibt 2 verschiedene Maßeinheiten, die hier interessant sind:

1) Dialog-Box-Template Einheit (im Resource File verwendet)
2) Bildschirm Pixel Einheit (am Bildschirm verwendet)
2a) Dialog-Box Pixel
2b) Screen Pixel

1) und 2) sind über Skalierung/Multiplikation miteinander verbunden, deren Faktoren für X und Y obendrein unterschiedlich sind. Der Skalierungsfaktor X basiert auf der durchschnittlichen Buchstabenbreite in Pixel, die wiederum vom aktuell eingestellten Dialog-Font abhängt. Der Skalierungsfaktor Y basiert auf der Höhe des Dialog-Fonts (Ascent + Descent). Die Skalierungsfaktoren basieren! auf den genannten Font-Metrics und sind nicht identisch damit.

2a) und 2b) sind über einen Offset verbunden. X- und Y-Offset sind hier auch unterschiedlich und abhängig von Höhe der Titeleiste bzw. der Breite des Dialograhmens.


Umrechnung von 1) in 2b) geht am einfachsten mit MapDialogRect(HWND hDlg, LPRECT lpRect), wie im nächsten Beispiel gezeigt (der masochistische Weg mit GetDialogBaseUnits() usw. ist nur aufwändig und bringt nichts).


Auszug aus dem Resource File:

C-/C++-Quelltext

1
2
3
    ...
    EDITTEXT        IDC_OUT,19,52,319,98,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,WS_EX_CLIENTEDGE
    ...


Umrechnung von Dialog-Box-Template Einheit in Screen-Pixel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    RECT r;

    r.left=19;
    r.top=52;
    r.right=319;
    r.bottom=98;
    MapDialogRect(m_hDlg, &r); // Hier Handle des Dialoges, nicht des  Controls

    MoveWindow(hCtl,
               r.left,         // ist jetzt (bei mir) 29

               r.top,          // ist jetzt (bei mir) 85

               r.right,        // ist jetzt (bei mir) 479

               r.bottom,       // ist jetzt (bei mir) 159

               TRUE            // repaint

               );


Die Kopplung von Größe und Lage der Controls eines Dialoges an den aktuell eingestellten Font-Size macht Sinn, da sich ja bei Änderung des Fonts der Dialog entsprechend mitändert. Das Ergebnis von MapDialogRect(..) wird also fom aktuellen Font beeinflusst.


Automatische Berechnung der Koodrinaten eines Controls, z. B. um es in WM_SIZE zu verschieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    RECT rCtlWin;                   // Koordinaten des Controls

    POINT p0;

    GetWindowRect(hCtl, &rCtlWin);  // Koordinaten relativ zum Parent Window und nicht zum

                                    // Ursprung des Screens, wie es fälschlich im SDK steht

                                    // hier lag mein Problem!


    
    // Breite des Rahmens und Höhe der Titelleiste des Parent Windows berechnen

    p0.x=0;
    p0.y=0;                         // Ursprung der Dialog-Client area ...

    ClientToScreen(m_hDlg, &p0);    // ... in Screenkoordinaten wandeln (Dialog-Handle verwenden)

                                    // --> p0.x = Breite der linken Border in Pixel

                                    // --> p0.y = Höhe derTitle bar in Pixel


    MoveWindow(
            hCtl,
            rCtlWin.left-p0.x,           // Breite der linken Border des Dialoges abziehen

            rCtlWin.top-p0.y,            // Höhe der Titelbar des Dialoges abziehen

            rCtlWin.right-rCtlWin.left,  // .right in Breite des Controls umrechnen

            rCtlWin.bottom-rCtlWin.top,  // .bottom in Höhe des Controls umrechnen

            TRUE                         // repaint

            );
Die Wahrheit ist die Geschichte des besseren Lügners.

Werbeanzeige