65.9K
CodeProject 正在变化。 阅读更多。
Home

IntelliFile - Total Commander 的 Windows 替代版本

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (40投票s)

2022年5月13日

GPL3

7分钟阅读

viewsIcon

139709

本文介绍的是IntelliFile应用程序,它是Total Commander的免费Windows替代版本,并使用了CodeProject上发布的许多组件。

功能列表

该应用程序是免费的,正如言论自由/免费啤酒一样,最终版本将具有以下功能:

  • 文件处理
    • 批量复制、移动、重命名和删除整个目录树
    • 按内容比较文件,内置文本编辑器
    • 以base64格式编码/解码文件
    • 显示/选择具有特定搜索模式、大小、日期或内容的文件
    • 增强的搜索功能,可在多个驱动器中的任何文件中进行全文搜索,甚至在存档中
    • 支持与Explorer/桌面的拖放操作
  • FTP客户端
    • 内置FTP客户端支持大多数公共FTP服务器
    • 通过SSL/TLS进行安全FTP,输入URL如下:ftps://ftp.servername.com
    • 后台下载(单独线程)
  • 存档处理
    • 存档被视为子目录。您可以轻松地将文件复制到存档中和从存档中复制文件。
    • 内置ZIP兼容打包器,支持长文件名!该打包器基于Info-Zip的ZLIB。
    • 后台打包(单独线程)

目前,仅实现了基本的文件操作:编辑、复制、移动、重命名和删除!
上述部分功能仍在开发中!

架构

每个文件定义都包含在一个CFileData类中,其接口如下:

  • DWORD GetFileAttributes(); - 返回文件的属性
  • void SetFileAttributes(DWORD dwFileAttributes); - 设置文件的属性
  • COleDateTime GetCreationTime(); - 返回文件的创建日期/时间
  • void SetCreationTime(COleDateTime ftCreationTime); - 设置文件的创建日期/时间
  • COleDateTime GetLastAccessTime(); - 返回文件的最后读取日期/时间
  • void SetLastAccessTime(COleDateTime ftLastAccessTime); - 设置文件的最后读取日期/时间
  • COleDateTime GetLastWriteTime(); - 返回文件的最后写入日期/时间
  • void SetLastWriteTime(COleDateTime ftLastWriteTime); - 设置文件的最后写入日期/时间
  • ULONGLONG GetFileSize(); - 返回文件大小
  • void SetFileSize(ULONGLONG nFileSize); - 设置文件大小
  • CString GetFileName(); - 返回文件名
  • void SetFileName(CString strFileName); - 设置文件名
  • CString GetAlternate(); - 返回文件的备用名称
  • void SetAlternate(CString strAlternateFileName); - 设置文件的备用名称

然后,我们将CFileList定义为typedef CArray<cfiledata*> CFileList;

此列表在CFileSystem类中管理,其接口如下:

  • BOOL RemoveAll(); - 从列表中移除所有文件
  • int GetSize(); - 返回列表中文件的计数
  • CFileData* GetAt(int nIndex); - 从列表中返回一个文件定义
  • int GetSystemType(); - 返回文件系统类型(FAT、FTP、ZIP)
  • void SetSystemType(int nSystemType); - 设置文件系统类型(FAT、FTP、ZIP)
  • CString GetFolder(); - 返回当前文件夹路径
  • BOOL SetFolder(CString strFolder); - 设置当前文件夹路径
  • BOOL Refresh(); - 从列表中更新文件定义
  • BOOL ViewFile(CString strFilePath); - 允许查看选定的文件
  • BOOL EditFile(CString strFilePath); - 允许编辑选定的文件
  • BOOL CopyFile(CFileSystem* pDestination, CFileList* arrSelection); - 复制选定的文件和文件夹
  • BOOL MoveFile(CFileSystem* pDestination, CFileList* arrSelection); - 移动选定的文件和文件夹
  • BOOL NewFolder(CFileSystem* pDestination, CFileList* arrSelection); - 创建新文件夹
  • BOOL DeleteFile(CFileSystem* pDestination, CFileList* arrSelection); - 删除选定的文件和文件夹

如何在Windows中编辑文件?

