000
18.01.2003, 14:49 Uhr
Uwe
C/C++ Master (Administrator)
|
Erstellt von Uwe
Bei den Standarddialogen (Dialogfeldern) ist der CFindReplaceDialog implementiert. Dieser Dialog sammelt jedoch nur die Benutzereingaben. Den eigentlichen Suchen- und Ersetzenvorgang muß man jedoch selbst programmieren. Das folgende Beispiel soll als kleine Hilfe dienen. Etwas wichtiges gleich zu Anfang der Erläuterungen. CFindReplaceDialog ist ein nichtmodaler Dialog. Er bleibt am Monitor angezeigt während der User andere Vorgänge tätigt. Wir können somit keine lokale Variable nutzen (welche ja nur innerhalb der Nachrichtenbehandlungsroutine Gültigkeit hat), wir benötigen hierfür eine Zeigervariable. Als erstes legen wir ein neues Projekt mit dem Namen FindReplace an. Als Art der Anwendung wählen wir Einzelnes Dokument (SDI). Bis zum Schritt 6 von 6 übernehmen wir die Standardeinstellungen. Hier nun aktivieren wir als Basisklasse "CEditView" und lassen unser Projekt erstellen. Nun legen wir im Header der Ansichtsklasse unsere Zeigervariable fest.
C++: |
....... .......// Implementierung public: afx_msg LONG OnFindReplace(WPARAM wParam, LPARAM lParam); virtual ~CFindReplaceView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif
private: // Unser Eintrag Anfang
CFindReplaceDialog * m_pFindReplace;
// Unser Eintrag Ende protected:
// Generierte Message-Map-Funktionen protected: //{{AFX_MSG(CFindReplaceView) afx_msg void OnBearbeitenSuchenersetzen(); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
|
Weiterhin muß der Zeiger auf NULL gesetzt werden. Im Konstruktor schreiben wir.
C++: |
CFindReplaceView::CFindReplaceView() { // ZU ERLEDIGEN: Hier Code zur Konstruktion einfügen,
// Unser Eintrag Anfang
m_pFindReplace=NULL;
// Unser Eintrag Ende }
|
Jetzt fügen wir einen neuen Menübefehl unter Bearbeiten mit dem Eintrag Suchen Erseten ein. Mit dem Klassenassistenten legen wir eine Nachrichtenbehandlungsroutine an und erzeugen unser Objekt.
C++: |
///////////////////////////////////////////////////////////////////////////// // CFindReplaceView Nachrichten-Handler
void CFindReplaceView::OnBearbeitenSuchenersetzen() { // TODO: Code für Befehlsbehandlungsroutine hier einfügen
// Unser Eintrag Anfang
if(!m_pFindReplace) { m_pFindReplace=new CFindReplaceDialog; m_pFindReplace->Create(TRUE,"",NULL,FR_DOWN |FR_HIDEWHOLEWORD,this); }
// Unser Eintrag Ende }
|
Das Neuerstellen des Objektes erfolgt nur, wenn m_pFindReplace den Wert NULL hat. Der erste Parameter von Create() ist übrigens dafür verantwortlich ob der Suchen oder Suchen- Ersetzen- Dialog angezeigt wird. Beim zweiten kann eine Voreinstellung für die Suchkette getroffen werden. Der vierte legt das Erscheinungsbild des Dialoges fest (näheres dazu in der MSDN oder per Mail. Der letzte ist ein Zeiger auf das übergeordnete Fenster. Achtung! Der Dialog darf nicht mit delete gelöscht werden. Dieser Dialog löscht sich selbst. Als nächstes sollten wir uns daran machen, eine Nachricht an die Ansichtsklasse vom Typ FINDMSGSTRING zu schicken, da der Dialog ja nicht geschlossen wird, aber trotzdem "suchen" soll. Mit
C++: |
UINT WM_FINDREPLACE = RegisterWindowMessage(FINDMSGSTRING);
|
definieren wir eine neue Windows-Nachricht. Diese fügen wir in der FindReplaceView.cpp ein.
C++: |
// FindReplaceView.cpp : Implementierung der Klasse CFindReplaceView //
#include "stdafx.h" #include "FindReplace.h"
#include "FindReplaceDoc.h" #include "FindReplaceView.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif
// Unser Eintrag Anfang
UINT WM_FINDREPLACE=RegisterWindowMessage(FINDMSGSTRING);
// Unser Eintrag Ende
///////////////////////////////////////////////////////////////////////////// // CFindReplaceView
IMPLEMENT_DYNCREATE(CFindReplaceView, CEditView)
|
Nun sollte das Makro On_REGISTERED_MESSAGE verwendet werden um unsere Nachricht bereitzustellen.
C++: |
.... .... UINT WM_FINDREPLACE=RegisterWindowMessage(FINDMSGSTRING); ///////////////////////////////////////////////////////////////////////////// // CFindReplaceView
IMPLEMENT_DYNCREATE(CFindReplaceView, CEditView)
BEGIN_MESSAGE_MAP(CFindReplaceView, CEditView) //{{AFX_MSG_MAP(CFindReplaceView) ON_COMMAND(ID_BEARBEITEN_SUCHENERSETZEN, OnBearbeitenSuchenersetzen) //}}AFX_MSG_MAP // Standard-Druckbefehle ON_COMMAND(ID_FILE_PRINT, CEditView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CEditView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CEditView::OnFilePrintPreview)
// Unser Eintrag Anfang
ON_REGISTERED_MESSAGE(WM_FINDREPLACE,OnFindReplace)
// Unser Eintrag Ende END_MESSAGE_MAP() .... ....
|
Wie wir sehen, wird die Nachricht mit einer Funktion OnFindReplace in Zusammenhang gebracht, welche wir noch schreiben müssen. In der Ansichtsklasse fügen wir mit dem Assistenten oder per Hand folgendes ein:
C++: |
.... .... // Überladungen // Vom Klassenassistenten generierte Überladungen virtueller Funktionen //{{AFX_VIRTUAL(CFindReplaceView) public: virtual void OnDraw(CDC* pDC); // überladen zum Zeichnen dieser Ansicht virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); //}}AFX_VIRTUAL
// Implementierung public: // Unser Eintrag Anfang
afx_msg LONG OnFindReplace(WPARAM wParam, LPARAM lParam);
// Unser Eintrag Ende
virtual ~CFindReplaceView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif
private: .... ....
|
Wurde mit dem Assistenten gearbeitet wurde der Funktionsrumpf bereits angelegt, wenn nicht müssen wir dies per Hand erledigen und schreiben wie folgt:
C++: |
LONG CFindReplaceView::OnFindReplace(WPARAM wParam, LPARAM lParam) { if (m_pFindReplace->IsTerminating()) { m_pFindReplace = NULL; }
else if (m_pFindReplace->FindNext()) { OnFindNext(m_pFindReplace->GetFindString(), m_pFindReplace->SearchDown(), m_pFindReplace->MatchCase()); }
else if (m_pFindReplace->ReplaceAll()) { OnReplaceAll(m_pFindReplace->GetFindString(), m_pFindReplace->GetReplaceString(), m_pFindReplace->MatchCase()); }
else if (m_pFindReplace->ReplaceCurrent()) { OnReplaceSel(m_pFindReplace->GetFindString(), m_pFindReplace->SearchDown(), m_pFindReplace->MatchCase(), m_pFindReplace->GetReplaceString()); }
return 0; }
|
Die beiden letzten Blöcke sind natürlich bei einem reinem Suchen - Dialog nicht notwendig. 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 14:50 Uhr von Uwe editiert. |