Parameter Dialog: Komma anstatt Punkt

#828351
Lesenswert?

Hallo Zusammen,

ich habe in meinem Programm ein CDialog integriert.
Es soll im Feld als Parameter eine float Zahl eingegeben werden.
Das Problem, es wird Punkt anstatt Komma akzeptiert, z. B. "0.03"
wie kann eine Gleitkommazahl entwieder mit komma oder Punkt angenommen 
werden?

Danke

C/C++ Code:
----------------------------------------------------------.cpp
1
///////////////////////////////////////////////////////////////////////////// 
2
// Dialogfeld CKalibrierfaktor 
3

4

5
CKalibrierfaktor::CKalibrierfaktor(CWnd* pParent) 
6
    : CDialog(CKalibrierfaktor::IDD, pParent) 
7
{ 
8
    //{{AFX_DATA_INIT(CKalibrierfaktor) 
9
    m_fWert = 0.0f; 
10
    //}}AFX_DATA_INIT 
11
} 
12

13

14
void CKalibrierfaktor::DoDataExchange(CDataExchange* pDX) 
15
{ 
16
    CDialog::DoDataExchange(pDX); 
17
    //{{AFX_DATA_MAP(CKalibrierfaktor) 
18
    DDX_Text(pDX, IDC_txtFaktor, m_fWert); 
19
    DDV_MinMaxFloat(pDX, m_fWert, 0.f, 100.f); 
20
    //}}AFX_DATA_MAP 
21
} 
22

23

24
BEGIN_MESSAGE_MAP(CKalibrierfaktor, CDialog) 
25
    //{{AFX_MSG_MAP(CKalibrierfaktor) 
26
        // HINWEIS: Der Klassen-Assistent fügt hier Zuordnungsmakros für Nachrichten ein 
27
    //}}AFX_MSG_MAP 
28
END_MESSAGE_MAP() 
29

30
----------------------------------------------------------.h 
31

32
class CKalibrierfaktor : public CDialog 
33
{ 
34
// Konstruktion 
35
public: 
36
    CKalibrierfaktor(CWnd* pParent = NULL);   // Standardkonstruktor 
37

38
// Dialogfelddaten 
39
    //{{AFX_DATA(CKalibrierfaktor) 
40
    enum { IDD = IDD_DLGFaktor }; 
41
    float    m_fWert; 
42
    //}}AFX_DATA 
43

44

45
// Überschreibungen 
46
    // Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen 
47
    //{{AFX_VIRTUAL(CKalibrierfaktor) 
48
    protected: 
49
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung 
50
    //}}AFX_VIRTUAL 
51

52
// Implementierung 
53
protected: 
54

55
    // Generierte Nachrichtenzuordnungsfunktionen 
56
    //{{AFX_MSG(CKalibrierfaktor) 
57
        // HINWEIS: Der Klassen-Assistent fügt hier Member-Funktionen ein 
58
    //}}AFX_MSG 
59
    DECLARE_MESSAGE_MAP() 
60
};
#828405
Lesenswert?

Besteht die Gefahr, daß deine Benutzer mit 1000-er Seperatoren
arbeiten?
Wenn ja, dann gibt es keine wirklich gute Lösung dafür. Allerdings
sollte man ihnen das IMHO sowieso abgewöhnen. Führt in der Praxis
immer wieder zu Ärger.

Zu deinem Problem.
Die MFC-spezial DDX Makros, mit denen man ein Edit Feld so
einschränken kann, daß eine Zahleneingabe erwartet wird, sind
so in der Praxis sowieso Müll. Lösch einfach mal die Zahl aus
so einem Edit Feld raus (zb. mit einem Backspace) und die MFC
mault rum, daß man bitte eine Zahl eingeben möge. Einen Endbenutzer
kann man damit in den Wahnsinn treiben.

