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
);
|