 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mar 17 Ene, 2017 4:58 pm Asunto: Check en el Header |
|
|
Hola estoy dando vueltas y no logro resolver, hay alguna manera de colocar un Check en el header de un TListView para poder seleccionar todos o deseleccionar todos los item, gracias. _________________ Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr) |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Jue 19 Ene, 2017 12:21 am Asunto: |
|
|
Te muestro un ejemplo con un formulario que tiene un TListView con una serie de columnas escrito con Builder 5. Necesitas añadir XP.RC.
Muestra un CheckBox en la cabecera y en cada Item. Si marcas la cabecera se marcan todos los Item. Si marcas todos los Item se marca la cabecera y se desmarcas un Item, se desmarca la Cabecera.
| Código: |
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TListView *ListView1;
private:
void __fastcall WndProc(Messages::TMessage &Message);
void __fastcall SetHeaderCheck();
void __fastcall OnHeaderChecked(bool Checked);
void __fastcall OnItemChecked(int Item, bool Checked);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
|
El codigo:
| Código: |
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
#define HDF_CHECKBOX 0x0040
#define HDF_FIXEDWIDTH 0x0100
#define HDF_CHECKED 0x0080
#define HDS_CHECKBOXES 0x0400
#define HDN_ITEMSTATEICONCLICK 0xFFFFFEC4
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
ListView_SetExtendedListViewStyle(ListView1->Handle, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
HANDLE hHeader = ListView_GetHeader(ListView1->Handle);
SetWindowLong(hHeader, GWL_STYLE, GetWindowLong(hHeader, GWL_STYLE) | HDS_CHECKBOXES);
HDITEM HD = {0};
HD.mask = HDI_FORMAT;
Header_GetItem(hHeader, 0, &HD);
HD.fmt |= HDF_CHECKBOX | HDF_FIXEDWIDTH;
Header_SetItem(hHeader, 0, &HD);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(Messages::TMessage &Message)
{
if(Message.Msg == WM_NOTIFY){
// Notificación del cambio del CheckBox de la cabecera
NMHEADER* pNMH = (NMHEADER*)(Message.LParam);
if(pNMH->hdr.code == HDN_ITEMSTATEICONCLICK){
if(pNMH->pitem->mask & HDI_FORMAT && pNMH->pitem->fmt & HDF_CHECKBOX){
bool HeaderChecked = !(pNMH->pitem->fmt & HDF_CHECKED);
for(int i = 0; i < ListView1->Items->Count; i++)
ListView_SetCheckState(ListView1->Handle, i, HeaderChecked);
OnHeaderChecked(HeaderChecked); // Evento para seguir haciendo cosas...
}
}
// Notificación del cambio del CheckBox de un Item
if(pNMH->hdr.code == LVN_ITEMCHANGED){
NMLISTVIEW* pNML = (NMLISTVIEW*)Message.LParam;
if (pNML->uChanged & LVIF_STATE){
SetHeaderCheck();
OnItemChecked(pNML->iItem, ListView_GetCheckState(ListView1->Handle, pNML->iItem)); // Evento para seguir haciendo cosas...
}
}
}
TForm::WndProc(Message);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SetHeaderCheck()
{
// Marcamos / desmarcamos la cabecera según si todos los Items están marcados o no
// si uno no está marcado...
BOOL HeaderChecked = TRUE;
for(int i = 0; i < ListView1->Items->Count; i++) {
if(!ListView_GetCheckState(ListView1->Handle, i)){
HeaderChecked = FALSE;
break;
}
}
// Marcamos la cabecera
HWND hHeader = ListView_GetHeader(ListView1->Handle);
HDITEM HDI = {0};
HDI.mask = HDI_FORMAT;
Header_GetItem(hHeader, 0, &HDI);
if(HeaderChecked)
HDI.fmt |= HDF_CHECKED;
else
HDI.fmt &= ~HDF_CHECKED;
Header_SetItem(hHeader, 0, &HDI);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnHeaderChecked(bool Checked)
{
// Aquí seguimos actuando según el cambio del ChecBox de la cabecera
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnItemChecked(int Item, bool Checked)
{
// Aquí seguimos actuando según el Item y si cambia su estado a Checked = true
}
//---------------------------------------------------------------------------
|
Espero que te resuelva la duda.
Saludos. |
|
| Volver arriba |
|
 |
escafandra Master

Registrado: 29 Nov 2007Mensajes: 625Ubicación: Madrid - España
|
Publicado: Sab 21 Ene, 2017 1:24 am Asunto: |
|
|
Dándole otra vuelta de tuerca puede escribirse una clase que encapsule la funcionalidad realizando un subclassing a la ventana contenedora del ListView:
Probada en BCB5, BCB6 y Berlin
| Código: |
//--------------------------------------------------------------------------------------------------
// TLVCheckBox (Versión Hook estilo C++)
// escafandra 2017
// Clase para manejo de CheckBox en la cabecera e Items de un ListView
#ifndef LVCheckBoxCPP
#define LVCheckBoxCPP
#include <Windows.h>
#include <Commctrl.h>
#define HDF_CHECKBOX 0x0040
#define HDF_CHECKED 0x0080
#define HDF_FIXEDWIDTH 0x0100
#define HDS_CHECKBOXES 0x0400
#ifndef HDN_ITEMSTATEICONCLICK
#define HDN_ITEMSTATEICONCLICK 0xFFFFFEC4
#endif
#ifndef STRICT
typedef int (__stdcall *PLRESULT)();
#else
typedef WNDPROC PLRESULT;
#endif
//typedef void (__fastcall *POnHeaderChecked)(bool Checked);
//typedef void (__fastcall *POnItemChecked)(int Item, bool Checked);
typedef void __fastcall(__closure* POnItemChecked)(int Item, bool Checked);
typedef void __fastcall(__closure* POnHeaderChecked)(bool Checked);
class TLVCheckBox
{
private:
HWND hListView;
int Focusfmt;
int FocusIndex;
PLRESULT OldWndProc;
static LRESULT __stdcall DefWndProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam)
{
TLVCheckBox* pLVCheckBox = (TLVCheckBox*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(pLVCheckBox)
return pLVCheckBox->WndProc(hWnd, Msg, WParam, LParam);
else
return DefWindowProc(hWnd, Msg, WParam, LParam);
}
LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam)
{
if(Msg == WM_NOTIFY){
// Notificación del cambio del CheckBox de la cabecera
NMHEADER* pNMH = (NMHEADER*)LParam;
//if(pNMH->hdr.hwndFrom == hListView)
if(pNMH->hdr.code == HDN_ITEMSTATEICONCLICK){
if(pNMH->pitem->mask & HDI_FORMAT && pNMH->pitem->fmt & HDF_CHECKBOX){
bool HeaderChecked = !(pNMH->pitem->fmt & HDF_CHECKED);
if(OnHeaderChecked)
OnHeaderChecked(HeaderChecked);
for(int i = 0; i < ListView_GetItemCount(hListView); i++)
ListView_SetCheckState(hListView, i, HeaderChecked);
}
}
// Notificación del cambio del CheckBox de un Item
if(pNMH->hdr.code == LVN_ITEMCHANGED){
NMLISTVIEW* pNMLV = (NMLISTVIEW*)LParam;
if (pNMLV->uChanged & LVIF_STATE){
if(OnItemChecked)
OnItemChecked(pNMLV->iItem, ListView_GetCheckState(hListView, pNMLV->iItem));
SetHeaderCheck();
}
}
}
return CallWindowProc(OldWndProc, hWnd, Msg, WParam, LParam);
}
public:
POnHeaderChecked OnHeaderChecked;
POnItemChecked OnItemChecked;
void __fastcall SetHeaderCheck()
{
BOOL HeaderChecked = TRUE;
for(int i = 0; i < ListView_GetItemCount(hListView); i++) {
if(!ListView_GetCheckState(hListView, i)){
HeaderChecked = FALSE;
break;
}
}
HWND hHeader = ListView_GetHeader(hListView);
HDITEM HDI = {0};
HDI.mask = HDI_FORMAT;
Header_GetItem(hHeader, 0, &HDI);
if(HeaderChecked)
HDI.fmt |= HDF_CHECKED;
else
HDI.fmt &= ~HDF_CHECKED;
Header_SetItem(hHeader, 0, &HDI);
}
void SetHandle(HWND hLV)
{
if(hLV != INVALID_HANDLE_VALUE && hLV != hListView){
if(!hLV){
SetWindowLong(GetParent(hListView), GWL_USERDATA, 0);
SetWindowLong(GetParent(hListView), GWL_WNDPROC, (LONG)OldWndProc);
}
if(hLV){
ListView_SetExtendedListViewStyle(hLV, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
//hHeader = (HANDLE)SendMessage(hLV, LVM_GETHEADER, 0, 0);
HWND hHeader = ListView_GetHeader(hLV);
SetWindowLong(hHeader, GWL_STYLE, GetWindowLong(hHeader, GWL_STYLE) | HDS_CHECKBOXES);
HDITEM HD = {0};
HD.mask = HDI_FORMAT;
Header_GetItem(hHeader, 0, &HD);
HD.fmt |= HDF_CHECKBOX | HDF_FIXEDWIDTH;
Header_SetItem(hHeader, 0, &HD);
SetWindowLongPtr(GetParent(hLV), GWL_USERDATA, (LONG)this);
OldWndProc = (PLRESULT)SetWindowLongPtr(GetParent(hLV), GWL_WNDPROC, (LONG)TLVCheckBox::DefWndProc);
}
hListView = hLV;
}
}
TLVCheckBox(HWND hListView = 0)
{
OnHeaderChecked = 0;
OnItemChecked = 0;
SetHandle(hListView);
}
~TLVCheckBox() {SetHandle(0);}
};
#endif
|
Ejemplo de uso:
| Código: |
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
LVC.SetHandle(ListView1->Handle);
LVC.OnItemChecked = &OnItemChecked;
LVC.OnHeaderChecked = &OnHeaderChecked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnHeaderChecked(bool Checked)
{
Beep(500, 100);
// Aquí seguimos actuando según el cambio del ChecBox de la cabecera
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnItemChecked(int Item, bool Checked)
{
Beep(1000, 100);
// Aquí seguimos actuando según el Item y si cambia su estado a Checked = true
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
LVC.SetHandle(ListView1->Handle);
LVC.OnItemChecked = &OnItemChecked;
LVC.OnHeaderChecked = &OnHeaderChecked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
LVC.SetHandle(0);
}
//---------------------------------------------------------------------------
|
Saludos. |
|
| Volver arriba |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Jue 26 Ene, 2017 11:09 pm Asunto: |
|
|
Hola escafandra, muchisimas gracias es justo lo que estaba buscando, estoy usando CB6 y va perfecto..
Saludos .. _________________ Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr) |
|
| Volver arriba |
|
 |
Angel Master


Registrado: 15 Abr 2003Mensajes: 2311Ubicación: Toledo (España)
|
Publicado: Vie 27 Ene, 2017 10:41 am Asunto: Re: Check en el Header |
|
|
| Tor escribió: | | Hola estoy dando vueltas y no logro resolver, hay alguna manera de colocar un Check en el header de un TListView para poder seleccionar todos o deseleccionar todos los item, gracias. |
Yo prefiero poner una primera línea con un Seleccionar todos / ninguno. Creo que queda más claro.
Por ejemplo:
| Código: | TListItem *pItem;
ListView1->Items->Clear();
pItem = ListView1->Items->Add();
pItem->Caption = "SELECCIONAR TODOS";
for (; !Query->Eof; Query->Next())
{
pItem = ListView1->Items->Add();
pItem->Caption = Query->FieldByName("Campo")->AsString;
} |
Y en los eventos OnChange y OnClick del TListView:
| Código: | void __fastcall TForm1::ListView1Change(TObject *Sender, TListItem *Item, TItemChange Change)
{
ListView1Click(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView1Click(TObject *Sender)
{
Button2->Enabled = false;
ListView1->OnChange = NULL;
if (ListView1->Items->Item[0]->Checked)
{
ListView1->Items->Item[0]->Checked = false;
for (int nItem = 1; nItem <ListView1>Items->Count; nItem ++)
ListView1->Items->Item[nItem]->Checked = ListView1->Items->Item[0]->Caption == "SELECCIONAR TODOS" ? true : false;
ListView1->Items->Item[0]->Caption = ListView1->Items->Item[0]->Caption == "SELECCIONAR TODOS" ? "SELECCIONAR NINGUNO" : "SELECCIONAR TODOS";
}
ListView1->OnChange = ListView1Change;
}
//--------------------------------------------------------------------------- |
_________________ Un saludo
Necesitamos tu ayuda: Envía AI al 27595 (Coste 1,20 euros + IVA) |
|
| Volver arriba |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mar 31 Ene, 2017 2:01 am Asunto: |
|
|
Hola Angel, gracias por tu sugerencia! _________________ Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr) |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|