2012-01-23 18 views
10

Szukałem w sieci różnych rzeczy na temat API win32, ale wydaje się, że wszystkie informacje na jego temat są raczej rzadkie.Tworzenie tabeli przy użyciu Win32 API

Szukam utworzyć proste okno, które pokazuje listę elementów, ale chcę wyświetlić różne kolumny danych dla każdego elementu, w formacie stylu tabeli, gdzie użytkownik może być może mieć możliwość zmiany rozmiaru różnych szerokości kolumn.

Jeśli to możliwe, chciałbym również móc zmieniać kolory tła różnych wierszy, w kodzie, między zwykłym białym, czerwonym, żółtym lub zielonym.

Użytkownik może również kliknąć prawym przyciskiem myszy na różne wiersze i mieć możliwość wywoływania na nich funkcji lub kopiowania danych do schowka (ale ta część to inna historia).

Teraz znalazłem obiekty przeglądarki listy (?), Które można umieścić w oknie, przyciski i menu z prawym przyciskiem myszy ... ale nie mogę wymyślić, jak wykonać tabelę, używając interfejsu Win32 API . Nawet nie czytałem nawet kolorów tła dla niczego innego niż samo okno.

Czy istnieją inne, lepsze ramy, których powinienem użyć w tym celu, czy są pewne funkcje lub elementy, których mi brakowało? Cała pomoc lub wskazówki dotyczące tego pomysłu zostaną docenione ...

Używam MSVC++ do robienia ... wszystkiego, nad czym pracuję.

+0

Z jakiego środowiska programistycznego korzystasz? (Pomaga dowiedzieć się, co może być dostępne do użycia.) –

+0

Pracuję w MSVC++, przepraszam, masz rację, powinienem powiedzieć, że ... – Serge

Odpowiedz

9

System Windows zapewnia dość podstawową kolekcję wbudowanych elementów sterujących, wymienionych na liście here.

Jeśli chcesz coś bardziej wyrafinowane opcje są:

  • Code to sam. Musisz sam go pomalować, obsłużyć wszystkie interakcje użytkownika, przewijanie itp. To jest wielka robota.
  • Znajdź istniejącą implementację.
  • Abandon VC++ i użyj WinForms lub WPF.

Jeśli utkniesz w VC++, The Grid Control i The Ultimate Grid są oparte na MFC.

Jeśli nie używasz MFC, jest BABYGRID lub The Win32 SDK Data Grid.

Jeśli żadna z nich nie pasuje, będziesz mieć więcej szczęścia szukając "siatki" niż "tabeli".

7

Korzystanie z API Windows i standardowego ListView kontroli można zrobić tabelę przy użyciu LVS_REPORT styl

odnośnik dokumentacja - niestety bez kodu :(-

About List-View Controls

Znalazłem ten dobry artykuł Windows Programmierung: List View wyjaśnienie jest w języku niemieckim, ale tłumaczenie google wraz z kodem powinno wystarczyć, aby to zrozumieć.Z artykułu, aby utworzyć okno:

#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); 

to jest wyjaśnione, jak tworzyć kolumny w metodzie

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

Jak wstawić element (jedna kolumna)

int CreateItem(HWND hwndList, char *Text) 

lub wstaw element z dwiema kolumnami:

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

itp ...

+0

Stary, to najlepsze rozwiązanie na to pytanie. Naprawdę dziwne, że wybrana odpowiedź próbuje oderwać się od rozwiązania podstawowego. –

+0

Również przykładowy kod w MSDN na [Dodawanie elementów LV i SubItems] (https://msdn.microsoft.com/en-us/library/windows/desktop/hh298346%28v=vs.85%29.aspx?f=255&MSPPError = -2147217396). –

0

W przypadku przykładów listview nic nie przebije klarowności modelu Classic Sample!

W międzyczasie, Google Translate wraz z Unicode + drobne modyfikacje na ratunek dla @ Alejadro w niemieckim linku do Listview - nie ma bezpośrednie tłumaczenie na oferty z wyników wyszukiwania, gdy strona nie zawiera odpowiedniego meta tag. Snipped trochę skrótowo:

Późniejsze zmiany stylów

Styl ListView mogą być zmieniane po stworzeniu. Do tego wykorzystywane są funkcje GetWindowLong i SetWindowLong. O maskach można definiować różne style.

Maska ................................. zamaskowany style:
LVS_TYPEMASK ... ........... LVS_ICON, LVS_LIST, LVS_REPORT i LVS_SMALLICON LVS_ALIGNMASK ............. LVS_ALIGNLEFT i LVS_ALIGNTOP LVS_TYPESTYLEMASK ... LVS_ALIGNLEFT i LVS_ALIGNTOP ale również VS_NOCOLUMNHEADER i LVS_NOSORTHEADER

W poniższej sekwencji dwView zawiera styl do użycia, taki jak 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); } 

Kontrola kontroli ListView

generowanie listy

widoku listy jest tworzony przy użyciu funkcji CreateWindow. Klasa okna używa stałej WC_LISTVIEW. Aby to zrobić, należy dołączyć wspólny plik nagłówkowy sterowania.

#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); 


W oknie dialogowym, to jest po prostu zdefiniowane w zasobie.

Jeśli istnieją nierozwiązane zewnętrzne, należy sprawdzić, czy dołączono bibliotekę dla Common Controls (comctl32.lib).

Kolumny ListView

Przed czymś może być włożona w REPORT, kolumny muszą być zdefiniowane. Kolumna jest opisana przez strukturę LVCOLUMN. Poniższa procedura tworzy kolumnę.

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); 
} 

Kolumny można modyfikować za pomocą wiadomości do ListView lub wywołując makra, które ostatecznie wykonają 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 

wstawić linię

Element ListView opisano strukturą LVITEMW (patrz poniżej). Każdy element może być reprezentowany jako element ICON, SMALLICON, LIST lub jako lewa kolumna linii REPORT.

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

Pole maski określa, które elementy struktury LVITEMW są rzeczywiście używane. Ponieważ często ma sens utrzymywanie wskaźnika w obiekcie pamięci, który przechowuje dane za obiektem, przydatne jest pole lParam. Aby można było z niego korzystać, należy ustawić LVIF_TEXT | LVIF_PARAM jako maskę.

Stałe maski i pola, które je umożliwiają:

LVIF_IMAGE Iimage
LVIF_INDENT iIndent
LVIF_PARAM lParam
stan LVIF_STATE
LVIF_TEXT pszText

Kolejne kolumny raportu

Sam element zawsze pozostaje w widoku raportu i można go wybrać. Aby wypełnić więcej kolumn, do elementu dodawany jest tekst.

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; 
} 

Powyższy Create2ColItem najlepiej świadczy coś wzdłuż linii następujących stwierdzeń:

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

Struktura LVITEMW

Struktura LVITEMW (w CommCtrl.h) opisuje element ListView. Najważniejsze elementy zostały tutaj krótko opisane. Pierwsza definicja:

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; 

W LVM_GETITEMW i LVM_SETITEMW komunikaty zmienić atrybuty elementu. Jako parametr otrzymasz wskaźnik do struktury LVITEMW obok HWND ListView, który należy wcześniej wypełnić.

Elementy strukturalne w szczegółach:

maski: określa, które elementy są używane.Kombinacja następujących flag jest możliwa:

LVIF_IMAGE Iimage

LVIF_INDENT iIndent

LVIF_PARAM lParam

stan LVIF_STATE

LVIF_TEXT pszText

iItem Indeks (oparty na 0) elementu, którego struktura dotyczy.

iSubItem Indeks (oparty na 1) podelementu, którego struktura dotyczy. 0, jeśli struktura odwołuje się do elementu zamiast podelementu.

pszText wskazuje na łańcuch zakończony znakiem NUL. Jeśli wartość to LPWSTR_TEXTCALLBACK, jest to element wywołania zwrotnego. Jeśli to się zmieni, parametr pszText musi być ustawiony na LPSTR_TEXTCALLBACK, a ListView jest informowany przez LVM_SETITEMW lub LVM_SETITEMTEXT. pszText nie można ustawić na LPWSTR_TEXTCALLBACK, jeśli ListView ma styl LVS_SORTASCENDING lub LVS_SORTDESCENDING.

