2012-01-23 21 views
10

Ho cercato la rete per cose diverse sull'API win32, ma sembra che tutte le informazioni siano piuttosto scarse.Creazione di una tabella utilizzando l'API Win32

Sto cercando di creare una finestra semplice che mostri un elenco di elementi, tuttavia voglio visualizzare colonne di dati diverse per ciascun elemento, in un formato in stile tabella, in cui l'utente potrebbe essere autorizzato a ridimensionare i diversi larghezze delle colonne.

Se possibile, mi piacerebbe anche essere in grado di modificare i colori di sfondo di diverse righe, nel codice, tra solo un bianco generale, rosso, giallo o verde.

E l'utente può anche fare clic con il pulsante destro del mouse su diverse righe, ed essere in grado di richiamare una funzione su di esse, oppure copiare i dati negli Appunti (ma quella parte è una storia diversa).

Ora, ho trovato gli oggetti list-viewer (?) Che possono essere inseriti nella finestra, nei pulsanti e nei menu di scelta rapida ... ma non riesco a capire come fare una tabella, usando l'API Win32 . Nemmeno io ho davvero letto i colori di sfondo per qualcosa di diverso dalla finestra stessa.

C'è una struttura diversa, migliore che dovrei usare per questo, o ci sono alcune funzioni o elementi che mi sono mancati? Tutto l'aiuto o l'orientamento sull'idea sarebbe apprezzato ...

Sto usando MSVC++ per fare ... tutto ciò su cui sto lavorando.

+0

