Bentutzen Sie diese Datenbank und erstellen sie eine Benutzer- oder System-DSN im ODBC Manager in der Systemsteuerung mit dem Namen "splitter". Wie das geht steht hier. Die Anwendung Splitter soll so verändert werden, dass die vorher in einem geteilten Fenster angezeigten Elemente nun mittels Karteikarten angezeigt werden. |
// MainFrm.cpp : Implementierung der Klasse CMainFrame // #include "stdafx.h" #include "splitter.h" #include "MainFrm.h" #include "SplitterDoc.h" //#include "DKunde.h" gelöscht //#include "DLand.h" gelöscht //#include "DJoin.h" gelöscht //#include "DAdresse.h" gelöscht
// splitter.cpp : Legt das Klassenverhalten für die Anwendung fest. // #include "stdafx.h" #include "splitter.h" #include "MainFrm.h" #include "splitterDoc.h" // Löschen der folgenden Zeile //#include "DKunde.h" // Includieren der am Anfang erstellten View #include "TabView.h"
BOOL CSplitterApp::InitInstance() { AfxEnableControlContainer(); // Standardinitialisierung // Wenn Sie diese Funktionen nicht nutzen und die Größe Ihrer fertigen // ausführbaren Datei reduzieren wollen, sollten Sie die nachfolgenden // spezifischen Initialisierungsroutinen, die Sie nicht benötigen, entfernen. #ifdef _AFXDLL Enable3dControls(); // Diese Funktion bei Verwendung von MFC in gemeinsam genutzten DLLs aufrufen #else Enable3dControlsStatic(); // Diese Funktion bei statischen MFC-Anbindungen aufrufen #endif // Ändern des Registrierungsschlüssels, unter dem unsere Einstellungen gespeichert sind. // ZU ERLEDIGEN: Sie sollten dieser Zeichenfolge einen geeigneten Inhalt geben // wie z.B. den Namen Ihrer Firma oder Organisation. SetRegistryKey(_T("Local AppWizard-Generated Applications")); LoadStdProfileSettings(); // Standard INI-Dateioptionen laden (einschließlich MRU) // Dokumentvorlagen der Anwendung registrieren. Dokumentvorlagen // dienen als Verbindung zwischen Dokumenten, Rahmenfenstern und Ansichten. CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CSplitterDoc), RUNTIME_CLASS(CMainFrame), // Haupt-SDI-Rahmenfenster RUNTIME_CLASS(CTabView)); // Hier die Anfang erstellte View eintragen. AddDocTemplate(pDocTemplate); // Befehlszeile parsen, um zu prüfen auf Standard-Umgebungsbefehle DDE, Datei offen CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // Verteilung der in der Befehlszeile angegebenen Befehle if (!ProcessShellCommand(cmdInfo)) return FALSE; // Das einzige Fenster ist initialisiert und kann jetzt angezeigt und aktualisiert werden. m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; }
void CTabView::OnInitialUpdate() { CFormView::OnInitialUpdate(); // Jeweils anlegen des Speichers für den Dialog // und anlegen der dahinterliegenden Windows Datenstruktur mit Create dialoge[0] = new DiaAdresse(); dialoge[0]->Create(IDD_ADRESSE,&m_tabctrl); m_tabctrl.InsertItem(0,"Adresse"); dialoge[1] = new DiaJoin(); dialoge[1]->Create(IDD_JOIN,&m_tabctrl); m_tabctrl.InsertItem(1,"Join"); dialoge[2] = new DiaKunde(); dialoge[2]->Create(IDD_KUNDE,&m_tabctrl); m_tabctrl.InsertItem(2,"Kunde"); dialoge[3] = new DiaLand(); dialoge[3]->Create(IDD_LAND,&m_tabctrl); m_tabctrl.InsertItem(3,"Land"); }
void CTabView::OnSize(UINT nType, int cx, int cy) { CFormView::OnSize(nType, cx, cy); // Wenn die Fenstergröße verändert wird, das CTabCtrl anpassen if (m_tabctrl.GetSafeHwnd() != NULL) m_tabctrl.MoveWindow(0,0,cx,cy); CRect rechteck; // Ebenso den angezeigten Dialog anpassen // Nur wenn CTabCtrl schon oder noch existiert. if (m_tabctrl.GetSafeHwnd() != NULL) { // Größe des CTabCtrls holen m_tabctrl.GetClientRect(rechteck); // Dialog an die Größe des Fensters anpassen und anzeigen dialoge[0]->SetWindowPos(NULL,rechteck.left+5,rechteck.top+25, rechteck.right-10,rechteck.bottom-30,SWP_SHOWWINDOW); } }
void CTabView::OnSelchangingTab1(NMHDR* pNMHDR, LRESULT* pResult) { int alt; // Nummer der alten aktivierten Registerkarte holen alt = m_tabctrl.GetCurSel(); // und verstecken dialoge[alt]->ShowWindow(SW_HIDE); *pResult = 0; }
void CTabView::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) { int neu; CRect rechteck; // Nummer der neuen aktivierten Registerkarte holen neu = m_tabctrl.GetCurSel(); // Holen der aktellen Größe des Fensters GetClientRect(rechteck); m_tabctrl.GetClientRect(rechteck); // Dialog an die Größe des Fensters anpassen und anzeigen dialoge[neu]->SetWindowPos(NULL,rechteck.left+5,rechteck.top+25, rechteck.right-10,rechteck.bottom-30,SWP_SHOWWINDOW); *pResult = 0; }
#include "RAdresse.h" class DiaAdresse : public CDialog { // etc...
BOOL DiaAdresse::OnInitDialog() { CDialog::OnInitDialog(); rec.Open(); Update(true); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurückgeben }
void DiaAdresse::Update(bool db_to_ctrl) { if (db_to_ctrl) { // von der DB in die Eingabefelder m_hausnr = rec.m_Hausnummer; m_id = rec.m_Index; m_land = rec.m_Land; m_ort = rec.m_Ort; m_plz = rec.m_Postleitzahl; m_strasse = rec.m_Strasse; UpdateData(false); }else { // von den Eingabefeldern in die DB UpdateData(true); rec.m_Hausnummer = m_hausnr; // Die ID wird von der Datenbank automatisch vergeben // desshalb nicht setzen // rec.m_Index = m_id; rec.m_Land = m_land; rec.m_Ort = m_ort; rec.m_Postleitzahl = m_plz; rec.m_Strasse = m_strasse; } }
void DiaAdresse::OnAdd() { // DB für neuen Datensatz vorbereiten rec.AddNew(); // Werte in den Eingabefeldern in die Variablen kopieren Update(false); // Einfügevorgang abschließen rec.Update(); // Datensätze neu selektieren // wenn man dies nicht tut, wird der eingefügte Datensatz nicht angezeigt rec.Requery(); // Den aktuellen Datensatz in die Eingabefelder kopieren Update(true); } void DiaAdresse::OnDel() { // Den aktuellen Datensatz löschen rec.Delete(); // Datensätze neu selektieren // Gelöschter Datensatz wird sonst noch angezeigt rec.Requery(); // Den aktuellen Datensatz in die Eingabefelder kopieren Update(true); } void DiaAdresse::OnUpdate() { // Den aktuellen Datensatz zum ändern vorbereiten rec.Edit(); // Den aktuellen Datensatz mit den Werten // in den Eingabefeldern überschreiben Update(false); // Updatevorgang abschließen rec.Update(); } void DiaAdresse::OnVor() { // Datensatzzeiger um eins vorbewegen rec.MoveNext(); // wenn er nun nach dem letzten Datensatz steht // wieder rückgängig machen if (rec.IsEOF()) rec.MovePrev(); // Aktuellen Datensatz in die Eingabefelder kopieren Update(true); } void DiaAdresse::OnZurueck() { // Datensatzzeiger um eins zurück bewegen rec.MovePrev(); // wenn er nun vor dem ersten Datensatz steht // wieder rückgängig machen if (rec.IsBOF()) rec.MoveNext(); // Aktuellen Datensatz in die Eingabefelder kopieren Update(true); }
BOOL DiaJoin::OnInitDialog() { CDialog::OnInitDialog(); rec.Open(); // Tabellenüberschriften setzen m_list.InsertColumn(0,"Kunde",LVCFMT_LEFT,60); m_list.InsertColumn(1,"Ort",LVCFMT_LEFT,60); m_list.InsertColumn(2,"Strasse",LVCFMT_LEFT,80); m_list.InsertColumn(3,"Hausnr",LVCFMT_LEFT,40); m_list.InsertColumn(4,"Land",LVCFMT_LEFT,80); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurückgeben }Methode für den Button:
void DiaJoin::OnSuch() { // Natural Join (jedes mit jedem) verhindern rec.m_strFilter = "Kunde.Adresse = Adresse.Index AND Adresse.Land = Land.Index"; // Schauen, ob etwas im Eingabefeld steht UpdateData(); if (m_kunde != "") //Wenn ja, danach suchen rec.m_strFilter += " AND Kunde.Name = '"+m_kunde+"'"; // Recordset aktualisieren ( Suchregel wird angewendet ) rec.Requery(); // Alte Items der CListCtrl löschen m_list.DeleteAllItems(); // Solange Elemente vorhanden while (!rec.IsEOF()) { // in CListCtrl einfügen int item = m_list.InsertItem(0,rec.m_kunde,-1); m_list.SetItemText(item,1,rec.m_ort); m_list.SetItemText(item,2,rec.m_strasse); m_list.SetItemText(item,3,rec.m_hausnummer); m_list.SetItemText(item,4,rec.m_land); // Aktellen Datensatz um eins weitersetzen rec.MoveNext(); } }
BOOL CSplitterApp::PreTranslateMessage(MSG* pMsg) { // Tastendrücke abfangen if (pMsg->message == WM_KEYDOWN) { // Die View holen CTabView* view = (CTabView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView(); // Tastendruck an die Behandlungsfunktion der eigenen View weiterleiten if (view->BehandleTastenDruck(pMsg)) // Taste behandelt wurde sofort zurückkehren return TRUE; } // Sonst Standardbehandlung durchführen return CWinApp::PreTranslateMessage(pMsg); }Und hier nun selbst erstellte Methode der Klasse CTabView, an die die Nachrichten weitergeleitet werden:
bool CTabView::BehandleTastenDruck(MSG *pMsg) { // Wenn die Tasten STRG und TAB gleichzeitig gedrückt werden if ((pMsg->wParam == VK_TAB) && (GetKeyState(VK_CONTROL) < 0)) { int alt = m_tabctrl.GetCurSel(); int neu; // Wenn die Shifttaste gedrückt wird if (GetKeyState(VK_SHIFT) < 0) // eins abziehen // mathematischer Trick neu = (m_tabctrl.GetCurSel()-1+4)%4; else // sonst eins dazuzählen neu = (m_tabctrl.GetCurSel()+1)%4; // Nächsten Reiterbutton aktivieren m_tabctrl.SetCurSel(neu); // Alten Dialog verstecken dialoge[alt]->ShowWindow(SW_HIDE); // Neuen anzeigen CRect rechteck; // Holen der aktellen Größe des Fensters m_tabctrl.GetClientRect(rechteck); // Dialog an die Größe des Fensters anpassen und anzeigen dialoge[neu]->SetWindowPos(NULL,rechteck.left+5,rechteck.top+25,rechteck.right-10,rechteck.bottom-30,SWP_SHOWWINDOW); } // Dialoge werden normalerweise bei ESC und ENTER geschlossen und zerstört // um dies zu verhindern leiten wir die Taste einfach nicht weiter if ((pMsg->wParam == VK_RETURN) || (pMsg->wParam == VK_ESCAPE)) return true; return false; }