⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clistctrlex.cpp

📁 <Visual C++ 网络程序设计实例详解>配套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				nCmp = 1;
		}
		else if(cType=='C')
			nCmp = strcmp(s1,s2);
	}
	else
	{
		if(cType=='N')
		{
			n1 = atoi(s1);
			n2 = atoi(s2);
			
			if(n2 < n1)
				nCmp = -1;
			else if(n2 > n1)
				nCmp = 1;
		}
		else if(cType=='C')
			nCmp = strcmp(s2,s1);
	}

	if(++n > 5)
	{
		n = 0;
		::PeekAndPump();
	}

	return(nCmp);
}

/*
	GetItemToken()

	Estrae dalla riga l'elemento relativo alla colonna.
	Gli elementi, all'interno della riga, devono essere separati dal carattere ';'.

	int nItem			indice (base 0) dell'elemento
	LPCSTR lpcszRow	riga contenente gli elementi separati dal carattere ';'
*/
LPCSTR GetItemToken(int nItem,LPCSTR lpcszRow)
{
	int i;
	LPSTR lpToken;
	static char szItem[MAX_CTRLROW_SIZE + 1];

	strcpy(szItem,"[null]");

	if(lpcszRow && *lpcszRow)
	{
		strcpyn(szItem,lpcszRow,sizeof(szItem));

		for(i = 0,lpToken = strtok(szItem,";"); lpToken!=NULL; i++)
		{
			if(i==nItem)
			{
				strcpyn(szItem,lpToken,sizeof(szItem));
				break;
			}

			lpToken = strtok(NULL,";");
		}
	}

	return(szItem);
}

/*
	PopUpMenu()

	Visualizza il menu popup sul controllo.
	Il menu visualizzato e' il primo sottomenu (base 0) del menu relativo all'id nel caso in cui venga
	fatto click su un elemento o il secondo se viene fatto click in una zona del controllo senza elementi.

	const CPoint& point		coordinate del click
*/
void CListCtrlEx::PopUpMenu(const CPoint& point)
{
	int i;
	CRect rect;
	CMenu menu;
	CMenu* pSubMenu = NULL;
	CTRL_ROW* ra;

	// coordinate dell'area client (CWnd, base 0,0)
	CWnd::GetClientRect(&rect);
	
	// trasforma le coordinate in assolute (schermo)
	// da aggiungere alle coordinate del click del mouse per ottenere le coordinate a cui visualizzare il menu a comparsa
	CWnd::ClientToScreen(&rect);	
	
	// click su un elemento del controllo
	if((i = CListCtrl::HitTest(point)) >= 0)
	{
		// carica il menu relativo all'id specificato dall'elemento su cui e' stato fatto click
		// (primo sottomenu, base 0)
		if((ra = GetRowByItem(i))!=(CTRL_ROW*)NULL)
			if(ra->menu > 0)
				if(menu.LoadMenu(ra->menu))
					pSubMenu = menu.GetSubMenu(0);
	}
	// click fuori dall'elemento
	else
	{
		// click su una zona del controllo contenente almeno un elemento
		if((ra = GetRowByItem(0))!=(CTRL_ROW*)NULL)
		{
			// carica il menu relativo all'id specificato dal primo elemento della lista
			// (secondo sottomenu, base 0)
			if(ra->menu > 0)
				if(menu.LoadMenu(ra->menu))
					pSubMenu = menu.GetSubMenu(1);
		}
		// click su una zona del controllo senza nessun elemento
		else
		{
			// carica il menu di default
			// (primo sottomenu, base 0)
			if(m_NullRow.menu > 0)
				if(menu.LoadMenu(m_NullRow.menu))
					pSubMenu = menu.GetSubMenu(0);
		}
	}

	// visualizza il menu popup
	if(pSubMenu && m_pWnd)
	{
		if(m_nMenuMessage!=(UINT)-1)
			::SendMessage(m_pWnd->m_hWnd,m_nMenuMessage,(WPARAM)m_nCurrentItem,(LPARAM)pSubMenu);

		pSubMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x+rect.left,point.y+rect.top,m_pWnd);
	}
}

/*
	Sort()
*/
void	CListCtrlEx::Sort(int nCol/* = 0*/)
{
	LRESULT lResult = 0L;
	NM_LISTVIEW nm_listview;
	memset(&nm_listview,'\0',sizeof(NM_LISTVIEW));
	nm_listview.iSubItem = nCol;
	OnColumnClick((NMHDR*)&nm_listview,&lResult);
}

/*
	OnColumnClick()

	Gestore per il click sull'header della colonna.
	Ordina le righe presenti nella colonna.
*/
void CListCtrlEx::OnColumnClick(NMHDR* pNMHDR,LRESULT* pResult) 
{
	// verifica che il controllo contenga almeno un elemento
	if(CListCtrl::GetItemCount() > 0)
	{
		NM_LISTVIEW* pNM_LISTVIEW = (NM_LISTVIEW*)pNMHDR;
		int nCol = pNM_LISTVIEW->iSubItem;
		CTRL_COL* ca = GetColByItem(nCol);

		if(ca)
		{
			// imposta l'ordinamento corrente (ascendente/discendente) in base al precedente
			ca->order = (ca->order==FALSE ? TRUE : FALSE);
			bAscending = ca->order;
			
			// distingue tra dati numerici e carattere
			cType = ca->type;
			if(cType!='C' && cType!='N')
				cType = 'C';
			
			// ordina le righe della colonna
			CListCtrl::SortItems((PFNLVCOMPARE)CompareItems,nCol);

			// rinumera l'indice (interno) delle rige secondo l'ordinamento corrente
			
			// notare che l'ordinamento avviene considerando la prima colonna (base 0) della lista
			// motivo per cui tale colonna non puo' contenere elementi duplicati: in tal caso il
			// confronto (vedi la strcmp() di cui sotto) tra i due elementi selezionerebbe sempre
			// il primo e tanti saluti alla rinumerazione dell'indice interno che se ne andrebbe a
			// puttane
			// il confronto non puo' essere fatto con memcmp() su n caratteri perche' fallirebbe
			// nel caso in cui ci siano elementi che iniziano con gli stessi caratteri (ftp e ftp-wpd)
			// per cui deve estrarre il testo relativo dal buffer interno (testo;testo;testo;etc.) e
			// confrontarlo con quello della riga con strcmp()
			ITERATOR iter;
			CTRL_ROW* ra = NULL;
			LPSTR p;
			char szItem[MAX_CTRLITEM_SIZE+1];
			char buffer[MAX_CTRLITEM_SIZE+1];
			int tot = CListCtrl::GetItemCount();
			register int i,n;

			// per ogni riga
			for(i = 0,n = 0; i < tot; i++)
			{
				// ricava il testo della riga a colonna 0
				if(CListCtrl::GetItemText(i,0,buffer,sizeof(buffer)-1) > 0)
					// cerca l'entrata corrispondente (testo;testo;testo;etc.) nella lista interna
					if((iter = m_RowList.First())!=(ITERATOR)NULL)
						while(iter!=(ITERATOR)NULL)
						{
							// puntatore alla riga
							ra = (CTRL_ROW*)iter->data;
							if(ra)
							{
								// estrae il testo corrispondente alla colonna 0
								if((p = strchr(ra->item,';'))!=NULL)
								{
									int n = p - ra->item;
									memcpy(szItem,ra->item,n);
									szItem[n] = '\0';
									
									if(strcmp(buffer,szItem)==0)
									{
										ra->index = i;
										break;
									}
								}
							}
							iter = m_RowList.Next(iter);
						}

				if(++n > 5)
				{
					n = 0;
					::PeekAndPump();
				}
			}
		}
	}

	*pResult = 0;
}