Quale ambiente di sviluppo stai utilizzando? (Aiuta a capire cosa potrebbe essere disponibile per l'uso.) –

+0

Sto lavorando in MSVC++, scusa, hai ragione, avrei dovuto dirlo ... – Serge

risposta

9

Windows fornisce una raccolta abbastanza semplice di controlli incorporati, elencati here.

Se si desidera qualcosa di più sofisticato Le opzioni disponibili sono:

  • codice da soli. Devi dipingerlo da solo, gestire tutte le interazioni dell'utente, lo scrolling, ecc. Questo è un grande lavoro.
  • Trova un'implementazione esistente.
  • Abbandonare VC++ e utilizzare WinForms o WPF.

Se sei bloccato con VC++, The Grid Control e The Ultimate Grid sono MFC-based.

Se non si utilizza MFC, c'è BABYGRID o The Win32 SDK Data Grid.

Se nessuno di loro è adatto, avrai più fortuna a cercare "griglia" che "tabella".

7

Utilizzando l'API di Windows e il controllo ListView standard potete fare una tabella utilizzando il LVS_REPORT stile

collegamento documentazione - sfortunatamente senza codice :(-

About List-View Controls

ho trovato questo buon articolo Windows Programmierung: List View la spiegazione è in lingua tedesca, ma una traduzione di google insieme al codice dovrebbe essere sufficiente per capirlo.Dall'articolo, per creare la finestra:

#include "commctrl.h" 

InitCommonControls(); 
hwndList = CreateWindow(WC_LISTVIEW, "", 
     WS_VISIBLE|WS_BORDER|WS_CHILD | LVS_REPORT | LVS_EDITLABELS, 
     10, 10, 300, 100, 
     hWnd, (HMENU)ID_LIST, hInst, 0); 

allora si spiega come creare le colonne nel metodo

int CreateColumn(HWND hwndLV, int iCol, char *Text, int iWidth) 

come inserire un elemento (una colonna)

int CreateItem(HWND hwndList, char *Text) 

o inserisci elemento con due colonne

int Create2ColItem(HWND hwndList, char *Text1, char *Text2) 

ecc ...

+0

Amico, questa è la migliore soluzione per la domanda. Davvero strano la risposta selezionata sta cercando di allontanarsi dalla soluzione madre. –

+0

Esempio di codice in MSDN su [Aggiunta di voci e sottomenu LV] (https://msdn.microsoft.com/en-us/library/windows/desktop/hh298346%28v=vs.85%29.aspx?f=255&MSPPError = -2.147,217396 millions). –

0

Per gli esempi di Listview, niente batte la chiarezza dello Classic Sample!

Nel frattempo, Google Translate insieme a Unicode + piccole modifiche al salvataggio @ collegamento tedesca di Alejadro per la Listview - non c'è traduzione diretta in offerta dai risultati di ricerca come pagina non contiene l'appropriato meta tag. Tagliò un po 'per brevità:

variazioni successive di stili

Lo stile di una ListView può essere modificato dopo la creazione. Per questo vengono utilizzate le funzioni GetWindowLong e SetWindowLong. Sulle maschere si possono definire diversi stili.

Maschera ................................. Stili mascherati:
LVS_TYPEMASK ... ........... LVS_ICON, LVS_LIST, LVS_REPORT e LVS_SMALLICON LVS_ALIGNMASK ............. LVS_ALIGNLEFT e LVS_ALIGNTOP LVS_TYPESTYLEMASK ... LVS_ALIGNLEFT e LVS_ALIGNTOP ma anche VS_NOCOLUMNHEADER e LVS_NOSORTHEADER

Per la sequenza seguente, dwView contiene lo stile da utilizzare, ad esempio LVS_REPORT or LVS_ICON.

DWORD dwStyle = GetWindowLong(hwndLV, GWL_STYLE); // get current style 
if ((dwStyle & LVS_TYPEMASK)! = dwView) // only on change 
SetWindowLong(hwndLV, GWL_STYLE, (dwStyle & ~ LVS_TYPEMASK) | dwView); } 

controllo del controllo ListView

generazione di una lista

Una vista elenco viene creato con la funzione CreateWindow. La classe della finestra utilizza la costante WC_LISTVIEW. Per fare ciò, è necessario includere il file di intestazione del controllo comune.

#include "commctrl.h" 

InitCommonControls(); 
hwndList = CreateWindow(WC_LISTVIEW, "", 
    WS_VISIBLE | WS_BORDER | WS_CHILD | LVS_REPORT | LVS_EDITLABELS, 
    10, 10, 300, 100, 
    hWnd, (HMENU) ID_LIST, hInst, 0); 


Nella finestra di dialogo, è semplicemente definita nella risorsa.

Se sono presenti elementi esterni non risolti, è necessario verificare se è inclusa la libreria per i controlli comuni (comctl32.lib).

colonne del ListView

Prima qualcosa possono essere inseriti in un REPORT, devono essere definite le colonne. Una colonna è descritta dalla struttura LVCOLUMN. La seguente routine crea una colonna.

int CreateColumn(HWND hwndLV, int iCol, char * text, intwidth) 
{ 
LVCOLUMN lvc; 

lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
lvc.fmt = LVCFMT_LEFT; 
lvc.cx = iWidth; 
lvc.pszText = text; 
lvc.iSubItem = iCol; 
return ListView_InsertColumn(hwndLV, iCol, & lvc); 
} 

Le colonne possono essere modificate con messaggi al ListView o chiamando macro che in ultima analisi, eseguire un SendMessage.

Message   Macro call         Function 
LVM_INSERTCOLUMN ListView_InsertColumn(HWND, int, LVCOLUMN *) Insert column 
LVM_DELETECOLUMN ListView_DeleteColumn(HWND, int)    Delete column 
LVM_GETCOLUMN  ListView_GetColumn(HWND, int, LVCOLUMN *) Get properties of the column 
LVM_SETCOLUMN  ListView_SetColumn(HWND, int, LVCOLUMN *) Change properties of the column 
LVM_GETCOLUMNWIDTH ListView_GetColumnWidth(HWND, int)   Determine column width 
LVM_SETCOLUMNWIDTH ListView_SetColumnWidth(HWND, int, int)  Set column width 

Inserire una linea

Un elemento della ListView è descritta dalla struttura LVITEMW (vedi sotto). Ogni elemento può essere rappresentato come elemento ICON, SMALLICON, LIST o come colonna di sinistra di una riga REPORT.

int CreateItem(HWND hwndList, wchar_t * text) 
{ 
LVITEMW lvi = {0}; 
lvi.mask = LVIF_TEXT; 
lvi.pszText = text; 
return ListView_InsertItem(hwndList, & lvi); 
} 

Il campo maschera stabilisce quali elementi della struttura LVITEMW vengono effettivamente utilizzati. Poiché spesso ha senso mantenere un puntatore all'oggetto di memoria che contiene i dati dietro l'oggetto, il campo lParam è utile. Per poter essere utilizzato, è necessario impostare LVIF_TEXT | LVIF_PARAM come maschera.

Le costanti di maschera ed i campi che consentono loro:

LVIF_IMAGE Iimage
LVIF_INDENT iIndent
LVIF_PARAM lParam
stato LVIF_STATE
LVIF_TEXT pszText

Le ulteriori colonne di un rapporto

L'elemento stesso viene sempre lasciato nella vista del report ed è selezionabile. Per riempire più colonne, viene aggiunto un testo all'elemento.

int Create2ColItem(HWND hwndList, wchar_t * Text1, wchar_t * Text2) 
{ 
LVITEMW lvi = {0}; 
int Ret; 
// Initialize LVITEMW members that are common to all items. 
lvi.mask = LVIF_TEXT; 
lvi.pszText = Text1; 
Ret = ListView_InsertItem(hwndList, & lvi); 
if (Ret >= 0) 
{ 
ListView_SetItemText(hwndList, Ret, 1, Text2); 
} 
return Ret; 
} 

Quanto sopra Create2ColItem è dimostrato dal qualcosa lungo la linea delle seguenti affermazioni:

LVHwnd = Your_Create_LV_Routine(); 
    if (LVHwnd) 
    { 
    CreateColumn(LVHwnd, 0, ptrColHeaderString1, iColSize1); 
    CreateColumn(LVHwnd, 1, ptrColHeaderString2, iColSize2); 
    Create2ColItem(LVHwnd, ptrItemText1, ptrItemText2); 
    } 

La struttura LVITEMW

La struttura LVITEMW (in commctrl.h) descrive un elemento di ListView. Gli elementi più importanti sono brevemente descritti qui. In primo luogo la definizione:

typedef struct tagLVITEMW 
{ 
    UINT mask; 
    int iItem; 
    int iSubItem; 
    UINT state; 
    UINT stateMask; 
    LPWSTR pszText; 
    int cchTextMax; 
    int iImage; 
    LPARAM lParam; 
    #if (_WIN32_IE >= 0x0300) //historical note for IE3 users! 
    int iIndent; 
    #endif 
    #if (NTDDI_VERSION >= NTDDI_WINXP) 
    int iGroupId; 
    UINT cColumns; // tile view columns 
    PUINT puColumns; 
    #endif 
    #if (NTDDI_VERSION >= NTDDI_VISTA) 
    int* piColFmt; 
    int iGroup; // readonly. only valid for owner data. 
    #endif 
} LVITEMW, *LPLVITEMW; 

I LVM_GETITEMW e LVM_SETITEMW messaggi modificare gli attributi di un elemento. Come parametro, si ottiene un puntatore a una struttura LVITEMW accanto allo HWND di ListView, che deve essere compilato in anticipo.

Gli elementi strutturali in dettaglio:

maschera: Specifica che vengono utilizzati elementi.Una combinazione dei seguenti flag è possibile:

LVIF_IMAGE Iimage

LVIF_INDENT iIndent

LVIF_PARAM lParam

stato LVIF_STATE

LVIF_TEXT pszText

iItem Indice (a base 0) dell'elemento a cui si riferisce la struttura.

iSubItem Indice (a base 1) del sottoelemento a cui si riferisce la struttura. 0 se la struttura fa riferimento a un articolo anziché a un sottoelemento.

pszText punti a una stringa con terminazione null. Se il valore è LPWSTR_TEXTCALLBACK, è un elemento di richiamata. Se questo cambia, pszText deve essere impostato su LPSTR_TEXTCALLBACK e sul ListView informato da LVM_SETITEMW o LVM_SETITEMTEXT. pszText non deve essere impostato su LPWSTR_TEXTCALLBACK se ListView ha lo stile LVS_SORTASCENDING o LVS_SORTDESCENDING.

cchTextMax dimensione del buffer quando il testo viene letto.

iImage Indice dell'icona di questo elemento dall'elenco di immagini.

lParam valore a 32 bit specifico per questo elemento.

azioni con elementi

LVM_INSERTITEM inserimento di un elemento LVM_DELETEITEM cancellare un elemento LVM_DELETEALLITEMS Cancella tutti gli elementi LVM_GETITEMW Leggi proprietà dell'elemento LVM_GETITEMTEXT Leggi testo dell'elemento cambiamento LVM_SETITEMW LVM_SETITEMTEXT Change al testo

Prima di inserire più articoli, un messaggio LVM_SETITEMCOUNT verrà inviato a ListView indicando il numero di elementi che verranno alla fine contenuti. Ciò consente a ListView di ottimizzare l'allocazione e il rilascio della memoria. Quanti elementi contiene un ListView può essere determinato con LVM_GETITEMCOUNT.

elementi Editing selezionati

int Pos = -1; 
LVITEMW Item; 
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED); 
while (Pos> = 0) 
{ 
Item.iItem = Pos; 
Item.iSubItem = 0; 
ListView_GetItem(hwndList, & Item); 
TuWasMitElement((Element Type *) Item.lParam); 
Pos = ListView_GetNextItem(hwndList, Pos, LVNI_SELECTED); 
} 

Eventi Il ListView invia WM_NOTIFY messaggi alla finestra padre.Il codice può assumere i seguenti valori:

messaggio ............ Descrizione
LVN_BEGINDRAG ............. Avviare un drag-and- cadere azione
LVN_BEGINRDRAG .......... Avviare un'azione di drag-and-drop con il tasto destro del mouse
LVN_BEGINLABELEDIT .... iniziare a modificare un'etichetta
LVN_ENDLABELEDIT ....... End modifica di un'etichetta
LVN_DELETEITEM .......... Segnala che l'elemento è stato eliminato
LVN_DELETEALLITEMS .. Segnala che tutti gli elementi vengono eliminati
LVN_COLUMNCLICK ...... Indica che l'utente ha fatto clic sull'intestazione di un report sul display
LVN_GETDISPINFO ....... Il controllo richiede informazioni sulla presentazione dalla finestra padre
LVN_SETDISPINFO ...... .Il informazioni della finestra padre per la voce deve essere rinnovato
LVN_INSERTITEM .......... Indica l'inserimento di un elemento
LVN_ITEMCHANGED ..... Indica che un oggetto è stato modificato
LVN_ITEMCHANGING .... Indica la modifica prevista di un articolo
LVN_KEYDOWN .............. Il tasto è stato premuto

Modifica delle etichette La visualizzazione elenco deve essere stata creata utilizzando lo stile LVS_EDITLABELS. Quindi è già possibile fare clic su un'etichetta e accettare gli input. Tuttavia, l'input viene scartato immediatamente dopo. Per consentire modifiche nell'etichetta, devi solo prendere lo WM_NOTIFY e restituire TRUE. Per accedere al testo inserito in mezzo, viene effettuato l'accesso al testo dell'articolo. L'esempio mostra l'input in una finestra di messaggio.

case WM_NOTIFY: 
switch (((LPNMHDR) lParam) -> code) 
{ 
    case LVN_ENDLABELEDIT: 
    pItem = (NMLVDISPINFO) lParam; 
    MessageBox (hWnd, pItem-> item.pszText, "entry", MB_OK); 
    return TRUE; 

Se la modifica è stata interrotta, l'elemento pszText sarà 0.

Se si desidera impedire la modifica, il messaggio LVN_BEGINLABELEDIT viene catturato e restituito TRUE. Anche qui è possibile accedere alla voce allo stesso modo tramite lParam e, ad esempio, è possibile escludere un determinato gruppo di articoli.

Clicca sul titolo della colonna nella ListView

case WM_NOTIFY: 
switch (((LPNMHDR) lParam) -> code) 
{ 
case LVN_COLUMNCLICK: 
ColumnNr = ((LPNMLISTVIEW) lParam) -> iSubItem; 
..... 

Selezione eventi

L'evento LVN_ITEMACTIVATE viene inviato quando l'utente attiva un elemento. Come con gli altri eventi ListView, raggiunge la funzione finestra come parte di un messaggio WM_NOTIFY.

case WM_NOTIFY: 
switch (((LPNMHDR) lParam) -> code) 
{ 
case LVN_ITEMACTIVATE: 
HWND hwndFrom = (HWND) ((LPNMHDR) lParam) -> hwndFrom;MarkedItemIndex = 
ListView_GetNextItem(hwndFrom, -1, LVNI_SELECTED); 
..... 

Il LVM_GETSELECTEDCOUNT messaggio può essere utilizzato per determinare il numero di elementi sono stati attivati. Il messaggio LVM_GETNEXTITEM viene inviato con l'attributo LVNI_SELECTED e tutti gli elementi sono stati modificati.

Problemi correlati