cchTextMax Rozmiar bufora, gdy tekst jest czytany.

iImage Indeks ikony tego elementu z listy obrazów.

lParam 32-bitowa wartość specyficzna dla tego elementu.

Operacje z elementami

LVM_INSERTITEM Wstawienie elementu LVM_DELETEITEM usunąć element LVM_DELETEALLITEMS Usuń wszystkie elementy właściwości LVM_GETITEMW odczytu elementu LVM_GETITEMTEXT Przeczytaj tekst elementem zmian LVM_SETITEMW LVM_SETITEMTEXT Zmian do tekstu

Przed wstawieniem wielu elementów, do listy będzie wysyłana wiadomość LVM_SETITEMCOUNT wskazująca, ile elementów będzie ostatecznie zawartych. Dzięki temu ListView może zoptymalizować przydzielanie i wydawanie pamięci. Ile elementów zawiera ListView można określić za pomocą LVM_GETITEMCOUNT.

Montaż wybrane elementy

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); 
} 

Wydarzenia ListView wysyła WM_NOTIFY wiadomości do okna nadrzędnego.Kod może przyjmować następujące wartości:

Wiadomość ............ Opis
LVN_BEGINDRAG ............. Zacznij przeciągnij-i- drop akcję przy
LVN_BEGINRDRAG .......... Rozpoczęcie działań przeciągnij i upuść prawym przyciskiem myszy
LVN_BEGINLABELEDIT .... Rozpocznij edycję etykietę
LVN_ENDLABELEDIT ....... End edycja etykiety
LVN_DELETEITEM .......... Raportuje, że element został usunięty
LVN_DELETEALLITEMS..Odnotowuje usunięcie wszystkich pozycji
LVN_COLUMNCLICK ...... Wskazuje, że użytkownik kliknął w nagłówku wyświetlanego raportu.
LVN_GETDISPINFO ....... Sterowanie żąda informacji o prezentacji z okna nadrzędnego
LVN_SETDISPINFO ...... .Powierzchnia informacje z okna nadrzędnego dla elementu musi być odnawiane
LVN_INSERTITEM .......... Wskazuje włożenie elementu
LVN_ITEMCHANGED ..... Wskazuje, że pozycja została zmieniona
LVN_ITEMCHANGING .... Wskazuje zamierzoną zmianę pozycji:
LVN_KEYDOWN ............. Przycisk został naciśnięty

Edytowanie etykiet Widok listy musi zostać utworzony przy użyciu stylu LVS_EDITLABELS. Następnie można już kliknąć etykietę i wejścia są akceptowane. Jednak dane wejściowe są natychmiast odrzucane. Aby umożliwić zmiany etykiety, wystarczy złapać numer WM_NOTIFY i zwrócić TRUE. W celu uzyskania dostępu do wpisanego tekstu pomiędzy, następuje dostęp do tekstu elementu. Przykład pokazuje dane wejściowe w oknie komunikatu.

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

Jeśli edycja została przerwana, element pszText będzie 0.

Jeśli chcesz zapobiec edycji, komunikat LVN_BEGINLABELEDIT zostanie złapany i wrócił TRUE. Tutaj również można uzyskać dostęp do elementu w ten sam sposób poprzez lParam, a zatem na przykład można wykluczyć określoną grupę produktów.

Kliknij na nagłówek kolumny w ListView

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

Wybór zdarzeń

Impreza LVN_ITEMACTIVATE jest wysyłany, gdy użytkownik aktywuje element. Podobnie jak w przypadku innych zdarzeń ListView, osiąga funkcję okna jako część komunikatu 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); 
..... 

Komunikat o nazwie LVM_GETSELECTEDCOUNT służy do określenia, ile pozycji zostało aktywowanych. Wiadomość LVM_GETNEXTITEM jest wysyłana z atrybutem LVNI_SELECTED, a wszystkie elementy zostały edytowane.

Powiązane problemy