000
18.01.2003, 14:58 Uhr
Uwe
C/C++ Master (Administrator)
|
Erstellt von Uwe
Zum Thema der dialogbasierenden Anwendung tauchen folgende Fragen immer wieder auf. Wie kann ich verhindern, daß sich die Anwendung nach betätigen der Enter-Taste schließt? Wie kann ich verhindern, daß sich die Anwendung nach betätigen der ESC- Taste schließt?
Wie kann ich realisieren, daß eingegebene Werte in einem Steuerelement sofort übernommen werden? Wie kann ich realisieren, daß eingegebene Werte in einem Steuerelement erst nach betätigen von "Enter" übernommen werden? Hier nun ein paar Vorschläge zu diesen Fragen. Als erstes legen wir eine dialogbasierende Anwendung an. Wir öffnen den Klassenassistenten und wählen unter den Objekt-ID's IDOK und dessen BN_CLICKED Handler. Wir fügen nun eine neue Funktion hinzu. Selbiges erledigen wir für IDCANCEL. Als nächstes wird die Dialogklasse selektiert und für den WM_CLOSE Nachrichtenhandler eine neue Behandlungsfunktion hinzugefügt. Jetzt bearbeiten wir den Quellcode, welcher sich uns im Moment wie folgt darstellt:
C++: |
void CKeepEnterDlg::OnCancel() { // TODO: Zusätzlichen Bereinigungscode hier einfügen
CDialog::OnCancel(); }
void CKeepEnterDlg::OnOK() { // TODO: Zusätzliche Prüfung hier einfügen
CDialog::OnOK(); }
void CKeepEnterDlg::OnClose() { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
CDialog::OnClose(); }
|
Wir fügen folgendes ein oder löschen:
C++: |
void CKeepEnterDlg::OnCancel() { // TODO: Zusätzlichen Bereinigungscode hier einfügen }
void CKeepEnterDlg::OnOK() { // TODO: Zusätzliche Prüfung hier einfügen }
void CKeepEnterDlg::OnClose() { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
CDialog::OnOK(); }
|
Als nächstes entfernen wir die OK und Abbrechen - Buttons in unserem Dialog. Das Programm lässt sich jetzt nur noch über die Maus bzw. durch Alt+F4 beenden. Jetzt brauchen wir drei Steuerelemente 2 Eingabefelder mit den ID's IDC_STAENDIGIDC_WARTEN und 1 statisches Textfeld mit der ID IDC_STATUS. Für IDC_STAENDIG und IDC_STATUS werden jeweils eine Membervariable der Kategorie Control angelegt. Für IDC_STAENDIG fügen wir eine Funktion für den EN_CHANGE Handler hinzu und bearbeiten diese Funktion.
C++: |
void CKeepEnterDlg::OnChangeStaendig() { CString str; m_cStaendig.GetWindowText(str); m_cStatus.SetWindowText(str);
}
|
Ein Testlauf zeigt uns die Reaktion. Im Eingabefeld mit der ID IDC_WARTEN wollen wir nun die Sache so gestalten, daß die Eingabewerte bei jedem Enter übernommen werden. Dazu legen wir uns mit dem Klassenassistenten eine von CEdit abgeleitete Klasse an. Dieser geben wir den Namen CEnterEdit und wählen als Basisklasse CEdit. Nach dem Anlegen der neuen Klasse binden wir zuerst den neuen Header in unsere Anwendungs- und Dialogklasse ein. Die Einbindung muß so erfolgen, daß vorher kompiliert wird bevor andere Dateien darauf zugreifen
C++: |
// KeepEnter.cpp : Legt das Klassenverhalten für die Anwendung fest. //
#include "stdafx.h" #include "KeepEnter.h" #include "EnterEdit.h" #include "KeepEnterDlg.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ........ ........
|
Nun legen wir eine Membervariable für IDC_WARTEN der Kategorie Control und vom Typ CEnterEdit fest. Mit dem Klassenassitenten wählen wir nun unsere neue Klasse aus und fügen für =EN_KILLFOCUS, WM_CHAR und WM_GETDLGCODE neue Funktionen hinzu. Als erstes bearbeiten wir jetzt die Funktion OnGetDlgCode(). Diese macht es bei von CEdit abgeleiteten Klassen möglich, den Tastaturcode, einschließlich der Enter und TAB Tasten abzufangen und weiter zu verarbeiten (mehr dazu in der MSDN).
C++: |
UINT CEnterEdit::OnGetDlgCode() { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
return CEdit::OnGetDlgCode()| DLGC_WANTALLKEYS; }
|
Die Funktionen liegen ja nun in der Quellcodedatei der neu angelegten Klasse aber die Ausgabe der Werte erfolgt ja in der Dialogklasse. Für die anderen beiden Funktionen brauchen wir also eine Möglichkeit der Benachrichtigung. Wir müssen eine benutzerdefinierte Nachricht an unsere Dialogklasse schicken. Dazu definieren wir eine WM_Konstante im Header der Dialogklasse.
C++: |
// KeepEnterDlg.h : Header-Datei //
#if !defined(AFX_KEEPENTERDLG_H__0CBED3B7_F551_4697_89C7_0CCBB3840127__INCLUDED_) #define AFX_KEEPENTERDLG_H__0CBED3B7_F551_4697_89C7_0CCBB3840127__INCLUDED_
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
#define WMU_EDIT WM_USER+5 ///////////////////////////////////////////////////////////////////////////// // CKeepEnterDlg Dialogfeld .......... ..........
|
Wir bearbeiten zunächst unsere beiden anderen Funktionen.
C++: |
void CEnterEdit::OnKillfocus() { // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
GetParent()->SendMessage(WMU_EDIT, GetDlgCtrlID(), (LPARAM)this); }
|
und danach
C++: |
void CEnterEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
switch(nChar) { case VK_RETURN: GetParent()->SendMessage(WMU_EDIT, GetDlgCtrlID(), (LPARAM)this); return; }
CEdit::OnChar(nChar, nRepCnt, nFlags); }
|
Wenn wir jetzt versuchen zu kompilieren gibt es ein paar Fehlermeldungen, da wir für unsere eigene Message ja noch nichts geschrieben haben. Los geht es. In der *.cpp Datei der Dialogklasse fügen wir folgendes ein:
C++: |
........ ........ BEGIN_MESSAGE_MAP(CKeepEnterDlg, CDialog)
ON_MESSAGE(WMU_EDIT, OnEditEnter)
//{{AFX_MSG_MAP(CKeepEnterDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() ON_EN_CHANGE(IDC_STAENDIG, OnChangeStaendig) //}}AFX_MSG_MAP END_MESSAGE_MAP() ........ ........
|
Danach wechseln wir in die Headerdatei und schreiben:
C++: |
........ ........ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung //}}AFX_VIRTUAL
// Implementierung protected: afx_msg LRESULT OnEditEnter(WPARAM, LPARAM lParam); HICON m_hIcon;
// Generierte Message-Map-Funktionen //{{AFX_MSG(CKeepEnterDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); virtual void OnCancel(); virtual void OnOK(); afx_msg void OnClose(); afx_msg void OnChangeStaendig(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ........ ........
|
Zurück zur *.cpp Datei und die Funktion OnEditEnter() geschrieben:
C++: |
LRESULT CKeepEnterDlg::OnEditEnter(WPARAM, LPARAM lParam) { CEnterEdit * edit = (CEnterEdit *)lParam; CString str; edit->GetWindowText(str); m_cStatus.SetWindowText(str); return 0; }
|
Nun sollte eigentlich der Ausführung des Programmes nichts mehr im Weg stehen. Den Weg mit der Unterklasse habe ich übrigens gewählt um dieses Thema einmal mit zu beleuchten. Das Beispiel steht als Projekt für VC++ im Downloadbereich zur Verfügung. -- "Es ist schwierig, ein Programm wirklich idiotensicher zu machen, weil Idioten so genial sind."
Bis dann... Uwe Dieser Post wurde am 18.01.2003 um 15:00 Uhr von Uwe editiert. |