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

📄 tabbedmdisave.cpp

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	bool success = true;

	long count = 0;
	list->get_Count(&count);
	for(long i=0; i<count; ++i)
	{
		ATL::CComPtr<ITabbedMDIChildModifiedItem> item;
		list->get_Item(i, &item);
		if(item)
		{
			ATL::CComBSTR displayName, description;
			item->get_DisplayName(&displayName);
			item->get_Description(&description);

			DATE lastModified = 0;
			item->get_LastModifiedUTC(&lastModified);

			_CSTRING_NS::CString displayNameForItem(displayName);
			_CSTRING_NS::CString descriptionForItem(description);
			_CSTRING_NS::CString lastModifiedForItem = this->FormatLastModifiedDateString(lastModified);

			if(displayNameForItem.GetLength() < 1)
			{
				displayNameForItem = _T("(New)");
			}

			int imageIndex = 0;
			HICON hIcon = NULL;
			item->get_Icon(&hIcon);
			if(hIcon != NULL)
			{
				imageIndex = m_images.AddIcon(hIcon);
			}

			// NOTE: The handler of LVN_INSERTITEM will AddRef,
			// and the handler of LVN_DELETEITEM will Release
			// to be sure we keep the item reference counted appropriately
			// no matter where the InsertItem comes from.
			//IUnknown* punkItem = NULL;
			ATL::CComPtr<IUnknown> punkItem;
			item->QueryInterface(IID_IUnknown, (void**)&punkItem);

			LVITEM lvItem = {0};
			lvItem.mask = (LVIF_TEXT | LVIF_INDENT | LVIF_IMAGE | LVIF_PARAM);
			lvItem.iItem = m_list.GetItemCount();
			lvItem.iSubItem = 0;
			lvItem.pszText = (LPTSTR)(LPCTSTR)displayNameForItem;
			lvItem.iIndent = indent;
			lvItem.iImage = imageIndex;
			lvItem.lParam = (LPARAM)punkItem.p;

			int index = m_list.InsertItem(&lvItem);
			if(index >= 0)
			{
				m_list.SetCheckState(index, TRUE);

				m_list.SetItemText(index, eColumn_Description, descriptionForItem);
				if(lastModifiedForItem.GetLength() > 0)
				{
					m_haveAtLeastOneModifiedDate = true;
					m_list.SetItemText(index, eColumn_LastModified, lastModifiedForItem);
				}
			}

			ATL::CComPtr<ITabbedMDIChildModifiedList> subItems;
			item->get_SubItems(&subItems);
			if(subItems)
			{
				this->AddItems(subItems, (indent + 1));
			}
		}
	}

	return success;
}

_CSTRING_NS::CString CSaveModifiedItemsDialog::FormatLastModifiedDateString(DATE lastModifiedUTC)
{
	_CSTRING_NS::CString lastModifiedString;

	if(lastModifiedUTC != 0)
	{
		SYSTEMTIME lastModifiedUTCSystem = {0};
		::VariantTimeToSystemTime(lastModifiedUTC, &lastModifiedUTCSystem);
		FILETIME lastModifiedUTCFileTime = {0};
		::SystemTimeToFileTime(&lastModifiedUTCSystem, &lastModifiedUTCFileTime);
		FILETIME lastModifiedLocalFileTime = {0};
		::FileTimeToLocalFileTime(&lastModifiedUTCFileTime, &lastModifiedLocalFileTime);

		COleDateTime nowLocal(COleDateTime::GetCurrentTime());
		COleDateTime dateTimeModifiedLocal(lastModifiedLocalFileTime);

		_CSTRING_NS::CString fullDateTimeString = dateTimeModifiedLocal.Format(_T("%#m/%#d/%Y %#I:%M %p"));;
		_CSTRING_NS::CString timeString = dateTimeModifiedLocal.Format(_T("%#I:%M %p"));;

		int yearDifference = (nowLocal.GetYear() - dateTimeModifiedLocal.GetYear());
		int dayOfYearDifference = (nowLocal.GetDayOfYear() - dateTimeModifiedLocal.GetDayOfYear());
		int hourDifference = (nowLocal.GetHour() - dateTimeModifiedLocal.GetHour());
		int minuteDifference = (nowLocal.GetMinute() - dateTimeModifiedLocal.GetMinute());
		int secondDifference = (nowLocal.GetSecond() - dateTimeModifiedLocal.GetSecond());
		if(	yearDifference >= 1 ||
			dayOfYearDifference > 1 ||
			nowLocal < dateTimeModifiedLocal)
		{
			lastModifiedString = fullDateTimeString;
		}
		else if(dayOfYearDifference == 1)
		{
			lastModifiedString.Format(_T("Yesterday, %s"), timeString);
		}
		else if(hourDifference >= 1)
		{
			lastModifiedString.Format(_T("%d hour%s ago"), hourDifference,
				(hourDifference!=1) ? _T("s") : _T(""));
		}
		else if(minuteDifference >= 1)
		{
			lastModifiedString.Format(_T("%d minute%s ago"), minuteDifference,
				(minuteDifference!=1) ? _T("s") : _T(""));
		}
		else if(secondDifference >= 1)
		{
			lastModifiedString.Format(_T("%d second%s ago"), secondDifference,
				(secondDifference!=1) ? _T("s") : _T(""));
		}
		else
		{
			lastModifiedString = fullDateTimeString;
		}
	}

	return lastModifiedString;
}

IUnknown* CSaveModifiedItemsDialog::GetIUnknownForItem(int index)
{
	LVITEM lvi={0};
	lvi.mask = LVIF_PARAM;
	lvi.iItem = index;
	lvi.iSubItem = 0;
	lvi.lParam = 0;
	if(m_list.GetItem(&lvi))
	{
		return (IUnknown*) lvi.lParam;
	}

	return NULL;
}

int CSaveModifiedItemsDialog::FindItemIndex(ITabbedMDIChildModifiedItem* item)
{
	if(item == NULL)
	{
		return -1;
	}

	ATL::CComPtr<IUnknown> punkNode;
	item->QueryInterface(IID_IUnknown, (void**)&punkNode);
	if(punkNode)
	{
		LVFINDINFO findInfo = {0};
		findInfo.flags = LVFI_PARAM;
		findInfo.lParam = (LPARAM)(IUnknown*)punkNode.p;

		return m_list.FindItem(&findInfo, -1);
	}

	return -1;
}

int CSaveModifiedItemsDialog::FindParentIndex(int item)
{
	// Find the index of the "parent" based on the indent
	LVITEM lvi = { 0 };
	lvi.iItem = item;
	lvi.iSubItem = 0;
	lvi.mask = LVIF_INDENT;
	m_list.GetItem(&lvi);

	if(lvi.iIndent == 0)
	{
		return -1;
	}

	int parentIndex = -1;
	for(int i=item; (i >= 0) && (parentIndex < 0); --i)
	{
		LVITEM lviParent = { 0 };
		lviParent.iItem = i;
		lviParent.iSubItem = 0;
		lviParent.mask = LVIF_INDENT;
		m_list.GetItem(&lviParent);
		if(lviParent.iIndent < lvi.iIndent)
		{
			// We've hit the first item before the
			// item in question where the indent is less.
			// Treat this as the parent
			parentIndex = i;
		}
	}

	return parentIndex;
}

