PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : VC++ (Win32/MFC): Return-Taste in Edit-Box


Gast
2005-09-29, 09:59:08
Hallo,

ich möchte in einem Programmfenster eine Edit-Box realisieren, bei der nach abgeschlossener Texteingabe durch Drücken der Return-Taste die Routine zum Verarbeiten des eingegebenen Textes aufgerufen wird (die also mittels GetWindowText() den Text aus der Edit-Box ausliest). Etwa so wie im Internet Explorer nach Eingabe des Textes in die Addresszeile durch Drücken der Return-Taste die Verarbeitung der Texteingabe (also das Ansteuern der eingegebenen URL) ausgelöst wird.

Nur habe ich überhaupt keine so rechte Idee wie das gehen soll. Ich hatte schon in Erwägung gezogen, es über die Ereignisbehandlungsroutine des Parent-Fensters für WM_KEYDOWN zu versuchen, in die geht das Programm aber bei Tastatureignissen innerhalb der Edit-Box offenbar gar nicht rein.
Dann kam mir die Idee, die Ereignisbehandlungsroutine der Edit-Box selbst zu verändern, indem ich von CEdit eine Klasse CReturnEdit ableite und deren OnKeyDown-Routine überschreibe.

Dabei treten aber noch zwei Probleme auf:
- in der MSDN habe ich zwar rein gar nichts gefunden, das mich bei der Umsetzung meines Vorhabens weiterbringen würde (eigentlich findet man so was in Programmen doch recht häufig vor, da mutet es schon etwas eigenartig an daß in der MSDN nichts dazu zu finden ist), dafür etwas anderes, nämlich daß eine Edit-Box auf Betätigungen von Tasten mit Keycodes kleiner als 0x20 - und das schließt die Return-Taste mit ein, die hat 0x0D - gar nicht annimmt (und dann wohl auch nicht an ihre WM_KEYDOWN-Routine weiterleiten kann), sofern sie nicht auf mehrzeiligen Style eingestellt ist. Geht das demnach nur mit mehrzeiligem Stil?
- im Parent-Fenster bewirkt das Drücken der Return-Taste (auch wenn der Focus gerade auf einem Child-Fenster wie der Edit-Box liegt) das Auslösen der Routine für das Anklicken des Default-Buttons. Wie kann man das abschalten?

In Zusammenhang mit dem zweiten Problem ist mir da noch eine weitere Idee gekommen: ich füge einen Dummy-Button ein, dessen BN_CLICKED-Routine die gewünschte Verarbeitung des Textes in der Edit-Box auslöst. In der EN_SETFOCUS-Routine der Edit-Box stelle ich dann den Default-Button des Parent-Fenster auf den Dummy-Button um, so daß ein Drücken der Return-Taste die gleiche Wirkung wie ein Klick auf den Dummy-Button hat. In der EN_KILLFOCUS-Routine der Edit-Box setze ich den Default-Button dann zurück. Während die Edit-Box den Focus hat, sollte das Drücken der Return-Taste dann den gewünschten Effekt haben.
Kann man das so realisieren?

Gast
2005-10-01, 01:19:48
ich habe da jetzt mal folgende Methode improvisiert:
ich stelle den Stil der Edit-Box auf mehrzeilig (ES_MULTILINE) und Return abzeptierend (ES_WANTRETURN) ein.
Dann schreibe ich eine Behandlungsroutine für EN_CHANGE oder EN_UPDATE Nachrichten, die die Edit-Box bei jeder durch Tastatureingaben ausgelösten Änderung des Box-Textes an das Parent-Fenster sendet.

Jetzt bediene ich mich folgenden Tricks: das Drücken der Return-Taste bewirkt durch den eingestellten Stil der Edit-Box, daß in dieser eine neue Zeile angefangen wird. Das führt dazu, daß der Textstring einen newline-Character '\n' enthält.
In der Behandlungsroutine für EN_CHANGE oder EN_UPDATE (welche der beiden man nimmt ist eigentlich ziemlich egal) lese ich dann einfach den Text der Edit-Box aus und überprüfe ob er ein '\n' enthält.
Enthält er keines, passiert nichts weiter. Enthält er eines, so interpretiere ich das als Gedrücktwordensein der Return-Taste. Es wird dann der Prozeß aufgerufen, der durch Drücken der Return-Taste ausgelöst werden soll.

Damit ich die neue Zeile in der Edit-Box anschließend nicht angezeigt bekomme, lösche ich dann den newline-Character aus dem String (ich habe herausgefunden, daß man auch den Character danach löschen muß) und setze den Text der Edit-Box neu.

Der Code sieht so aus:

void CParentWnd::OnEdit1Change()
{
CString sText;
m_cEdit1.GetWindowText(sText); // read text from edit box
int iPos = sText.Find('\n'); // look for newline char
if (iPos >=0) // newline char found?
{
// routine for Return key pressed...

// remove generated new line in edit box
sText.Delete(iPos-1, 2);
m_cEdit1.SetWindowText(sText);
}
}


}

Imperator Katarn
2006-02-23, 12:49:46
Ich habe da noch eine weitere Methode gefunden, mit Hilfe der Funktion CWnd::PreTranslateMessage. Diese fängt Nachrichten (z.B. WM_KEYDOWN für das Drücken einer Taste) ab bevor sie verarbeitet werden und ermöglicht eine Art Vorverarbeitung:


BOOL CParentWnd::PreTranslateMessage(MSG *pMsg)
{
// ist ankommende Nachrichte eine WM_KEYDOWN Nachricht?
if (pMsg->message == WM_KEYDOWN)
{
// ist die gedrückte Taste die Return-Taste?
if (pMsg->wParam == VK_RETURN)
{
// hat gerade Edit1 den Focus?
CWnd *pWnd = this->GetFocus();
if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
{
// Routine für Return pressed in Edit1
// Wert ungleich Null zurückgeben, um eine Weiterverarbeitung der Nachricht zu unterbinden
return 1;
}
}
}

// andere Nachrichten wie gewöhnlich behandeln
return CWnd::PreTranslateMessage();
}

Der Namenlose
2006-02-23, 14:18:21
Versuch es mal mit der OnOK() Funktion. Die sollte aufgerufen werden, wenn OK geklickt wird oder Enter in einem Text Element.

Imperator Katarn
2006-02-23, 15:30:10
OnOK() ist dafür vorgesehen, das Schließen des Fensters zu managen, und sollte, um den Code möglichst verständlich zu halten, auch nur dazu benutzt werden.

Hinzu kommt, daß in OnOK() dann ja noch überprüft werden müßte, ob die Return-Taste gedrückt wurde.