BOOL CFileSystem::EditFile(CString strFilePath)
{
    const int nDot = strFilePath.ReverseFind(_T('.'));
    if ((nDot != -1) && !IsApplication(strFilePath))
    {
        CString strExtension = strFilePath.Mid(nDot);

        CString strApplication;
        TCHAR lpszBuffer[0x1000] = { 0 };
        DWORD cbLength = sizeof(lpszBuffer);
        if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, 
                      strExtension, _T("open"), lpszBuffer, &cbLength)))
        {
            lpszBuffer[cbLength] = 0;
            strApplication = lpszBuffer;
        }

        if (strApplication.IsEmpty())
        {
            MessageBox(m_hWndParent, _T("There is no application associated with 
            this type of file."), _T("IntelliFile"), MB_OK | MB_ICONEXCLAMATION);
            return FALSE;
        }

        if (strApplication.Find(_T("%1")) != -1)
        {
            strApplication.Replace(_T("\"%1\""), (_T("\"") + strFilePath + _T("\"")));
            strApplication.Replace(_T("%1"), (_T("\"") + strFilePath + _T("\"")));
        }
        else
        {
            strApplication += _T(" ") + (_T("\"") + strFilePath + _T("\""));
        }

        CString strExe;
        CString strParam;
        if (strApplication.Find(_T("rundll32.exe")) != -1)
        {
            if ((int) ShellExecute(m_hWndParent, _T("open"), 
                      strFilePath, NULL, NULL, SW_SHOWNORMAL) <= 32)
            {
                DisplayErrorBox(m_wndCaptionBar, _T("ShellExecute"), GetLastError());
                return FALSE;
            }
        }
        else
        {
            if (strApplication[0] == _T('"'))
            {
                int nPos = strApplication.Find('"', 1);
                if (nPos != -1)
                {
                    strExe = strApplication.Left(nPos+1);
                    strParam = strApplication.Mid(nPos+1);
                }
                else
                {
                    ASSERT(0);
                }
            }
            else
            {
                int nPos = strApplication.Find(' ', 1);
                if (nPos != -1)
                {
                    strExe = strApplication.Left(nPos+1);
                    strParam = strApplication.Mid(nPos+1);
                }
                else
                {
                    ASSERT(0);
                }
            }

            strExe.Trim(_T(" \r\n\t"));
            strParam.Trim(_T(" \r\n\t"));

            SHELLEXECUTEINFO pShellExecuteInfo;
            pShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
            pShellExecuteInfo.fMask = SEE_MASK_FLAG_DDEWAIT | 
            SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST;
            pShellExecuteInfo.hwnd = m_hWndParent;
            pShellExecuteInfo.lpVerb = NULL;
            pShellExecuteInfo.lpFile = (LPCWSTR)(strExe);
            pShellExecuteInfo.lpParameters = (LPCWSTR)(strParam);
            pShellExecuteInfo.lpDirectory = NULL;
            pShellExecuteInfo.nShow = SW_SHOWNORMAL;

            if (!ShellExecuteEx(&pShellExecuteInfo))
            {
                DisplayErrorBox(m_wndCaptionBar, _T("ShellExecute"), GetLastError());
                return FALSE;
            }
        }
        return TRUE;
    }

    return FALSE;
}

如何在Windows中复制文件?

