Creating a table using Win32 API

前端 未结 3 2062
抹茶落季
抹茶落季 2021-02-01 09:57

I\'ve been searching the net for different things about the win32 API, but it seems all information on it is rather sparse.

I am looking to create a simple window that s

相关标签:
3条回答
  • 2021-02-01 10:10

    Windows provides a fairly basic collection of built-in controls, listed here.

    If you want something more sophisticated your options are:

    • Code it yourself. You have to paint it yourself, handle all the user-interaction, the scrolling, etc. This is a big job.
    • Find an existing implementation.
    • Abandon VC++ and use WinForms or WPF.

    If you're stuck with VC++, The Grid Control and The Ultimate Grid are MFC-based.

    If you're not using MFC there's BABYGRID or The Win32 SDK Data Grid.

    If none of them suit, you'll have more luck searching for "grid" than "table".

    0 讨论(0)
  • 2021-02-01 10:19

    For Listview examples, nothing beats the clarity of the Classic Sample!

    In the meantime, Google Translate along with Unicode + tiny modifications to the rescue for @Alejadro's German link for the Listview- there's no direct translation on offer from search results as the page doesn't contain the appropriate meta tag. Snipped a little for brevity:

    Subsequent changes of styles

    The style of a ListView can be changed after creation. For this the functions GetWindowLong and SetWindowLong are used. About masks different styles can be defined.

    Mask.................................Masked Styles:
    LVS_TYPEMASK..............LVS_ICON, LVS_LIST, LVS_REPORT and LVS_SMALLICON LVS_ALIGNMASK.............LVS_ALIGNLEFT and LVS_ALIGNTOP LVS_TYPESTYLEMASK...LVS_ALIGNLEFT and LVS_ALIGNTOP but also VS_NOCOLUMNHEADER and LVS_NOSORTHEADER

    For the following sequence, dwView contains the style to use, such as 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); }
    

    Control of the ListView control

    Generating a list

    A list view is created with the CreateWindow function. The window class uses the constant WC_LISTVIEW. To do this, the common control header file must be included.

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


    In the dialog, it is simply defined in the resource.

    If there are unresolved externals, you should check whether the library for the Common Controls (comctl32.lib) is included.

    Columns of the ListView

    Before something can be inserted in a REPORT, the columns must be defined. A column is described by the structure LVCOLUMN. The following routine creates a column.

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

    The columns can be modified by messages to the ListView or by calling macros that will ultimately execute a 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
    

    Insert a line

    An element of the ListView is described by the structure LVITEMW (see below). Each element can be represented as an ICON, SMALLICON, LIST element or as the left column of a REPORT line.

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

    The mask field determines which elements of the LVITEMW structure are really used. Since it often makes sense to keep a pointer to the memory object that holds the data behind the object, the lParam field is useful. In order for this to be used, LVIF_TEXT | LVIF_PARAM must be set as a mask.

    The constants of mask and the fields that enable them:

    LVIF_IMAGE iImage
    LVIF_INDENT iIndent
    LVIF_PARAM lParam
    LVIF_STATE state
    LVIF_TEXT pszText

    The further columns of a report

    The element itself is always left in the report view and is selectable. To fill more columns, a text is added to the item.

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

    The above Create2ColItem is best demonstrated by something along the line of the following statements:

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

    The structure LVITEMW

    The structure LVITEMW (in CommCtrl.h) describes an element of the ListView. The most important elements are briefly described here. First the definition:

    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;
    

    The LVM_GETITEMW and LVM_SETITEMW messages change the attributes of an element. As a parameter, you get a pointer to a LVITEMW structure next to the HWND of the ListView, which must be filled in advance.

    The structural elements in detail:

    Mask: Specifies which elements are used. A combination of the following flags is possible:

    LVIF_IMAGE iImage

    LVIF_INDENT iIndent

    LVIF_PARAM lParam

    LVIF_STATE state

    LVIF_TEXT pszText

    iItem Index (0-based) of the item to which the structure relates.

    iSubItem Index (1-based) of the subitem to which the structure relates. 0 if the structure refers to an item instead of a subitem.

    pszText points to a null-terminated string. If the value is LPWSTR_TEXTCALLBACK, it is a callback item. If this changes, pszText must be set to LPSTR_TEXTCALLBACK and the ListView informed by LVM_SETITEMW or LVM_SETITEMTEXT. pszText must not be set to LPWSTR_TEXTCALLBACK if the ListView has the style LVS_SORTASCENDING or LVS_SORTDESCENDING.

    cchTextMax Size of the buffer when the text is read.

    iImage Index of the icon of this element from the image list.

    lParam 32-bit value that is specific to this element.

    Actions with elements

    LVM_INSERTITEM Insertion of an element LVM_DELETEITEM Delete an element LVM_DELETEALLITEMS Delete all elements LVM_GETITEMW Read properties of the element LVM_GETITEMTEXT Read text of the element LVM_SETITEMW change LVM_SETITEMTEXT Change to the text

    Before inserting multiple items, an LVM_SETITEMCOUNT message will be sent to the ListView indicating how many items will ultimately be contained. This allows the ListView to optimize its memory allocation and release. How many elements a ListView contains can be determined with LVM_GETITEMCOUNT.

    Editing selected elements

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

    Events The ListView sends WM_NOTIFY messages to the parent window. The code can take the following values:

    Message............ Description
    LVN_BEGINDRAG.............Start a drag-and-drop action
    LVN_BEGINRDRAG..........Start a drag-and-drop action with the right mouse button
    LVN_BEGINLABELEDIT....Start editing a label
    LVN_ENDLABELEDIT.......End edit of a label
    LVN_DELETEITEM..........Reports that the item is deleted
    LVN_DELETEALLITEMS..Reports that all items are deleted
    LVN_COLUMNCLICK......Indicates that the user clicked in the header of a report display
    LVN_GETDISPINFO.......The control requests information about the presentation from the parent window
    LVN_SETDISPINFO.......The information of the parent window for the item must be renewed
    LVN_INSERTITEM..........Indicates the insertion of an item
    LVN_ITEMCHANGED.....Indicates that an item has been changed
    LVN_ITEMCHANGING....Indicates the intended change of an item
    LVN_KEYDOWN.............Key was pressed

    Editing the labels The list view must have been created using the LVS_EDITLABELS style. Then a label can already be clicked on and inputs are accepted. However, the input is discarded immediately afterwards. To allow changes in the label, you just need to catch the WM_NOTIFY and return TRUE. In order to access the entered text in between, access is made to the text of the item. The example shows the input in a message box.

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

    If editing was aborted, the pszText element will be 0.

    If you want to prevent editing, the message LVN_BEGINLABELEDIT is caught and returned TRUE. Here, too, the item can be accessed in the same way via lParam and thus, for example, a certain item group can be excluded.

    Click on the column header in the ListView

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

    Selection Event

    The LVN_ITEMACTIVATE event is sent when the user activates an item. As with the other ListView events, it achieves the window function as part of a WM_NOTIFY message.

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

    The LVM_GETSELECTEDCOUNT message can be used to determine how many items have been activated. The LVM_GETNEXTITEM message is sent with the LVNI_SELECTED attribute and all items have been edited.

    0 讨论(0)
  • 2021-02-01 10:32

    Using the windows API and the standard control ListView you can do a table using the style LVS_REPORT

    documentation link - unfortunatelly with no code :( -

    About List-View Controls

    I've found this good article Windows Programmierung: List View the explanation is in german language but a google translation together with the code should be enough to understand it. From the article, to create the window:

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

    then it is explained how to create the columns in the method

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

    how to insert an item (one column)

    int CreateItem(HWND hwndList, char *Text)
    

    or insert item with two columns

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

    etc...

    0 讨论(0)
提交回复
热议问题