void CSaveModifiedItemsDialog::ToggleCheckState(int item)
{
	LVITEM lvi = { 0 };
	lvi.iItem = item;
	lvi.iSubItem = 0;
	lvi.mask = (LVIF_INDENT | LVIF_STATE);
	lvi.stateMask = (LVIS_STATEIMAGEMASK | LVIS_SELECTED);
	m_list.GetItem(&lvi);

	CheckState checkState = (CheckState)(lvi.state & LVIS_STATEIMAGEMASK);

	CheckState newCheckState = eCheckState_Checked;
	switch(checkState)
	{
	case eCheckState_Unchecked:
		newCheckState = eCheckState_Checked;
		break;
	case eCheckState_Checked:
		newCheckState = eCheckState_Unchecked;
		break;
	case eCheckState_Indeterminate:
		newCheckState = eCheckState_Checked;
		break;
	}

	if((lvi.state & LVIS_SELECTED) != LVIS_SELECTED)
	{
		// If the item isn't selected, toggle the checkmark on just the item
		this->SetTristateCheckState(item, newCheckState);
	}
	else
	{
		// Otherwise, set the checkmark appropriately on all selected items.
		int itemToCheck = -1;
		while((itemToCheck = m_list.GetNextItem(itemToCheck, LVNI_SELECTED)) != -1)
		{
			this->SetTristateCheckState(itemToCheck, newCheckState);
		}
	}
}

void CSaveModifiedItemsDialog::SetTristateCheckState(int item, CheckState checkState)
{
	LVITEM lvi = { 0 };
	lvi.iItem = item;
	lvi.iSubItem = 0;
	lvi.mask = LVIF_INDENT;
	m_list.GetItem(&lvi);

	int itemToCheck = item;
	bool done = false;

	// Set the check of the item as well as all of the "child" items
	while(!done)
	{
		m_list.SetItemState(itemToCheck, checkState, LVIS_STATEIMAGEMASK);

		itemToCheck = m_list.GetNextItem(itemToCheck, LVNI_ALL);
		if(itemToCheck < 0)
		{
			done = true;
		}
		else
		{
			LVITEM lviToCheck = { 0 };
			lviToCheck.iItem = itemToCheck;
			lviToCheck.iSubItem = 0;
			lviToCheck.mask = LVIF_INDENT;
			m_list.GetItem(&lviToCheck);
			done = (lviToCheck.iIndent <= lvi.iIndent);
		}
	}

	this->UpdateParentCheckState(item, checkState);
}

CSaveModifiedItemsDialog::CheckState CSaveModifiedItemsDialog::GetTristateCheckState(int item)
{
	return (CheckState)m_list.GetItemState(item, LVIS_STATEIMAGEMASK);
}

void CSaveModifiedItemsDialog::UpdateParentCheckState(int item, CheckState checkState)
{
	// Update the "parent" item's checkbox to reflect the state of the descendants.
	// If all of the descendants are checked, then check the parent.
	// If all of the descendants are unchecked, then uncheck the parent.
	// If some of the descendants are checked, and some are unchecked, have
	// the parent's checkbox be indeterminate.
	// If the parent isn't a "root" parent, recursively give the same
	// treatment to all of the ancestors.

	int parentIndex = this->FindParentIndex(item);
	if(parentIndex >= 0)
	{
		LVITEM lviParent = { 0 };
		lviParent.iItem = parentIndex;
		lviParent.iSubItem = 0;
		lviParent.mask = LVIF_INDENT;
		m_list.GetItem(&lviParent);

		int itemToCheck = parentIndex + 1;

		bool checkStateMixed = false;
		bool done = false;
		while(!done)
		{
			LVITEM lviDescendant = { 0 };
			lviDescendant.iItem = itemToCheck;
			lviDescendant.iSubItem = 0;
			lviDescendant.mask = (LVIF_INDENT | LVIF_STATE);
			lviDescendant.stateMask = LVIS_STATEIMAGEMASK;
			BOOL validItem = m_list.GetItem(&lviDescendant);
			if(!validItem)
			{
				done = true;
			}
			else if(lviDescendant.iIndent <= lviParent.iIndent)
			{
				// There's no more possible siblings or descendants,
				// because we've hit our parent's sibling
				done = true;
			}
			else
			{
				CheckState descendantCheckState = (CheckState)(lviDescendant.state & LVIS_STATEIMAGEMASK);
				if(descendantCheckState != checkState)
				{
					checkStateMixed = true;
					done = true;
				}
			}

			if(!done)
			{
				itemToCheck = m_list.GetNextItem(itemToCheck, LVNI_ALL);
				done = (itemToCheck < 0);
			}
		}

		// Now we've visited all of the descendants of the parent.
		// If all of them have the same check state as the item,
		// set the parent's check state to the same.  If the descendants
		// have mixed check states, then set the parent's check
		// state to indeterminate.
		if(checkStateMixed)
		{
			m_list.SetItemState(parentIndex, eCheckState_Indeterminate, LVIS_STATEIMAGEMASK);
		}
		else
		{
			m_list.SetItemState(parentIndex, checkState, LVIS_STATEIMAGEMASK);
		}
		this->UpdateParentCheckState(parentIndex, checkState);
	}
}

