Up-Down Controll in WinAPI

athomi

Commander
Mitglied seit
11.11.2001
Beiträge
191
Renomée
0
Ich bin schon wirklich verzweifelt!

Ich versuche für mein Edit Fenster ein Up-Down Controll, in WinAPI, zu
implementieren, das sich in einem Dialogfenster befindet und über ein
Menü aufgeruffen wird. Ich habe es geschaft diese automatische die im
*.rc File erstellt wird zu konfigurieren, diese reicht aber nicht.
Ich will ein Wert von 0 bis 2000 inkrementieren oder dekrementieren.
Dazu will ich diese Events abfangen die diese beidne Button (Up-Down)
erzeugen abfangen. So stelle ich mir das vor. Kann mir jemand helfen?
Mit den Hilfen in der Online Help kann ich zu dem Thema nichts
anfangen. Ein kleines Beispielprogramm währe schon ganz hilfreich.

Vielen Dank!!!
 
MSDN Online über UpDown controls

Mit UDM_SETBUDDY sagst Du dem UpDown-Control, dass es sich mit dem Edit-Control zusammentun soll. Mit UDM_SETRANGE legst Du den Bereich (0-2000) fest und mit UDM_SETPOS den aktuellen Stand. Mit UDM_SETACCEL kannst Du noch die Beschleunigung festlegen und mit UDM_SETBASE zwischen Dezimal/Hexadezimal wählen.
Wenn der User den aktuellen Wert ändert, sendet das Control ein WM_NOTIFY mit NMHDR.code = UDN_DELTAPOS.
Wo genau hakt es denn?

/e: Ach ja, schau Dir auch mal die möglichen Control Styles an.
 
Hi,

als ich diese Einstellungen im Resouce File vorgenommen hatte lies sich der Wert nur bis 100 verändern, unabhängig davon welchen Wert ich voreingestellt habe.
Irgendwie kapiere ich das nicht wo ich diese Einstellungen mit CreateUpDownControl machen soll.
 
Original geschrieben von athomi
Irgendwie kapiere ich das nicht wo ich diese Einstellungen mit CreateUpDownControl machen soll.
Zitat aus dem MSDN:
Note: This function is obsolete. It is a 16 bit function and cannot handle 32 bit values for range and position
Nimm mal lieber CreateWindowEx(), um das Control zu erzeugen.

Minimalbeispiel:
Code:
// EditBox und UpDown erzeugen
HWND hWndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL, WS_CHILD | WS_VISIBLE, 10, 10, 100, 25, hWnd, NULL, hInst, NULL);
// man beachte die UDS_*-Stile
HWND hWndUD = CreateWindowEx(0, UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_SETBUDDYINT | WS_CHILD | WS_VISIBLE, 110, 10, 25, 25, hWnd, NULL, hInst, NULL);

// UpDown konfigurieren
SendMessage(hWndUD, UDM_SETBUDDY, (WPARAM) hWndEdit, NULL);
SendMessage(hWndUD, UDM_SETBASE, (WPARAM) 10, NULL);
SendMessage(hWndUD, UDM_SETRANGE, NULL, (LPARAM) MAKELONG ((short) 2000, (short) 0));
SendMessage(hWndUD, UDM_SETPOS, NULL, (LPARAM) MAKELONG ((short) 0, 0));
Vermutlich fehlt bei Dir der Stil UDS_SETBUDDYINT.
 
Hi vielen Dank,

das Edit Fesnter habe ich aber schon mit dem Resourceeditor erstellt, jetzt soll das Up-Down Control nur hinzugefügt werden. Muss ich diese Einstellungen in dem Dialogfenster vornehmen oder in meinem Windowsfenster von dem aus das Dialogfesnter geöffnent wird?
Wo muss das Minimalprogramm eingefügt werden?


Danke!!!
 
So habe ich das ganze implementiert und das Up-Down Control wird angezeigt aber die Verknöpfung mit dem Editfenster funktioniert noch nicht, und ich habe 13 Warnungen?

case WM_INITDIALOG:
{
HWND hWndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, IDC_WERT, NULL,
WS_CHILD|WS_VISIBLE, 10, 10, 100, 25, hwnd2, NULL, hInst, NULL);

HWND hWndUD = CreateWindowEx(0, UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS
| UDS_SETBUDDYINT | WS_CHILD | WS_VISIBLE, 202, 56, 28, 24,
hwnd2, NULL, hInst, NULL);

// UpDown konfigurieren
SendMessage(hWndUD, UDM_SETBUDDY, (WPARAM) hWndEdit, NULL);
SendMessage(hWndUD, UDM_SETBASE, (WPARAM) 10, NULL);
SendMessage(hWndUD, UDM_SETRANGE, NULL, (LPARAM) MAKELONG ((short) 2000, (short) 0));
SendMessage(hWndUD, UDM_SETPOS, NULL, (LPARAM) MAKELONG ((short) 0, 0));
}
break;
 
Jetzt habe ich folgendes gemacht:

case WM_INITDIALOG:
{
/*HWND hWndEdit = CreateWindowEx(0L, IDC_HOCHSPANNUNG, 0L, WS_CHILD|WS_VISIBLE, 10, 10
, 100, 25, hwnd2, 0L, hInst, 0L);*/

HWND hwndEdit = GetDlgItem (hwnd2, IDC_HOCHSPANNUNG);

HWND hWndUD = CreateWindowEx(0L, UPDOWN_CLASS, "", UDS_ALIGNLEFT | UDS_ARROWKEYS
| UDS_SETBUDDYINT | WS_CHILD | WS_VISIBLE, 202, 56, 28, 24, hwnd2, NULL, hInst, NULL);

// UpDown konfigurieren
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwnd2,0L);
SendMessage(hWndUD, UDM_SETBASE, (WPARAM) 10, 0L);
SendMessage(hWndUD, UDM_SETRANGE, 0L, (LPARAM) MAKELONG ((int) 2000, (int) 0));
SendMessage(hWndUD, UDM_SETPOS, 0L, (LPARAM) MAKELONG ((short) 0, 0));

SetDlgItemInt(hwnd2, IDC_HOCHSPANNUNG, 1000, FALSE);

}
return TRUE;

Somit habe ich keine Warnings aber der Wert im Edit reagiert immer noch noch nicht?

Ich bitte noch um etwas Unterstützung??????????????????????

Danke!!!
 
Original geschrieben von athomi
HWND hwndEdit = GetDlgItem (hwnd2, IDC_HOCHSPANNUNG);
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwnd2,0L);
Du musst natürlich auch das Edit-Fenster als Buddy zuweisen.;)
 
Hi, so habe ich es gemacht und es funktionert zum Teil aber der Wert geht nur von 1 bis 2.000, also, wenn ich bei 999 bin dann geht es mit 1.000 weiter???

Ein neues Problem was sich ergeben hat ist, dass ich den Wert überhauptnicht mehr aus dem Editfenster nehmen und über mein UART an den Atmel senden kann??? Vorher hat es funktioniert.

So sieht es jetzt aus:

case WM_INITDIALOG:
{
HWND hwndEdit = GetDlgItem (hwnd2, IDC_WERT);

HWND hWndUD = CreateWindowEx(0L,UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS
| UDS_SETBUDDYINT | WS_CHILD | WS_VISIBLE, 202, 56, 28, 24, hwnd2, NULL, hInst, NULL);

// UpDown konfigurieren
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwndEdit,0L);
SendMessage(hWndUD, UDM_SETBASE, (WPARAM) 10, 0L);
SendMessage(hWndUD, UDM_SETRANGE, 0L, (LPARAM) MAKELONG ((LONG) 200000, (LONG) 0));
SendMessage(hWndUD, UDM_SETPOS, 0L, (LPARAM) MAKELONG ((LONG) 0, 0));

//SetDlgItemInt(hwnd2, IDC_WERT, 1000, FALSE);

}
break;

case WM_COMMAND:
{
switch( LOWORD( wParam ) )
{

case IDC_SETZEN:

GetDlgItemInt(hwndEdit, IDC_WERT, &Spng, TRUE);
//(long)Spng = atoi(Str);
CanTrans(13, Spng);

break;

Von einem Problem zu anderen :)
 
:) Hi,

das mit dem Senden funktioniert jetzt doch aber das mit den 2.000 verstehe ich noch nicht ganz???

Ciao und vielen Dank!!!
 
Ich kann mit meiner Initialisierung des Up-Down Control Ganze Zahlen darstellen und bin damit glücklich. Ich brauch aber noch eine entsprechende Initialisierung für Float-Zahlen.

So wie in diesem Programmauschnitt zu sehen kann ich die Zahlen 9.999 darstellen aber nicht
0.9999. Wie kann ich das bewerkstelligen, geht das überhaupt? Wenn ich 1000 eingebe dann macht er mit 1.0001.... weiter, warum nicht mit 0.0001? Geht das überhaup?

hwndEdit5 = GetDlgItem (hwnd1, IDC_ZEITKONSTANTE1); // Handle von EditFenster
hWndUD5 = CreateWindowEx(0,UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS
| UDS_SETBUDDYINT | WS_CHILD | WS_VISIBLE, 202, 56, 28, 24, hwnd1, NULL, hInst, NULL);
// UpDown konfigurieren
SendMessage(hWndUD5, UDM_SETBUDDY, (DWORD) hwndEdit5,0);
SendMessage(hWndUD5, UDM_SETBASE, (WPARAM) 10, 0);
SendMessage(hWndUD5, UDM_SETRANGE, 0, (WPARAM) MAKELONG ((LONG)9999,(LONG)0.0001));
SendMessage(hWndUD5, UDM_SETPOS, 0, (WPARAM) MAKELONG ( (LONG)10000,(LONG) 10000));

Danke!!!
 
Nicht dass ich wüsste - zumindest nicht von Haus aus. Da müsstest Du wennschon UDS_SETBUDDYINT rausnehmen und den Text per Hand einfügen. Also bspw. wenn Du Zahlen von 0 bis 1,0 erlauben willst mit 3 Dezimalstellen, setzt Du die Grenzen des UpDown auf 0 und 1000 und fügst einen Event-Handler für WM_NOTIFY/UDN_DELTAPOS ein, in dem Du dann das Textfeld füllst. Dort kannst Du dann bspw. 815 als 0,815 anzeigen. Ebenso müsstest Du für das Textfeld EN_CHANGE behandeln und dort den Text in Integer zurückrechnen und das UpDown per UDM_SETPOS aktualisieren.
Ist halt etwas aufwendiger und ich habe es jetzt nicht getestet, müsste aber funktionieren.
 
Hi,

ich weiss nicht so recht wie ich so ein Event-Handler einfüge soll. Meinst Du die CreateEvent() - und SetEvent() Funktionen? Mit Evenst habe ich noch nichts gemacht, habe aber nichts dagegen es zu lernen. In meinem Buch stehen diese Funktionen zusammen mit Mutex und Semaphoren, meinst Du die?

WM_NOTIFY kommt in die Case - Anweisung?

Vielen Dank!!!
 
Nee, Event-Handler war das falsche Wort. Message-Handler passt besser. Also wie man Window-Nachrichten (WM_*) behandelt ist Dir bekannt (Stichwort WinMain)? Gut. UDN_DELTAPOS wird als WM_NOTIFY gesendet. Wenn also msg == WM_NOTIFY, castet man lParam erstmal zu LPNMHDR. Wenn LPNMHDR->code == UDN_DELTAPOS, wurde das UpDown bedient und Du musst dessen aktuellen Zählerstand als Float im Textfeld anzeigen.
Ähnlich ist es bei EN_CHANGE. Diese Notification wird als WM_COMMAND gesendet. Wenn also msg == WM_COMMAND und HIWORD(wParam) == EN_CHANGE, wurde der Inhalt des Textfeldes geändert und Du musst den Zählerstand des UpDowns anpassen.
 
HI,

so habe ich versucht ds Problem zu lösen:

switch(wMsg)
{
case WM_INITDIALOG:
{

hwndEdit = GetDlgItem(hWnd,IDC_EDIT1);

hWndUD = CreateWindowEx(0, UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS |
WS_CHILD | WS_VISIBLE, 95, 10, 25, 25, hWnd, NULL, hInst, NULL);

//SendMessage(hWndUD, UDM_SETPOS, NULL, (LPARAM) MAKELONG ((long) 0, 0));

hWndUD = GetDlgItem(hWnd,IDC_SPIN2);

SetDlgItemText(hWnd, IDC_EDIT1,"123");

}
break;


case WM_NOTIFY:

if(wp == (WPARAM)IDC_SPIN2)
{
lpnmud = (LPNMUPDOWN)lp;
if(lpnmud->hdr.code == UDN_DELTAPOS)
{
GetDlgItemText(hwndEdit,IDC_EDIT1, str, 4);
x=atof(str);
if((lpnmud->iDelta)==0) x+=1;
//else if((lpnmud->iDelta)>0) x-=1;

sprintf(str,"%lf",x);
SetDlgItemText(hwndEdit, IDC_EDIT1,str);
sprintf(str,"%i",lp);
SetDlgItemText(hWnd, IDC_EDIT2,str);

return TRUE;
}
}


Leider passiert da nichts? Eigentlich doch, Wenn ich auf den SpinButton drücke, dann erscheint im IDC_EDIT1 eine "0"???
 
So, folgendes habe ich jetzt geändert und jetzt passiert auch schon was aber noch nicht das was ich gerne hätte, ich hoffe aber, dass ich es noch hinkreige:

switch(wMsg)
{
case WM_INITDIALOG:
{


//hWndUD = CreateWindowEx(0, UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS |
// WS_CHILD | WS_VISIBLE, 95, 10, 25, 25, hWnd, NULL, hInst, NULL);


hWndUD = GetDlgItem(hWnd,IDC_SPIN1);

SetDlgItemText(hWnd, IDC_EDIT1,"123");

}
break;


case WM_NOTIFY:

if(wp == (WPARAM)IDC_SPIN1)
{
SetDlgItemText(hWnd, IDC_EDIT2,"xxx");

lpnmud = (LPNMHDR)lp;
if(lpnmud->code == UDN_DELTAPOS)
{
GetDlgItemText(hWnd,IDC_EDIT1, str, 4);
x=atof(str);
if((lpnmud)<0)
x+=1;
else if((lpnmud)>0)
x-=1;

sprintf(str,"%lf",x);
SetDlgItemText(hWnd, IDC_EDIT1,str);
sprintf(str,"%i",wp);
SetDlgItemText(hWnd, IDC_EDIT2,str);

return TRUE;
}
}


SetDlgItemText(hWnd, IDC_EDIT1, "00"); //Ausgabe am Fenster

break;

Den SpinButton IDC_SPIN1 habe ich jetzt im Resource-Editor erstellt und nicht mehr mir CreateWinndowEx. Warum das jetzt funktioniert weiss ich nicht?
 
Jetzt funktioniert es so wie ich es haben wollte, jedenfalls zu 95%:

switch(wMsg)
{
case WM_INITDIALOG:
{
SetDlgItemText(hWnd, IDC_EDIT1,"0.9999");
}
break;

case WM_NOTIFY:

if(wp == (WPARAM)IDC_SPIN1)
{
lpnmud = (LPNMUPDOWN)lp;
if(lpnmud->hdr.code == UDN_DELTAPOS)
{
GetDlgItemText(hWnd,IDC_EDIT1, str, (int)sizeof(str));
x=atof(str);
if((lpnmud->iDelta)<0)
x+=0.0001;
else if((lpnmud->iDelta)>0)
x-=0.0001;

sprintf(str,"%lf",x);
len = strlen(str);
str[len-2] = '\0';
if(atof(str) > 0.9999)
{
sprintf(str,"%lf",0.9999);
str[len-2] = '\0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
if(atof(str) < 0.0001)
{
sprintf(str,"%lf",0.0001);
str[len-2] = '\0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
SetDlgItemText(hWnd, IDC_EDIT1,str);
sprintf(str,"%i",len);
SetDlgItemText(hWnd, IDC_EDIT2,str);

return TRUE;
}
}
break;


case IDC_EDIT1:
GetDlgItemText(hWnd,IDC_EDIT1, str, (int)sizeof(str));
len = strlen(str);
if(len > 6)
{
str[len-1] = '\0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
if(str[0] != '0')
{
//MessageBox(hWnd,"Falscher Wert!!!","Error", MB_OK);
str[0] = '0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
MB_OK);

break;


Ich kann eine Wert im Bereich 0.0001 - 0.9999 inkrementieren bzw. dekrementieren und ich kann max. 6 Zeichen im IDC_EDIT1 eingeben.
Weiterhin darf der erste Wert nicht ungleich "0" sein und der zweite ungleich "." aber das habe ich noch nicht eingebaut.
 
HI,

es funktioniert zwar schon mit dem SpinButton aber nur, wenn ich den Button im Resourceeditor erstelle. Ich möchte aber, dass der Button mit in das Edit Fenster eingebunden wird und dazu muss ich es mit CreateWindowEx() erstellen. Das hab ich auch gemacht aber ich weiss nicht wie ich den eingebundenen UpDownControl jetzt ansprechen kann.
Ich meine, der hat ja kein Namen co wie der, den ich im Resourceeditor erstellt habe (IDC_SPIN1).

case WM_INITDIALOG:
{
hwndEdit = GetDlgItem (hWnd, IDC_EDIT1); // Handle von EditFenster

hWndUD = CreateWindowEx(0L,UPDOWN_CLASS, NULL, UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS
| WS_CHILD | WS_VISIBLE, 202, 56, 28, 24, hWnd, NULL, hInst, NULL);
// UpDown konfigurieren
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwndEdit,0L);
//SendMessage(hWndUD, UDM_SETBASE, (WPARAM) 10, 0L);
//SendMessage(hWndUD, UDM_SETRANGE, 0L, (LPARAM) MAKELONG ((LONG) 4095, (LONG) 0));
//SendMessage(hWndUD, UDM_SETPOS, 0L, (LPARAM) MAKELONG ((LONG) 0, 0));
//SetDlgItemInt(hwnd1, IDC_MITTENKANAL1, 364, FALSE); // DefaultWert


SetDlgItemText(hWnd, IDC_EDIT1,"0.9999");
}
break;

case WM_NOTIFY:

if(wp == (WPARAM)IDC_SPIN1)
{
lpnmud = (LPNMUPDOWN)lp;
if(lpnmud->hdr.code == UDN_DELTAPOS )
{
GetDlgItemText(hWnd,IDC_EDIT1, str, (int)sizeof(str));
x=atof(str);
if((lpnmud->iDelta)<0)
x+=0.0001;
else if((lpnmud->iDelta)>0)
x-=0.0001;

sprintf(str,"%lf",x);
len = strlen(str);
str[len-2] = '\0';
if(atof(str) > 0.9999)
{
sprintf(str,"%lf",0.9999);
str[len-2] = '\0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
if(atof(str) < 0.0001)
{
sprintf(str,"%lf",0.0001);
str[len-2] = '\0';
SetDlgItemText(hWnd, IDC_EDIT1,str);
}
SetDlgItemText(hWnd, IDC_EDIT1,str);
sprintf(str,"%i",len);
SetDlgItemText(hWnd, IDC_EDIT2,str);

return TRUE;
}
}
break;8

Wenn ich also das Programm Starte habe ich zwei SpinButton aber nur der im Resouceeditor erstellt funktioniert, der ander reagiert nicht. Wie kann ich auf den zugreifen. Mein Problem war, dass ich den Wert als Fliesskommazahl darstellen und verändern möchte, was auich schon funktioniert aber eben mit der geschilderten Einschränkung.

Weiss jemand wie ich das machen könnte???

Danke!
 
Warum machst Du eigentlich jedes Mal einen neuen Thread auf??? Das ist jetzt schon der 3. zum UpDown-Control!

@Topic:
Um
Code:
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwndEdit,0L);
nutzen zu können, muss man das UpDown nicht per CreateWindowEx() erzeugen. Alles was Du brauchst, ist das Window-Handle des UpDowns (hWndUD) und das bekommst Du doch normalerweise auch per GetDlgItem(). Sorry, ich kann da kein Problem erkennen.
 
Irgendiwe habe ich immer das Gefühlt, dass keine mehr auf alte Treads antwortet und deswegen der neue Thread.

Jetzt habe ich das Handle erzeugt: hWndUD = GetDlgItem (hWnd, IDC_SPIN1);

Nach diesem Zug sollte das UpDownControl jetzt in das Editfenster eingebunden sein?
Das hat leider noch nicht geklappt.
 
Hast Du wirklich das hier dastehen?
Code:
HWND hWndUD = GetDlgItem (hWnd, IDC_SPIN1);
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hwndEdit,0L);
 
Hi,

ich habe das jetzt so stehen und es funktionier leider noch nicht.

case WM_INITDIALOG:
{
hWndEdit = GetDlgItem (hWnd, IDC_EDIT1); // Handle von EditFenster
hWndUD = GetDlgItem (hWnd, IDC_SPIN1);
SendMessage(hWndUD, UDM_SETBUDDY, (LONG) hWndEdit,0L);

SetDlgItemText(hWnd, IDC_EDIT1,"0.9999");
}
break;


Muss man da vielleicht auch was mit der UPDOWN_CLASS machen?
 
Original geschrieben von TiKu
Warum machst Du eigentlich jedes Mal einen neuen Thread auf??? Das ist jetzt schon der 3. zum UpDown-Control!

Jep, 2 reichen aus, und desswegen hab ich das hier mal etwas zusammengetackert ;).

Und weil 2 eigentlich auch zuviel sind und sich der Thread so nun schön um das Thema Up-Down Control dreht hab ich gleich einen draus gemacht ;).
 
Und kennst Du zufällig auch die Lösung für mein UpDown Control Problem?

Mfg,

Athomi
 
Zurück
Oben Unten