/*
	OnLButtonDown()

	Gestore per il click con il bottone sinistro del mouse sull'elemento del controllo.
	Imposta la riga come selezionata ed invia il messaggio alla finestra principale (in wParam l'indice
	dell'elemento selezionato ed in lParam le coordinate del click).
	Per catturare il rilascio del bottone sinistro del mouse con OnLButtonUp() anche quando il cursore
	del mouse e' stato spostato fuori dall'area client, utilizzare la SetCapture().
*/
void CListCtrlEx::OnLButtonDown(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	m_MouseClick.point.x = point.x;
	m_MouseClick.point.y = point.y;
	m_MouseClick.flags = nFlags;

	// chiama il gestore originale
	CListCtrl::OnLButtonDown(nFlags,point);

	// per continuare a ricevere i messaggi quando il mouse si sposta fuori dell'area client
	//::SetCapture(this->m_hWnd);
	
	// indice dell'elemento cliccato
	m_nCurrentItem = CListCtrl::HitTest(point);

	// imposta il flag relativo alla selezione
	// se viene cambiato l'ordinamento del controllo l'elemento relativo all'indice non corrisponde a quanto
	// presente nella lista del chiamante, per cui deve cercare l'elemento relativo prima di impostare il
	// flag per la selezione
	// effettua tale ricerca con il primo subitem (indice 0), per cui il valore presente in tale posizione
	// deve essere unico
	int nTotItems = CListCtrl::GetItemCount();

	if(m_nCurrentItem >= 0 && m_nCurrentItem < nTotItems)
	{
		CTRL_ROW* ra = NULL;
		ITERATOR iter;
		register int i;
		char buffer[MAX_CTRLITEM_SIZE+1];

		// azzera le selezioni correnti
		if((iter = m_RowList.First())!=(ITERATOR)NULL)
			while(iter!=(ITERATOR)NULL)
			{
				ra = (CTRL_ROW*)iter->data;
				if(ra)
					ra->selected = FALSE;
				iter = m_RowList.Next(iter);
			}

		// per ogni elemento del controllo verifica se e' stato selezionato, ricava il valore relativo al
		// subitem con indice 0 e lo confronta con l'elemento corrente: se coincidono imposta il flag per
		// la selezione
		// deve scorrere il controllo per gestire le selezioni multiple (click sul primo, shift+click
		// sull'ultimo)
		for(i = 0; i < nTotItems/*CListCtrl::GetItemCount()*/; i++)
		{
			// il cazzo di elemento e' stato cliccato ?
			// (click sull'elemento o elemento nel mezzo di una selezione click su i, shift+click su i+n)
			if(CListCtrl::GetItemState(i,LVIS_SELECTED) & LVIS_SELECTED)
			{
				memset(buffer,'\0',sizeof(buffer));

				LV_ITEM lvitem;
				lvitem.mask = LVIF_TEXT;
				lvitem.iItem = i;
				lvitem.iSubItem = 0;
				lvitem.pszText = buffer;
				lvitem.cchTextMax = sizeof(buffer)-1;
				CListCtrl::GetItem(&lvitem);

				if((ra = GetRowByItem(i))!=(CTRL_ROW*)NULL)
				{
					if(memcmp(ra->item,buffer,strlen(buffer))==0)
					{
						ra->selected = TRUE;
						break;
					}
				}

				if(!m_bMultipleSelection)
					break;
			}
		}
	}

	// salva l'indice (base 0) dell'elemento corrente (selezionato), controllando l'intervallo
	if(m_nCurrentItem < 0)
		m_nCurrentItem = LB_ERR;
	else if(m_nCurrentItem >= nTotItems/*CListCtrl::GetItemCount()*/)
		m_nCurrentItem = nTotItems/*CListCtrl::GetItemCount()*/ - 1;

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del click
	if(m_pWnd!=NULL && m_nLButtonDownMessage!=(UINT)-1)
		::SendMessage(m_pWnd->m_hWnd,m_nLButtonDownMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_MouseClick);
}

/*
	OnLButtonUp()

	Gestore per il rilascio del bottone sinistro del mouse.
	Invia il messaggio alla finestra principale (in wParam l'indice dell'elemento su cui e' stato rilasciato
	il mouse ed in lParam le coordinate del rilascio).
	Vedi le note in OnLButtonDown() a proposito di SetCapture().
*/
void CListCtrlEx::OnLButtonUp(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	// chiama il gestore originale
	CListCtrl::OnLButtonUp(nFlags,point);

	// per terminare di ricevere i messaggi con il mouse fuori dell'area client
	//if(::GetCapture()==this->m_hWnd)
	//	::ReleaseCapture();

	// indice dell'elemento su cui e' stato effettuato il rilascio
	int m_nCurrentItem = CListCtrl::HitTest(point);

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del rilascio
	if(m_pWnd!=NULL && m_nLButtonUpMessage!=(UINT)-1)
		::SendMessage(m_pWnd->m_hWnd,m_nLButtonUpMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_Point);
}

