2012-01-23 28 views
10

He estado buscando en la red cosas diferentes sobre la API de win32, pero parece que toda la información en ella es bastante dispersa.Creando una tabla usando Win32 API

Estoy buscando crear una ventana simple que muestre una lista de elementos; sin embargo, quiero mostrar diferentes columnas de datos para cada elemento, en un formato de tabla, donde el usuario podría cambiar el tamaño de los diferentes anchos de columna.

Si es posible, me gustaría también poder cambiar los colores de fondo de diferentes filas, en el código, entre solo un blanco general, rojo, amarillo o verde.

Y al usuario también se le permitiría hacer clic con el botón secundario en diferentes filas, y poder invocar una función en ellas, o copiar los datos en el portapapeles (pero esa parte es una historia diferente).

Ahora, he encontrado objetos de visor de lista (?) Que se pueden colocar en la ventana, botones y menús con el botón derecho ... pero no puedo entender cómo hacer una tabla, usando la API de Win32 . Ni siquiera he leído realmente los colores de fondo para otra cosa que no sea la ventana en sí.

¿Hay algún marco diferente y mejor que deba usar para esto, o hay algunas funciones o elementos que me he perdido? Toda la ayuda u orientación sobre la idea sería apreciada ...

Estoy usando MSVC++ para hacer ... todo en lo que estoy trabajando.

+0

¿Qué entorno de desarrollo está utilizando? (Ayuda a averiguar qué podría estar disponible para que lo use). –

+0

Estoy trabajando en MSVC++, lo siento, tiene razón, debería haber dicho eso ... – Serge

Respuesta

9

Windows proporciona una colección bastante básica de controles integrados, enumerados here.

Si quieres algo más sofisticado sus opciones son:

  • Código usted mismo. Tienes que pintarlo tú mismo, manejar toda la interacción del usuario, el desplazamiento, etc. Este es un gran trabajo.
  • Encuentra una implementación existente.
  • Abandona VC++ y usa WinForms o WPF.

Si tiene problemas con VC++, The Grid Control y The Ultimate Grid están basados ​​en MFC.

Si no está utilizando MFC, hay BABYGRID o The Win32 SDK Data Grid.

Si ninguno de ellos es adecuado, tendrás más suerte buscando "cuadrícula" que "mesa".

7

Uso de la API de Windows y el ListView control estándar que puede hacer una tabla utilizando el estilo LVS_REPORT

enlace de documentación - desafortunadamente sin código :(-

About List-View Controls

he encontrado este buen artículo Windows Programmierung: List View la explicación está en idioma alemán, pero una traducción de google junto con el código debería ser suficiente para entenderlo.Desde el artículo, para crear la ventana:

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

continuación se explica cómo crear las columnas en el método

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

cómo insertar un elemento (una columna)

int CreateItem(HWND hwndList, char *Text) 

o inserte el artículo con dos columnas

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

etc ...

+0

Amigo, esta es la mejor solución para la pregunta. Realmente extraña la respuesta seleccionada es tratar de alejarse de la solución madre. –

+0

También muestra el código en MSDN en [Agregar elementos y subtítulos de baja transmisión] (https://msdn.microsoft.com/en-us/library/windows/desktop/hh298346%28v=vs.85%29.aspx?f=255&MSPPError = -2147217396). –

0

Para ejemplos de Listview, ¡nada supera la claridad del Classic Sample!

Mientras tanto, Google Translate junto con Unicode + pequeñas modificaciones al rescate de enlace @ alemana de Alejadro para la Listview - no hay traducción directa en la oferta de resultados de búsqueda que la página no contiene la apropiada meta tag. Cortó un poco por razones de brevedad:

Los cambios posteriores de estilos

El estilo de un ListView se puede cambiar después de la creación. Para esto se usan las funciones GetWindowLong y SetWindowLong. Sobre las máscaras se pueden definir diferentes estilos.

Máscara ................................. Estilos enmascarados:
LVS_TYPEMASK ... ........... LVS_ICON, LVS_LIST, LVS_REPORT y LVS_SMALLICON LVS_ALIGNMASK ............. LVS_ALIGNLEFT y LVS_ALIGNTOP LVS_TYPESTYLEMASK ... LVS_ALIGNLEFT y LVS_ALIGNTOP sino también VS_NOCOLUMNHEADER y LVS_NOSORTHEADER

Para la secuencia siguiente, dwView contiene el estilo para usar, como 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); } 

de control del control ListView

generación de una lista

una vista de lista se crea con la función CreateWindow. La clase de ventana usa la constante WC_LISTVIEW. Para hacer esto, se debe incluir el archivo de encabezado de control común.

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


En el cuadro de diálogo, que se define simplemente en el recurso.

Si hay elementos externos no resueltos, debe comprobar si se incluye la biblioteca para los controles comunes (comctl32.lib).

Columnas del ListView

antes de que algo se pueden insertar en un REPORT, se deben definir las columnas. Una columna está descrita por la estructura LVCOLUMN. La siguiente rutina crea una columna.

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

Las columnas se pueden modificar mediante mensajes a ListView o llamando a macros que finalmente ejecutarán 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 

insertar una línea

Un elemento de la ListView se describe mediante la estructura LVITEMW (ver abajo). Cada elemento se puede representar como un elemento ICON, SMALLICON, LIST o como la columna izquierda de una línea REPORT.

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

El campo de máscara determina qué elementos de la estructura LVITEMW se utilizan realmente. Como a menudo tiene sentido mantener un puntero al objeto de memoria que contiene los datos detrás del objeto, el campo lParam es útil. Para que esto se pueda usar, LVIF_TEXT | LVIF_PARAM se debe establecer como una máscara.

