Compare commits

...

6 Commits

Binary file not shown.

@ -16,31 +16,31 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
//该cpp文件实现了处理崩溃的类MiniDumper.h
#include <shlwapi.h> #include <shlwapi.h>
#include "MiniDumper.h" #include "MiniDumper.h"
//消息标题
LPCTSTR msgTitle = TEXT("Notepad++ crash analysis"); LPCTSTR msgTitle = TEXT("Notepad++ crash analysis");
MiniDumper::MiniDumper() MiniDumper::MiniDumper()
{ {
} }
//写入崩溃转储的函数
bool MiniDumper::writeDump(EXCEPTION_POINTERS * pExceptionInfo) bool MiniDumper::writeDump(EXCEPTION_POINTERS * pExceptionInfo)
{ {
TCHAR szDumpPath[MAX_PATH]; TCHAR szDumpPath[MAX_PATH];
TCHAR szScratch[MAX_PATH]; TCHAR szScratch[MAX_PATH];
LPCTSTR szResult = NULL; LPCTSTR szResult = NULL;
bool retval = false; bool retval = false;
//加载动态链接库
HMODULE hDll = ::LoadLibraryEx(TEXT("DBGHELP.DLL"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); //that wont work on older windows version than XP, #care :) HMODULE hDll = ::LoadLibraryEx(TEXT("DBGHELP.DLL"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); //that wont work on older windows version than XP, #care :)
if (hDll) if (hDll)
{ {
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" ); MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
if (pDump) if (pDump)
{ {//获取当前模块的文件路径
::GetModuleFileName(NULL, szDumpPath, MAX_PATH); ::GetModuleFileName(NULL, szDumpPath, MAX_PATH);
::PathRemoveFileSpec(szDumpPath); ::PathRemoveFileSpec(szDumpPath);
wcscat_s(szDumpPath, TEXT("\\NppDump.dmp")); wcscat_s(szDumpPath, TEXT("\\NppDump.dmp"));
@ -93,7 +93,7 @@ bool MiniDumper::writeDump(EXCEPTION_POINTERS * pExceptionInfo)
{ {
szResult = TEXT("Unable to load the debugging DLL,\r\nfind a recent copy of dbghelp.dll and install it."); szResult = TEXT("Unable to load the debugging DLL,\r\nfind a recent copy of dbghelp.dll and install it.");
} }
//弹出消息框显示结果
if (szResult) if (szResult)
::MessageBox(NULL, szResult, msgTitle, MB_OK); ::MessageBox(NULL, szResult, msgTitle, MB_OK);

@ -25,7 +25,7 @@
bool DocTabView::_hideTabBarStatus = false; bool DocTabView::_hideTabBarStatus = false;
//向标签视图添加新的缓冲区,首先检查缓冲区是否有效(不是无效的缓冲区),然后检查是否已经存在相同的缓冲区。如果缓冲区有效且尚未存在,则将其添加到标签页视图中,并更新父窗口的大小。
void DocTabView::addBuffer(BufferID buffer) void DocTabView::addBuffer(BufferID buffer)
{ {
if (buffer == BUFFER_INVALID) //valid only if (buffer == BUFFER_INVALID) //valid only
@ -48,25 +48,25 @@ void DocTabView::addBuffer(BufferID buffer)
::SendMessage(_hParent, WM_SIZE, 0, 0); ::SendMessage(_hParent, WM_SIZE, 0, 0);
} }
//关闭指定的缓冲区,到要关闭的缓冲区的索引,然后从标签页视图中删除它,并通知父窗口进行调整。
void DocTabView::closeBuffer(BufferID buffer) void DocTabView::closeBuffer(BufferID buffer)
{ {
int indexToClose = getIndexByBuffer(buffer); int indexToClose = getIndexByBuffer(buffer);
deletItemAt((size_t)indexToClose); deletItemAt((size_t)indexToClose);
::SendMessage(_hParent, WM_SIZE, 0, 0); ::SendMessage(_hParent, WM_SIZE, 0, 0);
} }
//为特定的标签设置颜色。根据提供的缓冲区ID设置该缓冲区在标签页中的颜色。
void DocTabView::setIndividualTabColour(BufferID bufferId, int colorId) void DocTabView::setIndividualTabColour(BufferID bufferId, int colorId)
{ {
bufferId->setDocColorId(colorId); bufferId->setDocColorId(colorId);
} }
//获取特定标签的颜色,根据提供的标签索引,返回该标签的颜色。
int DocTabView::getIndividualTabColour(int tabIndex) int DocTabView::getIndividualTabColour(int tabIndex)
{ {
BufferID bufferId = getBufferByIndex(tabIndex); BufferID bufferId = getBufferByIndex(tabIndex);
return bufferId->getDocColorId(); return bufferId->getDocColorId();
} }
//激活特定的缓冲区通过缓冲区的ID找到其索引位置并尝试激活该缓冲区如果成功则返回true否则返回false。
bool DocTabView::activateBuffer(BufferID buffer) bool DocTabView::activateBuffer(BufferID buffer)
{ {
int indexToActivate = getIndexByBuffer(buffer); int indexToActivate = getIndexByBuffer(buffer);
@ -77,14 +77,14 @@ bool DocTabView::activateBuffer(BufferID buffer)
return true; return true;
} }
//获取当前激活的缓冲区。
BufferID DocTabView::activeBuffer() BufferID DocTabView::activeBuffer()
{ {
int index = getCurrentTabIndex(); int index = getCurrentTabIndex();
return getBufferByIndex(index); return getBufferByIndex(index);
} }
//遍历所有标签页根据文件名查找匹配的缓冲区找到则返回其ID否则返回BUFFER_INVALID。
BufferID DocTabView::findBufferByName(const TCHAR * fullfilename) //-1 if not found, something else otherwise BufferID DocTabView::findBufferByName(const TCHAR * fullfilename) //-1 if not found, something else otherwise
{ {
TCITEM tie{}; TCITEM tie{};
@ -103,7 +103,7 @@ BufferID DocTabView::findBufferByName(const TCHAR * fullfilename) //-1 if not fo
return BUFFER_INVALID; return BUFFER_INVALID;
} }
//通过缓冲区ID找到其在标签中的索引位置如果不存在则返回 - 1。
int DocTabView::getIndexByBuffer(BufferID id) int DocTabView::getIndexByBuffer(BufferID id)
{ {
TCITEM tie{}; TCITEM tie{};
@ -118,7 +118,7 @@ int DocTabView::getIndexByBuffer(BufferID id)
return -1; return -1;
} }
//通过缓冲区ID找到其在标签中的索引位置如果不存在则返回-1。
BufferID DocTabView::getBufferByIndex(size_t index) BufferID DocTabView::getBufferByIndex(size_t index)
{ {
TCITEM tie{}; TCITEM tie{};
@ -129,7 +129,7 @@ BufferID DocTabView::getBufferByIndex(size_t index)
return reinterpret_cast<BufferID>(tie.lParam); return reinterpret_cast<BufferID>(tie.lParam);
} }
//根据mask中的标志位更新与缓冲区相关的信息例如文件名变化、只读状态变化等。
void DocTabView::bufferUpdated(Buffer * buffer, int mask) void DocTabView::bufferUpdated(Buffer * buffer, int mask)
{ {
int index = getIndexByBuffer(buffer->getID()); int index = getIndexByBuffer(buffer->getID());
@ -183,7 +183,7 @@ void DocTabView::bufferUpdated(Buffer * buffer, int mask)
*out = '\0'; *out = '\0';
} }
} }
::SendMessage(_hSelf, TCM_SETITEM, index, reinterpret_cast<LPARAM>(&tie)); ::SendMessage(_hSelf, TCM_SETITEM, index, reinterpret_cast<LPARAM>(&tie));
// send WM_SIZE only when change tab // send WM_SIZE only when change tab
@ -192,7 +192,7 @@ void DocTabView::bufferUpdated(Buffer * buffer, int mask)
::SendMessage(_hParent, WM_SIZE, 0, 0); ::SendMessage(_hParent, WM_SIZE, 0, 0);
} }
//根据给定的索引设置相应的缓冲区ID并更新标签显示的相关信息。
void DocTabView::setBuffer(size_t index, BufferID id) void DocTabView::setBuffer(size_t index, BufferID id)
{ {
if (index >= _nbItem) if (index >= _nbItem)
@ -208,7 +208,7 @@ void DocTabView::setBuffer(size_t index, BufferID id)
::SendMessage(_hParent, WM_SIZE, 0, 0); ::SendMessage(_hParent, WM_SIZE, 0, 0);
} }
//根据隐藏/显示标签栏状态,调整标签页视图和文本编辑器视图的大小,并根据需要发送消息以更新可点击链接。
void DocTabView::reSizeTo(RECT & rc) void DocTabView::reSizeTo(RECT & rc)
{ {
int borderWidth = ((NppParameters::getInstance()).getSVP())._borderWidth; int borderWidth = ((NppParameters::getInstance()).getSVP())._borderWidth;

@ -14,11 +14,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
//该类继承自TabBarPlus类。该类负责管理文档选项卡视图并提供一系列方法用于添加、关闭、激活缓冲区以及设置选项卡的个性化选项等功能。
#pragma once #pragma once
#include "TabBar.h" #include "TabBar.h"
#include "Buffer.h" #include "Buffer.h"
// 定义一些常量用作图片索引
const int SAVED_IMG_INDEX = 0; const int SAVED_IMG_INDEX = 0;
const int UNSAVED_IMG_INDEX = 1; const int UNSAVED_IMG_INDEX = 1;
const int REDONLY_IMG_INDEX = 2; const int REDONLY_IMG_INDEX = 2;
@ -33,7 +37,7 @@ public :
void destroy() override { void destroy() override {
TabBarPlus::destroy(); TabBarPlus::destroy();
}; };
//初始化函数传入实例句柄、父窗口句柄、ScintillaEditView指针、以及图片列表和选择的图片索引
void init(HINSTANCE hInst, HWND parent, ScintillaEditView * pView, std::vector<IconList *> pIconListVector, unsigned char indexChoice) { void init(HINSTANCE hInst, HWND parent, ScintillaEditView * pView, std::vector<IconList *> pIconListVector, unsigned char indexChoice) {
TabBarPlus::init(hInst, parent); TabBarPlus::init(hInst, parent);
_pView = pView; _pView = pView;
@ -52,45 +56,50 @@ public :
TabBar::setImageList(_pIconListVector[_iconListIndexChoice]->getHandle()); TabBar::setImageList(_pIconListVector[_iconListIndexChoice]->getHandle());
return; return;
}; };
// 改变选中的图片列表
void changeIcons(unsigned char choice) { void changeIcons(unsigned char choice) {
if (choice >= _pIconListVector.size()) if (choice >= _pIconListVector.size())
return; return;
_iconListIndexChoice = choice; _iconListIndexChoice = choice;
TabBar::setImageList(_pIconListVector[_iconListIndexChoice]->getHandle()); TabBar::setImageList(_pIconListVector[_iconListIndexChoice]->getHandle());
}; };
// 添加缓冲区
void addBuffer(BufferID buffer); void addBuffer(BufferID buffer);
// 关闭缓冲区
void closeBuffer(BufferID buffer); void closeBuffer(BufferID buffer);
// 缓冲区更新
void bufferUpdated(Buffer * buffer, int mask); void bufferUpdated(Buffer * buffer, int mask);
// 激活缓冲区
bool activateBuffer(BufferID buffer); bool activateBuffer(BufferID buffer);
// 获取当前激活的缓冲区
BufferID activeBuffer(); BufferID activeBuffer();
// 根据文件名查找缓冲区,返回索引值,如果未找到则返回-1
BufferID findBufferByName(const TCHAR * fullfilename); //-1 if not found, something else otherwise BufferID findBufferByName(const TCHAR * fullfilename); //-1 if not found, something else otherwise
// 根据缓冲区获取索引值
int getIndexByBuffer(BufferID id); int getIndexByBuffer(BufferID id);
// 根据索引值获取缓冲区
BufferID getBufferByIndex(size_t index); BufferID getBufferByIndex(size_t index);
// 设置指定索引位置的缓冲区
void setBuffer(size_t index, BufferID id); void setBuffer(size_t index, BufferID id);
// 静态函数,用于设置隐藏或显示选项卡栏的状态
static bool setHideTabBarStatus(bool hideOrNot) { static bool setHideTabBarStatus(bool hideOrNot) {
bool temp = _hideTabBarStatus; bool temp = _hideTabBarStatus;
_hideTabBarStatus = hideOrNot; _hideTabBarStatus = hideOrNot;
return temp; return temp;
}; };
// 静态函数,获取隐藏或显示选项卡栏的状态
static bool getHideTabBarStatus() { static bool getHideTabBarStatus() {
return _hideTabBarStatus; return _hideTabBarStatus;
}; };
// 重写父类的reSizeTo方法
void reSizeTo(RECT & rc) override; void reSizeTo(RECT & rc) override;
// 获取ScintillaEditView指针
const ScintillaEditView* getScintillaEditView() const { const ScintillaEditView* getScintillaEditView() const {
return _pView; return _pView;
}; };
// 设置指定缓冲区的个性化选项卡颜色
void setIndividualTabColour(BufferID bufferId, int colorId); void setIndividualTabColour(BufferID bufferId, int colorId);
// 获取指定索引位置的个性化选项卡颜色
int getIndividualTabColour(int tabIndex) override; int getIndividualTabColour(int tabIndex) override;
private : private :

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
//fileBrowser类的具体实现
#include "fileBrowser.h" #include "fileBrowser.h"
#include "resource.h" #include "resource.h"
#include "tinyxml.h" #include "tinyxml.h"
@ -41,7 +41,7 @@
#define FB_CMD_FOLDALL 2 #define FB_CMD_FOLDALL 2
#define FB_CMD_EXPANDALL 3 #define FB_CMD_EXPANDALL 3
//停止所有文件监视器
FileBrowser::~FileBrowser() FileBrowser::~FileBrowser()
{ {
for (const auto folder : _folderUpdaters) for (const auto folder : _folderUpdaters)
@ -55,7 +55,7 @@ FileBrowser::~FileBrowser()
delete cd; delete cd;
} }
} }
//将一个字符串分割成多个子字符串函数使用了for循环依次检查字符串中的每个字符当找到等于`sep`或者空字符的字符时,就把这之前的字符作为一个子字符串存储在`splitedStrings`向量中。
vector<generic_string> split(const generic_string & string2split, TCHAR sep) vector<generic_string> split(const generic_string & string2split, TCHAR sep)
{ {
vector<generic_string> splitedStrings; vector<generic_string> splitedStrings;
@ -71,7 +71,7 @@ vector<generic_string> split(const generic_string & string2split, TCHAR sep)
} }
return splitedStrings; return splitedStrings;
} }
//检查子文件夹是否与根文件相关
bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_string & subFolder) bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_string & subFolder)
{ {
if (relatedRoot.empty()) if (relatedRoot.empty())
@ -91,11 +91,11 @@ bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_strin
return relatedRootArray[index2Compare] == subFolderArray[index2Compare]; return relatedRootArray[index2Compare] == subFolderArray[index2Compare];
} }
//消息处理
intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{ {
switch (message) switch (message)
{ {//会话框初始化,包括创建工具条,树状视图的初始化等。
case WM_INITDIALOG : case WM_INITDIALOG :
{ {
NppParameters& nppParam = NppParameters::getInstance(); NppParameters& nppParam = NppParameters::getInstance();
@ -175,7 +175,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
return TRUE; return TRUE;
} }
//处理黑暗模式刷新的消息
case NPPM_INTERNAL_REFRESHDARKMODE: case NPPM_INTERNAL_REFRESHDARKMODE:
{ {
if (static_cast<BOOL>(lParam) != TRUE) if (static_cast<BOOL>(lParam) != TRUE)
@ -185,7 +185,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
NppDarkMode::setTreeViewStyle(_treeView.getHSelf()); NppDarkMode::setTreeViewStyle(_treeView.getHSelf());
return TRUE; return TRUE;
} }
//鼠标消息
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if (_treeView.isDragging()) if (_treeView.isDragging())
_treeView.dragItem(_hSelf, LOWORD(lParam), HIWORD(lParam)); _treeView.dragItem(_hSelf, LOWORD(lParam), HIWORD(lParam));
@ -197,13 +197,13 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
} }
break; break;
//通知消息
case WM_NOTIFY: case WM_NOTIFY:
{ {
notified((LPNMHDR)lParam); notified((LPNMHDR)lParam);
} }
return TRUE; return TRUE;
//得到窗体的新宽度和高度,然后调整工具条和树形视图的位置和大小。
case WM_SIZE: case WM_SIZE:
{ {
int width = LOWORD(lParam); int width = LOWORD(lParam);
@ -220,28 +220,28 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
::MoveWindow(hwnd, 0, toolbarMenuRect.bottom + extraValue, width, height - toolbarMenuRect.bottom - extraValue, TRUE); ::MoveWindow(hwnd, 0, toolbarMenuRect.bottom + extraValue, width, height - toolbarMenuRect.bottom - extraValue, TRUE);
break; break;
} }
//文本菜单
case WM_CONTEXTMENU: case WM_CONTEXTMENU:
if (!_treeView.isDragging()) if (!_treeView.isDragging())
showContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); showContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return TRUE; return TRUE;
//来自菜单的选择
case WM_COMMAND: case WM_COMMAND:
{ {
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {//选择当前正在编辑的文件。
case FB_CMD_AIMFILE: case FB_CMD_AIMFILE:
{ {
selectCurrentEditingFile(); selectCurrentEditingFile();
break; break;
} }
//折叠
case FB_CMD_FOLDALL: case FB_CMD_FOLDALL:
{ {
_treeView.foldAll(); _treeView.foldAll();
break; break;
} }
//展开
case FB_CMD_EXPANDALL: case FB_CMD_EXPANDALL:
{ {
_treeView.expandAll(); _treeView.expandAll();
@ -253,7 +253,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
} }
break; break;
} }
//销毁
case WM_DESTROY: case WM_DESTROY:
{ {
::DestroyWindow(_hToolbarMenu); ::DestroyWindow(_hToolbarMenu);
@ -261,7 +261,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
destroyMenus(); destroyMenus();
break; break;
} }
//添加
case FB_ADDFILE: case FB_ADDFILE:
{ {
@ -274,7 +274,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
break; break;
} }
//移除
case FB_RMFILE: case FB_RMFILE:
{ {
@ -287,7 +287,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
break; break;
} }
//重命名
case FB_RNFILE: case FB_RNFILE:
{ {
const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam; const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam;
@ -324,7 +324,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
} }
return DockingDlgInterface::run_dlgProc(message, wParam, lParam); return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
} }
//创建一个文件浏览器的时候,初始化弹出菜单。首先收集各种与菜单项相关的字符串,然后创建三种不同的菜单:全局菜单、根菜单、文件夹菜单和文件菜单,向这些菜单中插入各种菜单项。
void FileBrowser::initPopupMenus() void FileBrowser::initPopupMenus()
{ {
NativeLangSpeaker* pNativeSpeaker = NppParameters::getInstance().getNativeLangSpeaker(); NativeLangSpeaker* pNativeSpeaker = NppParameters::getInstance().getNativeLangSpeaker();
@ -370,7 +370,7 @@ void FileBrowser::initPopupMenus()
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, explorerHere.c_str()); ::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, explorerHere.c_str());
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, cmdHere.c_str()); ::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, cmdHere.c_str());
} }
//通过一个给定的路径选中文件浏览器中的一个项目。它首先检查路径是否为空,然后通过遍历所有的文件夹来寻找对应的项目。
bool FileBrowser::selectItemFromPath(const generic_string& itemPath) const bool FileBrowser::selectItemFromPath(const generic_string& itemPath) const
{ {
if (itemPath.empty()) if (itemPath.empty())
@ -409,7 +409,7 @@ bool FileBrowser::selectItemFromPath(const generic_string& itemPath) const
} }
return false; return false;
} }
//选择当前正在编辑的文件。
bool FileBrowser::selectCurrentEditingFile() const bool FileBrowser::selectCurrentEditingFile() const
{ {
TCHAR currentDocPath[MAX_PATH] = { '\0' }; TCHAR currentDocPath[MAX_PATH] = { '\0' };
@ -418,7 +418,7 @@ bool FileBrowser::selectCurrentEditingFile() const
return selectItemFromPath(currentDocPathStr); return selectItemFromPath(currentDocPathStr);
} }
//摧毁创建的菜单
void FileBrowser::destroyMenus() void FileBrowser::destroyMenus()
{ {
::DestroyMenu(_hGlobalMenu); ::DestroyMenu(_hGlobalMenu);
@ -426,7 +426,7 @@ void FileBrowser::destroyMenus()
::DestroyMenu(_hFolderMenu); ::DestroyMenu(_hFolderMenu);
::DestroyMenu(_hFileMenu); ::DestroyMenu(_hFileMenu);
} }
//返回一个给定节点的完整路径。
generic_string FileBrowser::getNodePath(HTREEITEM node) const generic_string FileBrowser::getNodePath(HTREEITEM node) const
{ {
if (!node) return TEXT(""); if (!node) return TEXT("");
@ -460,12 +460,12 @@ generic_string FileBrowser::getNodePath(HTREEITEM node) const
return fullPath; return fullPath;
} }
//返回一个给定节点的名称。
generic_string FileBrowser::getNodeName(HTREEITEM node) const generic_string FileBrowser::getNodeName(HTREEITEM node) const
{ {
return node ? _treeView.getItemDisplayName(node) : TEXT(""); return node ? _treeView.getItemDisplayName(node) : TEXT("");
} }
//打开选定的文件。如果选定的项目是一个文件,那么就打开它;否则,不执行任何操作。
void FileBrowser::openSelectFile() void FileBrowser::openSelectFile()
{ {
// Get the selected item // Get the selected item
@ -483,7 +483,7 @@ void FileBrowser::openSelectFile()
::PostMessage(_hParent, NPPM_DOOPEN, 0, reinterpret_cast<LPARAM>(_selectedNodeFullPath.c_str())); ::PostMessage(_hParent, NPPM_DOOPEN, 0, reinterpret_cast<LPARAM>(_selectedNodeFullPath.c_str()));
} }
//处理各种菜单操作的事件。例如,如果一个菜单项被双击,那么就调用函数进行对应的处理;如果一个节点标签被编辑,那么函数就保存新的标签。
void FileBrowser::notified(LPNMHDR notification) void FileBrowser::notified(LPNMHDR notification)
{ {
if (notification->code == DMN_CLOSE) if (notification->code == DMN_CLOSE)
@ -673,7 +673,7 @@ void FileBrowser::notified(LPNMHDR notification)
} }
} }
} }
//获取给定项目(`hItem`)的节点类型。函数首先获取项目的索引(`iImage`),如果索引为`INDEX_LEAF`,则节点类型为文件;如果项目的参数(`lParam`)不为空并且`SortingData4lParam`类中`_rootPath`成员不为空,那么节点类型为根;否则,节点类型为文件夹。
BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem) BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem)
{ {
TVITEM tvItem; TVITEM tvItem;
@ -697,7 +697,7 @@ BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem)
return browserNodeType_folder; return browserNodeType_folder;
} }
} }
//(x, y)位置显示上下文菜单。函数首先检测给定位置是否在一个元素上,如果是的话就选中该元素,并获取该元素的节点类型,然后根据节点类型显示相应的上下文菜单。
void FileBrowser::showContextMenu(int x, int y) void FileBrowser::showContextMenu(int x, int y)
{ {
TVHITTESTINFO tvHitInfo{}; TVHITTESTINFO tvHitInfo{};
@ -735,7 +735,7 @@ void FileBrowser::showContextMenu(int x, int y)
x, y, 0, _hSelf, NULL); x, y, 0, _hSelf, NULL);
} }
} }
//执行与给定命令ID(`cmdID`)关联的上下文菜单命令。例如如果命令ID为`IDM_FILEBROWSER_REMOVEROOTFOLDER`,则函数将删除选定的根文件夹。
void FileBrowser::popupMenuCmd(int cmdID) void FileBrowser::popupMenuCmd(int cmdID)
{ {
// get selected item handle // get selected item handle
@ -872,7 +872,7 @@ void FileBrowser::popupMenuCmd(int cmdID)
} }
//在目录`dir`中获取符合`patterns`模式的所有文件和子目录的结构信息,并将其保存到`directoryStructure`中。`isRecursive`参数指定是否递归遍历子目录,`isInHiddenDir`参数指示当前目录是否为隐藏目录。
void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir) void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir)
{ {
if (directoryStructure._parent == nullptr) // Root! if (directoryStructure._parent == nullptr) // Root!
@ -954,12 +954,13 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
} }
::FindClose(hFile); ::FindClose(hFile);
} }
//添加根文件夹
void FileBrowser::addRootFolder(generic_string rootFolderPath) void FileBrowser::addRootFolder(generic_string rootFolderPath)
{ {//检查根文件夹路径是否存在
if (!::PathFileExists(rootFolderPath.c_str())) if (!::PathFileExists(rootFolderPath.c_str()))
return; return;
// 检查根文件夹路径是否是一个目录
if (!::PathIsDirectory(rootFolderPath.c_str())) if (!::PathIsDirectory(rootFolderPath.c_str()))
return; return;
@ -968,13 +969,13 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
{ {
rootFolderPath = rootFolderPath.substr(0, rootFolderPath.length() - 1); rootFolderPath = rootFolderPath.substr(0, rootFolderPath.length() - 1);
} }
// 遍历已添加的根文件夹更新器
for (const auto f : _folderUpdaters) for (const auto f : _folderUpdaters)
{ { // 检查是否已经添加相同路径的根文件夹
if (f->_rootFolder._rootPath == rootFolderPath) if (f->_rootFolder._rootPath == rootFolderPath)
return; return;
else else
{ { // 检查是否存在相关的根文件夹,以便选择目录
if (isRelatedRootFolder(f->_rootFolder._rootPath, rootFolderPath)) if (isRelatedRootFolder(f->_rootFolder._rootPath, rootFolderPath))
{ {
//do nothing, go down to select the dir //do nothing, go down to select the dir
@ -987,9 +988,9 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
_treeView.selectItem(foundItem); _treeView.selectItem(foundItem);
return; return;
} }
// 检查是否存在相对于要添加的根文件夹的子文件夹
if (isRelatedRootFolder(rootFolderPath, f->_rootFolder._rootPath)) if (isRelatedRootFolder(rootFolderPath, f->_rootFolder._rootPath))
{ {// 显示消息框,指示存在子文件夹,需要先移除
NppParameters::getInstance().getNativeLangSpeaker()->messageBox("FolderAsWorspaceSubfolderExists", NppParameters::getInstance().getNativeLangSpeaker()->messageBox("FolderAsWorspaceSubfolderExists",
_hParent, _hParent,
TEXT("A sub-folder of the folder you want to add exists.\rPlease remove its root from the panel before you add folder \"$STR_REPLACE$\"."), TEXT("A sub-folder of the folder you want to add exists.\rPlease remove its root from the panel before you add folder \"$STR_REPLACE$\"."),
@ -1001,10 +1002,10 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
} }
} }
} }
// 设置要匹配的文件模式
std::vector<generic_string> patterns2Match; std::vector<generic_string> patterns2Match;
patterns2Match.push_back(TEXT("*.*")); patterns2Match.push_back(TEXT("*.*"));
// 获取根文件夹的名称并创建相应的文件夹信息对象
TCHAR *label = ::PathFindFileName(rootFolderPath.c_str()); TCHAR *label = ::PathFindFileName(rootFolderPath.c_str());
TCHAR rootLabel[MAX_PATH] = {'\0'}; TCHAR rootLabel[MAX_PATH] = {'\0'};
wcscpy_s(rootLabel, label); wcscpy_s(rootLabel, label);
@ -1019,10 +1020,11 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
_folderUpdaters.push_back(new FolderUpdater(directoryStructure, this)); _folderUpdaters.push_back(new FolderUpdater(directoryStructure, this));
_folderUpdaters[_folderUpdaters.size() - 1]->startWatcher(); _folderUpdaters[_folderUpdaters.size() - 1]->startWatcher();
} }
//创建文件夹项目从目录结构
HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, const FolderInfo & directoryStructure) HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, const FolderInfo & directoryStructure)
{ {
HTREEITEM hFolderItem = nullptr; HTREEITEM hFolderItem = nullptr;
// 如果是根目录,则创建根节点
if (directoryStructure._parent == nullptr && hParentItem == nullptr) if (directoryStructure._parent == nullptr && hParentItem == nullptr)
{ {
TCHAR rootPath[MAX_PATH] = { '\0' }; TCHAR rootPath[MAX_PATH] = { '\0' };
@ -1033,14 +1035,14 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
SortingData4lParam* customData = new SortingData4lParam(rootPath, TEXT(""), true); SortingData4lParam* customData = new SortingData4lParam(rootPath, TEXT(""), true);
sortingDataArray.push_back(customData); sortingDataArray.push_back(customData);
// 添加根节点到树视图
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), TVI_ROOT, INDEX_CLOSE_ROOT, reinterpret_cast<LPARAM>(customData)); hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), TVI_ROOT, INDEX_CLOSE_ROOT, reinterpret_cast<LPARAM>(customData));
} }
else else
{ {
SortingData4lParam* customData = new SortingData4lParam(TEXT(""), directoryStructure._name, true); SortingData4lParam* customData = new SortingData4lParam(TEXT(""), directoryStructure._name, true);
sortingDataArray.push_back(customData); sortingDataArray.push_back(customData);
// 添加节点到树视图
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), hParentItem, INDEX_CLOSE_NODE, reinterpret_cast<LPARAM>(customData)); hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), hParentItem, INDEX_CLOSE_NODE, reinterpret_cast<LPARAM>(customData));
} }
@ -1053,7 +1055,7 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
{ {
SortingData4lParam* customData = new SortingData4lParam(TEXT(""), file._name, false); SortingData4lParam* customData = new SortingData4lParam(TEXT(""), file._name, false);
sortingDataArray.push_back(customData); sortingDataArray.push_back(customData);
// 添加文件节点到树视图
_treeView.addItem(file._name.c_str(), hFolderItem, INDEX_LEAF, reinterpret_cast<LPARAM>(customData)); _treeView.addItem(file._name.c_str(), hFolderItem, INDEX_LEAF, reinterpret_cast<LPARAM>(customData));
} }
@ -1061,7 +1063,7 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
return hFolderItem; return hFolderItem;
} }
//根据路径找到根目录
HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) const HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) const
{ {
HTREEITEM node = nullptr; HTREEITEM node = nullptr;
@ -1080,7 +1082,7 @@ HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) cons
} }
return node; return node;
} }
//在指定父节点下查找具有特定名称的子节点。
HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, const generic_string& label) const HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, const generic_string& label) const
{ {
for (HTREEITEM hItemNode = _treeView.getChildFrom(parent); for (HTREEITEM hItemNode = _treeView.getChildFrom(parent);
@ -1102,7 +1104,7 @@ HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, const generic_str
} }
return nullptr; return nullptr;
} }
//得到所有根节点的路径
vector<generic_string> FileBrowser::getRoots() const vector<generic_string> FileBrowser::getRoots() const
{ {
vector<generic_string> roots; vector<generic_string> roots;
@ -1121,7 +1123,7 @@ vector<generic_string> FileBrowser::getRoots() const
} }
return roots; return roots;
} }
//获取选中文件的路径
generic_string FileBrowser::getSelectedItemPath() const generic_string FileBrowser::getSelectedItemPath() const
{ {
generic_string itemPath; generic_string itemPath;
@ -1132,7 +1134,7 @@ generic_string FileBrowser::getSelectedItemPath() const
} }
return itemPath; return itemPath;
} }
//将传递的文件路径信息分组,按照共同路径和根路径进行分类。
std::vector<FileBrowser::FilesToChange> FileBrowser::getFilesFromParam(LPARAM lParam) const std::vector<FileBrowser::FilesToChange> FileBrowser::getFilesFromParam(LPARAM lParam) const
{ {
const std::vector<generic_string> filesToChange = *(std::vector<generic_string>*)lParam; const std::vector<generic_string> filesToChange = *(std::vector<generic_string>*)lParam;
@ -1189,7 +1191,7 @@ std::vector<FileBrowser::FilesToChange> FileBrowser::getFilesFromParam(LPARAM lP
return groupedFiles; return groupedFiles;
} }
//将文件组添加到树中,根据文件类型在树中创建相应的节点。
bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node) bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node)
{ {
if (node == nullptr) // it's a root. Search the right root with rootPath if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1266,7 +1268,7 @@ bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node)
} }
} }
//在树中查找并删除指定的文件组。
bool FileBrowser::deleteFromTree(FilesToChange & group) bool FileBrowser::deleteFromTree(FilesToChange & group)
{ {
std::vector<HTREEITEM> foundItems = findInTree(group, nullptr); std::vector<HTREEITEM> foundItems = findInTree(group, nullptr);
@ -1283,7 +1285,7 @@ bool FileBrowser::deleteFromTree(FilesToChange & group)
return true; return true;
} }
//在树形结构中查找指定路径,首先判断当前节点是否为根节点,若是则根据根路径查找对应的根节点。然后根据路径数组的大小,判断是否继续查找子节点或者返回当前节点。
HTREEITEM FileBrowser::findInTree(const generic_string& rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray) const HTREEITEM FileBrowser::findInTree(const generic_string& rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray) const
{ {
if (node == nullptr) // it's a root. Search the right root with rootPath if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1326,7 +1328,7 @@ HTREEITEM FileBrowser::findInTree(const generic_string& rootPath, HTREEITEM node
return nullptr; return nullptr;
} }
} }
//该函数也用于在树形结构中查找指定路径但参数不同。参数group是一个包含文件信息和路径的对象node表示当前节点。函数首先判断当前节点是否为根节点若是则根据路径信息查找对应的根节点。然后根据路径信息的大小判断是否继续查找子节点或者返回找到的节点集合。
std::vector<HTREEITEM> FileBrowser::findInTree(FilesToChange & group, HTREEITEM node) const std::vector<HTREEITEM> FileBrowser::findInTree(FilesToChange & group, HTREEITEM node) const
{ {
if (node == nullptr) // it's a root. Search the right root with rootPath if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1367,7 +1369,7 @@ std::vector<HTREEITEM> FileBrowser::findInTree(FilesToChange & group, HTREEITEM
return {}; return {};
} }
} }
//找到指定父节点的子节点
std::vector<HTREEITEM> FileBrowser::findChildNodesFromNames(HTREEITEM parent, std::vector<generic_string> & labels) const std::vector<HTREEITEM> FileBrowser::findChildNodesFromNames(HTREEITEM parent, std::vector<generic_string> & labels) const
{ {
std::vector<HTREEITEM> itemNodes; std::vector<HTREEITEM> itemNodes;
@ -1394,6 +1396,7 @@ std::vector<HTREEITEM> FileBrowser::findChildNodesFromNames(HTREEITEM parent, st
} }
return itemNodes; return itemNodes;
} }
//移除已经在父节点中的名字。它遍历父节点的所有子节点,并将与给定标签集合中名字相匹配的标签清除。
void FileBrowser::removeNamesAlreadyInNode(HTREEITEM parent, std::vector<generic_string> & labels) const void FileBrowser::removeNamesAlreadyInNode(HTREEITEM parent, std::vector<generic_string> & labels) const
{ {
@ -1418,7 +1421,7 @@ void FileBrowser::removeNamesAlreadyInNode(HTREEITEM parent, std::vector<generic
} }
} }
} }
//在树形结构中重命名节点,找到匹配给定线性路径数组的节点,并将其重新命名为指定的字符串。
bool FileBrowser::renameInTree(const generic_string& rootPath, HTREEITEM node, const std::vector<generic_string>& linarPathArrayFrom, const generic_string & renameTo) bool FileBrowser::renameInTree(const generic_string& rootPath, HTREEITEM node, const std::vector<generic_string>& linarPathArrayFrom, const generic_string & renameTo)
{ {
HTREEITEM foundItem = findInTree(rootPath, node, linarPathArrayFrom); HTREEITEM foundItem = findInTree(rootPath, node, linarPathArrayFrom);
@ -1433,7 +1436,7 @@ bool FileBrowser::renameInTree(const generic_string& rootPath, HTREEITEM node, c
return true; return true;
} }
//排序回调函数,按照文件夹和文件名进行排序。首先是文件夹,然后是文件。如果两者都是文件夹或文件,那么比较它们的名字。
int CALLBACK FileBrowser::categorySortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM /*lParamSort*/) int CALLBACK FileBrowser::categorySortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM /*lParamSort*/)
{ {
SortingData4lParam* item1 = reinterpret_cast<SortingData4lParam*>(lParam1); SortingData4lParam* item1 = reinterpret_cast<SortingData4lParam*>(lParam1);
@ -1449,7 +1452,7 @@ int CALLBACK FileBrowser::categorySortFunc(LPARAM lParam1, LPARAM lParam2, LPARA
else else
return lstrcmpi(item1->_label.c_str(), item2->_label.c_str()); return lstrcmpi(item1->_label.c_str(), item2->_label.c_str());
} }
//将给定的完整路径添加到文件夹信息结构中。该路径可能是文件或目录如果该路径已经存在于结构中则返回false如果成功添加则返回true。
bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray) bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray)
{ {
if (linarPathArray.size() == 1) // could be file or folder if (linarPathArray.size() == 1) // could be file or folder
@ -1494,7 +1497,7 @@ bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_s
return false; return false;
} }
} }
//从文件夹信息结构中删除给定的线性路径数组。成功删除返回true否则返回false。
bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray) bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
{ {
if (linarPathArray.size() == 1) // could be file or folder if (linarPathArray.size() == 1) // could be file or folder
@ -1532,7 +1535,7 @@ bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
} }
return false; return false;
} }
//在文件夹信息结构中重命名给定的线性路径。它将 "linarPathArrayFrom" 指定的路径的名字更改为 "linarPathArrayTo" 指定的名字。
bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo) bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo)
{ {
if (linarPathArrayFrom.size() == 1) // could be file or folder if (linarPathArrayFrom.size() == 1) // could be file or folder
@ -1572,6 +1575,7 @@ bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFro
return false; return false;
} }
} }
//打开监视器,创建一个事件对象并开启一个新的线程,线程开始运行 `watching` 函数。
void FolderUpdater::startWatcher() void FolderUpdater::startWatcher()
{ {
@ -1579,6 +1583,7 @@ void FolderUpdater::startWatcher()
_EventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); _EventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
_watchThreadHandle = ::CreateThread(NULL, 0, watching, this, 0, NULL); _watchThreadHandle = ::CreateThread(NULL, 0, watching, this, 0, NULL);
} }
//停止监视器。它通过设定事件和关闭对应的线程实现。
void FolderUpdater::stopWatcher() void FolderUpdater::stopWatcher()
{ {
@ -1586,6 +1591,7 @@ void FolderUpdater::stopWatcher()
::CloseHandle(_watchThreadHandle); ::CloseHandle(_watchThreadHandle);
::CloseHandle(_EventHandle); ::CloseHandle(_EventHandle);
} }
//根据动作类型的代码返回相应的动作名字。
LPCWSTR explainAction(DWORD dwAction) LPCWSTR explainAction(DWORD dwAction)
{ {
@ -1606,6 +1612,7 @@ LPCWSTR explainAction(DWORD dwAction)
} }
} }
//负责监视目录下的文件变化。当有文件被创建、删除、重命名等操作时,就会将这个改动放入改动队列,并通过事件提醒主线程进行处理。
DWORD WINAPI FolderUpdater::watching(void *params) DWORD WINAPI FolderUpdater::watching(void *params)
{ {
@ -1704,6 +1711,7 @@ DWORD WINAPI FolderUpdater::watching(void *params)
//printStr(L"Quit watching thread"); //printStr(L"Quit watching thread");
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
//根据改动的类型,调用不同的文件浏览器的方法,例如文件创建、删除、重命名等。
void FolderUpdater::processChange(DWORD dwAction, std::vector<generic_string> filesToChange, FolderUpdater* thisFolderUpdater) void FolderUpdater::processChange(DWORD dwAction, std::vector<generic_string> filesToChange, FolderUpdater* thisFolderUpdater)
{ {

@ -13,7 +13,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
//处理工具栏按钮
#include <stdexcept> #include <stdexcept>
#include "TabBar.h" #include "TabBar.h"
#include "Parameters.h" #include "Parameters.h"
@ -40,7 +40,7 @@ COLORREF TabBarPlus::_inactiveBgColour = RGB(192, 192, 192);
HWND TabBarPlus::_hwndArray[nbCtrlMax] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; HWND TabBarPlus::_hwndArray[nbCtrlMax] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
int TabBarPlus::_nbCtrl = 0; int TabBarPlus::_nbCtrl = 0;
//初始化标签栏,创建窗口
void TabBar::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLine) void TabBar::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLine)
{ {
Window::init(hInst, parent); Window::init(hInst, parent);
@ -49,7 +49,7 @@ void TabBar::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLin
_isVertical = isVertical; _isVertical = isVertical;
_isMultiLine = isMultiLine; _isMultiLine = isMultiLine;
INITCOMMONCONTROLSEX icce{}; INITCOMMONCONTROLSEX icce{};//初始化通用控件库
icce.dwSize = sizeof(icce); icce.dwSize = sizeof(icce);
icce.dwICC = ICC_TAB_CLASSES; icce.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icce); InitCommonControlsEx(&icce);
@ -75,27 +75,27 @@ void TabBar::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLin
} }
} }
//清理与TabBar相关的资源
void TabBar::destroy() void TabBar::destroy()
{ {
if (_hFont) if (_hFont)
{ {
::DeleteObject(_hFont); ::DeleteObject(_hFont);
_hFont = nullptr; _hFont = nullptr;
} }//删除字体对象
if (_hLargeFont) if (_hLargeFont)
{ {
::DeleteObject(_hLargeFont); ::DeleteObject(_hLargeFont);
_hLargeFont = nullptr; _hLargeFont = nullptr;
} }//删除字体大小格式
if (_hVerticalFont) if (_hVerticalFont)
{ {
::DeleteObject(_hVerticalFont); ::DeleteObject(_hVerticalFont);
_hVerticalFont = nullptr; _hVerticalFont = nullptr;
} }
//删除垂直字体对象
if (_hVerticalLargeFont) if (_hVerticalLargeFont)
{ {
::DeleteObject(_hVerticalLargeFont); ::DeleteObject(_hVerticalLargeFont);
@ -106,13 +106,13 @@ void TabBar::destroy()
_hSelf = nullptr; _hSelf = nullptr;
} }
//在TabBar末尾插入一个新的选项卡并设置名称。使用TCITEM结构设置选项卡的属性并发送消息将选项卡插入TabBar中
int TabBar::insertAtEnd(const TCHAR *subTabName) int TabBar::insertAtEnd(const TCHAR *subTabName)
{ {
TCITEM tie{}; TCITEM tie{};
tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.mask = TCIF_TEXT | TCIF_IMAGE;
int index = -1; int index = -1;
//如果存在图像列表那么新TabItem应该被放置在列表的开始。
if (_hasImgLst) if (_hasImgLst)
index = 0; index = 0;
tie.iImage = index; tie.iImage = index;
@ -120,7 +120,7 @@ int TabBar::insertAtEnd(const TCHAR *subTabName)
return int(::SendMessage(_hSelf, TCM_INSERTITEM, _nbItem++, reinterpret_cast<LPARAM>(&tie))); return int(::SendMessage(_hSelf, TCM_INSERTITEM, _nbItem++, reinterpret_cast<LPARAM>(&tie)));
} }
//获取当前选定选项卡的标题。
void TabBar::getCurrentTitle(TCHAR *title, int titleLen) void TabBar::getCurrentTitle(TCHAR *title, int titleLen)
{ {
TCITEM tci{}; TCITEM tci{};
@ -130,7 +130,7 @@ void TabBar::getCurrentTitle(TCHAR *title, int titleLen)
::SendMessage(_hSelf, TCM_GETITEM, getCurrentTabIndex(), reinterpret_cast<LPARAM>(&tci)); ::SendMessage(_hSelf, TCM_GETITEM, getCurrentTabIndex(), reinterpret_cast<LPARAM>(&tci));
} }
//为TabBar中的选项卡设置字体。根据提供的参数创建新字体并发送消息为TabBar设置该字体
void TabBar::setFont(const TCHAR *fontName, int fontSize) void TabBar::setFont(const TCHAR *fontName, int fontSize)
{ {
if (_hFont) if (_hFont)
@ -147,7 +147,7 @@ void TabBar::setFont(const TCHAR *fontName, int fontSize)
::SendMessage(_hSelf, WM_SETFONT, reinterpret_cast<WPARAM>(_hFont), 0); ::SendMessage(_hSelf, WM_SETFONT, reinterpret_cast<WPARAM>(_hFont), 0);
} }
//激活指定索引处的选项卡。发送消息以确保在TabBar中激活指定索引处的选项卡。
void TabBar::activateAt(int index) const void TabBar::activateAt(int index) const
{ {
if (getCurrentTabIndex() != index) if (getCurrentTabIndex() != index)
@ -163,14 +163,14 @@ void TabBar::activateAt(int index) const
} }
} }
//删除指定索引处的选项卡
void TabBar::deletItemAt(size_t index) void TabBar::deletItemAt(size_t index)
{ {
if (index == _nbItem - 1) if (index == _nbItem - 1)
{ {
//prevent invisible tabs. If last visible tab is removed, other tabs are put in view but not redrawn //prevent invisible tabs. If last visible tab is removed, other tabs are put in view but not redrawn
//Therefore, scroll one tab to the left if only one tab visible //Therefore, scroll one tab to the left if only one tab visible
if (_nbItem > 1) if (_nbItem > 1)//至少两个
{ {
RECT itemRect{}; RECT itemRect{};
::SendMessage(_hSelf, TCM_GETITEMRECT, index, reinterpret_cast<LPARAM>(&itemRect)); ::SendMessage(_hSelf, TCM_GETITEMRECT, index, reinterpret_cast<LPARAM>(&itemRect));
@ -182,7 +182,7 @@ void TabBar::deletItemAt(size_t index)
//There seems to be no negative effect on any internal state of the tab control or the up/down control //There seems to be no negative effect on any internal state of the tab control or the up/down control
int wParam = MAKEWPARAM(SB_THUMBPOSITION, index - 1); int wParam = MAKEWPARAM(SB_THUMBPOSITION, index - 1);
::SendMessage(_hSelf, WM_HSCROLL, wParam, 0); ::SendMessage(_hSelf, WM_HSCROLL, wParam, 0);
//TabBar控件向左滚动一个Tab项的位置。
wParam = MAKEWPARAM(SB_ENDSCROLL, index - 1); wParam = MAKEWPARAM(SB_ENDSCROLL, index - 1);
::SendMessage(_hSelf, WM_HSCROLL, wParam, 0); ::SendMessage(_hSelf, WM_HSCROLL, wParam, 0);
} }
@ -192,14 +192,14 @@ void TabBar::deletItemAt(size_t index)
_nbItem--; _nbItem--;
} }
//设置TabBar中的图像列表。使用TCM_SETIMAGELIST消息来设置图像列表。
void TabBar::setImageList(HIMAGELIST himl) void TabBar::setImageList(HIMAGELIST himl)
{ {
_hasImgLst = true; _hasImgLst = true;
::SendMessage(_hSelf, TCM_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(himl)); ::SendMessage(_hSelf, TCM_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(himl));
} }
//调整TabBar的大小以适应给定的矩形区域。调整TabBar的显示方式并计算新的大小然后调整提供的矩形区域。
void TabBar::reSizeTo(RECT & rc2Ajust) void TabBar::reSizeTo(RECT & rc2Ajust)
{ {
RECT rowRect{}; RECT rowRect{};
@ -208,6 +208,7 @@ void TabBar::reSizeTo(RECT & rc2Ajust)
// Important to do that! // Important to do that!
// Otherwise, the window(s) it contains will take all the resouce of CPU // Otherwise, the window(s) it contains will take all the resouce of CPU
// We don't need to resize the contained windows if they are even invisible anyway // We don't need to resize the contained windows if they are even invisible anyway
//调用display方法根据调整矩形的右边界是否大于10来决定是否显示TabBar中的窗口
display(rc2Ajust.right > 10); display(rc2Ajust.right > 10);
RECT rc = rc2Ajust; RECT rc = rc2Ajust;
Window::reSizeTo(rc); Window::reSizeTo(rc);
@ -226,7 +227,7 @@ void TabBar::reSizeTo(RECT & rc2Ajust)
if (rowCount == 1) if (rowCount == 1)
{ {
style &= ~TCS_BUTTONS; style &= ~TCS_BUTTONS;
} }// 如果有多行Tab项至少两行则启用TabCtrl的按钮样式并计算间距的值
else // (rowCount >= 2) else // (rowCount >= 2)
{ {
style |= TCS_BUTTONS; style |= TCS_BUTTONS;
@ -249,15 +250,19 @@ void TabBar::reSizeTo(RECT & rc2Ajust)
} }
} }
//销毁TabBarPlus及其资源。
void TabBarPlus::destroy() void TabBarPlus::destroy()
{ {
TabBar::destroy(); TabBar::destroy();
::DestroyWindow(_tooltips); ::DestroyWindow(_tooltips);
_tooltips = NULL; _tooltips = NULL;
} }
/*
TabBarPlus
TabControl
TabBarPlus便
*/
void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLine) void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMultiLine)
{ {
Window::init(hInst, parent); Window::init(hInst, parent);
@ -290,7 +295,7 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
{ {
throw std::runtime_error("TabBarPlus::init : CreateWindowEx() function return null"); throw std::runtime_error("TabBarPlus::init : CreateWindowEx() function return null");
} }
//工具提示
_tooltips = ::CreateWindowEx( _tooltips = ::CreateWindowEx(
0, 0,
TOOLTIPS_CLASS, TOOLTIPS_CLASS,
@ -306,7 +311,7 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
{ {
throw std::runtime_error("TabBarPlus::init : tooltip CreateWindowEx() function return null"); throw std::runtime_error("TabBarPlus::init : tooltip CreateWindowEx() function return null");
} }
//暗色主题
NppDarkMode::setDarkTooltips(_tooltips, NppDarkMode::ToolTipsType::tooltip); NppDarkMode::setDarkTooltips(_tooltips, NppDarkMode::ToolTipsType::tooltip);
::SendMessage(_hSelf, TCM_SETTOOLTIPS, reinterpret_cast<WPARAM>(_tooltips), 0); ::SendMessage(_hSelf, TCM_SETTOOLTIPS, reinterpret_cast<WPARAM>(_tooltips), 0);
@ -317,12 +322,13 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
_ctrlID = _nbCtrl; _ctrlID = _nbCtrl;
} }
else else
{ {//查找第一个为空的位置并设置_ctrlID为该位置的值
int i = 0; int i = 0;
bool found = false; bool found = false;
for ( ; i < nbCtrlMax && !found ; ++i) for ( ; i < nbCtrlMax && !found ; ++i)
if (!_hwndArray[i]) if (!_hwndArray[i])
found = true; found = true;
//满了未找到,销毁
if (!found) if (!found)
{ {
_ctrlID = -1; _ctrlID = -1;
@ -354,7 +360,7 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
_hVerticalLargeFont = CreateFontIndirect(&lfVer); _hVerticalLargeFont = CreateFontIndirect(&lfVer);
} }
//处理选项卡控件的自定义填充。
void TabBarPlus::doOwnerDrawTab() void TabBarPlus::doOwnerDrawTab()
{ {
::SendMessage(_hwndArray[0], TCM_SETPADDING, 0, MAKELPARAM(6, 0)); ::SendMessage(_hwndArray[0], TCM_SETPADDING, 0, MAKELPARAM(6, 0));
@ -363,6 +369,7 @@ void TabBarPlus::doOwnerDrawTab()
if (_hwndArray[i]) if (_hwndArray[i])
{ {
LONG_PTR style = ::GetWindowLongPtr(_hwndArray[i], GWL_STYLE); LONG_PTR style = ::GetWindowLongPtr(_hwndArray[i], GWL_STYLE);
//检查是否需要自定义
if (isOwnerDrawTab()) if (isOwnerDrawTab())
style |= TCS_OWNERDRAWFIXED; style |= TCS_OWNERDRAWFIXED;
else else
@ -378,7 +385,7 @@ void TabBarPlus::doOwnerDrawTab()
} }
} }
//根据给定的索引为选项卡栏设置不同的颜色(如活动文本颜色、背景颜色等)。在更新颜色之后它调用doOwnerDrawTab()来刷新显示。
void TabBarPlus::setColour(COLORREF colour2Set, tabColourIndex i) void TabBarPlus::setColour(COLORREF colour2Set, tabColourIndex i)
{ {
switch (i) switch (i)
@ -404,7 +411,7 @@ void TabBarPlus::setColour(COLORREF colour2Set, tabColourIndex i)
doOwnerDrawTab(); doOwnerDrawTab();
} }
//设置垂直选项卡
void TabBarPlus::doVertical() void TabBarPlus::doVertical()
{ {
for (int i = 0 ; i < _nbCtrl ; ++i) for (int i = 0 ; i < _nbCtrl ; ++i)
@ -414,7 +421,7 @@ void TabBarPlus::doVertical()
} }
} }
//显示多行选项卡
void TabBarPlus::doMultiLine() void TabBarPlus::doMultiLine()
{ {
for (int i = 0 ; i < _nbCtrl ; ++i) for (int i = 0 ; i < _nbCtrl ; ++i)
@ -423,7 +430,7 @@ void TabBarPlus::doMultiLine()
SendMessage(_hwndArray[i], WM_TABSETSTYLE, isMultiLine(), TCS_MULTILINE); SendMessage(_hwndArray[i], WM_TABSETSTYLE, isMultiLine(), TCS_MULTILINE);
} }
} }
//向父窗口发送通知消息,其中包含有关选项卡索引和特定通知代码的信息。
void TabBarPlus::notify(int notifyCode, int tabIndex) void TabBarPlus::notify(int notifyCode, int tabIndex)
{ {
TBHDR nmhdr{}; TBHDR nmhdr{};
@ -433,7 +440,7 @@ void TabBarPlus::notify(int notifyCode, int tabIndex)
nmhdr._tabOrigin = tabIndex; nmhdr._tabOrigin = tabIndex;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr)); ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
} }
//启动对选项卡栏控件上的鼠标事件的跟踪,例如当鼠标进入或离开控件区域时。
void TabBarPlus::trackMouseEvent(DWORD event2check) void TabBarPlus::trackMouseEvent(DWORD event2check)
{ {
TRACKMOUSEEVENT tme = {}; TRACKMOUSEEVENT tme = {};
@ -442,12 +449,13 @@ void TabBarPlus::trackMouseEvent(DWORD event2check)
tme.hwndTrack = _hSelf; tme.hwndTrack = _hSelf;
TrackMouseEvent(&tme); TrackMouseEvent(&tme);
} }
//消息处理,处理窗口消息
LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{ {
switch (Message) switch (Message)
{ {
// Custom window message to change tab control style on the fly // Custom window message to change tab control style on the fly
//改变窗口样式
case WM_TABSETSTYLE: case WM_TABSETSTYLE:
{ {
LONG_PTR style = ::GetWindowLongPtr(hwnd, GWL_STYLE); LONG_PTR style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
@ -465,13 +473,13 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
return TRUE; return TRUE;
} }
//深色模式
case NPPM_INTERNAL_REFRESHDARKMODE: case NPPM_INTERNAL_REFRESHDARKMODE:
{ {
NppDarkMode::setDarkTooltips(hwnd, NppDarkMode::ToolTipsType::tabbar); NppDarkMode::setDarkTooltips(hwnd, NppDarkMode::ToolTipsType::tabbar);
return TRUE; return TRUE;
} }
//鼠标滚轮
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
// .............................................................................. // ..............................................................................
@ -489,7 +497,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
// CTRL + SHIFT + MOUSEWHEEL: // CTRL + SHIFT + MOUSEWHEEL:
// will switch to the first/last tab // will switch to the first/last tab
// .............................................................................. // ..............................................................................
//是否被拖动,如是,会交换当前鼠标所在位置和目标位置的数据
if (_isDragging) if (_isDragging)
return TRUE; return TRUE;
@ -581,7 +589,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
} }
return TRUE; return TRUE;
} }
//左键按下
case WM_LBUTTONDOWN : case WM_LBUTTONDOWN :
{ {
if (::GetWindowLongPtr(_hSelf, GWL_STYLE) & TCS_BUTTONS) if (::GetWindowLongPtr(_hSelf, GWL_STYLE) & TCS_BUTTONS)
@ -592,7 +600,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
setActiveTab(nTab); setActiveTab(nTab);
} }
} }
//是否关闭
if (_drawTabCloseButton) if (_drawTabCloseButton)
{ {
int xPos = LOWORD(lParam); int xPos = LOWORD(lParam);
@ -621,7 +629,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
return TRUE; return TRUE;
} }
//右键按下,处理选项
case WM_RBUTTONDOWN : //rightclick selects tab aswell case WM_RBUTTONDOWN : //rightclick selects tab aswell
{ {
// TCS_BUTTONS doesn't select the tab // TCS_BUTTONS doesn't select the tab
@ -637,7 +645,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam); ::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam);
return TRUE; return TRUE;
} }
//鼠标移动
case WM_MOUSEMOVE : case WM_MOUSEMOVE :
{ {
if (_mightBeDragging && !_isDragging) if (_mightBeDragging && !_isDragging)
@ -670,7 +678,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
POINT p{}; POINT p{};
p.x = LOWORD(lParam); p.x = LOWORD(lParam);
p.y = HIWORD(lParam); p.y = HIWORD(lParam);
//是否拖动tag光标移动tab数据交换判断并进行相关操作
if (_isDragging) if (_isDragging)
{ {
exchangeItemData(p); exchangeItemData(p);
@ -758,7 +766,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
break; break;
} }
//鼠标移开,重绘鼠标区域,重置相关变量
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
{ {
if (_isCloseHover) if (_isCloseHover)
@ -772,7 +780,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
notify(TCN_MOUSELEAVING, _currentHoverTabItem); notify(TCN_MOUSELEAVING, _currentHoverTabItem);
break; break;
} }
//释放左键,告知操作结束
case WM_LBUTTONUP : case WM_LBUTTONUP :
{ {
_mightBeDragging = false; _mightBeDragging = false;
@ -820,7 +828,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
break; break;
} }
//抓取鼠标输入的改变
case WM_CAPTURECHANGED : case WM_CAPTURECHANGED :
{ {
if (_isDragging) if (_isDragging)
@ -830,20 +838,20 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
} }
break; break;
} }
//重绘tab
case WM_DRAWITEM : case WM_DRAWITEM :
{ {
drawItem((DRAWITEMSTRUCT *)lParam); drawItem((DRAWITEMSTRUCT *)lParam);
return TRUE; return TRUE;
} }
//是否按下control键
case WM_KEYDOWN : case WM_KEYDOWN :
{ {
if (wParam == VK_LCONTROL) if (wParam == VK_LCONTROL)
::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_PLUS_TAB))); ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_PLUS_TAB)));
return TRUE; return TRUE;
} }
//鼠标中键释放
case WM_MBUTTONUP: case WM_MBUTTONUP:
{ {
int xPos = LOWORD(lParam); int xPos = LOWORD(lParam);
@ -852,7 +860,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
notify(TCN_TABDELETE, currentTabOn); notify(TCN_TABDELETE, currentTabOn);
return TRUE; return TRUE;
} }
//双击鼠标左键
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
{ {
if (_isDbClk2Close) if (_isDbClk2Close)
@ -864,7 +872,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
} }
return TRUE; return TRUE;
} }
//如果程序正在使用暗黑模式将会用指定的画刷填充整个Tab的客户区代替了系统默认的橡皮擦背景操作。
case WM_ERASEBKGND: case WM_ERASEBKGND:
{ {
if (!NppDarkMode::isEnabled()) if (!NppDarkMode::isEnabled())
@ -878,7 +886,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
return 1; return 1;
} }
//在Tab控件需要重绘时调用这里会进行大量的绘制操作内容包括Tab本身和每一个Tab的文字、关闭按钮等元素。
case WM_PAINT: case WM_PAINT:
{ {
if (!NppDarkMode::isEnabled()) if (!NppDarkMode::isEnabled())
@ -1049,7 +1057,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam); return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam);
} }
//实现了Tab的绘制过程包括对Tab背景颜色、文字颜色的调整判断并处理当前Tab的激活状态处理Tab的图标和标题等。
void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode) void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode)
{ {
RECT rect = pDrawItemStruct->rcItem; RECT rect = pDrawItemStruct->rcItem;
@ -1371,7 +1379,7 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode)
::RestoreDC(hDC, nSavedDC); ::RestoreDC(hDC, nSavedDC);
} }
//用于改变鼠标光标的形状,根据用户托拽标签的不同位置(是否在同一应用中、是否在一个有效的放置位置等)表现为不同的光标形状。
void TabBarPlus::draggingCursor(POINT screenPoint) void TabBarPlus::draggingCursor(POINT screenPoint)
{ {
HWND hWin = ::WindowFromPoint(screenPoint); HWND hWin = ::WindowFromPoint(screenPoint);
@ -1394,7 +1402,7 @@ void TabBarPlus::draggingCursor(POINT screenPoint)
::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_OUT_TAB))); ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_OUT_TAB)));
} }
} }
//简单地把指定的标签设为活动状态。
void TabBarPlus::setActiveTab(int tabIndex) void TabBarPlus::setActiveTab(int tabIndex)
{ {
// TCM_SETCURFOCUS is busted on WINE/ReactOS for single line (non-TCS_BUTTONS) tabs... // TCM_SETCURFOCUS is busted on WINE/ReactOS for single line (non-TCS_BUTTONS) tabs...
@ -1407,7 +1415,7 @@ void TabBarPlus::setActiveTab(int tabIndex)
::SendMessage(_hSelf, TCM_SETCURSEL, tabIndex, 0); ::SendMessage(_hSelf, TCM_SETCURSEL, tabIndex, 0);
notify(TCN_SELCHANGE, tabIndex); notify(TCN_SELCHANGE, tabIndex);
} }
//交换两个Tab的数据实现两个Tab的位置交换。
void TabBarPlus::exchangeTabItemData(int oldTab, int newTab) void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
{ {
//1. shift their data, and insert the source //1. shift their data, and insert the source
@ -1449,7 +1457,7 @@ void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
//2. set to focus //2. set to focus
setActiveTab(newTab); setActiveTab(newTab);
} }
//在接收到鼠标托拽消息的时候被调用,用于各个标签的排序和交换位置。
void TabBarPlus::exchangeItemData(POINT point) void TabBarPlus::exchangeItemData(POINT point)
{ {
// Find the destination tab... // Find the destination tab...
@ -1486,7 +1494,7 @@ void TabBarPlus::exchangeItemData(POINT point)
} }
//用于处理与关闭按钮相关的操作,如获取关闭按钮的大小及位置,判断是否点击到了关闭按钮等。
CloseButtonZone::CloseButtonZone() CloseButtonZone::CloseButtonZone()
{ {
// TODO: get width/height of close button dynamically // TODO: get width/height of close button dynamically

Loading…
Cancel
Save