Fraunz81 Geschrieben 16. November 2004 Geschrieben 16. November 2004 Ich habe ein ListView mit 10 subItems erstellt und habe es schon mit einigen Zeilen befüllen lassen. Jetzt möchte ich aber noch items hinzufügen können. Wie funktioniert das, bei mir liefert es immer ein -1 zurück. Ich hätte das mit einem SetItem Macro versucht und eine LVITEM struct verwendet. Dann wollte ich die Zeile mit dem Macro SetTextItem befüllen wollen. Vielen Dank im voraus. Zitieren
Fraunz81 Geschrieben 16. November 2004 Autor Geschrieben 16. November 2004 Ich glaube ich habe etwas gefunden in der MSDN. Nur leider weis ich nicht ganz wie ich das verwenden soll, da ich 2 verschiedene structs verwendet. Eine davon verwendet schon das WM_NOTIFY. Wie könnte ich den folgenden Code umschreiben um ohne dem WM_NOTIFY arbeiten zu können? Hier der Link zur Info: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/listview_using.asp Hier das Beispiel von der MSDN: // This code snippet adds three items, each with three // subitems, to a list-view control. // hWndListView - handle to the list-view control. // The following application-specific structure, // PETINFO, is used in the snippet. typedef struct tagPETINFO { char szKind[10]; char szBreed[50]; char szPrice[20]; }PETINFO; // A PETINFO variable is declared and initialized as // follows: PETINFO rgPetInfo[ ] = { {"Dog", "Poodle", "$300.00"}, {"Cat", "Siamese", "$100.00"}, {"Fish", "Angel Fish", "$10.00"}, }; // Some code to create the list-view control. // Initialize LVITEM members that are common to all // items. lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvI.state = 0; lvI.stateMask = 0; // Initialize LVITEM members that are different for each item. for (index = 0; index < 3; index++) { lvI.iItem = index; lvI.iImage = index; lvI.iSubItem = 0; lvI.lParam = (LPARAM) &rgPetInfo[index]; lvI.pszText = LPSTR_TEXTCALLBACK; // sends an // LVN_GETDISP // message. if(ListView_InsertItem(hWndListView, &lvI) == -1) return NULL; } // Because the application specifies LPSTR_TEXTCALLBACK, it // sends LVN_GETDISPINFO notification messages. The // application must process these notification messages and // supply the text for the subitems. // The text is stored in a previously listed // application-defined structure called PETINFO. case WM_NOTIFY: switch (((LPNMHDR) lParam)->code) { case LVN_GETDISPINFO: switch (((LPNMLVDISPINFO)lParam)->item.iSubItem) { case 0: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szKind; break; case 1: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szBreed; break; case 2: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szPrice; break; default: break; } return 0; } // NOTE: in addition to setting pszText to point to // the item text, you could copy the item text into pszText // using StringCchCopy. For example: // StringCchCopy(rgPetInfo[plvdi->item.iItem].szKind, // sizeof(rgPetInfo[plvdi->item.iItem].szKind), // plvdi->item.pszText); Danke schon mal. Zitieren
Klotzkopp Geschrieben 16. November 2004 Geschrieben 16. November 2004 Dieser Code hilft dir nur, wenn du ein virtuelles ListControl brauchst. Falls du nicht weißt, was das ist, brauchst du es sehr wahrscheinlich nicht. Fehler in deinem Code können wir nur finden, wenn du uns den Code zeigst. Zitieren
Fraunz81 Geschrieben 16. November 2004 Autor Geschrieben 16. November 2004 Also ich weis nicht was ein virtuelles ListView ist. Genau so weis ich auch nicht wie du das erkennst, dass es für ein virtuelles ListView gehört. Kannst du mir sagen an was man das kennt???? :confused: void InsertItem_func(HWND hwnd_Dlg) { LPLVITEM lvItem; HWND hwnd_ListView = NULL, hwnd_Parent = NULL; long Index = 0; TCHAR szIndex[10] = ""; hwnd_Parent = GetParent(hwnd_Dlg); hwnd_ListView = Dlg..(hwnd_Parent, ID_LISTVIEW); lvItem = (struct _LVITEM *) malloc(sizeof(_LVITEM)); Index = ListView_InsertItem(hwnd_ListView, lvItem); //Hier bekomme ich immer ein -1 als Ergebnis //ListView_SetItemText(HWND hwnd, int i, int iSubItem, LPCSTR pszText); wsprintf(szIndex, "%d", Index); ListView_SetItemText(hwnd_ListView, Index, 0, szIndex); ListView_SetItemText(hwnd_ListView, Index, 1, dsh.szpName); ListView_SetItemText(hwnd_ListView, Index, 2, dsh.szpFilmlength); ... } So irgendwie habe ich das versucht zu lösen. Aber jetzt habe ich gelesen das ListView_SetItemText eine LVN_GETDISPINFO notification message auslöst und ich glaub da wird ein WM_NOTIFY ausgelöst. Vorschläge??? Zitieren
Klotzkopp Geschrieben 16. November 2004 Geschrieben 16. November 2004 Also ich weis nicht was ein virtuelles ListView ist. Genau so weis ich auch nicht wie du das erkennst, dass es für ein virtuelles ListView gehört. Kannst du mir sagen an was man das kennt???? :confused: Ein virtuelles ListControl hält die anzuzeigenden Daten nicht selbst vor, sondern fragt immer beim Parent nach. Dazu schickt es die Nachricht LVN_GETDISPINFO. LPLVITEM lvItem; lvItem = (struct _LVITEM *) malloc(sizeof(_LVITEM)); Mal davon abgesehen, dass es hier nicht notwendig ist, Speicher vom Heap anzufordern (du könntest auch eine lokale LVITEM-Variable benutzen): Du musst die Struktur mit Daten füllen. Setz alle Member auf 0, bis auf iItem, den setzt du auf den Index, wo das Item eingefügt werden soll. Den Text kannst du gleich mit angeben, musst du aber nicht. Zitieren
Fraunz81 Geschrieben 16. November 2004 Autor Geschrieben 16. November 2004 Ich glaube ich habe so ein virtuelles ListView eingebaut. Bei so einem ListView werden nur die Daten geholt, die im Fenster Platz haben, verstehe ich das richtig?? Erst wenn ich hinuterscrolle werden die nächsten Daten eingelesen? Kann es deswegen erst dann zu Fehler kommen, wenn man weiter hinuterscrollt, die wie folgt kurz beschrieben sind. 1. Ist der Text auf eine bestimmte Länge begrenzt, weil wenn ich zu der Zeilennummer 67 gescrollt habe meldet mein Programm einen Fehler (read konnte nicht durchgeführt werden) und beendet sich. 2. Bei der Zeilennummer 187 beendet sich mein Programm mit dem Fehler: unbekannter Softwarefehler und eine Fehlernummer dazu, ich glaub das war 409. Diese Fehler bekomme ich wenn ich die Schauspieler in das ListView auch eintragen lasse. Die Schauspieler werden zu jedem Film wie folgt eingetragen: z. B.: id Filmbezeichnung ... Schauspieler Kurztext 1 film1 Actor1; Actor2; Actor3; ... kurze Beschreibung Habe ich vielleicht zu viele Daten in das ListView schon geschrieben? Muss ich mehr Speicher für das ListView anfordern? Geht das überhaupt oder wird das von Windows intern erledigt? Ich hoffe ich habe nicht zu verwirrend geschrieben. Danke schon mal. Zitieren
Klotzkopp Geschrieben 16. November 2004 Geschrieben 16. November 2004 Ich glaube ich habe so ein virtuelles ListView eingebaut. Bei so einem ListView werden nur die Daten geholt, die im Fenster Platz haben, verstehe ich das richtig?? Erst wenn ich hinuterscrolle werden die nächsten Daten eingelesen? Wenn du mit "Einlesen" das Anfordern vom Parentfenster mittels Notifikation meinst, ja. Habe ich vielleicht zu viele Daten in das ListView schon geschrieben? Muss ich mehr Speicher für das ListView anfordern? Geht das überhaupt oder wird das von Windows intern erledigt?Wenn du wirklich ein virtuelles ListView hast, dann brauchst du gar keine Daten hineinzuschreiben. Du brauchst auch keinen Speicher anzufordern. Zeig mal deine LVN_GETDISPINFO-Behandlung. Zitieren
Fraunz81 Geschrieben 17. November 2004 Autor Geschrieben 17. November 2004 So habe ich die LVN_GETDISPINFO - Behandlung eingebaut: LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HINSTANCE hInstance; static HWND hwndStatus, hwndStatusBar, hwndListView, hwndComboBox; LPSTR lpstr = "String1"; int ComboBox_Index = 0, i = 0; TCHAR *dbName = "film_dbtest"; switch(message) { case WM_CREATE: hwndListView = CreateListView(hinst, hwnd); InitListView(hwndListView); hwnd_ListView = hwndListView; break; } } break; case WM_NOTIFY: return ListViewNotify(hwnd, lParam); case WM_SIZE: case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_FILE_LOGIN: DialogBox(hInstance, TEXT("LoginBox"), hwnd, LoginDlg); break; case IDM_FILE_END: DestroyWindow(hwnd); break; case IDM_EDIT_DS_ADD: DialogBox(hInstance, TEXT("Datensatz_h"), hwnd, DatensatzHDlg); ListViewItem_add(hwndListView); break; case IDM_EDIT_DS_CHANGE: DialogBox(hInstance, TEXT("Datensatz_ae"), hwnd, DatensatzAEDlg); break; case IDM_EDIT_DS_CLEAR: DialogBox(hInstance, TEXT("Datensatz_l"), hwnd, DatensatzLDlg); break; case IDM_EDIT_SEARCH: DialogBox(hInstance, TEXT("SearchBox"), hwnd, DatensatzSearchDlg); break; } return 0; case WM_DESTROY: verbindung_schliessen(); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } So füge ich ein weiteres Item ein: void ListViewItem_add(HWND hwnd_ListView) { /* typedef struct _LVITEM { UINT mask; int iItem; int iSubItem; UINT state; UINT stateMask; LPTSTR pszText; int cchTextMax; int iImage; LPARAM lParam; #if (_WIN32_IE >= 0x0300) int iIndent; #endif } LVITEM, FAR *LPLVITEM; */ LPLVITEM lvItem; TCHAR szItem[10] = ""; TCHAR *szpTemp = NULL; TCHAR *szpBindestrich = " - ", *szpStrichpunkt = "; "; long lIndex = 0, i = 0, j = 0, anzahl_zeichen = 0; lvItem = (LPLVITEM) malloc(sizeof(LPLVITEM)); lvItem->mask = 0; lvItem->iSubItem = 0; lvItem->state = 0; lvItem->stateMask = 0; lvItem->pszText = ""; lvItem->cchTextMax = 0; lvItem->iImage = 0; lvItem->iItem = ListView_GetItemCount(hwnd_ListView) + 1; lIndex = ListView_InsertItem(hwnd_ListView, lvItem); for(i = 0; i < 10; i++) { switch(i) { case 0: wsprintf(szItem, "%d", lIndex); MessageBox(NULL, szItem, TEXT("Itemidex"), MB_OK); lvItem->pszText = szItem; ListView_SetItemText(hwnd_ListView, lIndex, i, szItem); break; case 1: ListView_SetItemText(hwnd_ListView, lIndex, i, dsh.szpid); break; .... case 6: //Audio j = 0; anzahl_zeichen = 0; while(*(dsh.szpSprache + j) != NULL || *(dsh.szpAQuality + j) != NULL) { anzahl_zeichen += strlen(*(dsh.szpSprache + j)) + strlen(szpBindestrich) + strlen(*(dsh.szpAQuality + j)) + strlen(szpStrichpunkt); j++; } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); j = 0; while(*(dsh.szpSprache + j) != NULL || *(dsh.szpAQuality + j) != NULL) { if (j == 0) strcpy(szpTemp, *(dsh.szpSprache + j)); else strcat(szpTemp, *(dsh.szpSprache + j)); strcat(szpTemp, szpBindestrich); strcat(szpTemp, *(dsh.szpAQuality + j)); strcat(szpTemp, szpStrichpunkt); j++; } ListView_SetItemText(hwnd_ListView, lIndex, i, szpTemp); free(szpTemp); break; case 7: //Schauspieler j = 0; anzahl_zeichen = 0; while(*(dsh.szpActor + j) != NULL) { anzahl_zeichen += strlen(*(dsh.szpActor + j)) + strlen(szpStrichpunkt); j++; } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); j = 0; while(*(dsh.szpActor + j) != NULL) { if (j == 0) strcpy(szpTemp, *(dsh.szpActor + j)); else strcat(szpTemp, *(dsh.szpActor + j)); strcat(szpTemp, szpStrichpunkt); j++; } ListView_SetItemText(hwnd_ListView, lIndex, i, szpTemp); free(szpTemp); break; .... case 10: ListView_SetItemText(hwnd_ListView, lIndex, i, dsh.szpText); break; } } } Das neue Item wird hinzugefügt, nur der Text wird nicht richtig dargestellt bzw wenn ich zu dem neuen Item scrolle beendet sich mein Programm mit einem Fehler: read kann nicht ausgeführt werden. Ich denke das es mit dem WM_NOTIFY zusammen hängt, da 2 verschiedene structs verwendet werden. Zitieren
Fraunz81 Geschrieben 17. November 2004 Autor Geschrieben 17. November 2004 Habe noch etwas vergessen. So sieht das ListViewNotify(hwnd, lParam) aus: LRESULT ListViewNotify(HWND hWnd, LPARAM lParam) { LPNMHDR lpnmh = (LPNMHDR) lParam; HWND hwndListView = GetDlgItem(hWnd, ID_LISTVIEW); unsigned long j = 0; unsigned long anzahl_zeichen = 0; TCHAR *szpTemp = NULL; TCHAR *szpBindestrich = " - ", *szpStrichpunkt = "; "; switch(lpnmh->code) { case LVN_GETDISPINFO: { LV_DISPINFO *lpdi = (LV_DISPINFO *)lParam; TCHAR szString[MAX_PATH]; if(lpdi->item.iSubItem) { if(lpdi->item.mask & LVIF_TEXT) { if (lpdi->item.iSubItem == 1) lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpid); if (lpdi->item.iSubItem == 2) lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpName); if (lpdi->item.iSubItem == 3) lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpFilmlength); if (lpdi->item.iSubItem == 4) lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpVQuality); if (lpdi->item.iSubItem == 5) lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpGenre); if (lpdi->item.iSubItem == 6) { j = 0; anzahl_zeichen = 0; for(j = 0; j < dbD_ptr[lpdi->item.iItem].iAudio_count; j++) { anzahl_zeichen += strlen(*(dbD_ptr[lpdi->item.iItem].szpSprache + j)) + strlen(szpBindestrich) + strlen(*(dbD_ptr[lpdi->item.iItem].szpAQuality + j)) + strlen(szpStrichpunkt); } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); //j = 0; for(j = 0; j < dbD_ptr[lpdi->item.iItem].iAudio_count; j++) { if (j == 0) strcpy(szpTemp, *(dbD_ptr[lpdi->item.iItem].szpSprache + j)); else strcat(szpTemp, *(dbD_ptr[lpdi->item.iItem].szpSprache + j)); strcat(szpTemp, szpBindestrich); strcat(szpTemp, *(dbD_ptr[lpdi->item.iItem].szpAQuality + j)); strcat(szpTemp, szpStrichpunkt); } lstrcpy(lpdi->item.pszText, szpTemp); free(szpTemp); } if (lpdi->item.iSubItem == 7) { //wsprintf(szString, "Schauspieler - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem); //lstrcpy(lpdi->item.pszText, szString); j = 0; anzahl_zeichen = 0; for(j = 0; j < dbD_ptr[lpdi->item.iItem].iActor_count; j++) { anzahl_zeichen += strlen(*(dbD_ptr[lpdi->item.iItem].szpActor + j)) + strlen(szpStrichpunkt); } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); for(j = 0; j < dbD_ptr[lpdi->item.iItem].iActor_count; j++) { if (j == 0) strcpy(szpTemp, *(dbD_ptr[lpdi->item.iItem].szpActor + j)); else strcat(szpTemp, *(dbD_ptr[lpdi->item.iItem].szpActor + j)); strcat(szpTemp, szpStrichpunkt); } lstrcpy(lpdi->item.pszText, szpTemp); free(szpTemp); } if (lpdi->item.iSubItem == 8) { //wsprintf(szString, "Besitzer - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem); lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpUser); } if (lpdi->item.iSubItem == 9) { //wsprintf(szString, "Medienanzahl - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem); lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpAnzahl); } if (lpdi->item.iSubItem == 10) { //wsprintf(szString, "Kurzbeschreibung - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem); lstrcpy(lpdi->item.pszText, dbD_ptr[lpdi->item.iItem].szpText); } } } else { if(lpdi->item.mask & LVIF_TEXT) { wsprintf(szString, "%d", lpdi->item.iItem + 1); lstrcpy(lpdi->item.pszText, szString); } } } return 0; case LVN_ODCACHEHINT: { LPNMLVCACHEHINT lpCacheHint = (LPNMLVCACHEHINT)lParam; /* This sample doesn't use this notification, but this is sent when the ListView is about to ask for a range of items. On this notification, you should load the specified items into your local cache. It is still possible to get an LVN_GETDISPINFO for an item that has not been cached, therefore, your application must take into account the chance of this occurring. */ } return 0; case LVN_ODFINDITEM: { LPNMLVFINDITEM lpFindItem = (LPNMLVFINDITEM)lParam; /* This sample doesn't use this notification, but this is sent when the ListView needs a particular item. Return -1 if the item is not found. */ } return 0; } return 0; } Zitieren
Klotzkopp Geschrieben 17. November 2004 Geschrieben 17. November 2004 int item.cchTextMax steht, wie groß der Puffer für den Text ist. Wenn du mehr brauchst, musst du pszText selbst zuweisen. Dieser Speicher muss solange unverändert bereit stehen, bis das Element entfernt wird oder zwei weitere LVN_GETDISPINFO-Nachrichten eingetroffen sind. Zitieren
Fraunz81 Geschrieben 17. November 2004 Autor Geschrieben 17. November 2004 Deine Aussage verstehe ich nicht ganz. :confused: Kannst du mir das nochmal etwas genauer erklären?? Kann ich für jedes neue Item eine andere Grösse eingeben bzw. für jedes subItem? Wenn ich diese Grösse (int item.cchTextMax ) verändere muss ich dann ein malloc durchführen und dann den Text in die Variable pszText kopieren mit strcpy?? Ist das bezogen auf mein ListViewNotify bezogen oder wie ich ein weiters Element einfüge. Dieser Speicher muss solange unverändert bereit stehen, bis das Element entfernt wird oder zwei weitere LVN_GETDISPINFO-Nachrichten eingetroffen sind. Warum gerade 2 weitere Nachrichten bzw. entfernt wird??? Entfernt: von der struct oder von dem angezeigten Bereich? Danke schon mal. Zitieren
Klotzkopp Geschrieben 17. November 2004 Geschrieben 17. November 2004 Wenn du eine LVN_GETDISPINFO-Nachricht bekommst, steht in der LVITEM-Struktur schon ein Puffer für den Text bereit. Wie groß der ist, steht in item.cchTextMax. Wenn du mehr Platz brauchst, musst du selbst einen Puffer bereitstellen und item.pszText darauf zeigen lassen. Ich verstehe nicht, warum du beim Hinzufügen der Items überhaupt schon Texte hineinschreibst. Wenn du unbedingt ein virtuelles ListControl haben musst, dann wird es dich schon fragen, wenn es Texte braucht. Wie und wo stellst du eigentlich sicher, dass du schon genügend Einträge in dbD_ptr eingelesen hast? Warum gerade 2 weitere Nachrichten bzw. entfernt wird???So steht's in der MSDN Library. Keine Ahnung, warum. Entfernt: von der struct oder von dem angezeigten Bereich? Weder noch. Entfernt aus dem ListControl. Zitieren
Fraunz81 Geschrieben 17. November 2004 Autor Geschrieben 17. November 2004 Also kann ich item.cchTextMax nicht verändern? Wenn du mehr Platz brauchst, musst du selbst einen Puffer bereitstellen und item.pszText darauf zeigen lassen. Das könnte ich z. B.: dann so lösen: item.pszText = dsh.pszName ist das richtig? Ich verstehe nicht, warum du beim Hinzufügen der Items überhaupt schon Texte hineinschreibst. Wenn du unbedingt ein virtuelles ListControl haben musst, dann wird es dich schon fragen, wenn es Texte braucht. Ein virtuelles ListControl muss ich nicht wirklich haben, aber das habe ich gefunden und habe es deshalb eingebaut. Wie könnte ich die Texte hineinschreiben, wenn ich das nicht sofort mache. Komme ich da nicht mit dem WM_NOTIFY und der struct dbD_ptr in konflikt?? Für dbD_ptr wird in 5 Funktionen die Daten eingelesen - kommen von einer MySQL Datenbank. 1. Funktion sieht wie folgt aus: void filmtable_data() { unsigned long anzahl_reihen = 0; unsigned int i = 0, j = 0; int iIndex = 0, iLength = 0; MYSQL_ROW row; MYSQL_RES *mysql_res; TCHAR *query; TCHAR *select = "SELECT * FROM filmtable WHERE besitzerid = "; TCHAR *select1 = "SELECT * FROM filmtable " "order by besitzerid, videoformatid, filmbezeichnung"; query = (TCHAR *) malloc(strlen(select1) + 1); strcpy(query, select1); /* Jetzt die Anfrage an den Datenbankserver */ mysql_query(mysql, query); check_error(); /* Daten der Anfrage abholen */ mysql_res = mysql_store_result(mysql); check_error(); /* Anzahl der gefundenen Datensätze ermitteln */ anzahl_reihen = (unsigned long) mysql_num_rows (mysql_res); iDatensaetze = anzahl_reihen; dbD_ptr = (struct _dbDaten *) malloc(sizeof(_dbDaten) * anzahl_reihen); /* Gefundener Datensatz bzw. Datensätze ausgeben */ while ((row = mysql_fetch_row (mysql_res)) != NULL) { /* Einzelne Spalten der Zeile ausgeben */ for (i = 0; i < mysql_num_fields(mysql_res); i ++) switch(i) { case 0: //Hier kann man die ID erfassen dbD_ptr[j].id = str2int(row[i]); dbD_ptr[j].szpid = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dbD_ptr[j].szpid, "%s", row[i]); break; case 1: //Filmbezeichnung dbD_ptr[j].szpName = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dbD_ptr[j].szpName, "%s", row[i]); break; case 2: //Filmlänge dbD_ptr[j].szpFilmlength = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dbD_ptr[j].szpFilmlength, "%s", row[i]); break; case 3: //VideoformatID dbD_ptr[j].iVformatID = str2int(row[i]); if (dbD_ptr[j].iVformatID) { dbD_ptr[j].szpVQuality = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(video.format + (dbD_ptr[j].iVformatID - 1))) + 1)); wsprintf(dbD_ptr[j].szpVQuality, "%s", *(video.format + (dbD_ptr[j].iVformatID - 1))); } break; case 4: //FilmartID dbD_ptr[j].iGenreID = str2int(row[i]); if (dbD_ptr[j].iGenreID) { dbD_ptr[j].szpGenre = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(genre.art + dbD_ptr[j].iGenreID - 1)) + 1)); wsprintf(dbD_ptr[j].szpGenre, "%s", *(genre.art + dbD_ptr[j].iGenreID - 1)); } break; case 5: //BesitzerID dbD_ptr[j].iBesitzerID = str2int(row[i]); dbD_ptr[j].szpUser = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(besitzer.user + dbD_ptr[j].iBesitzerID - 1)) + 1)); wsprintf(dbD_ptr[j].szpUser, "%s", *(besitzer.user + dbD_ptr[j].iBesitzerID - 1)); break; case 6: //Medienanzahl dbD_ptr[j].szpAnzahl = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); strcpy(dbD_ptr[j].szpAnzahl, row[i]); break; case 7: //Kurzbeschreibung dbD_ptr[j].szpText = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); strcpy(dbD_ptr[j].szpText, row[i]); break; } j++; } /* Speicherplatz wieder freigeben */ mysql_free_result(mysql_res); free(query); } Diese Daten lese ich noch bevor das ListView erzeugt wird ein. //Füllen der struct _dbDaten filmtable_data(); //Audiodaten abfragen und speichern audiotable_count(); audiotable_data(); //Schauspielerdaten abfragen und speichern schauspieler_count(); schauspieler_data(); Zitieren
Klotzkopp Geschrieben 17. November 2004 Geschrieben 17. November 2004 Also kann ich item.cchTextMax nicht verändern? Es ergibt keinen Sinn, cchTextMax zu verändern. Das könnte ich z. B.: dann so lösen: item.pszText = dsh.pszName ist das richtig?Wenn dsh.pszName lange genug verfügbar ist, ja. Ein virtuelles ListControl muss ich nicht wirklich haben, aber das habe ich gefunden und habe es deshalb eingebaut.Schlecht. Mit dem virtuellen ListControl sollte man nur arbeiten, wenn man einen guten Grund dafür hat, z.b. wenn man häufig Objekte am Anfang oder in der Mitte entfernt. Da muss ein nicht-virtuelles ListControl viel umkopieren, und das dauert. Diese Daten lese ich noch bevor das ListView erzeugt wird ein.Gibt es einen Grund dafür? Wenn du die Daten erst dann einlesen würdest, wenn du sie einfügen kannst, bräuchtest du kein virtuelles ListControl und könntest auf das Array dbD_ptr komplett verzichten. Du kannst auch alles vorher einlesen und dafür dein Array benutzen, aber ein virtuelles ListControl brauchst du dann immer noch nicht. Zitieren
Fraunz81 Geschrieben 17. November 2004 Autor Geschrieben 17. November 2004 Ich habe mich jetzt ein wenig schlau gemacht in der MSDN. Damit ich kein virtuelles ListView mehr habe müsste ich den Style LVS_ONERDATA herausnehmen. Dann bekommt man auch keine LVN_GETDISPINFO - Nachrichten mehr. Ist hoffentlich richtig so? Um Daten zu dem virtuellen ListView hinzufügen zu können müsste ich mein dynamisches dbD_ptr - Array immer wieder vergrössern und kann auch nicht, wie ich wollte, die Message LVM_SETITEMTEXT verwenden, die ich in der Funktion void ListViewItem_add(HWND hwnd_ListView) verwende. Das sind Gründe um kein virtuelles ListView zu verwenden, zumindest zur Zeit. Hast du einige Tipps, wie ich "schnell" und unkompliziert die Daten in ein normales ListView eintragen kann, oder muss ich jede einzelne Zeile, so wie ich es mit der Funktion ListViewItem_add(HWND hwnd_ListView) mache, einfügen? Danke. PS: Hoffentlich bekomme ich den Umbau ohne viele Seufzer hin Zitieren
Fraunz81 Geschrieben 18. November 2004 Autor Geschrieben 18. November 2004 Wenn es jemanden interessiert, so füge ich meine Struct in das ListView ein. Vielleicht hat jemand Verbesserungsvorschläge. void ListView_add_Data(HWND hwnd_ListView) { unsigned long i = 0, j = 0, n = 0; unsigned long anzahl_zeichen = 0; long lIndex = 0; TCHAR *szpTemp = NULL, sz_vid[10] = ""; TCHAR *szpBindestrich = " - ", *szpStrichpunkt = "; "; TCHAR szString[MAX_PATH] = ""; LVITEM lvItem; lvItem.mask = LVIF_TEXT; for(n = 0; n < iDatensaetze; n++) { for(i = 0; i < 11; i++) { switch(i) { case 0: //BOOL ListView_SetItem(HWND hwnd, const LPLVITEM pitem); wsprintf(sz_vid, "%d", n + 1); lvItem.iItem = n; lvItem.iSubItem = i; lvItem.pszText = sz_vid; lIndex = ListView_InsertItem(hwnd_ListView, &lvItem); ListView_SetItemText(hwnd_ListView, n, i, sz_vid); break; case 1: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpid); break; case 2: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpName); break; case 3: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpFilmlength); break; case 4: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpVQuality); break; case 5: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpGenre); break; case 6: j = 0; anzahl_zeichen = 0; for(j = 0; j < dbD_ptr[n].iAudio_count; j++) { anzahl_zeichen += strlen(*(dbD_ptr[n].szpSprache + j)) + strlen(szpBindestrich) + strlen(*(dbD_ptr[n].szpAQuality + j)) + strlen(szpStrichpunkt); } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); for(j = 0; j < dbD_ptr[n].iAudio_count; j++) { if (j == 0) strcpy(szpTemp, *(dbD_ptr[n].szpSprache + j)); else strcat(szpTemp, *(dbD_ptr[n].szpSprache + j)); strcat(szpTemp, szpBindestrich); strcat(szpTemp, *(dbD_ptr[n].szpAQuality + j)); strcat(szpTemp, szpStrichpunkt); } ListView_SetItemText(hwnd_ListView, n, i, szpTemp); free(szpTemp); break; case 7: j = 0; anzahl_zeichen = 0; for(j = 0; j < dbD_ptr[n].iActor_count; j++) { anzahl_zeichen += strlen(*(dbD_ptr[n].szpActor + j)) + strlen(szpStrichpunkt); } szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * (anzahl_zeichen + 1)); /* if (szpTemp == NULL) { MessageBox(NULL, TEXT("Zu wenig Speicher"), TEXT("Speicher?"), MB_OK); szpTemp = (TCHAR *) malloc(sizeof(TCHAR) * 30); wsprintf(szpTemp, "%s", "zu wenig Speicher"); } else { */ for(j = 0; j < dbD_ptr[n].iActor_count; j++) { if (j == 0) strcpy(szpTemp, *(dbD_ptr[n].szpActor + j)); else strcat(szpTemp, *(dbD_ptr[n].szpActor + j)); strcat(szpTemp, szpStrichpunkt); } ListView_SetItemText(hwnd_ListView, n, i, szpTemp); free(szpTemp); break; case 8: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpUser); break; case 9: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpAnzahl); break; case 10: ListView_SetItemText(hwnd_ListView, n, i, dbD_ptr[n].szpText); break; }//ende switch(i) } //ende for(j = 0; j < 11; j++) } //ende for(i = 0; i < iDatensaetze; i++) } Viel Spaß damit. Zitieren
Klotzkopp Geschrieben 18. November 2004 Geschrieben 18. November 2004 Die innere for-Schleife und das switch sind unnötig, du könntest das auch so machen: for(n = 0; n < iDatensaetze; n++) { wsprintf(sz_vid, "%d", n + 1); lvItem.iItem = n; lvItem.iSubItem = 0; lvItem.pszText = sz_vid; lIndex = ListView_InsertItem(hwnd_ListView, &lvItem); //ListView_SetItemText(hwnd_ListView, n, 0, sz_vid); ListView_SetItemText(hwnd_ListView, n, 1, dbD_ptr[n].szpid); ListView_SetItemText(hwnd_ListView, n, 2, dbD_ptr[n].szpName); ListView_SetItemText(hwnd_ListView, n, 3, dbD_ptr[n].szpFilmlength); // usw... [/CODE] SetItemText für die erste Spalte brauchst du nicht, den Text gibst du ja schon bei InsertItem an. Zitieren
Fraunz81 Geschrieben 18. November 2004 Autor Geschrieben 18. November 2004 Ich dachte mit dem InsertItem wird nur eine neue Zeile eingefügt, jodch kein Text. Geht aus der SDK bzw. MSDN nicht wirklich hervor - zumindest für mich. Oder mein Englisch ist ein wenig rost-durch-drungen. Ich weis nicht warum ich die 2. for-Schleife und das switch eingebaut habe. Ich denk mal in der hektig gestern, habe da wohl zu wenig überlegt. Danke für die Tipps. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.