std & lib ?



  • Hi,

    ich habe in meinem WinAPI - Code eine std::map eingebaut, oder besser ich versuche es gerade.

    includiere <map> und auch compilieren ohne Probs, doch beim linken bekomme ich folgenden Fehler:

    PGM error LNK2019: unresolved external symbol "public: void __thiscall std::_String_base::_Xran(void)const " (?_Xran@_String_base@std@@QBEXXZ) referenced in function "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::assign(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned int,unsigned int)" (?assign@?basic_string@DU?basic\_string@DU?char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@ABV12@II@Z)

    Sorry, habe noch nie mit den Container Klassen gearbeitet, aber kann es sein, dass ich zusätzlich zum Header noch eine Lib dem Linker mitteilen muss? Oder fehlt mir noch ein include? Für andere Stellen benötige ich noch <windows.h> und <string.h> <commctrl.h> <iostream.h> <fstream.h> "Shlwapi.h"

    Vielen Dank im Voraus
    Buster



  • Zeig uns ein kleines Stück vollständigen Quellcode, der sich kompilieren läßt, aber nicht zu linken ist.



  • ich seh da niergends ListView, aber Du hast mich kalt erwischt, ich hänge immer noch an dem Eck. Warum ich das nun nicht linken kann, ist für mich ein Rätsel. Eigentlich möchte ich jetzt versuchen meine ListView zu kapseln und in eine Klasse zu bannen und habe das Prob mit der Procedure. Wollte Sie global machen und über einen Tree/Map die jeweiligen Child HWND's und dazugehörigen Pointer der ClassenInstanzen abspeichern. Das zur Theorie - nun habe ich aber gelesen, dass in Containern besser keine Pointer gespeichert werden, wegen der Kopiererei, wodurch es zu Fehlern kommen kann.

    Aber wenn Du mich nicht dumm sterben lassen möchtest, und Dir auch die Map-Problematik anschauen könntest, 🙂 Danke. Doch ich bin eigentlich auf der Suche nach einer funzenden Referenz für die this-Pointer der ListView Klassen, wobei Map wohl nicht so toll ist.

    aber mal zur Ansicht - linkenden Teil geht leider nicht, da brauchtest Du das ganze Projekt.

    #ifndef _LISTVIEWCHILD_HPP
    #define _LISTVIEWCHILD_HPP
    
    #include "RESOURCE.HPP"
    #include <windows.h>
    #include <string.h>
    #include <commctrl.h>
    #include <map>
    
    class ListViewChild
    {
    public:
        ListViewChild ( HINSTANCE hInstance, HWND hwndClient, char const * ListViewTitle ) ;
        HWND WINAPI NewChildListViewWin ( HINSTANCE hInstance, HWND hwndClient, char const * ListViewTitle ) ;
    private:
        HWND ListViewHwnd ;        
    } ;
    
    LRESULT CALLBACK ChildListViewProc  ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) ;
    
    #endif
    
    //--------------------------------------------------------
    //--------------------------------------------------------
    //--------------------------------------------------------
    
    #include "LISTVIEWCHILD.HPP"
    
    std::map<long,ListViewChild> ListTree ;
    
    ListViewChild::ListViewChild ( HINSTANCE hInstance, HWND hwndClient, char const * ListViewTitle )
    {
        ListViewHwnd = NewChildListViewWin ( hInstance, hwndClient, ListViewTitle ) ;
    }
    
    HWND WINAPI ListViewChild::NewChildListViewWin ( HINSTANCE hInstance, HWND hwndClient, char const * ListViewTitle ) 
    {
        HWND hwnd ; 
        MDICREATESTRUCT mcs ;  
        //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
        // Register ChildWindowProperties
        //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
        WNDCLASS wndclass ;
        wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
        wndclass.lpfnWndProc   = ChildListViewProc ;
        wndclass.cbClsExtra    = 0 ;
        wndclass.cbWndExtra    = 0 ;
        wndclass.hInstance     = hInstance ;
        wndclass.hIcon         = LoadIcon ( hInstance, MAKEINTRESOURCE ( IDI_TABLE ) ) ;
        wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW ) ;
        wndclass.hbrBackground = ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ;
        wndclass.lpszMenuName  = NULL ;
        wndclass.lpszClassName = ListViewTitle ;
        RegisterClass ( &wndclass ) ;
    
        mcs.szTitle = ListViewTitle ; 
        mcs.szClass = ListViewTitle ; 
        mcs.hOwner  = hInstance ; 
    
        // Use the default size for the child window. 
        mcs.x     = CW_USEDEFAULT ; 
        mcs.cx    = CW_USEDEFAULT ; 
        mcs.y     = CW_USEDEFAULT ; 
        mcs.cy    = CW_USEDEFAULT ; 
        mcs.style = MDIS_ALLCHILDSTYLES ; 
    
        // Tell the MDI client window to create the child window. 
        hwnd =  ( HWND ) SendMessage ( hwndClient, WM_MDICREATE, 0, ( LONG ) ( LPMDICREATESTRUCT ) &mcs ); 
    
        // Im ChildFenster den this-Pointer der zu ihm gehörenden Instanz speichern !
        // Wichtig um aus der WndProc auf Membervariablen dieser Instanz zugreifen zu können !!!
    
        INITCOMMONCONTROLSEX lpInitCtrls;
        lpInitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
        lpInitCtrls.dwICC  = ICC_LISTVIEW_CLASSES;
        InitCommonControlsEx( &lpInitCtrls );
    
        RECT ChildWinRect ;
        GetClientRect(hwnd, &ChildWinRect);
    
        HWND HwndListView = CreateWindow  ( WC_LISTVIEW,
                                            "",
                                            WS_VISIBLE | WS_CHILD | LVS_REPORT,
                                            0,
                                            0,
                                            ChildWinRect.right  - ChildWinRect.left,
                                            ChildWinRect.bottom - ChildWinRect.top,
                                            hwnd,
                                            0,
                                            hInstance,
                                            0 ) ;
    
        ListView_SetExtendedListViewStyle ( HwndListView, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT );
    
        LVCOLUMN    Spalte ;
                    Spalte.mask     = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT ;
                    Spalte.fmt      = LVCFMT_LEFT ;
        LVITEM      Item ;
                    Item.iSubItem   = 0;
                    Item.stateMask  = 0;
                    Item.mask       = 0;
                    Item.cchTextMax = MAX_PATH;
        int         index ;
    
        for (index = 0; index < 5; index++)
        {
            char HeaderText[]   = "Test" ;
            int  Spaltenbreite  = 100 ;
            Spalte.cx           = Spaltenbreite ;                      
            Spalte.pszText      = HeaderText ;
            Spalte.cchTextMax   = sizeof(HeaderText) ;
            ListView_InsertColumn ( HwndListView, index, &Spalte ) ;
        }
    
        for (index = 0; index < 5; index++)
        {
            Item.iItem = index;
            ListView_InsertItem(HwndListView,&Item);
            for (int SubIndex = 0; SubIndex < 5; SubIndex++)
            {
                ListView_SetItemText( HwndListView, index, SubIndex, "SubItem" ); 
            }
        }
        return HwndListView ; 
    }
    
    //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
    // Procedure - ChildListViewProc
    //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
    LRESULT CALLBACK ChildListViewProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
    {
        switch (message)
        {
            case WM_SIZE:
                RECT ChildWinRect ;
                GetClientRect ( hwnd, &ChildWinRect ) ;
                /*
                MoveWindow ( ListViewHwnd, 
                             0, 
                             50, 
                             ChildWinRect.right  - ChildWinRect.left, 
                             ChildWinRect.bottom - ChildWinRect.top, 
                             TRUE ) ;
                */
                return 0;
    
            case WM_DESTROY:
                PostQuitMessage ( 0 ) ;
                return 0 ;
    
            default:
                break;
        }
        return DefMDIChildProc ( hwnd, message, wParam, lParam ) ;
    }
    

    Die Map hatte ich in der HPP, global und auch im Konstruktor, immer dasselbe.

    Dank Dir ????

    Buster



  • Neee,
    M$ hat mehrere Versionen von der Lib fuer die std Sachen ( MSVCRT.LIB C++ Standard Library) .... fuer Multithread faehig oder nicht .... fuer Exe oder DLL ...

    Schau Dir mal folgende Compiler-Optionen an:
    /MD
    /MDd
    /ML
    /MLd
    /MT
    /MTd

    Was fuer ein Projekt hast DU ? Exe oder DLL, mit mfc oder ohne ? vielleicht ATL ? Benutzt Du multithraeding ? ....

    Ciao ...



  • Das ließ sich erfolgreich kompilieren und linken.

    (Mal abgesehen, das ich ne WinMain einfügen musste, Resource.hpp rausnehmen musste... )

    Mach das nächste mal ein Minimalbeispiel!!



  • habe EXE ohne MFC und ALT

    also das mit der MSDN .......... ich checks nicht, da steht wirklich alles drin, aber für meine Logik in solch einem Verhau.

    Wo finde ich, oder unter welchem Schlagwort kann man suchen, um auf die benötigten Lib's zu stoßen? Bei der std map class steht nichts dabei, an dieser Stelle hätte ich es eigentlich erwartet, hmmm

    Danke
    Buster



  • @ListView,

    Du hast ja mindestens die comctl32.lib einbinden müssen, was steht da bei Dir noch drin?

    Danke übrigens
    Buster



  • Mach mal ein ganz neues Projekt zum testen. da machst du einfach nur das rein

    #include <map>
    
    int main() {
        std::map<int, int> MapInstanz;
            return 0;
    }
    

    Funzt das?



  • nur comctl32.lib



  • nöööö,

    test error LNK2019: unresolved external symbol _WinMain@16 referenced in function _WinMainCRTStartup

    sorry, bin learning by doing 😃



  • Trottel!! Da musste auch ne Konsolenanwendung für erstellen!!



  • @ListView,
    check ich nicht ????

    @furz,
    leeres Project, neu cpp rein, dein Code und die obige Fehlermeldung.



  • @furz,
    ist w32 keine Konsole?



  • bei Visual C++ kann man bei der Projekterstellung auswählen ob es eine Win32-Konsolenanwendung oder eine Win32-Anwendung werden soll. weiß jetzt nicht die genauen bezeichner. da wählste dann Konsolenanwendung



  • @furz,

    ok, console funzt!!!



  • dann erstell nochmal ein neues win32 projekt und füg da deinen aktuellen code nochmal rein. vielleicht hast du dir bei den projektoptionen was verstellt.



  • @furz,

    danke, probiers mal!

    Buster



  • Grad deinen Code gesehen ...
    Zu dem Linken ... siehe oben !

    1. du benutzt MFC, warum ned die MFC-Klassen ?
    Das ist wie in der Schule, wo man den Buben rechnen lernen will und ihnen deshalb den Taschenrechner verbietet ! Die STL Container haben Ihre berechtigung, wenn man Biblotheks- /und Betriebssystemunabhaengig programmieren muss, bzw. keine Biblothek hat, die einem unter die Arme greift (ATL, Konsolen-Apps ... etc) ! Und wenn man es lernen will 🙂
    Anmerkung: die STL Implementierung von M$ hat probleme bei Multithreading ... die MFC Container nicht ! Die MFC hat auch ne Klasse, die Direct auf das Speichern von CObject Objekten Spezialisiert ist .... !!!

    2. Pointer in Container ist ok ! Jeder der was anderes behauptet .... 😃 Ich benutz es fast ausschliesslich, bin kein Fan von Operatoren ueberschreiben und Kopiekonstruktoren erzeugen, nur um meine Klassen in einen COntainer boxen zu koennen !!! :-))) Ja, aufpassen muss man schon, das man keine Speicherleaks bekommt, aber das muss man anderswo auch 🙂

    3. Der sauberere weg waere ne eigene Listenklasse zu schreiben, die dir nur deine ListViewChild Objekte verwaltet .... mittels nen member als Containerklasse oder direkt von ner Containerklasse abgeleitet ....

    4. Noch sauberer waere ne Pointerklasse, die Dir ein ListViewChild-pointer verwaltet ... vielleicht mit referenzzaehlung aehnlich wie smartpointer .... man kanns aber auch uebertreiben ....

    5. der Typ des Containers richtet sich nach dem Zugriff - dem verwendungszweck ... und der benoetigten Performance ....
    willst einfach nur durchiterieren -> Liste
    willst die sache Sortiert vorliegen haben -> Set
    willst eine Zuordnung von Objekt zu Key (und mittels Key schnell zugreifen koennen) -> Map
    willst ein dynamisches array mit schnellen zugriff auf nen Index (5.tes Objekt z:B.) -> vector
    willst nen Stapel -> stack
    willst nen Fifo -> queue
    ...
    vieles ist geschmachssache 🙂

    Ciao ...

    Ciao ....



  • Ups doch keine MFC ... ok vergiss 1. ! 😃

    Ciao ...



  • @XYZ,

    danke für Deine Mühe, ich will einfach nur die this-Pointer in Verbindung mit dem in der Classe erzeugten FensterHandle ablegen, beim Destructor aus der Liste löschen.

    Das soll in der Procedure des Fensters dann abgefragt werden, denn da bekommt man den FensterHandle, weiß aber nicht, auf welche KlassenInstanz sich das bezieht, nun this rauswurschtel und freie Fahrt auf alle Member Vars u. Methoden.

    Hattu da Idee?


Anmelden zum Antworten