Als Ergänzung wollen wir noch den Bereich eines UpDown-Controls setzen. Damit ist der minimale und der maximale Wert gemeint. Im Fall unseres Beispielprogramms richten sich die Werte allerdings nach der Länge des Strings im Eingabefeld.
Unsere Grundlage ist ja das bekannte Eingabefeld-Beispiel, in dem wir mit Hilfe der beiden neuen UpDown-Controls nur das Aussehen zweier Eingabefelder leicht verändert haben:

Wir müssen also den Bereich des ersten UpDown-Controls von Null bis zur Stringlänge minus Eins, und den Bereich des zweiten UpDown-Controls von Eins bis zur Stringlänge einstellen. Damit kann das erste Control nie das tatsächliche Ende des Strings erreichen, und das zweite kann nie den Anfang des Strings erreichen. Im Code sieht das so aus:
SendMessage(hTrack1,UDM_SETRANGE32,0, SendMessage(hwndEdit1,WM_GETTEXT,sizeof(buffer),LPARAM(@buffer)) - 1); SendMessage(hTrack2,UDM_SETRANGE32,1, SendMessage(hwndEdit1,WM_GETTEXT,sizeof(buffer),LPARAM(@buffer)));
Setzt man den Bereich mit "UDM_SETRANGE/UDM_SETRANGE32" nicht, so reagiert das UpDown-Control etwas merkwürdig. Klickt man auf den "Nach oben"-Pfeil, werden die Werte kleiner ... und umgekehrt. Erst wenn man den Bereich festlegt, reagiert das Control wie man es erwartet. Dass das bei Microsoft noch niemanden aufgefallen ist. :o(
Außerdem legen wir die Position des zweiten Controls auf den minimalen Wert fest:
SendMessage(hTrack2,UDM_SETPOS,0,MAKELONG(1,0));
Es wäre des weiteren möglich, die Werte hexdezimal anzuzeigen. Im Beispielprogramm nutzt uns diese Funktion allerdings nicht wirklich etwas, aber aussehen könnte der Aufruf so:
SendMessage(hTrack1, UDM_SETBASE, 16, 0); // for real programmers only :o)
Mehr Informationen und weitere Nachrichten finden Sie im MSDN oder im PSDK.
Für unser Beispiel wollen wir nur noch auf die Benachrichtigung "UDN_DELTAPOS" eingehen. Wir wollen sie benutzen und die Position des zweiten UpDown-Controls automatisch vergrößern, damit sein Wert nicht kleiner als der des ersten Controls sein kann. Diese Kontrolle benötigen wir auch, wenn die Position des zweiten UpDown-Controls verringert wird. In diesem Fall muss die Position des ersten Controls ggf. angepasst werden.
Die Benachrichtigung wird in Form einer "WM_NOTIFY"-Nachricht übergeben und enthält im lParam einen Zeiger auf folgendes Record:
typedef struct _NM_UPDOWN {
NMHDR hdr;
int iPos; // aktuelle Position
int iDelta; // erwartete Änderung
}
Für uns ist dabei besonders der Wert iDelta interessant: wird der "Nach oben"-Pfeil angeklickt, enthält er einen positiven Wert, andernfalls einen negativen. Im Fall des ersten UpDown-Controls sieht unsere Kontrolle dann so aus:
WM_NOTIFY:
with PNMUPDOWN(lp)^ do
if(hdr.code = UDN_DELTAPOS) then
if(hdr.hwndFrom = hTrack1) then
begin
if(iDelta >= 0) then
begin
SelEnd := LOWORD(SendMessage(hTrack2,UDM_GETPOS,0,0));
if(SelEnd <= iPos + 1) then
SendMessage(hTrack2,UDM_SETPOS,0,MAKELONG(iPos + 2,0));
end;
end
Die Benachrichtigung wird vor der tatsächlichen Positionsänderung des Controls gesendet. Aus dem Grund enthält "iPos" die aktuelle Position des Controls, und wir müssen für unseren Vergleich den Nachfolger dieses Wertes heranziehen. Demzufolge ist bei einer Änderung der Position des zweiten UpDown-Controls auch der Nachfolger des Nachfolgers zu übergeben ... :o)
Das trifft dann natürlich auch für die Kontrolle des zweiten UpDown-Controls zu; nur dass es hier der Vorgänger ist, den wir prüfen müssen, bzw. der Vorgänger des Vorgängers, den wir als neue Position des ersten Controls angeben müssen:
else if(hdr.hwndFrom = hTrack2) then
begin
if(iDelta < 0) then
begin
SelEnd := LOWORD(SendMessage(hTrack1,UDM_GETPOS,0,0));
if(SelEnd >= iPos - 1) then
SendMessage(hTrack1,UDM_SETPOS,0,MAKELONG(iPos - 2,0));
end;
end;