ERLEDIGT
NEIN
NEIN
ANTWORTEN
6
6
ZUGRIFFE
1071
1071
EMPFEHLEN
-
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
nescan.cppCode :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); };
3.main.cpp versuche ich in meine Unit1.cpp zu integrieren: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; }
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
-
29.01.09 20:45 #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ß Danielwe would change the world if god gave us the source code...
and remember, science is nothing more than reverse engineering nature...
Current projects:
- LdrawConverter
-
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
-
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.
-
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:
Wenn _TCHAR char ist, wird RT_RCDATA einem char* zugeordnet, aber die VCL erwartet wchar_t.Code :1 2
TResourceStream* res = new TResourceStream(HInstance, ResourceId, RT_RCDATA);
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änderungen sind für _TCHAR entspricht wchar_t erforderlichCode :1 2
::MessageBox(0, _TEXT("The message"), _TEXT("The caption"), MB_OK);
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.
-
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?
-
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
-
Netzwerk durchsuchen
Von Danielku15 im Forum Visual Basic 6.0Antworten: 3Letzter Beitrag: 14.03.06, 17:16 -
Umgebung in c4d
Von lenGi im Forum Cinema 4DAntworten: 4Letzter Beitrag: 30.10.05, 14:08 -
Netzwerk nach aktiven Rechnern durchsuchen
Von ABCD im Forum PHPAntworten: 2Letzter Beitrag: 17.02.04, 16:03 -
umgebung
Von buddha im Forum 3D Studio MaxAntworten: 14Letzter Beitrag: 04.08.03, 23:24





Zitieren
Login