bool CFileSystem::CopyFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pFolderItem = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))) &&
		(SUCCEEDED(hResult = SHCreateItemFromParsingName(strDestination, nullptr, IID_PPV_ARGS(&pFolderItem)))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->CopyItem(pShellItem, pFolderItem, nullptr, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->CopyItems(pShellItemArray, pFolderItem))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFolderItem != nullptr)
	{
		pFolderItem->Release();
		pFolderItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

如何在Windows中移动/重命名文件?

bool CFileSystem::MoveFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pFolderItem = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))) &&
		(SUCCEEDED(hResult = SHCreateItemFromParsingName(strDestination, nullptr, IID_PPV_ARGS(&pFolderItem)))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->MoveItem(pShellItem, pFolderItem, nullptr, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;

			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->MoveItems(pShellItemArray, pFolderItem))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFolderItem != nullptr)
	{
		pFolderItem->Release();
		pFolderItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

如何在Windows中删除文件?

bool CFileSystem::DeleteFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->DeleteItem(pShellItem, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;

			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->DeleteItems(pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

结束语

IntelliFile应用程序使用了CodeProject上发布的许多组件。非常感谢:

  • 我的CMFCListView窗体视图(请参阅源代码
  • Armen Hakobyan 提供的CFolderDialog
  • Paul DiLascia 提供的CHtmlCtrl
  • PJ Naughter 提供的CInstanceChecker
  • PJ Naughter 提供的CVersionInfo
  • Mizan Rahman 提供的CWndResizer

历史

  • 版本 1.01 (2022年5月13日):首次发布
  • 版本 1.02 (2022年5月20日):实现了“新建文件夹”功能
  • 版本 1.03 (2022年5月23日):实现了“更改驱动器”功能
  • 版本 1.04 (2022年5月24日):实现了“查看文本文件”功能
  • 版本 1.05 (2022年5月27日)
    • 实现了“查看RTF文件”功能
    • 实现了“查看XML文件”功能
    • 实现了“上下文菜单”功能
  • 版本 1.06 (2022年8月21日):添加了“更改驱动器…”图标
  • 版本 1.07 (2022年9月9日):在关于框对话框中添加了“贡献者”超链接
  • 版本 1.08 (2023年1月23日):将PJ Naughter的CVersionInfo库更新到最新可用版本
    更新了代码,对所有变量声明使用C++统一初始化。
  • 版本 1.09 (2023年1月24日):将PJ Naughter的CInstanceChecker库更新到最新可用版本
    更新了代码,对所有变量声明使用C++统一初始化。
  • 将代码库中的NULL替换为nullptr
    将代码库中的BOOL替换为bool
    这意味着该应用程序的最低要求现在是Microsoft Visual C++ 2010。
  • 版本 1.10 (2023年4月25日):添加了base64编码/解码函数
  • 版本 1.11 (2023年5月13日):根据Rick Dishman的建议添加了新更改:重置视图和保存上次使用的文件夹
  • 版本 1.12 (2023年5月15日):在MFC ListView中通过单击标签添加了重命名文件名的功能
  • 版本 1.13 (2023年5月18日):修复了Rick Dishman报告的关于编辑图像文件的问题
  • 版本 1.14 (2023年5月19日):修复了Rick Dishman报告的关于状态栏的问题
  • 版本 1.15 (2023年5月21日):更改了双击实现,以在编辑模式下打开文件
  • 版本 1.16 (2023年5月27日):更新了关于对话框,增加了GPLv3声明
  • 版本 1.17 (2023年6月17日):为收藏夹文件夹添加了快速访问对话框
  • 版本 1.18 (2023年6月25日)
    • 实现了“命令提示符”功能
    • 用 PJ Naughter 的 CHLinkCtrl 库替换旧的 CHyperlinkStatic
  • 版本 1.19 (2023年8月17日)
    • 实现了“切换视图”功能(在源视图和目标视图之间切换)
    • 添加社交媒体链接:Twitter、LinkedIn、Facebook 和 Instagram
    • 添加 GitHub 存储库的问题、讨论和 Wiki 的快捷方式
  • 版本 1.20 (2023年8月26日)
    • 重构了CopyFileMoveFileDeleteFile函数
    • 更改了文章的下载链接。更新了关于对话框(电子邮件和网站)
  • 版本 1.21 (2023年9月22日):切换到Visual Studio Enterprise 2022(项目源代码做了一些更改)
  • 版本 1.22 (2023年9月30日):添加了SCINTILLA控件,用于以语法高亮显示查看源代码
  • 版本 1.23 (2023年12月10日):将PJ Naughter的CScintillaCtrl库更新到最新可用版本
    移除了 SetCallDirectGetCallDirect 方法。现在,如果调用线程与创建 Scintilla 控件的线程相同,CScintillaCtrl 类将调用 m_DirectStatusFunction。感谢 Markus Nissl 提供的此更新。
  • 版本 1.24 (2023年12月29日):将PJ Naughter的CScintillaCtrl库更新到最新可用版本
    更新了类以支持 Scintilla v5.4.1。新封装的消息包括:SCI_CHANGESELECTIONMODESCI_SETMOVEEXTENDSSELECTIONSCI_SELECTIONFROMPOINT。还更新了以下方法的签名:GetDocPointerSetDocPointerCreateDocumentAddRefDocumentReleaseDocument
  • 版本 1.25 (2024年1月28日)
    • ReleaseNotes.htmlSoftwareContentRegister.html添加到GitHub仓库
    • 用Armen Hakobyan的CFolderDialog库替换了旧的CFileDialogST
  • 版本 1.26 (2024年2月21日):将MFC应用程序的主题切换回原生Windows。
  • 版本 1.27.1 (2024年3月31日)
    • LEXILLA库更新到5.3.1版本,将SCINTILLA库更新到5.4.3版本。
    • 将PJ Naughter的CScintillaCtrl库更新到最新可用版本。
      更新了类以支持 Scintilla v5.4.3。新封装的消息包括:SCI_GETUNDOACTIONSSCI_GETUNDOSAVEPOINTSCI_SETUNDODETACHSCI_SETUNDOTENTATIVESCI_SETUNDOCURRENTSCI_PUSHUNDOACTIONTYPESCI_CHANGELASTUNDOACTIONTEXTSCI_GETUNDOACTIONTYPESCI_GETUNDOACTIONPOSITIONSCI_GETUNDOACTIONTEXT
  • 版本 1.28 (2024年4月26日)
    • LEXILLA库更新到5.3.2版本,将SCINTILLA库更新到5.5.0版本。
    • 将PJ Naughter的CScintillaCtrl库更新到最新可用版本。
  • 版本 1.29 (2024年7月21日)
    • 为C/C++编程语言实现了“查看文本文件”功能。
    • 实现了按特定搜索模式、大小、日期或内容选择文件。
    • 实现了增强的搜索功能,包括全文搜索和替换。
  • 版本 1.30 (2024年7月26日)
    • 为HTML / CSS / XML / JavaScript实现了“查看文本文件”功能。
    • 为Java编程语言实现了“查看文本文件”功能。
    • 为Python编程语言实现了“查看文本文件”功能。
    • LEXILLA库更新到5.3.3版本,将SCINTILLA库更新到5.5.1版本。
    • 将PJ Naughter的CScintillaCtrl库更新到最新可用版本。
      更新类以支持Scintilla v5.5.1。新增的包装消息包括:SCI_AUTOCSETSTYLESCI_AUTOCGETSTYLESCI_CUTALLOWLINE
  • 版本 1.31 (2024年8月24日)
    • LEXILLA库更新到5.4.0版本,将SCINTILLA库更新到5.5.2版本。
    • 将PJ Naughter的CScintillaCtrl库更新到最新可用版本。
      更新了类以支持 Scintilla v5.5.2。新封装的消息包括:SCI_STYLESETSTRETCHSCI_STYLEGETSTRETCHSCI_GETUNDOSEQUENCESCI_LINEINDENTSCI_LINEDEDENTSCI_SETCOPYSEPARATORSCI_GETCOPYSEPARATOR
  • 版本 1.32 (2024年9月3日)
    • 为以下编程语言启用了语法高亮显示:
      • Bash
      • 批处理
      • CMake
      • Groovy
      • JavaScript
      • JSON
      • Makefile
      • MATLAB
      • R
      • Rust
    • 在帮助菜单中添加了用户手册选项。
    • 在帮助菜单中添加了检查更新…选项。
  • 版本 1.33 (2024年9月14日):使用Jovibor的HexCtrl库实现了“查看二进制文件”功能。
  • 版本 1.34 (2024年10月11日)
    • 修复了对Google Drive的访问问题(由simon mago报告的bug)。
    • 修复了对收藏夹文件夹的访问问题(由markjuggles报告的bug)。
    • 修复了查看文本文件时可能导致崩溃的情况。
    • 为TCL/TK编程语言启用了语法高亮显示。
IntelliFile - Total Commander的替代Windows版本 - CodeProject - 代码之家
© . All rights reserved.