📄 shareselectdialog.cpp
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
//---------------------------------------------------------------------------
// don't change this order, VCL's shlobj.hpp collides with window's shlobj.h
#define NO_WIN32_LEAN_AND_MEAN
#include <shlobj.hpp>
#undef NO_WIN32_LEAN_AND_MEAN
#include <vcl.h>
#include <KCeasy.h>
#pragma hdrstop
#include "ShareSelectDialog.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "VirtualTrees"
#pragma link "VirtualTrees"
#pragma resource "*.dfm"
TShareSelectForm *ShareSelectForm;
//---------------------------------------------------------------------------
// TFolder
class TFolder
{
public:
TFolder(const string& NPath) : Path(NPath), IconIndex(-1), OpenIconIndex(-1)
{
// add backslash to path if necessary
if(Path[Path.length()-1] != '\\')
Path.push_back('\\');
// get display name
SHFILEINFO FileInfo;
if(SHGetFileInfo(Path.c_str(),0,&FileInfo,sizeof(FileInfo),SHGFI_DISPLAYNAME))
DisplayName = FileInfo.szDisplayName;
// get icons
if(SHGetFileInfo(Path.c_str(),0,&FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX | SHGFI_SMALLICON))
IconIndex = FileInfo.iIcon;
if(SHGetFileInfo(Path.c_str(),0,&FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON))
OpenIconIndex = FileInfo.iIcon;
}
list<TFolder*> GetSubFolders()
{
list<TFolder*> SubFolders;
WIN32_FIND_DATA FindData;
string SubFolderPath;
string Mask = Path + "*.*";
HANDLE hFind = FindFirstFile(Mask.c_str(),&FindData);
if(hFind == INVALID_HANDLE_VALUE)
return SubFolders;
do {
if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
strcmp(FindData.cFileName,".") !=0 &&
strcmp(FindData.cFileName,"..") != 0 )
{
SubFolderPath = Path + FindData.cFileName;
SubFolders.push_back(new TFolder(SubFolderPath));
}
} while(FindNextFile(hFind,&FindData));
FindClose(hFind);
return SubFolders;
}
string DisplayName;
string Path;
int IconIndex, OpenIconIndex;
};
//---------------------------------------------------------------------------
// TShareSelectForm
__fastcall TShareSelectForm::TShareSelectForm(TComponent* Owner, const list<string>& Folders)
: TForm(Owner),
SharedFolders(Folders)
{
TranslateComponent(this);
Caption = Brand->ReplaceAppName(Caption);
FolderTree->NodeDataSize = sizeof(TFolder*);
// use system image list for icons
FolderImageList = new TImageList(this);
FolderTree->Images = FolderImageList;
SHFILEINFO FileInfo;
FolderImageList->Handle = SHGetFileInfo("*.exe",FILE_ATTRIBUTE_NORMAL,&FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
FolderImageList->ShareImages = true;
FolderTree->BeginUpdate();
// get drives
char Drives[MAX_PATH];
if(GetLogicalDriveStrings(MAX_PATH,Drives) != 0) {
for(char *p=Drives;*p;p += strlen(p) + 1) {
TFolder* Folder = new TFolder(string(p));
TVirtualNode* Node = FolderTree->AddChild(NULL,Folder);
FolderTree->HasChildren[Node] = true;
FolderTree->CheckType[Node] = ctTriStateCheckBox;
FolderTree->CheckState[Node] = csUncheckedNormal;
}
}
// overlaps with file system
/*
// add "my documents"
LPITEMIDLIST pidl;
if(SHGetSpecialFolderLocation(NULL,CSIDL_PERSONAL,&pidl) == NOERROR) {
char Path[MAX_PATH];
if(SHGetPathFromIDList(pidl,Path)) {
TFolder* Folder = new TFolder(string(Path));
TVirtualNode* Node = FolderTree->AddChild(NULL,Folder);
FolderTree->HasChildren[Node] = true;
FolderTree->CheckType[Node] = ctTriStateCheckBox;
FolderTree->CheckState[Node] = csUncheckedNormal;
}
// free pidl
IMalloc *MallocIntf = NULL;
if(SHGetMalloc(&MallocIntf) == NOERROR) {
MallocIntf->Free(pidl);
MallocIntf->Release();
}
}
*/
// add backslash to path if necessary
for(list<string>::iterator itr=SharedFolders.begin();itr!=SharedFolders.end();++itr) {
if((*itr)[(*itr).length()-1] != '\\')
(*itr).push_back('\\');
}
// check already shared dirs
for(TVirtualNode* Node=FolderTree->GetFirst();Node;Node=FolderTree->GetNextSibling(Node)) {
TFolder* Folder = *((TFolder**)FolderTree->GetNodeData(Node));
for(list<string>::iterator itr=SharedFolders.begin();itr!=SharedFolders.end();++itr){
string Cmp = (*itr).substr(0,Folder->Path.length());
if(Cmp == Folder->Path) {
if((*itr).length() == Folder->Path.length())
FolderTree->CheckState[Node] = csCheckedNormal;
else
FolderTree->CheckState[Node] = csMixedNormal;
break;
}
}
}
FolderTree->EndUpdate();
}
__fastcall TShareSelectForm::~TShareSelectForm()
{
delete FolderImageList;
}
//---------------------------------------------------------------------------
void __fastcall TShareSelectForm::FolderTreeFreeNode(
TBaseVirtualTree *Sender, PVirtualNode Node)
{
// delete TFolder
delete *((TFolder**)FolderTree->GetNodeData(Node));
}
//---------------------------------------------------------------------------
void __fastcall TShareSelectForm::FolderTreeInitChildren(
TBaseVirtualTree *Sender, PVirtualNode Node, DWORD &ChildCount)
{
TFolder* Folder = *((TFolder**)Sender->GetNodeData(Node));
FolderTree->BeginUpdate();
list<TFolder*> SubFolders = Folder->GetSubFolders();
ChildCount = SubFolders.size();
for(list<TFolder*>::iterator itr=SubFolders.begin();itr != SubFolders.end();++itr) {
TVirtualNode* SubNode = FolderTree->AddChild(Node,(*itr));
FolderTree->HasChildren[SubNode] = true;
FolderTree->CheckType[SubNode] = ctTriStateCheckBox;
if(FolderTree->CheckState[Node] == csCheckedNormal) {
FolderTree->CheckState[SubNode] = csCheckedNormal;
} else if(FolderTree->CheckState[Node] == csMixedNormal) {
// check already shared dirs
for(list<string>::iterator ditr=SharedFolders.begin();ditr!=SharedFolders.end();++ditr){
string Cmp = (*ditr).substr(0,(*itr)->Path.length());
if(Cmp == (*itr)->Path) {
if((*ditr).length() == (*itr)->Path.length())
FolderTree->CheckState[SubNode] = csCheckedNormal;
else
FolderTree->CheckState[SubNode] = csMixedNormal;
break;
}
}
}
}
FolderTree->EndUpdate();
}
//---------------------------------------------------------------------------
void __fastcall TShareSelectForm::FolderTreeGetText(
TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column,
TVSTTextType TextType, WideString &CellText)
{
if(TextType == ttNormal) {
TFolder* Folder = *((TFolder**)Sender->GetNodeData(Node));
CellText = Folder->DisplayName.c_str();
}
}
void __fastcall TShareSelectForm::FolderTreeGetImageIndex(
TBaseVirtualTree *Sender, PVirtualNode Node, TVTImageKind Kind,
TColumnIndex Column, bool &Ghosted, int &ImageIndex)
{
TFolder* Folder = *((TFolder**)Sender->GetNodeData(Node));
if(Kind == ikNormal || Kind == ikSelected)
ImageIndex = FolderTree->Expanded[Node] ? Folder->OpenIconIndex : Folder->IconIndex;
else
ImageIndex = -1;
}
//---------------------------------------------------------------------------
void __fastcall TShareSelectForm::CollectPaths(TVirtualNode* Node, list<string>& Paths)
{
if(FolderTree->CheckState[Node] == csCheckedNormal) {
TFolder* Folder = *((TFolder**)FolderTree->GetNodeData(Node));
Paths.push_back(Folder->Path);
} else if(FolderTree->CheckState[Node] == csMixedNormal) {
// init children if the user hadn't expanded a previously selected path
if(FolderTree->ChildCount[Node] == 0)
FolderTree->InvalidateChildren(Node,false);
for(TVirtualNode* SubNode=FolderTree->GetFirstChild(Node);SubNode;SubNode=FolderTree->GetNextSibling(SubNode)) {
if(FolderTree->CheckState[SubNode] == csCheckedNormal) {
TFolder* Folder = *((TFolder**)FolderTree->GetNodeData(SubNode));
Paths.push_back(Folder->Path);
} else if(FolderTree->CheckState[SubNode] == csMixedNormal) {
CollectPaths(SubNode,Paths); // recurse
}
}
}
}
void __fastcall TShareSelectForm::OkBtnClick(TObject *Sender)
{
list<string> Paths;
// recursively collect paths, this may use SharedFolders
for(TVirtualNode* Node=FolderTree->GetFirst();Node;Node=FolderTree->GetNextSibling(Node))
CollectPaths(Node,Paths);
SharedFolders.clear();
SharedFolders = Paths;
}
//---------------------------------------------------------------------------
void __fastcall TShareSelectForm::CheckChildren(TVirtualNode* Node, TCheckState State)
{
if(FolderTree->ChildrenInitialized[Node]) {
TVirtualNode* CNode = FolderTree->GetFirstChild(Node);
while(CNode) {
CNode->CheckState = State;
CheckChildren (CNode, State); // recurse
CNode = FolderTree->GetNextSibling(CNode);
}
}
}
void __fastcall TShareSelectForm::FolderTreeChecked(
TBaseVirtualTree *Sender, PVirtualNode Node)
{
FolderTree->BeginUpdate();
if(Node->CheckState == csCheckedNormal) {
// if the direct parent is not csCheckedNormal then csMixedNormal all parents
TVirtualNode* PNode = FolderTree->NodeParent[Node];
if(PNode && PNode->CheckState != csCheckedNormal) {
while(PNode) {
PNode->CheckState = csMixedNormal;
PNode = FolderTree->NodeParent[PNode];
}
}
// check all initialized childrens
CheckChildren (Node, csCheckedNormal);
} else {
// remove checks from parents
bool CheckedChildren = false;
TVirtualNode* PNode = FolderTree->NodeParent[Node];
while(PNode) {
// are other children checked?
TVirtualNode* CNode = FolderTree->GetFirstChild(PNode);
while(!CheckedChildren && CNode) {
if(CNode->CheckState != csUncheckedNormal)
CheckedChildren = true;
CNode = FolderTree->GetNextSibling(CNode);
}
PNode->CheckState = CheckedChildren ? csMixedNormal : csUncheckedNormal;
PNode = FolderTree->NodeParent[PNode];
}
// remove checks from all initialized children
CheckChildren (Node, csUncheckedNormal);
}
FolderTree->EndUpdate();
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -