tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
6
ZUGRIFFE
1071
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    toma3 toma3 ist offline Rookie
    Registriert seit
    Jan 2009
    Beiträge
    5
    Hallo,
    ich versuche eine GUI zu programmieren zum folgenden Beitrag:
    http://www.tutorials.de/forum/c-c-tu...-teil-1-a.html

    Das Programm als Konsolenanwedung klappt wunderbar, jedoch mit GUI komm ich ins stottern. Wahrscheinlich zu wenig Hintergrundwissen....

    Meine Vorgehensweise:

    1. Erstelle eine neue VCL -Formularanwendung (Borland C++ Builder) (Oberfläche mit einem Button als Auslöser, ComboBoxEx zur Auswahl der Domänen und CheckListBox für die einzelnen Rechner, die An- oder Abgewählt werden können, zur Weiterverarbeitung gedacht)
    2. Binde Dateien (netscan.cpp und netscan.h) im Projekt ein
    netscan.h
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    #ifndef NETSCAN_H
    #define NETSCAN_H
     
    //#error  !!  Bitte das Projekt gegen die mpr.lib linken ==> dann diese Zeile löschen
     
    #include <windows.h>
    #include <string>
    #include <map>
    #include <winerror.h>
     
    using namespace std;
     
    typedef map<string,string> StringToString;
    typedef void (*func)(void *, DWORD, string);
     
    class NetworkBase
    {
    public:
     
        
        bool NetScan(StringToString* dic,
                                 void* obj,
                                 func eh,
                                 string resource="",
                                 DWORD displaytype = RESOURCEDISPLAYTYPE_GENERIC,
                                 DWORD type = RESOURCETYPE_ANY, 
                                 LPNETRESOURCE lpnr=NULL);
     
    };
    nescan.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    
    #include "netscan.h"
     
    bool NetworkBase::NetScan(StringToString* dic,
                             void* obj,
                             func eh, 
                             string resource,
                             DWORD displaytype, 
                             DWORD type,
                             LPNETRESOURCE lpnr)
    {
      DWORD dwResult, dwResultEnum;
      HANDLE hEnum;
      DWORD cbBuffer = 16384;      
      DWORD cEntries = -1;         
      LPNETRESOURCE lpnrLocal;    
      DWORD i;
     
     
        // wenn wir eine Resource übergeben, dann erstellen wir und eine
        // NETRECOURCE Struktur
        if(lpnr == NULL && !resource.empty())
        {
            NETRESOURCE rec;
            rec.dwScope             = RESOURCE_GLOBALNET;
            rec.dwType              = type;
            rec.dwDisplayType = displaytype;
            
            // wenn wir nach einer Freigabe oder nach einem Netzwerkdrucker suchen
            if( (type == RESOURCETYPE_DISK) || (type == RESOURCETYPE_PRINT) )
                rec.dwUsage = RESOURCEUSAGE_CONNECTABLE;
            else
                rec.dwUsage             = RESOURCEUSAGE_CONTAINER;
            
            rec.lpLocalName     = NULL;
            rec.lpComment           = NULL;
            rec.lpProvider      =   NULL;
            rec.lpRemoteName    = (char *)resource.c_str();
            lpnr = &rec;    
        }
     
        
        // open the enumeration of network
        dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, // alle Netzwerkressourcen
                                                        type,       // alle Ressources
                                                        0,                                  // enumerate alle Ressources    
                                                        lpnr,                               // die vordefinierte Ressource z.B. ein Server zum scannen seiner Shares
                                                        &hEnum );                       // handle zu der Resource
        
        if(dwResult != NO_ERROR)
        {
            eh(obj, dwResult, "");
            return false; // Error Handling
        }
            
     
        
        // start enumeration
        // Schleife bis the enumeration keine Items mehr findet
        do
        {
            // Speicher für das struct-array allokieren
            lpnrLocal = new NETRESOURCE[cbBuffer];
        
            // es konnte kein Speicher allokiert werden
            if(!lpnrLocal)
            {
                eh(obj, 0, "Speicher allokieren fehlgeschlagen");
                return false;
            }
                
            
            // denn Speicher auf 0 setzen
            ZeroMemory(lpnrLocal, cbBuffer);
            
     
            // Das Netzwerk enumieren und die Ressourcen raus holen
            dwResultEnum = WNetEnumResource(hEnum,      // resource handle
                                        &cEntries,  // auf -1 vorbelegt
                                        lpnrLocal,  // Zeiger auf die lokale Struktur
                                        &cbBuffer); // Puffergröße
            
            // wenn kein Fehler auf getreten ist ( es wurden Ressourcen gefunden
            if (dwResultEnum == NO_ERROR)
        {
          // Die Ressourcen iterieren, die in dieser Ebene gefunden wurden
                for(i = 0; i < cEntries; i++)
          {
                    // hier holen wir die Daten raus
                    string name = ""; 
                    string comment = ""; 
                    
                    if(lpnrLocal[i].lpRemoteName)
                        name= (char*)lpnrLocal[i].lpRemoteName;
                    
                    if(lpnrLocal[i].lpComment)
                        comment= (char*)lpnrLocal[i].lpComment;
     
                    // Überprüfen, ob die Resource ein Container ist
                    if(RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER))
                    {
                        
     
                        // jetzt überprüfen wir ob die Ressource der angegebenen Ebene von <displaytype> entspricht
                        if(displaytype == lpnrLocal[i].dwDisplayType)
                        {
                            // wir ersetzten alle Backslashes durch nichts fals vorhanden
                            while(name.find("\\") != string::npos)
                                name.replace(name.find("\\"), strlen("\\"), "");
     
                            //jetzt fügen wir die gefundene Resource in unsere map ein
                            dic->insert(StringToString::value_type(name, comment));
                        }
                        // wenn die Resource nicht userer eben entspricht, aber trotzdem ein Conteiner ist (s.o.)
                        // dann rufen wir die NetScan-Funktion rekursiv auf
                        else
                        {
                            if(!NetScan(dic, obj, eh, name, displaytype, type, &lpnrLocal[i] ))
                            {
                                eh(obj, 0, "NetScan fehlgeschlagen");
                            }                       
                        }
                    }
                    else
                    {
                    
                        // Wenn die Resource kein Container ist (evtl. eine Datenfreigabe oder Drucker
                        // dann überprüfen wir trotzdem, ob sie der angegebenen Ebene enspricht
                        // denn dann können wir sie in die map einfügen
                        if(displaytype == lpnrLocal[i].dwDisplayType)
                        {
                            // wir entfernen zunächst den Rechnernamen
                            if(name.find(resource) != string::npos)
                                name.replace(name.find(resource), resource.size(), "");
                            
                            //dann entfernen wir wieder alle Backslashes
                            while(name.find("\\") != string::npos)
                                    name.replace(name.find("\\"), strlen("\\"), "");
     
                            // Schließlich können wir die Resource in die map einfügen
                            dic->insert(StringToString::value_type(name, comment));
                        }
                    }
                }
            }
            else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
            {   
                // löschen des arrays
                delete[] lpnrLocal;
                eh(obj, dwResultEnum, "");
                // ein Fehler ist in dieser Ebene aufgetreten wir brechen die Schleife ab
                break;
            }
     
            // löschen des arrays
            delete[] lpnrLocal;
        }
        while(dwResultEnum != ERROR_NO_MORE_ITEMS);     // ende der Schleife
     
        
     
        // schließen der Enumeration
        dwResult = WNetCloseEnum(hEnum);
      
        
      if(dwResult != NO_ERROR)
        {
            eh(obj, dwResult, "");
            return false; 
        }
        
     
        return true;
    }
    3.main.cpp versuche ich in meine Unit1.cpp zu integrieren:
    Unit1.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include "netscan.cpp"
    #include "netscan.h"
    #include <iostream>
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void ErrorHandling(void*, DWORD error, string errortext);
     
     
    void __fastcall TForm1::[COLOR="Red"][B]Button1Click[/B][/COLOR](TObject *Sender)
    {
        StringToString dic;
        // der Iterator der für die Map
        StringToString::iterator iter;
        bool ret;
        NetworkBase net;
        
    /*
     *              Domain suchen
     */
        // hier holen wir uns die domains/workgroups
        ret = net.NetScan(&dic, NULL, &ErrorHandling, "", RESOURCEDISPLAYTYPE_DOMAIN);
     
        if(!ret)
        {
            ShowMessage((NULL, 0, "NetScan fehlgeschlagen"));
            exit;
            //return -1;
        }
     
        // wurden domains gefunden ?
        if(!dic.size())
        {
            ShowMessage("Keine Domains/Wourkgroups gefunden");
            exit;
            //return -1;
        }
     
        // iterate der domains und ausgeben
        iter = dic.begin();
        //cout << "Folgende Domains gefunden:" << endl;
        while(iter != dic.end())
        {
     
            [COLOR="Red"][B]ShowMessage(iter->first);[/B][/COLOR]
            cout << "Domain: " << iter->first << " | Kommentar: " << iter->second << endl;
            iter++;
        }
     
        // wir speichern uns die 1. domain
        iter = dic.begin();
        string firstDomain = iter->first;
        // dann löschen wir die map
        [COLOR="Red"][B]ComboBoxEx1->Items->Text=iter->first;[/B][/COLOR]
        dic.clear();
     
    /*
     *              Rechner in der 1. Domain suchen
    */
     
     
        // nun holen wir uns die Rechner aus der 1. Domain
        cout << "\n\nRechner aus " << firstDomain << ":" << endl;
     
        // aufruf der NetScan-Funktion mit der 1. Domain
        ret = net.NetScan(&dic, NULL, &ErrorHandling, firstDomain, RESOURCEDISPLAYTYPE_SERVER);
        if(!ret)
        {
            ErrorHandling(0, NULL, "NetScan fehlgeschlagen");
            exit;
            //return -1;
        }
     
        // wurden Rechner gefunden
        if(!dic.size())
        {
            cout << "Keine Rechner in " << firstDomain << " gefunden" << endl;
            exit;
            //return -1;
        }
        // wenn ja dann ausgeben
        iter = dic.begin();
        cout    << "\nFolgende Rechner in " << firstDomain << " gefunden:" << endl;
        while(iter != dic.end())
        {
            cout << "Rechner: " << iter->first << " | Kommentar: " << iter->second << endl;
            iter++;
        }
     
        // wir speichern uns den 1. Rechner
        iter = dic.begin();
        string firstServer = iter->first;
        // dann löschen wir die map
        dic.clear();
     
    }
     
    void ErrorHandling(void*, DWORD error, string errortext)
    {
        cout << " FEHLER ";
        if(error)
            cout << "-> Fehlernummer: " << error << endl;
        if(errortext.empty())
            cout << "Hier koennte jetzt noch eine Beschreibung des Fehlers stehen\n" << endl;
        else
            cout << "-> " << errortext << endl;
    }

    Erste rot markierte Zeile ist der Auslöser und dann folgen meine Änderungen in dem ich versuche die Ausgabe (statt cout)in ShowMessage oder ComboBoxEx zuumwandeln:
    ComboBoxEx1->Items->Text=iter->first;
    So und beim Compilieren kommt schon ein Fehler:
    Konvertierung von 'const string' nach 'UnicodeString' nicht möglich

    So wie kann ich das am besten lösen? Ist meine Vorgehensweise falsch?
    Geändert von toma3 (29.01.09 um 09:49 Uhr) Grund: Quellcode Ergänzung
     

  2. #2
    Registriert seit
    Jan 2002
    Ort
    Bayern
    Beiträge
    1.390
    Hi,

    die Frage ist was ist 'UnicodeString'? in meinem Tutorial hab ich mich nicht wirklich um encoding geschert und hab die ANSI-Api verwendet.
    Borland VCL (hab ich keine Ahnung davon) erwartet warscheinlich bei
    ShowMessage()
    bzw.
    ComboBoxEx1->Items->Text =
    einen 'UnicodeString' das wird warscheinlich ein Datentyp sein, der Strings in beliebigen Encodings verwalten kann.
    Also musst du dafür sorgen, dass du den std::string den dir der Iterator zurückliefert in einen UnicodeString konvertierst.

    Gruß Daniel
     
    we would change the world if god gave us the source code...
    and remember, science is nothing more than reverse engineering nature...

    Current projects:
    - LdrawConverter

  3. #3
    Crash Kid Crash Kid ist offline Mitglied Gold
    Registriert seit
    Jan 2009
    Beiträge
    147
    Hey,
    also ich hab hier mal ein paar Links für ein API-Tutorial. Es ist wirklich gut, um dein 'Hintergrundwissen' mal ein bisschen aufzubessern
    http://www.win-api.de/tutorials.php

    Du schreibst in deinem Code zudem 'cout', warum? cout ist doch nur für Konsolenanwendungen gedacht, meiner Meinung nach. Bei ner Win-API oder auch GUI gibt es kein 'cout' um etwas anzuzeigen. Außer du willst es in einer Konsole anzeigen.

    Zu deinem Unicode: Ich bin kein Unicode-Experte, aber Unicode
    spezifiziert primär die Interpretation von Werten als Zeichen. Dieser Link wird dir vielleicht helfen: http://de.wikipedia.org/wiki/UTF
     

  4. #4
    toma3 toma3 ist offline Rookie
    Registriert seit
    Jan 2009
    Beiträge
    5
    Der ursprüngliche Quellcode enthält cout usw..(als Konsolenanwedung schon getestet)
    Ich versuche mit GUI das ganze anzupassen und ersetze cout mit ShowMessage als Test, jedoch beim Compilieren kommt der Fehler mit dem Unicode...
    Und ich weiß es nicht wie ich es wandeln soll.
     

  5. #5
    toma3 toma3 ist offline Rookie
    Registriert seit
    Jan 2009
    Beiträge
    5
    Hab was gefunden, nur mit dem Verstehen tue ich mir schwer...

    TCHAR (deklariert in der Header-Datei tchar.h) ist ein typedef (Alias), der entweder zu char oder zu wchar_t abgebildet wird. Wenn Sie portierbaren Quelltext schreiben möchten, sollten Sie TCHAR verwenden, anstatt char oder wchar_t hart zu codieren.

    Die Option _TCHAR entspricht steuert die Floating-Definition von _TCHAR. Sie haben folgende Möglichkeiten:

    wchar_t: legt UNICODE fest und _UNICODE definiert und verwendet Wide-Definitionen der Standardbibliothek und der API-Funktionen.
    char: _TCHAR verwendet keine Wide-Definition.
    Die Option _TCHAR entspricht wird auf der Seite ProjektOptionenVerzeichnisse und Bedingungen gesetzt.

    Verwendung von _TCHAR entspricht wchar_t für die VCL
    Die VCL ist in Unicode implementiert und erwartet immer Unicode. Für die Verwendung der VCL sollten Sie _TCHAR entspricht auf wchar_t setzen. Beispielsweise kann der folgende Code erst compiliert werden, wenn Sie _TCHAR auf wchar_t gesetzt haben:
    Code :
    1
    2
    
    TResourceStream* res =  new 
        TResourceStream(HInstance, ResourceId, RT_RCDATA);
    Wenn _TCHAR char ist, wird RT_RCDATA einem char* zugeordnet, aber die VCL erwartet wchar_t.

    Verwendung der Funktion _TEXT für Konstanten-Strings
    Mit der Funktion _TEXT oder _T stellen Sie sicher, dass für Konstanten-Strings ANSI oder Unicode verwendet wird. Zum Beispiel:
    Code :
    1
    2
    
    ::MessageBox(0, _TEXT("The message"), 
        _TEXT("The caption"), MB_OK);
    Codeänderungen sind für _TCHAR entspricht wchar_t erforderlich
    Bevor Sie die Option _TCHAR auf wchar_t setzen können, muss Ihr Projekt einen Einsprungspunkt namens _tmain oder _tWinMain haben. Neue (mit C++Builder 2009 erstellte) Projekte enthalten standardmäßig diese Einsprungspunkte, aber bei importierten Projekten müssen Sie sie eventuell manuell hinzufügen. Sie müssen auch die Header-Datei tchar.h einbeziehen, die die Floating-Definitionen und die erforderlichen Einsprungspunkte enthält. Eine Liste der in tchar.h enthaltenen Floating-Funktionen, finden Sie unter Floating-Funktionen.
     

  6. #6
    toma3 toma3 ist offline Rookie
    Registriert seit
    Jan 2009
    Beiträge
    5
    so hab was gefunden und der Fehler mit Unicode kommt nicht mehr:

    Code :
    1
    2
    3
    
    Unicode xyz;
    xyz.c_str(),iter->first;
    ShowMessage(xyz);

    bekomme aber leere Message Box...

    Vielleicht ist die Umwandlung auch falsch?
     

  7. #7
    toma3 toma3 ist offline Rookie
    Registriert seit
    Jan 2009
    Beiträge
    5
    hab eine andere Routine gefunden und es t

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     
      LPSERVER_INFO_101 pBuf = NULL;
      LPSERVER_INFO_101 pTmpBuf;
      DWORD dwLevel = 101;
      DWORD dwPrefMaxLen = -1;
      DWORD dwEntriesRead = 0;
      DWORD dwTotalEntries = 0;
      DWORD dwTotalCount = 0;
      DWORD dwServerType = SV_TYPE_SERVER; // all servers
      DWORD dwResumeHandle = 0;
      NET_API_STATUS nStatus;
      LPTSTR pszServerName = NULL;
      DWORD i;
     
      // Call the NetServerEnum function to retrieve information
      // for all servers, specifying information level 101.
      nStatus = NetServerEnum(pszServerName,
                              dwLevel,
                              (LPBYTE *) &pBuf,
                              dwPrefMaxLen,
                              &dwEntriesRead,
                              &dwTotalEntries,
                              dwServerType,
                              NULL,
                              &dwResumeHandle);
     
      // If the call succeeds,
      if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
      {
        if ((pTmpBuf = pBuf) != NULL)
        {
          // Loop through the entries and
          // print the data for all server types.
          for (i = 0; i < dwEntriesRead; i++)
          {
            //TListItem  *ListItem = ListView1->Items->Add();
            [COLOR="Red"]CheckListBox1->Items->Add(pTmpBuf->sv101_name);[/COLOR]
            //ListItem->Caption = pTmpBuf->sv101_name;
            //ListItem->SubItems->Add(pTmpBuf->sv101_platform_id);
            //ListItem->SubItems->Add(String(pTmpBuf->sv101_version_major) + "." +
            //                        String(pTmpBuf->sv101_version_minor));
            //ListItem->SubItems->Add(pTmpBuf->sv101_type);
     
            // Check to see if the server is a domain controller;
            // if so, identify it as a PDC or a BDC.
            /*if (pTmpBuf->sv101_type & SV_TYPE_DOMAIN_CTRL)
              ListItem->SubItems->Add("PDC");
            else if (pTmpBuf->sv101_type & SV_TYPE_DOMAIN_BAKCTRL)
              ListItem->SubItems->Add("BDC");
     
            ListItem->SubItems->Add(pTmpBuf->sv101_comment);
            */
            pTmpBuf++;
            dwTotalCount++;
          }
     
          // Display a warning if all available entries were not enumerated,
          // print the number actually enumerated, and the total number available.
          //if (nStatus == ERROR_MORE_DATA)
          //  Application->MessageBox(("Total entries: " + String(dwTotalEntries)).c_str(),
          //                             "More entries available!", MB_OK | MB_ICONSTOP);
     
          //Caption = "Entries enumerated: " + String(dwTotalCount);
          StatusBar1->Panels->Items[1]->Text=dwTotalCount;
        }
      }
     
      // Free the allocated buffer.
      if (pBuf)
        NetApiBufferFree(pBuf);
    }

    ..kann jetzt entspannt ins WE gehen...
    Danke für alle Antworten
     

Ähnliche Themen

  1. Netzwerk durchsuchen
    Von Danielku15 im Forum Visual Basic 6.0
    Antworten: 3
    Letzter Beitrag: 14.03.06, 17:16
  2. Umgebung in c4d
    Von lenGi im Forum Cinema 4D
    Antworten: 4
    Letzter Beitrag: 30.10.05, 14:08
  3. Antworten: 2
    Letzter Beitrag: 17.02.04, 16:03
  4. umgebung
    Von buddha im Forum 3D Studio Max
    Antworten: 14
    Letzter Beitrag: 04.08.03, 23:24

Stichworte