Las constantes de la máscara y los campos que les permitan:

LVIF_IMAGE iImage
LVIF_INDENT iIndent
LVIF_PARAM IParam
estado LVIF_STATE
LVIF_TEXT pszText

Las otras columnas de un informe

El elemento en sí siempre se deja en la vista de informe y se puede seleccionar. Para llenar más columnas, se agrega un texto al 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; 
} 

Lo anterior Create2ColItem se demuestra mejor por algo a lo largo de la línea de las siguientes afirmaciones:

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

La estructura LVITEMW

La estructura LVITEMW (en commctrl.h) describe un elemento de ListView. Los elementos más importantes se describen brevemente aquí. En primer lugar la definición:

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; 

Los LVM_GETITEMW y LVM_SETITEMW mensajes de cambio de los atributos de un elemento. Como parámetro, se obtiene un puntero a una estructura LVITEMW junto al HWND del ListView, que se debe completar con anticipación.

Los elementos estructurales en detalle:

Máscara: Especifica los que se utilizan elementos.Una combinación de las siguientes banderas es posible:

LVIF_IMAGE iImage

LVIF_INDENT iIndent

LVIF_PARAM lParam

estado LVIF_STATE

LVIF_TEXT pszText

iItem Índice (basado en 0) del elemento con el que se relaciona la estructura.

iSubItem Índice (1-basado) del subelemento al que se refiere la estructura. 0 si la estructura se refiere a un elemento en lugar de a un subelemento.

pszText apunta a una cadena terminada en nulo. Si el valor es LPWSTR_TEXTCALLBACK, es un elemento de devolución de llamada. Si esto cambia, pszText debe establecerse en LPSTR_TEXTCALLBACK y el ListView informado por LVM_SETITEMW o LVM_SETITEMTEXT. pszText no debe establecerse en LPWSTR_TEXTCALLBACK si el ListView tiene el estilo LVS_SORTASCENDING o LVS_SORTDESCENDING.

cchTextMax Tamaño del búfer cuando se lee el texto.

iImage Índice del icono de este elemento de la lista de imágenes.

lParam Valor de 32 bits que es específico de este elemento.

acciones con elementos

LVM_INSERTITEM inserción de un elemento LVM_DELETEITEM eliminar un elemento LVM_DELETEALLITEMS Eliminar todos los elementos propiedades LVM_GETITEMW de lectura del elemento LVM_GETITEMTEXT Leer texto del elemento cambio LVM_SETITEMW LVM_SETITEMTEXT Cambio al texto

Antes de insertar varios elementos, se enviará un mensaje LVM_SETITEMCOUNT al ListView que indica cuántos elementos se incluirán finalmente. Esto permite que ListView optimice su asignación y lanzamiento de memoria. Cuantos elementos contiene un ListView se puede determinar con LVM_GETITEMCOUNT.

elementos seleccionados Edició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); 
} 

Eventos El ListView envía WM_NOTIFY mensajes a la ventana padre.El código puede tomar los siguientes valores:

mensaje ............ Descripción
LVN_BEGINDRAG ............. Iniciar un arrastrar y soltar deje caer la acción
LVN_BEGINRDRAG .......... Iniciar una acción de arrastrar y soltar con el botón derecho del ratón
LVN_BEGINLABELEDIT .... empezar a editar una etiqueta
LVN_ENDLABELEDIT ....... Fin edición de una etiqueta
LVN_DELETEITEM .......... Informa que se ha eliminado el elemento
LVN_DELETEALLITEMS..Informa que todos los elementos se eliminaron
LVN_COLUMNCLICK ...... Indica que el usuario hizo clic en el encabezado de una pantalla de informe
LVN_GETDISPINFO ....... El control solicita información sobre la presentación desde la ventana primaria
LVN_SETDISPINFO ...... .La información de la ventana padre para el elemento debe ser renovada
LVN_INSERTITEM .......... Indica la inserción de un elemento
LVN_ITEMCHANGED ..... Indica que un artículo ha sido cambiado
LVN_ITEMCHANGING .... Indica el cambio previsto de un artículo
LVN_KEYDOWN ............. Se presionó la tecla

Edición de etiquetas La vista de lista debe haberse creado con el estilo LVS_EDITLABELS. Entonces, ya se puede hacer clic en una etiqueta y se aceptan las entradas. Sin embargo, la entrada se descarta inmediatamente después. Para permitir cambios en la etiqueta, solo necesita tomar el WM_NOTIFY y devolver TRUE. Para acceder al texto ingresado, se accede al texto del elemento. El ejemplo muestra la entrada en un cuadro de mensaje.

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

Si la edición fue abortado, el elemento pszText será 0.

Si desea impedir la modificación, el mensaje LVN_BEGINLABELEDIT es capturado y devuelto TRUE. Aquí, también, se puede acceder al elemento de la misma manera a través del lParam y, por lo tanto, por ejemplo, se puede excluir un determinado grupo de elementos.

Haga clic en la cabecera de la columna en el ListView

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

evento de selección

El evento LVN_ITEMACTIVATE se envía cuando el usuario activa un elemento. Al igual que con los otros eventos ListView, logra la función de ventana como parte de un mensaje 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); 
..... 

LVM_GETSELECTEDCOUNT El mensaje se puede utilizar para determinar cuántos elementos han sido activados. El mensaje LVM_GETNEXTITEM se envía con el atributo LVNI_SELECTED y todos los elementos se han editado.

Cuestiones relacionadas