Lösung: Auch Zahleneingaben immer als Texteingaben machen, und
die Umwandlung in eine Zahl dann selbst (zb. mit einem sscanf)
machen. Dann ist es auch einfach im String, den man vom Control
bekommt, alle ',' durch '.' zu ersetzen, sodaß sscanf das richtig
parsen kann. Der Vorteil: Der Benutzer kann dann wahlweise
sowohl ',' als auch '.' als Dezimaltrenner verwenden. Geht aber
klarerweise nur dann, wenn 1000-er Seperatoren nicht benutzt werden.

Wir haben uns dafür spezielle DDX Funktionen geschrieben.
Zb. sowas
1
void C3dDDX_Text( CDataExchange* pDX, int nIdC, double& d, int Comma = 2 );

1
void C3dDDX_Text( CDataExchange* pDX, int nIdC, double& d, int Comma /* = 2 */ )
2
{
3
  CWnd*   pWnd = pDX->m_pDlgWnd->GetDlgItem( nIdC );
4
  CString str;
5

6
  pDX->PrepareEditCtrl( nIdC );
7

8
  ASSERT( pWnd );
9
  if( pDX->m_bSaveAndValidate ) {
10
    pWnd->GetWindowText( str );
11
    
12
    int n = str.Find( _T( "," ) );
13
    if( -1 < n ) {
14
      str.SetAt( n, '.' );
15
    }
16

17
    d = 0;
18
    _stscanf( str, _T( "%lf" ), &d );
19
  }
20

21
  else {
22
    TCHAR szBuf[64];
23
    _stprintf( szBuf, _T( "%-8.*lf" ), Comma, d );
24
    pWnd->SetWindowText( szBuf );
25
  }
26
}

Die haben dann auch noch den netten Nebeneffekt, dass man die
Anzahl der auszugebenden Nachkommastellen sauber definieren
kann.

Wenn der Dialog dann fertig ist, wird die DDX Zeile in DoDataExchange
gegen einen Aufruf so einer Funktion ersetzt:
1
void CKalibrierfaktor::DoDataExchange(CDataExchange* pDX) 
2
{ 
3
    CDialog::DoDataExchange(pDX); 
4
    //{{AFX_DATA_MAP(CKalibrierfaktor) 
5
    C3dDDX_Text(pDX, IDC_txtFaktor, m_fWert, 3); 
6
    //}}AFX_DATA_MAP 
7
}

Allerdings spielt dann der Dialogeditor nicht mehr mit. Daher
diesen Austausch erst ganz zum Schluss machen.
Persönliche Seite #828687
Lesenswert?

Nein, das kennt der Compiler nicht - das hier ist eine MFC-Anwendung.

Wobei es auch gar nicht dorthin gehört, richtig wäre es, die 
Locale-Informationen über das verwendete Zahlenformat auszuwerten.

Die für das Einlesen von Float-Zahlen verwendbare Funktion atof kann 
sehr wohl auch die Locale-Einstellugen des OS auswerten, dazu muss nur 
im Programm  die Win32-API-Funktion setlocale mit der Kategorie 
LC_NUMERIC und dem entsprechenden Landescode aufgerufen werden.
#828856
Lesenswert?

Rufus t. Firefly wrote:
> Nein, das kennt der Compiler nicht - das hier ist eine MFC-Anwendung.
>
> Wobei es auch gar nicht dorthin gehört, richtig wäre es, die
> Locale-Informationen über das verwendete Zahlenformat auszuwerten.

Yep. Das wäre die schöne Lösung.
Der Krampf an der Sache (in meinem/unserem Fall) ist aber, daß
viele Leute aus der Technik daran gewöhnt sind einen Kommapunkt
einzugeben. Und wenn deine Clientel dann aus eine Mischung aus
Punkt und Komma Fetischisten besteht, hast du den A.... offen.

Für uns hat sich die Lösung mit dem String manipulieren
bewährt.
Jeder der schon mal versucht hat eine amerikanische
Datendatei in ein deutsches Excel zu importieren, kennt diesen
Krampf.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren