Zum Inhalt springen

orsino

Mitglieder
  • Gesamte Inhalte

    33
  • Benutzer seit

  • Letzter Besuch

Beiträge von orsino

  1. Jeff Prosise beschreibt in 'Programming Windows with MFC' eine Möglichkeit

    This problem is easily solved with a message pump. Here's the proper way to execute a lengthy procedure in a single-threaded MFC program:

    void CMainWindow::OnStartDrawing ()

    {

    m_bQuit = FALSE;

    for (int i=0; i<NUMELLIPSES && !m_bQuit; i++) {

    DrawRandomEllipse ();

    if (!PeekAndPump ()) // PeekAndPump entspricht DoEvents

    break;

    }

    }

    void CMainWindow::OnStopDrawing ()

    {

    m_bQuit = TRUE;

    }

    BOOL CMainWindow::PeekAndPump ()

    {

    MSG msg;

    while (::PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {

    if (!AfxGetApp ()->PumpMessage ()) {

    ::PostQuitMessage (0);

    return FALSE;

    }

    }

    LONG lIdle = 0;

    while (AfxGetApp ()->OnIdle (lIdle++));

    return TRUE;

    }

    PeekAndPump enacts a message loop within a message loop. Called at the conclusion of each iteration through OnStartDrawing's for loop, PeekAndPump first calls CWinThread::PumpMessage to retrieve and dispatch messages if ::PeekMessage indicates that messages are waiting in the queue. A 0 return from PumpMessage indicates that the last message retrieved and dispatched was a WM_QUIT message, which calls for special handling because the application won't terminate unless the WM_QUIT message is retrieved by the main message loop. That's why PeekAndPump posts another WM_QUIT message to the queue if PumpMessage returns 0, and why the for loop in OnStartDrawing falls through if PeekAndPump returns 0. If a WM_QUIT message doesn't prompt an early exit, PeekAndPump simulates the framework's idle mechanism by calling the application object's OnIdle function before returning.

    funktioniert prinzipiell, habe es auch schon mal verwendet, kann aber je nach verwendung etwas umständlich werden. ich weiß nicht, ob sich dein problem so lösen lässt. vielleicht solltest du über einen worker thread nachdenken.

  2. Also das mit den konstruktoren musst du dir wohl nochmal ansehen, Crush.

    class bing

    {

    public:

    bing(int x=0):zahl(0){}

    virtual ~bing(){};

    virtual void set(const int x){zahl=x;}

    virtual int get() const {return zahl;}

    private:

    int zahl;

    };

    class ding : virtual bing

    {

    public:

    ding(){bing::bing();}; // basis konstruktor wird zweimal aufgerufen

    virtual ~ding(){bing::~bing();}; // subobject vom typ bing wird zweimal zerstört

    void set(const int x){bing::set(x);}

    void setown(const int x) {zahl=x;}

    int get() const {return bing::get();}

    int getown() const {return zahl;}

    private:

    int zahl;

    };

    ich hab mal die zwei klassen als beispiel genommen. wozu wird im ctor von ding der basis-ctor expilzit aufgerufen? wenn das programm die öffnende geschweifte Klammer des ctors von ding erreicht ist das komplette ding - objekt schon konstruiert und der basis ctor wurde bereits aufgerufen. der compiler generiert standardmäßig einen aufruf des default ctors der Basisklasse. wenn man das nicht möchte oder es nicht geht, muss man den aufruf selbst explizit in der initialisierungsliste VOR der geschweiften klammer angeben

    ding() : bing("ding ruft bing") {}

    // unter der annahme bing hat einen ctor bing(char* Msg);

    im vorliegenden fall

    ding(){bing::bing();};

    wird innerhalb das anweisungsblocks ein namenloses objekt vom typ bing erzeugt, das beim verlassen des blocks sofort wieder zerstört wird (im debugger kann man den destruktor aufruf von bing verfolgen).

    ähnlich ist es beim destruktor. NACHDEM ~ding() fertig ist wird automatisch ~bing() aufgerufen. der explizite aufruf innerhalb von ~ding() ist etwa so, als wollte man den keller vor dem dach abreißen.

    der folgende code würde zum beispiel abstürzen

    class bing

    {

    public:

    bing(int x=0):zahl(0){pFoo = new int(10);}

    virtual ~bing(){delete pFoo;}

    private:

    int zahl;

    int *pFoo;

    };

    class ding : virtual bing

    {

    public:

    ding(){bing::bing();};

    virtual ~ding(){bing::~bing();}; // zweimal delete pFoo

    private:

    int zahl;

    };

    man könnte das problem umgehen

    virtual ~bing(){if (pFoo) {delete pFoo; pFoo = NULL;};}

    aber die eigentliche logik ist nicht korrekt. richtiger wäre ding so zu definieren

    class ding : virtual bing

    {

    public:

    ding(){}

    virtual ~ding(){}

    private:

    int zahl;

    };

    und noch was zum goto. ich selbst hab mein letztes goto vor vielen jahren (damals noch in basic) verwendet. aber es gibt durchaus sinnvolle verwendungen, wie ich erst jetzt wieder in Tom Archers 'Inside C#' gelesen habe (ja c# hat ein goto). er beschreibt, dass der goto befehl in ungnade fiel mit der veröffentlichung des artikels 'Go To Statement Considered Harmful' (Edsger W. Dijkstra, 1968) http://www.acm.org/classics/oct95/

    in einem switch block zum beispiel könnte es sinnvoll sein ein goto zu verwenden.

  3. Das Makro _UNICODE wird nur für die Header-Dateien der C-Laufzeitbibliothek verwendet, das Makro UNICODE dagegen für die Win32-Header-Dateien. Normalerweise müssen beide Makros definiert sein. Ich mache das immer in Projekt-Settings bei den Präprozessor-Einstellungen. In der MSDN habe ich folgendes gefunden:

    To compile code for Unicode, you need to #define UNICODE for the Win32 header files and #define _UNICODE for the C Run-time header files. These #defines must appear before the following:

    #include <windows.h>

    and any included C Run-time headers. The leading underscore indicates deviance from the ANSI C standard. Because the Windows header files are not part of this standard, it is allowable to use UNICODE without the leading underscore.

  4. Ich hab das ganze auch mal ausprobiert und festgestellt das mit den Pointer-Addressen alles stimmt. Wenn man sich den Assembler Code (ich benutze Visual C++6 als Compiler) dazu ansieht, dann ist es eigentlich ganz leicht zu erklären. Bei der Zuweisung:

    int nErgebnis = nConstWert + 50;

    schreibt der Compiler

    int nErgebnis = 150;

    das heißt der Wert steht schon zu Beginn fest im Code. Der Compiler sieht das nConstWert als konstanter Integer 100 definiert ist und ersetzt deshalb jedes Vorkommen mit dem konkreten Wert. Jede Manipulation der Variablen während des Programms bleibt also unberücksichtigt. Dieses Verhalten ist compilerabhängig und in den Standards nicht definiert. Nach der Zeile * pAufConstWert = 50;

    ist jeder Ausdruck der nConstWert benutzt nicht definiert. Ich habe auf Google einige Posts zu diesem Thema gefunden und bei einigen Compilern würde 100 und bei anderen 150 herauskommen.

    Um wirklich den aktuellen Wert aus dem Speicher zu lesen müsste man in dem Fall:

    int nErgebnis = *const_cast<int*>(&nConstWert) + 50;

    schreiben.

  5. vielleicht ist das ja auch interessant

    //: C11:PmemFunDefinition.cpp

    class Simple2 {

    public:

    int f(float) const { return 1; }

    };

    int (Simple2::*fp)(float) const;

    int (Simple2::*fp2)(float) const = &Simple2::f;

    int main() {

    fp = &Simple2::f;

    } ///:~

    In the definition for fp2 you can see that a pointer to member

    function can also be initialized when it is created, or at any other

    time. Unlike non-member functions, the & is not optional when

    taking the address of a member function. However, you can give

    the function identifier without an argument list, because overload

    resolution can be determined by the type of the pointer to member.

    weiteres Beispiel:

    //: C11:PointerToMemberFunction2.cpp

    #include <iostream>

    using namespace std;

    class Widget {

    void f(int) const { cout << "Widget::f()\n"; }

    void g(int) const { cout << "Widget::g()\n"; }

    void h(int) const { cout << "Widget::h()\n"; }

    void i(int) const { cout << "Widget::i()\n"; }

    enum { cnt = 4 };

    void (Widget::*fptr[cnt])(int) const;

    public:

    Widget() {

    fptr[0] = &Widget::f; // Full spec required

    fptr[1] = &Widget::g;

    fptr[2] = &Widget::h;

    fptr[3] = &Widget::i;

    }

    void select(int i, int j) {

    if(i < 0 || i >= cnt) return;

    (this->*fptr)(j);

    }

    int count() { return cnt; }

    };

    int main() {

    Widget w;

    for(int i = 0; i < w.count(); i++)

    w.select(i, 47);

    } ///:~

    Similarly, when the pointer-to-member is dereferenced, it seems

    like

    (this->*fptr)(j);

    is also over-specified; this looks redundant. Again, the syntax

    requires that a pointer-to-member always be bound to an object

    when it is dereferenced.

    die Beispiele sind aus dem Buch Thinking in C++ von Bruce Eckel. Kann man sich als pdf bei http://www.bruceeckel.com laden.

  6. Original geschrieben von Technician

    Hi!

    Ich hab hier folgendes Problemchen:

    Eine Klasse "Kunde" soll als Attribut einen Vector enthalten, in dem Objekte der Klasse "Anlage" gespeichert werden.

    Da ich noch nie mit Vector und OOP gleichzeitig zu tun hatte:

    gehören die Zeilen

    
    
    #include <vector>
    
    
    using namespace std ;
    
    
    typedef vector<Anlage> ANLVECTOR;
    
    
    in die Header- oder CPP-Datei von "Kunde"?!
    
    
    ANLVECTOR myVector;
    
    
    ANLVECTOR::iterator myIterator;
    
    
    gehören in die Headerdatei, das ist mir klar... das ist hier mal (vereinfacht) meine Kunde-Headerdatei, noch ohne Vector.
    
    
    //KUNDE.H
    
    
    #ifndef KUNDE_H
    
    	#define KUNDE_H
    
    
    class Anlage;
    
    
    
    class Kunde
    
    {
    
    public:
    
    	Kunde(char* n);
    
    	~Kunde(){};
    
    
    ...
    
    private:
    
    	char* seinName;
    
    Anlage* seineAnlage;
    
    	//bisher nur eine Anlage, mit dem Vector werden's viele!
    
    ...	
    
    
    
    };
    
    
    #endif
    
    
    Ich hoffe, ihr könnt mir da weiterhelfen; mit "mal rumprobieren ob's so oder so ist" is nämlich nix -> Projekt schon zu groß! Gruß, Technician
    In dem Fall würde ich es in die Header Datei schreiben, zumindest die Typdefinition.
    
    //KUNDE.H
    
    
    #include <vector>
    
    using namespace std ; 
    
    /*
    
    den vector include würde ich in das standard include stdafx.h ziehen
    
    */
    
    
    #ifndef KUNDE_H
    
    	#define KUNDE_H
    
    
    class Anlage; // Vorwärtsdeklaration
    
    
    typedef vector<Anlage*> ANLVECTOR;
    
    /* 
    
    Muss nach der vorwärtsdeklaration von class Anlage stehen deshalb kann es auch nicht im Kunde.cpp vor dem dem Kunde.h include stehen. Und wenn es danach stehen würde, kannst du ANLVECTOR logischerweise nicht im header verwenden. Außerdem enthält der ANLVECTOR bei mir nur pointer auf anlage-objekte - macht operationen mit dem vector schneller. Wenn du wirklich komplette objekte in dem vector ablegen willst, reicht die einfache vorwärtsdeklaration nicht aus (geht nur für pointer). In diesem fall musst du vorher Anlage.h inkludieren.
    
    */
    
    
    
    class Kunde
    
    {
    
    public:
    
    	Kunde(char* n);
    
    	~Kunde(){};
    
    
    ...
    
    private:
    
    	char* seinName;
    
    Anlage* seineAnlage;
    
    	//bisher nur eine Anlage, mit dem Vector werden's viele!
    
    ...	
    
    
    
    };
    
    
    #endif
    
    

  7. Original geschrieben von Klotzkopp

    ShellExecute startet allerdings nicht den Kommandozeileninterpreter (command/cmd), daher funktioniert

    ShellExecute( NULL, "open", "dir c:\\", NULL, NULL, SW_SHOWDEFAULT );

    nicht, weil dir ein interner Befehl ist, der in den Kommandozeileninterpreter eingebaut ist.

    In dem Fall kann man aber den Umweg über eine .bat-Datei gehen.

    so gehts

    ShellExecute(NULL, "open", "cmd", "/k dir c:", NULL, SW_SHOWNORMAL );

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...