2012-01-23 41 views
10

Tôi đã tìm kiếm trên mạng những thứ khác nhau về API win32, nhưng dường như tất cả thông tin về nó khá thưa thớt.Tạo bảng bằng Win32 API

Tôi đang tìm cách tạo một cửa sổ đơn giản hiển thị danh sách các mục, tuy nhiên tôi muốn hiển thị các cột dữ liệu khác nhau cho từng mục, theo định dạng kiểu bảng, trong đó người dùng có thể được phép thay đổi kích thước chiều rộng cột.

Nếu có thể, tôi cũng muốn có thể thay đổi màu nền của các hàng khác nhau, trong mã, chỉ giữa màu trắng chung, đỏ, vàng hoặc xanh lục.

Và người dùng cũng sẽ được phép nhấp chuột phải vào các hàng khác nhau và có thể gọi chức năng trên chúng hoặc sao chép dữ liệu vào khay nhớ tạm (nhưng phần đó là một câu chuyện khác).

Bây giờ, tôi đã tìm thấy đối tượng xem danh sách (?) Có thể được đặt trong cửa sổ, nút và trình đơn nhấp chuột phải ... nhưng tôi không thể tìm ra cách thực hiện bảng, sử dụng API Win32 . Tôi thậm chí không thực sự đọc lên trên màu nền cho bất cứ điều gì khác hơn là cửa sổ chính nó, một trong hai.

Có khung khác, tốt hơn tôi nên sử dụng cho điều này hay không hoặc có một số chức năng hoặc mục mà tôi đã bỏ lỡ không? Tất cả trợ giúp hoặc hướng dẫn về ý tưởng sẽ được đánh giá cao ...

Tôi đang sử dụng MSVC++ để làm ... mọi thứ tôi đang làm.

+0

Bạn đang sử dụng môi trường phát triển nào? (Nó giúp tìm ra những gì có thể có sẵn cho bạn để sử dụng.) –

+0

Tôi đang làm việc trong MSVC++, xin lỗi, bạn nói đúng, tôi nên nói rằng ... – Serge

Trả lời

9

Windows cung cấp bộ sưu tập khá cơ bản về các điều khiển tích hợp sẵn, được liệt kê here.

Nếu bạn muốn một cái gì đó phức tạp hơn lựa chọn của bạn là:

  • Mã đó cho mình. Bạn phải tự vẽ nó, xử lý tất cả tương tác người dùng, cuộn, v.v. Đây là một công việc lớn.
  • Tìm một triển khai hiện có.
  • Bỏ qua VC++ và sử dụng WinForms hoặc WPF.

Nếu bạn bị kẹt với VC++, The Grid ControlThe Ultimate Grid là dựa trên MFC.

Nếu bạn không sử dụng MFC có BABYGRID hoặc The Win32 SDK Data Grid.

Nếu không có trang nào phù hợp, bạn sẽ có nhiều may mắn tìm kiếm "lưới" hơn "bảng".

7

Sử dụng các cửa sổ API và điều khiển ListView tiêu chuẩn mà bạn có thể làm một bảng bằng cách sử dụng phong cách LVS_REPORT

liên kết tài liệu

- unfortunatelly với không có mã :(-

About List-View Controls

tôi đã tìm thấy này bài viết tốt Windows Programmierung: List View giải thích bằng tiếng Đức nhưng bản dịch google cùng với mã phải đủ để hiểu nó.Từ bài viết, để tạo ra các cửa sổ:

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

sau đó nó được giải thích làm thế nào để tạo ra các cột trong phương pháp

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

làm thế nào để chèn một mục (một cột)

int CreateItem(HWND hwndList, char *Text) 

hoặc chèn mục với hai cột

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

etc ...

+0

Dude, đây là giải pháp tốt nhất cho câu hỏi. Thực sự lạ câu trả lời được lựa chọn là cố gắng để tránh xa giải pháp chứng khoán. –

+0

Ngoài ra mã mẫu trong MSDN trên [Thêm mục LV & mục phụ] (https://msdn.microsoft.com/en-us/library/windows/desktop/hh298346%28v=vs.85%29.aspx?f=255&MSPPError = -2147217396). –

0

Ví dụ về chế độ xem danh sách, không có gì làm nổi bật độ rõ của Classic Sample!

Trong thời gian chờ đợi, Google Dịch cùng với Unicode + các sửa đổi nhỏ để giải cứu liên kết tiếng Đức của @ Alejadro cho số Listview - không có bản dịch trực tiếp từ phiếu mua hàng vì trang không chứa meta tag thích hợp. Snipped một chút cho ngắn gọn:

thay đổi tiếp theo của phong cách

Các phong cách của một ListView có thể được thay đổi sau khi tạo. Đối với điều này, các hàm GetWindowLong và SetWindowLong được sử dụng. Giới thiệu về mặt nạ các kiểu khác nhau có thể được xác định.

Mask ................................. Styles Masked:
LVS_TYPEMASK ... ........... LVS_ICON, LVS_LIST, LVS_REPORT và LVS_SMALLICON LVS_ALIGNMASK ............. LVS_ALIGNLEFT và LVS_ALIGNTOP LVS_TYPESTYLEMASK ... LVS_ALIGNLEFT và LVS_ALIGNTOP nhưng cũng VS_NOCOLUMNHEADER và LVS_NOSORTHEADER

Đối với chuỗi sau, dwView chứa kiểu để sử dụng, chẳng hạn như 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); } 