/*
	OnRButtonDown()

	Gestore per il click con il bottone destro del mouse sull'elemento del controllo.
	Visualizza il menu popup ed invia il messaggio alla finestra principale (in wParam
	l'indice dell'elemento selezionato ed in lParam le coordinate del click).
*/
void CListCtrlEx::OnRButtonDown(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	// chiama il gestore originale
	CListCtrl::OnRButtonDown(nFlags,point);

	// indice dell'item cliccato
	m_nCurrentItem = CListCtrl::HitTest(point);

	// a seconda del flag imposta l'item corrente come selezionato
	// (per default solo il click con il sinistro imposta l'elemento come selezionato)
	if(m_bRightClickSelects)
	{
		// resetta le selezioni correnti dato la selezione multiple puo' effettuarsi solo con CTRL+click destro
		ResetItemsSelection();
		
		// seleziona l'item
		SetItemSelection(m_nCurrentItem,TRUE);
	}

	// visualizza il menu a comparsa
	PopUpMenu(point);

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del click
	if(m_pWnd!=NULL && m_nRButtonDownMessage!=(UINT)-1)
		::PostMessage(m_pWnd->m_hWnd,m_nRButtonDownMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_Point);
}

/*
	OnRButtonUp()

	Gestore per il rilascio del bottone destro del mouse.
	Invia il messaggio alla finestra principale (in wParam l'indice dell'elemento su cui e' stato rilasciato
	il mouse ed in lParam le coordinate del rilascio).
*/
void CListCtrlEx::OnRButtonUp(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	// chiama il gestore originale
	CListCtrl::OnRButtonUp(nFlags,point);

	// indice dell'elemento su cui e' stato effettuato il rilascio
	int m_nCurrentItem = CListCtrl::HitTest(point);

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del rilascio
	if(m_pWnd!=NULL && m_nRButtonUpMessage!=(UINT)-1)
		::SendMessage(m_pWnd->m_hWnd,m_nRButtonUpMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_Point);
}

/*
	OnLButtonDblClk()

	Gestore per il doppio click con il bottone sinistro del mouse sull'elemento del controllo.
	Invia il messaggio alla finestra principale (in wParam l'indice dell'elemento selezionato ed in lParam
	le coordinate del click).
*/
void CListCtrlEx::OnLButtonDblClk(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	// chiama il gestore originale
	CListCtrl::OnLButtonDblClk(nFlags,point);

	// indice dell'elemento cliccato
	m_nCurrentItem = CListCtrl::HitTest(point);

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del click
	if(m_pWnd!=NULL && m_nLButtonDblClkMessage!=(UINT)-1)
		::PostMessage(m_pWnd->m_hWnd,m_nLButtonDblClkMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_Point);
}

/*
	OnRButtonDblClk()

	Gestore per il doppio click con il bottone destro del mouse sull'elemento del controlo.
	Invia il messaggio alla finestra principale (in wParam l'indice dell'elemento selezionato ed in lParam
	le coordinate del click).
*/
void CListCtrlEx::OnRButtonDblClk(UINT nFlags,CPoint point)
{
	// salva le coordinate del click
	m_Point.x = point.x;
	m_Point.y = point.y;

	// chiama il gestore originale
	CListCtrl::OnRButtonDblClk(nFlags,point);

	// indice dell'elemento cliccato
	m_nCurrentItem = CListCtrl::HitTest(point);

	// se e' stato specificato un gestore, invia il messaggio relativo
	// in wParam l'indice dell'elemento ed in lParam le coordinate del click
	if(m_pWnd!=NULL && m_nRButtonDblClkMessage!=(UINT)-1)
		::PostMessage(m_pWnd->m_hWnd,m_nRButtonDblClkMessage,(WPARAM)m_nCurrentItem,(LPARAM)&m_Point);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -