SDI-Anwendung öffnet immer separaten Task in der Windows Taskleiste
-
Hallo,
in der Doc-Klasse werden folgende Pointer (auf Hauptdialog und Unterdialoge) erstellt://* Pointer auf die einzelnen Unterdialoge und auf Klassen für Einstellungen, Dateneingabe, Hauptdialog CDataLink *m_pDataLink; CData *m_pData; CParameters *m_pParameter; CDigitalIO *m_pDigitalIO; CAuxSystems *m_pAuxSystems; COffsets *m_pOffsets; CSaveConfig *m_pSaveConfig; CLoadConfig *m_pLoadConfig; CKonfigurationDlg *m_pKonfigDlg; // Hauptdialog für alle Unterdialoge
Die einzelnen Unterdialog-Klassen (CDataLink, CData, ...) sind von dem Hauptdialog CKonfigurationDlg abgeleitet.
In der Doc-Klasse werden die einzelnen Dialog auch erzeugt und das Doc mitübergeben.
// Unterdialoge erzeugen m_pLoadConfig = new CLoadConfig(this); m_pData = new CData(this); m_pDataLink = new CDataLink(this); m_pParameter = new CParameters(this); m_pDigitalIO = new CDigitalIO(this); m_pAuxSystems = new CAuxSystems(this); m_pOffsets = new COffsets(this); m_pSaveConfig = new CSaveConfig(this); // Dlg-Fenster erstellen (Hauptdialog und alle Unterdialoge) m_pKonfigDlg->Create(IDD_CONFIG_FRAME); m_pData->Create(IDD_DATA); m_pDataLink->Create(IDD_DATA_LINK); m_pParameter->Create(IDD_PARAMETERS); m_pDigitalIO->Create(IDD_DIGITAL_IO); m_pAuxSystems->Create(IDD_AUX_SYSTEMS); m_pOffsets->Create(IDD_OFFSETS); m_pSaveConfig->Create(IDD_SAVE_CONFIG); m_pLoadConfig->Create(IDD_LOAD_CONFIG);
Im Hauptdialog (CKonfigurationDlg) werden dann die Unterdialoge entsprechend einer switch-Fkt angezeigt:
// -------- alle Dialoge auf HIDE m_pDataLink->ShowWindow(SW_HIDE); m_pData->ShowWindow(SW_HIDE); m_pDigitalIO->ShowWindow(SW_HIDE); // m_pSystem->ShowWindow(SW_HIDE); m_pParameter->ShowWindow(SW_HIDE); m_pAuxSystems->ShowWindow(SW_HIDE); m_pOffsets->ShowWindow(SW_HIDE); m_pLoadConfig->ShowWindow(SW_HIDE); m_pSaveConfig->ShowWindow(SW_HIDE); // ++ je nach Step, entsprechenden Dialog anzeigen switch (step) { case LOAD_CONFIG: // Dialog anzeigen m_pLoadConfig->SetParent(m_pKonfigDlg); m_pLoadConfig->ShowWindow(SW_SHOW); // restliche Buttons im linken Frame deaktivieren (-> zuerst Einstellungen laden!) m_pKonfigDlg->SetStatusButtons(FALSE, FALSE, 0); // Config-Modus in Titelleiste deaktivieren -> Vermeidung von Doppelerzeugungen m_pParentDoc->m_bEnConfiguration = FALSE; // in disem Fall ist der Com-Port noch auswählbar pMainFrame->m_bEnConfigCommSettings = TRUE; // als aktives Fenster setzen m_pDataLink->SetActiveWindow(); // Focus in Dialog setzen setzen m_pLoadConfig->GetDlgItem(IDC_BUTTON_LOAD_SETTINGS)->SetFocus(); break; case DATA_LINK: // Dialog anzeigen m_pDataLink->SetParent(m_pKonfigDlg); m_pDataLink->ShowWindow(SW_SHOW); // Membervariablen initialisieren ( aus Struktur ) m_pDataLink->ReadIniEntries( m_pEinstellungenIni); // Dialog anpassen nachdem Werte aus Struktur gesetzt wurden (Chkbox, Combo,...) m_pDataLink->SetUpdateView(); //m_pDataLink->SetFocus(); //m_pDataLink->SetActiveWindow(); // Focus in Dialog setzen setzen m_pDataLink->GetDlgItem(IDC_RADIO_CAN)->SetFocus(); break; .........etc.
So weit zu meiner Ausführung. Ich hoffe Du kannst damit jetzt etwas anfangen....
Ich weiß nicht wo ich diesen separaten Task erzeugt haben soll....!
Danke schon mal für Deine Hilfe.
Gruss
S.
-
Wenn ich das richtig verstanden habe erzeugst Du zunächst von allen Dialogen Instanzen im Speicher und setzt sie alle auf SW_HIDE. In der case-Schleife wird dann die Sichtbarkeit auf Grund der Benutzereingaben geregelt.
Warum fragst Du nicht erst den Benutzer was er machen möchte und erzeugst dann innerhalb der case-Anweisung die Fenster? Ansonsten kann ich zunächst nicht erkennen wo ein Task zusätzlich erzeugt wird.
-
Hi,
das ganze Programm ist eine Art -WIZARD- und die einzelnen Unterdialoge "kommunizieren" auch untereinander, sprich Eingaben in Unterdialog 1 verändern den Steuerelemente-Status in Unterdialog 2.
Es wird aber ja immer nur ein Unterdialog angezeigt, die restlichen sind immer auf "HIDE" gesetzt.Noch ne Idee....
Danke.
S.
-
Hi,
ich hatte das gleiche Problem zu lösen. Ich habe modale Dialoge erstellt, die ihre Daten in einer separaten Klasse (eine Art Doc-Klasse zum Dialog) abgelegt haben. Dazu steht im Kern eine Datei, in die ich die Daten schreibe bzw. aus der ich die Daten lese. Ein Dialog kann somit immer auf die für ihn bestimmten Daten zugreifen, ein anderer Dialog kann aber die gleichen Felder auch manipulieren. Ich finde Deine Lösung problematisch, da Du im Speicher Instanzen anlegst, die Du evtl. gar nicht benötigst und weiterhin es mit dem Datenaustausch komlizierter ist als bei modalen Dialogen.
Hast Du mal geschaut, bei welcher Zeile der Task erscheint?
-
Hallo,
Danke für den Tipp. Ich habe es so realisiert, da es dem User möglich sein soll den Dialog zu wechseln OHNE auf OK zu drücken. Ist mit Sicherheit nicht die eleganteste Variante....da gebe ich Dir schon Recht.
Es werden immer alle Dialoge, bzw. dazugehörige Membervariablen benötigt...von daher ist das Erstellen dieser ja nicht überflüssig.Habe jetzt mal nachgeschaut wo der zweite Task geöffnet wird.
m_pKonfigDlg->Create(IDD_CONFIG_FRAME);
Das passiert also bei der Zuweisung des Hauptdialoges....!
Kommentiere ich diese Zeile aus, dann werden ja als nächstes die Unterdialoge zugewiesen:
// m_pKonfigDlg->Create(IDD_CONFIG_FRAME); [b]<-- hier wird der zweite TASK erzeugt m_pData->Create(IDD_DATA); m_pDataLink->Create(IDD_DATA_LINK); m_pParameter->Create(IDD_PARAMETERS); m_pDigitalIO->Create(IDD_DIGITAL_IO); m_pAuxSystems->Create(IDD_AUX_SYSTEMS); m_pOffsets->Create(IDD_OFFSETS); m_pSaveConfig->Create(IDD_SAVE_CONFIG); m_pLoadConfig->Create(IDD_LOAD_CONFIG);
Bei der Zuweisung der Unterdialoge wird der zweite Task NICHT erzeugt. Also muss es wohl etwas mit dem Hauptdialog zu tun haben, oder?
Vielleicht hast Du ja jetzt noch ne Idee?
Danke schon mal und noch nen schönen Abend.
gruss
S.
-
Stefan H schrieb:
Hallo,
Danke für den Tipp. Ich habe es so realisiert, da es dem User möglich sein soll den Dialog zu wechseln OHNE auf OK zu drücken. Ist mit Sicherheit nicht die eleganteste Variante....da gebe ich Dir schon Recht.
Es werden immer alle Dialoge, bzw. dazugehörige Membervariablen benötigt...von daher ist das Erstellen dieser ja nicht überflüssig.
....Das versteh ich jetzt nicht ganz. Irgendeine Interaktion muss ja der User machen um zwischen den Dialogen hin und her zu schalten. Sehen kann man die doch nicht...
Hast Du mal den Rückgabewert der Funktion Create() ausgewertet? Wenn ich mich nicht irre kehrt die ja sofort zurück bei nicht modalen Dialogen.
Die nächste Frage bezieht sich auf den Task. Du schaust doch sicher unter dem Taskmanager unter Prozesse. Was steht denn da genau? Oder wird in der das Programm in der Taskleiste so angezeigt, als ob es ein zweites Mal gestartet wurde?
-
Hallo,
also jetzt mal zur Verdeutlichung.
In meinem CMainFrame erstelle ich dann meinen Hauptdialog (siehe Bild: großes Rechteck inkl. Button-Teil). Über die einzelnen Buttons kann ich dann also die unterschiedlichen Unterdialoge im rechten Teil (innerhalb des Hauptdialoges) anzeigen lassen.
Der Wechsel der Dialoge geschieht also über Buttons, bzw. über Hotkeys. Aus diesem Grund habe ich auch keine modalen Dialoge gewählt....!___________________ | | | | Btn | | | | | | Btn | Unter- | | | dlg | | Btn | | |_____|_____________|
OK, nun zu Deinen Fragen:
Hast Du mal den Rückgabewert der Funktion Create() ausgewertet? Wenn ich mich nicht irre kehrt die ja sofort zurück bei nicht modalen Dialogen.
Also der Rückgabewert ist "1". -> Dialog kann also erstellt werden
Die nächste Frage bezieht sich auf den Task. Du schaust doch sicher unter dem Taskmanager unter Prozesse. Was steht denn da genau? Oder wird in der das Programm in der Taskleiste so angezeigt, als ob es ein zweites Mal gestartet wurde?
Im Taskmanager wird das Programm nur 1 Mal angezeigt. Gleiches Spiel bei den Prozessen. Aber nach dem Create-Aufruf des Hauptdialoges erscheint in der Windows-Taskleiste ein neuer Task( dieses Rechteck ) ohne Beschriftung.
Dieser -unnötige- Task wird so lange angezeigt, bis der Hauptdialog wieder geschlossen wird. Hierzu rufe ich die Methode OnOK() von CDialog auf -> danach ist -unnötiger" Task wieder weg.Bin auf dem Gebiet der SDI-Anwendung noch blutiger Anfänger...aber kann das nicht sein das er so ein "neues" Dokument / View irgendwie automatischer erstellt?!?!
Puh, so siehts halt irgendwie doof aus und ist für den Kunden verwirrend.
Trotzdem Danke für die Hilfe.
Gruss
S.
-
Poste doch mal den Code der Klasse deines Hauptdialoges. Was ist denn dessen Basisklasse? CDialog?
-
Hallo,
also dann hier mal das Header-File meines Hauptdialoges.
Die Basisklasse ist CDialog:#if !defined(AFX_KONFIGURATIONDLG_H__264EAAEB_3F0E_4A17_A32B_A14C5F6BAE03__INCLUDED_) #define AFX_KONFIGURATIONDLG_H__264EAAEB_3F0E_4A17_A32B_A14C5F6BAE03__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // KonfigurationDlg.h : Header-Datei // // ----- Includes für farbige Edits und Statics #include "ColorStatic.h" #include "ColorEdit.h" #include "Color.h" //#include "BDialog.h" // ----------- Include für farbige Button ------------------------- #include "ColorButton.h" #include "adma_sw.h" #include "Dateneingabe.h" // ----------------------------------------------------------------- // ----- ENUM für Fonts und Steps // ----------------------------------------------------------------- // ------ Fonts-Namen enum FONTS { FONT_TOPIC, FONT_DESCRIPTION, FONT_BOLD, FONT_UNDERLINED_BOLD, FONT_SEMIBOLD, FONT_HINT, FONT_ADRESSE }; class CEinstellungenIni; class CKonfigurationDoc; class CColorButton; class CDateneingabe; ///////////////////////////////////////////////////////////////////////////// // Dialogfeld CKonfigurationDlg //----------------------------------------------------------------------------------------- /*! @class CKonfigurationDlg * @brief Hauptdialog von allen Unterdialogen (Data, DataLink, Parameter, ...) * @author S.H. * @version 0.2 * @date 02-06-2005 * @bug * @warning * @todo Gleiche Fkt/Var aller Unterdialoge hier hinzufügen * * Alle Unterdialoge sind von dieser Klasse abgeleitet\n * Gestalten des Aussehens des Hauptdialoges (Steuerelemente: Farbe, Font, etc.)\n * Alle Fkt/Var welche in allen UDLG gleich sind, werden hier implementiert */ class CKonfigurationDlg : public CDialog { // Konstruktion public: int m_nElementWithFocus; void SetImageHint(UINT ID_BMP); void PushButtonBack(); void PushButtonNext(); // ============================================================================= //! Die Methode SetStatusButtons aktiviert / deaktiviert die MenüBtn (li Frame) /*! * @param newModus : BOOL = Lade Settings / Generiere Settings * @param enableBtn : BOOL = Buttons enablen / disablen * @param nNewStep : int = aktueller Schritt (dieser Btn ist dann aktiviert!) * @return * @sa * * Wird verwendet um die 3 Modi zum Laden der Settings durchzuführen */ void SetStatusButtons(BOOL newModus, BOOL enableBtn, int nNewStep); // ============================================================================= //! Die Methode SetBtnBackNext dient zur visuellen Anzeige der Back / Next - Buttons /*! * @param step : int = aktueller Schritt * @param anzSteps : int = Gesamtanzahl der Schritte * @return * * Bei erstem Step -> kein Back-Button\n * Bei letztem Step -> kein Next-Button */ void SetBtnBackNext( int step, int anzSteps); // ============================================================================= //! Die Methode SetDlgBtnColor ändert die Farben der Buttons im linken Frame (UDLG-Aufrufe) /*! * @param step : enum STEP = Name des zu öffnenden UDLGs ( -> Button) * @return * @sa * * Bei aktivem Dlg ist auch der entsprechende Button farblich hervorgehoben */ void SetDlgBtnColor(enum STEP step); // ============================================================================= //! Die Methode SetTextFrame dient zur Anzeige der Texte in den Frames (li / oben) entsprechend des aktiven UDLGs /*! * @param step : enum STEP = Name des aktuellen UDLGs * @return * @sa * * Anzeige von Titel, Description, Step x of y, .... */ void SetTextFrame(enum STEP step); // ============================================================================= //! Die Methode SetChkDateneingabe setzt einen Zeiger auf eine Instanz von CDateneingabe /*! * @param dateneingabe : CDateneingabe * = Zeiger auf Objekt * @return * @sa SetEinstellungenIni * * Zeigerübergabe: auf diese Variable greifen alle UDLG zu (STATIC - Variable in CKonfigDlg.h) * * Instanz von Dateneingabe auf welche von allen Unterdlg zugegriffen wird * Vorgehen:\n * 1. static-Variable* in CKonfigurationDlg deklinieren\n * 2. Variable wird in DataLink.cpp ganz oben initialisiert (WICHTIG: Egal wo, muss aber gemacht werden )\n * 3. Mittels "SetChkDateneingabe(....)" wird Objekt übergeben und mit "Klassenangabe::statVariable = übergabeObjekt" zugewiesen * */ void SetChkDateneingabe( CDateneingabe *dateneingabe ); // ----------------------------------------------------------------- // ----- Konstruktor / Destruktor // ----------------------------------------------------------------- CKonfigurationDlg(/*CKonfigurationDoc *pDoc, */ CWnd* pParent = NULL); // Standardkonstruktor // ============================================================================= //! Die Methode CKonfigurationDlg ist ein modifizierter Konstruktor dieser Klasse /*! * @param pDoc : CKonfigurationDoc * = Zeiger auf Doc (hinzugefügt!) * @param pParent : CWnd* = * @return * * Im Konstruktor dann pDoc übergeben und somit Zugriff auf Doc erhalten */ CKonfigurationDlg(CKonfigurationDoc *pDoc, CWnd* pParent = NULL); // modifizierter Konstruktor // ----------------------------------------------------------------- // ----- Öffentliche Funktionen // ----------------------------------------------------------------- // ============================================================================= //! Die Methode OnSelectFont dient zur Auswahl eines vordefinierten Fonts /*! * @param n_Fonts : FONTS = Bezeichnung des zu ladenden Fonts * @return * * In dieser sind Funktion sind diverse Fonts vordefiniert und können ausgewählt werden; \n * Es können noch weiter Fonts hinzugefügt, bzw. vorhandene verändert werden;\n * Bei Erstellung neuer Fonts sind diese der ENUM-Aufzählung (siehe Dekl. oben) hinzuzufügen */ void OnSelectFont(enum FONTS n_Fonts); // ============================================================================= //! Die Methode SetControlProperties setzt die Eigenschaften der Steuerelemente im K-HauptDLG (Farbe, Font, etc.) /*! * @return * * @todo oberer Frame (Farbe) ist momentan nur hingetrickst (IDC_STATIC_FILL_UPPER_FRAME, ...) * * Frames, Buttons, Textfeldern, etc. Farbe und Schriftart zuweisen\n * WICHTIG:\n * Probleme, wenn man EDIT/STATIC Feld sowohl Farbe, als auch FONTS zuweisen möchte.\n * --> Farbe über Nachrichtenfunktion "OnCtlColor(...); */ void SetControlProperties(); // ============================================================================= //! Die Methode CreateFramework zeigt die éinzelnen Steuerelemente (Frames, etc.) an (SW_SHOW) /*! * @return * * Anzeige des Konfiguration Hauptdialoges */ void CreateFramework(); // ============================================================================= //! Die Methode SetEinstellungenIni setzt einen Zeiger auf eine Instanz von CEinstellungenIni /*! * @param einstellIni : CEinstellungenIni * = Zeiger auf Instanz von Klasse CEinstellungenIni (defniert in ...Doc) * @return * @sa SetChkDateneingabe * * Zeigerübergabe: auf diese Variable greifen alle UDLG zu (STATIC - Variable in CKonfigDlg.h) * * Instanz von CEinstellungenIni auf welche von allen Unterdlg zugegriffen wird * Vorgehen:\n * 1. static-Variable* in CKonfigurationDlg deklinieren\n * 2. Variable wird in DataLink.cpp ganz oben initialisiert (WICHTIG: Egal wo, muss aber gemacht werden )\n * 3. Gefülltte Struktur mittels "SetEinstellungenIni(....)" übergeben und mit "Klassenangabe::statVariable = übergabeStruktur" */ void SetEinstellungenIni(CEinstellungenIni *einstellIni); // ============================================================================= //! Die Methode ExitConfigMode schließt den Konfig-Modus /*! * @return * @sa * * Prinzipiell der Aufruf von OnOK()! */ void ExitConfigMode(); // ----------------------------------------------------------------- // ----- Allgemeine Variablen // ----------------------------------------------------------------- /* Instanz von CEinstellungenIni auf welche von allen Unterdlg zugegriffen wird Vorgehen: 1. Variable hier deklinieren 2. Variable wird in DataLink.cpp ganz oben initialisiert (WICHTIG: Egal wo, muss aber gemacht werden ) 3. Gefülltte Struktur mittels "SetEinstellungenIni(....)" übergeben und mit "Klassenangabe::statVariable = übergabeStruktur" */ static CEinstellungenIni *m_pKonfigEinstell; // Zeiger auf Hauptdialog CKonfigurationDoc *m_pDoc; // Instanz von CDateneingabe um die Werte auf Min/Max etc. zu überprüfen static CDateneingabe *m_pChkDateneingabe; // ----- Fonts CFont m_SelFont; // Ausgewählter Font CFont m_FontTopic, m_FontDescription, m_FontBold, m_FontUnderlinedBold, m_FontHint, m_FontAdresse; // Definierte Fonts // Hinweis Bild CBitmap m_bmpHint; // Bild welches als Hinweis angezeigt wird //------ Variablen für alle FARBIGEN Steuerelemente (EDIT / STATIC) //CColorStatic m_statGenesysAdress; CColorStatic m_statLeftFill; CColorStatic m_statUpperFill; // Hotkeys implementieren HANDLE m_hAccel; // Dialogfelddaten //{{AFX_DATA(CKonfigurationDlg) enum { IDD = IDD_CONFIG_FRAME }; CEdit m_ctlGeneSys; CEdit m_ctlstatGeneSys; CStatic m_ctlLabHint; CButton m_btnExitConfig; CColorButton m_btnSaveConfig; CColorButton m_btnEnterConfig; CStatic m_ctlTopic; CColorButton m_btnAuxSystems; CButton m_btnBack; CColorButton m_btnData; CColorButton m_btnDataLink; CColorButton m_btnDIO; CButton m_btnNext; CColorButton m_btnOffsets; CColorButton m_btnParameter; CEdit m_ctlHint; CStatic m_ctlPicHint; CStatic m_ctlDescriptionTopic; CStatic m_ctlStep; CString m_strGeneSysAdresse; CString m_strTopic; CString m_strStep; CString m_strDescriptionTopic; CString m_strHint; //}}AFX_DATA // Überschreibungen // Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen //{{AFX_VIRTUAL(CKonfigurationDlg) public: virtual BOOL PreTranslateMessage(MSG* pMsg); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung //}}AFX_VIRTUAL // Implementierung protected: // Handle um Hints (CStatics) farbig zu gestalten (Fkt.: OnCtlColor() ) CBrush m_hBrush; // Generierte Nachrichtenzuordnungsfunktionen //{{AFX_MSG(CKonfigurationDlg) virtual BOOL OnInitDialog(); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg void OnButtonData(); afx_msg void OnButtonSystem(); afx_msg void OnButtonDio(); afx_msg void OnButtonAuxiliarySystems(); afx_msg void OnButtonParameters(); afx_msg void OnButtonOffsets(); afx_msg void OnButtonDataLink(); afx_msg void OnButtonBack(); afx_msg void OnButtonNext(); afx_msg void OnCancelMode(); afx_msg void OnButtonConfig(); afx_msg void OnButtonSaveConfig(); afx_msg void OnButtonHelp(); virtual void OnCancel(); virtual void OnOK(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. #endif // AFX_KONFIGURATIONDLG_H__264EAAEB_3F0E_4A17_A32B_A14C5F6BAE03__INCLUDED_
So, wenn ich irgendwelche Funktionen noch posten soll, dann kurz bescheid sagen.
Ich hoffe der Quelltext bringt Dich weiter.....
Danke.
Gruss
S.
-
Hallo,
also der Tast wird angezeigt, da der Dialog IDD_CONFIG_FRAME ein Dialog des Stils Konstextmenü ist. (Für meine Applikation ist das auch zwingend erforderlich!)Mit dem entsprechenden Aufruf:
m_pKonfigDlg->Create(IDD_CONFIG_FRAME);
wird dann dieser -unnötige- Task erzeugt.
Nun ist die Frage immer noch: Wie kann ich das verhindern??Zur Not kann ich über SetWindowText("....") diesem Task ja zumindest einen Namen zuweisen der dann in der Taskzeile angezeigt wird... :p
Also, vielleicht hat ja jetzt doch noch jemand eine Idee.
Schon mal Danke.
Gruss
S.