Kiểm soát của kiểm soát ListView

Tạo một danh sách

Một xem danh sách được tạo ra với các chức năng CreateWindow. Lớp cửa sổ sử dụng hằng số WC_LISTVIEW. Để thực hiện việc này, tệp tiêu đề kiểm soát chung phải được bao gồm.

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


Trong hộp thoại, nó chỉ đơn giản là quy định tại các tài nguyên.

Nếu có các phần tử bên ngoài chưa được giải quyết, bạn nên kiểm tra xem thư viện cho các điều khiển chung (comctl32.lib) có được bao gồm hay không.

Cột của ListView

Trước khi một cái gì đó có thể được chèn trong một REPORT, các cột phải được xác định. Cột được mô tả theo cấu trúc LVCOLUMN. Các thói quen sau đây tạo ra một cột.

Các cột có thể được sửa đổi bằng thư đến ListView hoặc bằng cách gọi macro sẽ thực thi 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 

Chèn một dòng

Một yếu tố của ListView được mô tả bằng cấu trúc LVITEMW (xem dưới đây). Mỗi phần tử có thể được thể hiện dưới dạng một thành phần ICON, SMALLICON, LIST hoặc dưới cột bên trái của đường dây REPORT.

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

Trường mặt nạ xác định phần tử nào của cấu trúc LVITEMW thực sự được sử dụng. Vì nó thường có ý nghĩa để giữ một con trỏ tới đối tượng bộ nhớ chứa dữ liệu phía sau đối tượng, trường lParam rất hữu ích. Để sử dụng, LVIF_TEXT | LVIF_PARAM phải được đặt làm mặt nạ.

Các hằng số của mặt nạ và các lĩnh vực cho phép họ:

LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM lParam
bang LVIF_STATE
LVIF_TEXT pszText

Các cột thêm báo cáo

Bản thân phần tử luôn nằm trong chế độ xem báo cáo và có thể chọn. Để điền thêm các cột, một văn bản sẽ được thêm vào mục đó.

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

Trên đây Create2ColItem được thể hiện tốt nhất bởi một cái gì đó dọc theo dòng của câu sau đây:

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

Cấu trúc LVITEMW

Cấu trúc LVITEMW (trong CommCtrl.h) mô tả một phần tử của ListView. Các yếu tố quan trọng nhất được mô tả ngắn gọn ở đây. Đầu tiên định nghĩa:

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; 

Các LVM_GETITEMWLVM_SETITEMW thông điệp thay đổi các thuộc tính của một phần tử. Là một tham số, bạn sẽ nhận được một con trỏ đến một cấu trúc LVITEMW bên cạnh HWND của ListView, mà phải được điền trước.

Các yếu tố cấu trúc một cách chi tiết:

Mask: Chỉ định các yếu tố được sử dụng.Một sự kết hợp của những lá cờ sau có thể:

LVIF_IMAGE iImage

LVIF_INDENT iIndent

LVIF_PARAM lParam

bang LVIF_STATE

LVIF_TEXT pszText

iItem Chỉ mục (0-based) của mục mà cấu trúc liên quan.

iSubItem Chỉ mục (1-based) của tiểu mục mà cấu trúc liên quan. 0 nếu cấu trúc đề cập đến một mục thay vì một tiểu mục.

pszText trỏ đến chuỗi bị chấm dứt null. Nếu giá trị là LPWSTR_TEXTCALLBACK, đó là một mục gọi lại. Nếu thay đổi này, pszText phải được đặt thành LPSTR_TEXTCALLBACK và ListView được thông báo bởi LVM_SETITEMW hoặc LVM_SETITEMTEXT. pszText không được đặt thành LPWSTR_TEXTCALLBACK nếu ListView có kiểu LVS_SORTASCENDING hoặc LVS_SORTDESCENDING.

cchTextMax Kích thước bộ đệm khi đọc văn bản.

iImage Chỉ mục biểu tượng của yếu tố này từ danh sách hình ảnh.

lParam Giá trị 32 bit dành riêng cho thành phần này.

Hoạt động với các yếu tố

LVM_INSERTITEM Đầu vào một yếu tố LVM_DELETEITEM Xóa một yếu tố LVM_DELETEALLITEMS Xóa tất cả các yếu tố LVM_GETITEMW đọc thuộc tính của phần tử LVM_GETITEMTEXT đọc văn bản của phần tử thay đổi LVM_SETITEMW LVM_SETITEMTEXT Thay đổi vào văn bản

Trước khi chèn nhiều mục, một thông báo LVM_SETITEMCOUNT sẽ được gửi đến ListView cho biết có bao nhiêu mục cuối cùng sẽ được chứa. Điều này cho phép ListView tối ưu hóa cấp phát bộ nhớ và giải phóng bộ nhớ của nó. Có bao nhiêu phần tử chứa trong ListView có thể được xác định với LVM_GETITEMCOUNT.

yếu tố Editing chọn

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

Sự kiện Các ListView gửi WM_NOTIFY thông điệp đến cửa sổ cha mẹ.Mã này có thể mất các giá trị sau:

nhắn ............ Mô tả
LVN_BEGINDRAG ............. Bắt đầu một kéo-và- thả hành động
LVN_BEGINRDRAG .......... Bắt đầu thao tác kéo và thả bằng nút chuột phải
LVN_BEGINLABELEDIT .... Bắt đầu chỉnh sửa nhãn
LVN_ENDLABELEDIT ....... End chỉnh sửa nhãn
LVN_DELETEITEM .......... Báo cáo rằng mục bị xóa
LVN_DELETEALLITEMS..Báo cáo rằng tất cả các mục sẽ bị xóa
LVN_COLUMNCLICK ...... Cho biết người dùng đã nhấp vào tiêu đề của báo cáo hiển thị
LVN_GETDISPINFO ....... Kiểm soát yêu cầu thông tin về bản trình bày từ cửa sổ chính
LVN_SETDISPINFO ...... .Công thông tin của cửa sổ cha mẹ cho mục phải được gia hạn
LVN_INSERTITEM .......... cho biết chèn của một mục
LVN_ITEMCHANGED ..... Chỉ ra rằng một mục đã được thay đổi
LVN_ITEMCHANGING .... Cho biết thay đổi dự định của một mục
LVN_KEYDOWN ............. Khóa được nhấn

Chỉnh sửa nhãn Chế độ xem danh sách phải được tạo bằng cách sử dụng kiểu LVS_EDITLABELS. Sau đó, một nhãn có thể đã được nhấp vào và đầu vào được chấp nhận. Tuy nhiên, đầu vào sẽ bị hủy ngay sau đó. Để cho phép thay đổi trong nhãn, bạn chỉ cần nắm bắt số WM_NOTIFY và trả lại TRUE. Để truy cập văn bản đã nhập ở giữa, quyền truy cập được thực hiện đối với văn bản của mục. Ví dụ cho thấy đầu vào trong một hộp tin nhắn.

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

Nếu chỉnh sửa đã bị hủy bỏ, yếu tố pszText sẽ là 0.

Nếu bạn muốn ngăn chặn chỉnh sửa, thông điệp LVN_BEGINLABELEDIT bị bắt và trở TRUE. Ở đây, quá, mục có thể được truy cập theo cùng một cách thông qua lParam và do đó, ví dụ, một nhóm mặt hàng nhất định có thể được loại trừ.

Nhấn vào tiêu đề cột trong ListView

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

Lựa chọn tổ chức sự kiện

Sự kiện LVN_ITEMACTIVATE được gửi khi người dùng kích hoạt một mục. Giống như với các sự kiện ListView khác, nó đạt được chức năng cửa sổ như một phần của thông báo 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); 
..... 

Các LVM_GETSELECTEDCOUNT nhắn có thể được sử dụng để xác định có bao nhiêu mục đã được kích hoạt. Thông báo LVM_GETNEXTITEM được gửi với thuộc tính LVNI_SELECTED và tất cả các mục đã được chỉnh sửa.

Các vấn đề liên quan