void CSaveModifiedItemsDialog::CreateDefaultImages(void)
{
	// IMPORTANT! Win2K and WinXP have the same index for this bitmap.
	//  There's even a standard TB_LOADIMAGES message for toolbar that loads it,
	//  along with standard image indexes into the bitmap.
	//  However, instead of creating a toolbar and issuing TB_LOADIMAGES,
	//  we'll load the bitmap directly by its index (120) and
	//  the color mask (192,192,192).
	//  Double check future versions of Windows to make sure
	//  this all works correctly.
	HMODULE hComCtl32 = GetModuleHandle(_T("comctl32.dll"));
	if(hComCtl32)
	{
		HIMAGELIST hCommonToolbar = ImageList_LoadBitmap(hComCtl32, MAKEINTRESOURCE(120), 16, 0, RGB(192,192,192));
		if(hCommonToolbar)
		{
			HICON hFileNew = ImageList_ExtractIcon(NULL, hCommonToolbar, STD_FILENEW);
			HICON hFileSave = ImageList_ExtractIcon(NULL, hCommonToolbar, STD_FILESAVE);

			if(hFileNew)
			{
				int fileNewIndex = m_images.AddIcon(hFileNew);
				ATLASSERT(fileNewIndex == 0);

				::DestroyIcon(hFileNew);
				hFileNew = NULL;
			}

			if(hFileSave)
			{
				int fileSaveIndex = m_images.AddIcon(hFileSave);
				ATLASSERT(fileSaveIndex == 1);

				m_dialogIcon = hFileSave;

				this->SetIcon(m_dialogIcon, ICON_SMALL);
			}

			ImageList_Destroy(hCommonToolbar);
			hCommonToolbar = NULL;
		}
	}
}

void CSaveModifiedItemsDialog::CreateDefaultStateImages(void)
{
	if(!m_stateImages.IsNull())
	{
		WTL::CWindowDC dcScreen(NULL);

		int cx = ::GetSystemMetrics(SM_CXSMICON);
		int cy = ::GetSystemMetrics(SM_CYSMICON);

		m_imageUnchecked     = this->AddCheckStateImage(dcScreen, cx, cy, eCheckState_Unchecked);
		m_imageChecked       = this->AddCheckStateImage(dcScreen, cx, cy, eCheckState_Checked);
		m_imageIndeterminate = this->AddCheckStateImage(dcScreen, cx, cy, eCheckState_Indeterminate);
	}
}

int CSaveModifiedItemsDialog::AddCheckStateImage(HDC dcScreen, int cx, int cy, enum CheckState checkState)
{
	ImageUtil::eCheckbox type = ImageUtil::eCheckboxChecked;
	switch(checkState)
	{
	case eCheckState_Unchecked:
		type = ImageUtil::eCheckboxUnchecked;
		break;
	case eCheckState_Checked:
		type = ImageUtil::eCheckboxChecked;
		break;
	case eCheckState_Indeterminate:
		type = ImageUtil::eCheckboxIndeterminate;
		break;
	default:
		ATLASSERT(0 && "Invalid checkbox type!");
		break;
	}

	int index = -1;

	WTL::CBitmap bitmap = ImageUtil::CreateCheckboxImage(dcScreen, type, cx, cy, RGB(255,0,0), m_list);
	if(!bitmap.IsNull())
	{
		index = m_stateImages.Add(bitmap, RGB(255,0,0));
	}

	return index;
}

⌨️ 快捷键说明

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