📄 winutil.cpp
字号:
// check for the existence of magnet.exe
if(File::getSize(Text::fromT(magnetExe)) == -1) {
magnetExe = Text::toT(Util::getAppPath() + "magnet.exe");
if(File::getSize(Text::fromT(magnetExe)) == -1) {
// gracefully fall back to registering DC++ to handle magnets
magnetExe = Text::toT(Util::getAppName());
haveMagnet = false;
} else {
// set Magnet\Location
if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Magnet"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL)) {
LogManager::getInstance()->message(STRING(ERROR_CREATING_REGISTRY_KEY_MAGNET));
return;
}
::RegSetValueEx(hk, _T("Location"), NULL, REG_SZ, (LPBYTE)magnetExe.c_str(), sizeof(TCHAR) * (magnetExe.length()+1));
::RegCloseKey(hk);
}
magnetLoc = _T('"') + magnetExe + _T('"');
}
// (re)register the handler if magnet.exe isn't the default, or if DC++ is handling it
if(BOOLSETTING(MAGNET_REGISTER) && (Util::strnicmp(openCmd, magnetLoc, magnetLoc.size()) != 0 || !haveMagnet)) {
SHDeleteKey(HKEY_CLASSES_ROOT, _T("magnet"));
if (::RegCreateKeyEx(HKEY_CLASSES_ROOT, _T("magnet"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL)) {
LogManager::getInstance()->message(STRING(ERROR_CREATING_REGISTRY_KEY_MAGNET));
return;
}
::RegSetValueEx(hk, NULL, NULL, REG_SZ, (LPBYTE)CTSTRING(MAGNET_SHELL_DESC), sizeof(TCHAR)*(TSTRING(MAGNET_SHELL_DESC).length()+1));
::RegSetValueEx(hk, _T("URL Protocol"), NULL, REG_SZ, NULL, NULL);
::RegCloseKey(hk);
::RegCreateKeyEx(HKEY_CLASSES_ROOT, _T("magnet\\DefaultIcon"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL);
::RegSetValueEx(hk, NULL, NULL, REG_SZ, (LPBYTE)magnetLoc.c_str(), sizeof(TCHAR)*(magnetLoc.length()+1));
::RegCloseKey(hk);
magnetLoc += _T(" %1");
::RegCreateKeyEx(HKEY_CLASSES_ROOT, _T("magnet\\shell\\open\\command"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL);
::RegSetValueEx(hk, NULL, NULL, REG_SZ, (LPBYTE)magnetLoc.c_str(), sizeof(TCHAR)*(magnetLoc.length()+1));
::RegCloseKey(hk);
}
// magnet-handler specific code
// clean out the DC++ tree first
SHDeleteKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Magnet\\Handlers\\DC++"));
// add DC++ to magnet-handler's list of applications
::RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Magnet\\Handlers\\DC++"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL);
::RegSetValueEx(hk, NULL, NULL, REG_SZ, (LPBYTE)CTSTRING(MAGNET_HANDLER_ROOT), sizeof(TCHAR) * (TSTRING(MAGNET_HANDLER_ROOT).size()+1));
::RegSetValueEx(hk, _T("Description"), NULL, REG_SZ, (LPBYTE)CTSTRING(MAGNET_HANDLER_DESC), sizeof(TCHAR) * (STRING(MAGNET_HANDLER_DESC).size()+1));
// set ShellExecute
tstring app = Text::toT("\"" + Util::getAppName() + "\" %URL");
::RegSetValueEx(hk, _T("ShellExecute"), NULL, REG_SZ, (LPBYTE)app.c_str(), sizeof(TCHAR) * (app.length()+1));
// set DefaultIcon
app = Text::toT('"' + Util::getAppName() + '"');
::RegSetValueEx(hk, _T("DefaultIcon"), NULL, REG_SZ, (LPBYTE)app.c_str(), sizeof(TCHAR)*(app.length()+1));
::RegCloseKey(hk);
// These two types contain a tth root, and are in common use. The other two are variations picked up
// from Shareaza's source, which come second hand from Gordon Mohr. -GargoyleMT
// Reference: http://forums.shareaza.com/showthread.php?threadid=23731
// Note: the three part hash types require magnethandler >= 1.0.0.3
DWORD nothing = 0;
::RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Magnet\\Handlers\\DC++\\Type"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, NULL);
::RegSetValueEx(hk, _T("urn:bitprint"), NULL, REG_DWORD, (LPBYTE)¬hing, sizeof(nothing));
::RegSetValueEx(hk, _T("urn:tree:tiger"), NULL, REG_DWORD, (LPBYTE)¬hing, sizeof(nothing));
::RegSetValueEx(hk, _T("urn:tree:tiger/"), NULL, REG_DWORD, (LPBYTE)¬hing, sizeof(nothing));
::RegSetValueEx(hk, _T("urn:tree:tiger/1024"), NULL, REG_DWORD, (LPBYTE)¬hing, sizeof(nothing));
::RegCloseKey(hk);
}
void WinUtil::unRegisterMagnetHandler() {
SHDeleteKey(HKEY_CLASSES_ROOT, _T("magnet"));
SHDeleteKey(HKEY_LOCAL_MACHINE, _T("magnet"));
}
void WinUtil::openLink(const tstring& url) {
CRegKey key;
TCHAR regbuf[MAX_PATH];
ULONG len = MAX_PATH;
tstring x;
tstring::size_type i = url.find(_T("://"));
if(i != string::npos) {
x = url.substr(0, i);
} else {
x = _T("http");
}
x += _T("\\shell\\open\\command");
if(key.Open(HKEY_CLASSES_ROOT, x.c_str(), KEY_READ) == ERROR_SUCCESS) {
if(key.QueryStringValue(NULL, regbuf, &len) == ERROR_SUCCESS) {
/*
* Various values (for http handlers):
* C:\PROGRA~1\MOZILL~1\FIREFOX.EXE -url "%1"
* "C:\Program Files\Internet Explorer\iexplore.exe" -nohome
* "C:\Apps\Opera7\opera.exe"
* C:\PROGRAMY\MOZILLA\MOZILLA.EXE -url "%1"
* C:\PROGRA~1\NETSCAPE\NETSCAPE\NETSCP.EXE -url "%1"
*/
tstring cmd(regbuf); // otherwise you consistently get two trailing nulls
if(cmd.length() > 1) {
string::size_type start,end;
if(cmd[0] == '"') {
start = 1;
end = cmd.find('"', 1);
} else {
start = 0;
end = cmd.find(' ', 1);
}
if(end == string::npos)
end = cmd.length();
tstring cmdLine(cmd);
cmd = cmd.substr(start, end-start);
size_t arg_pos;
if((arg_pos = cmdLine.find(_T("%1"))) != string::npos) {
cmdLine.replace(arg_pos, 2, url);
} else {
cmdLine.append(_T(" \"") + url + _T('\"'));
}
STARTUPINFO si = { sizeof(si), 0 };
PROCESS_INFORMATION pi = { 0 };
AutoArray<TCHAR> buf(cmdLine.length() + 1);
_tcscpy(buf, cmdLine.c_str());
if(::CreateProcess(cmd.c_str(), buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
return;
}
}
}
}
::ShellExecute(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
void WinUtil::parseDchubUrl(const tstring& aUrl) {
string server, file;
u_int16_t port = 411;
Util::decodeUrl(Text::fromT(aUrl), server, port, file);
if(!server.empty()) {
HubFrame::openWindow(Text::toT(server + ":" + Util::toString(port)));
}
if(!file.empty()) {
if(file[0] == '/') // Remove any '/' in from of the file
file = file.substr(1);
try {
User::Ptr user = ClientManager::getInstance()->findLegacyUser(file);
if(user)
QueueManager::getInstance()->addList(user, QueueItem::FLAG_CLIENT_VIEW);
// @todo else report error
} catch(const Exception&) {
// ...
}
}
}
void WinUtil::parseADChubUrl(const tstring& aUrl) {
string server, file;
u_int16_t port = 0; //make sure we get a port since adc doesn't have a standard one
Util::decodeUrl(Text::fromT(aUrl), server, port, file);
if(!server.empty() && port > 0) {
HubFrame::openWindow(Text::toT("adc://" + server + ":" + Util::toString(port)));
}
}
void WinUtil::parseMagnetUri(const tstring& aUrl, bool /*aOverride*/) {
// official types that are of interest to us
// xt = exact topic
// xs = exact substitute
// as = acceptable substitute
// dn = display name
if (Util::strnicmp(aUrl.c_str(), _T("magnet:?"), 8) == 0) {
LogManager::getInstance()->message(STRING(MAGNET_DLG_TITLE) + ": " + Text::fromT(aUrl));
StringTokenizer<tstring> mag(aUrl.substr(8), _T('&'));
typedef map<tstring, tstring> MagMap;
MagMap hashes;
tstring fname, fhash, type, param;
for(TStringList::iterator idx = mag.getTokens().begin(); idx != mag.getTokens().end(); ++idx) {
// break into pairs
string::size_type pos = idx->find(_T('='));
if(pos != string::npos) {
type = Text::toT(Text::toLower(Util::encodeURI(Text::fromT(idx->substr(0, pos)), true)));
param = Text::toT(Util::encodeURI(Text::fromT(idx->substr(pos+1)), true));
} else {
type = Text::toT(Util::encodeURI(Text::fromT(*idx), true));
param.clear();
}
// extract what is of value
if(param.length() == 85 && Util::strnicmp(param.c_str(), _T("urn:bitprint:"), 13) == 0) {
hashes[type] = param.substr(46);
} else if(param.length() == 54 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger:"), 15) == 0) {
hashes[type] = param.substr(15);
} else if(param.length() == 55 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger/:"), 16) == 0) {
hashes[type] = param.substr(16);
} else if(param.length() == 59 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger/1024:"), 20) == 0) {
hashes[type] = param.substr(20);
} else if(type.length() == 2 && Util::strnicmp(type.c_str(), _T("dn"), 2) == 0) {
fname = param;
}
}
// pick the most authoritative hash out of all of them.
if(hashes.find(_T("as")) != hashes.end()) {
fhash = hashes[_T("as")];
}
if(hashes.find(_T("xs")) != hashes.end()) {
fhash = hashes[_T("xs")];
}
if(hashes.find(_T("xt")) != hashes.end()) {
fhash = hashes[_T("xt")];
}
if(!fhash.empty()){
// ok, we have a hash, and maybe a filename.
//if(!BOOLSETTING(MAGNET_ASK)) {
// switch(SETTING(MAGNET_ACTION)) {
// case SettingsManager::MAGNET_AUTO_DOWNLOAD:
// break;
// case SettingsManager::MAGNET_AUTO_SEARCH:
// SearchFrame::openWindow(fhash, 0, SearchManager::SIZE_DONTCARE, SearchManager::TYPE_HASH);
// break;
// };
//} else {
// use aOverride to force the display of the dialog. used for auto-updating
MagnetDlg dlg(fhash, fname);
dlg.DoModal(mainWnd);
//}
} else {
MessageBox(mainWnd, CTSTRING(MAGNET_DLG_TEXT_BAD), CTSTRING(MAGNET_DLG_TITLE), MB_OK | MB_ICONEXCLAMATION);
}
}
}
int WinUtil::textUnderCursor(POINT p, CEdit& ctrl, tstring& x) {
int i = ctrl.CharFromPos(p);
int line = ctrl.LineFromChar(i);
int c = LOWORD(i) - ctrl.LineIndex(line);
int len = ctrl.LineLength(i) + 1;
if(len < 3) {
return 0;
}
AutoArray<TCHAR> buf(len);
ctrl.GetLine(line, buf, len);
x = tstring(buf, len-1);
string::size_type start = x.find_last_of(_T(" <\t\r\n"), c);
if(start == string::npos)
start = 0;
else
start++;
return start;
}
bool WinUtil::parseDBLClick(const tstring& aString, string::size_type start, string::size_type end) {
if( (Util::strnicmp(aString.c_str() + start, _T("http://"), 7) == 0) ||
(Util::strnicmp(aString.c_str() + start, _T("www."), 4) == 0) ||
(Util::strnicmp(aString.c_str() + start, _T("ftp://"), 6) == 0) ||
(Util::strnicmp(aString.c_str() + start, _T("irc://"), 6) == 0) ||
(Util::strnicmp(aString.c_str() + start, _T("https://"), 8) == 0) ||
(Util::strnicmp(aString.c_str() + start, _T("mailto:"), 7) == 0) )
{
openLink(aString.substr(start, end-start));
return true;
} else if(Util::strnicmp(aString.c_str() + start, _T("dchub://"), 8) == 0) {
parseDchubUrl(aString.substr(start, end-start));
return true;
} else if(Util::strnicmp(aString.c_str() + start, _T("magnet:?"), 8) == 0) {
parseMagnetUri(aString.substr(start, end-start));
return true;
} else if(Util::strnicmp(aString.c_str() + start, _T("adc://"), 6) == 0) {
parseADChubUrl(aString.substr(start, end-start));
return true;
}
return false;
}
void WinUtil::saveHeaderOrder(CListViewCtrl& ctrl, SettingsManager::StrSetting order,
SettingsManager::StrSetting widths, int n,
int* indexes, int* sizes) throw() {
string tmp;
ctrl.GetColumnOrderArray(n, indexes);
int i;
for(i = 0; i < n; ++i) {
tmp += Util::toString(indexes[i]);
tmp += ',';
}
tmp.erase(tmp.size()-1, 1);
SettingsManager::getInstance()->set(order, tmp);
tmp.clear();
for(i = 0; i < n; ++i) {
sizes[i] = ctrl.GetColumnWidth(i);
tmp += Util::toString(sizes[i]);
tmp += ',';
}
tmp.erase(tmp.size()-1, 1);
SettingsManager::getInstance()->set(widths, tmp);
}
int WinUtil::getIconIndex(const tstring& aFileName) {
if(BOOLSETTING(USE_SYSTEM_ICONS)) {
SHFILEINFO fi;
string x = Text::toLower(Util::getFileExt(Text::fromT(aFileName)));
if(!x.empty()) {
ImageIter j = fileIndexes.find(x);
if(j != fileIndexes.end())
return j->second;
}
tstring fn = Text::toT(Text::toLower(Util::getFileName(Text::fromT(aFileName))));
::SHGetFileInfo(fn.c_str(), FILE_ATTRIBUTE_NORMAL, &fi, sizeof(fi), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
fileImages.AddIcon(fi.hIcon);
::DestroyIcon(fi.hIcon);
fileIndexes[x] = fileImageCount++;
return fileImageCount - 1;
} else {
return 2;
}
}
int WinUtil::getOsMajor() {
OSVERSIONINFOEX ver;
memset(&ver, 0, sizeof(OSVERSIONINFOEX));
if(!GetVersionEx((OSVERSIONINFO*)&ver))
{
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
}
GetVersionEx((OSVERSIONINFO*)&ver);
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
return ver.dwMajorVersion;
}
int WinUtil::getOsMinor()
{
OSVERSIONINFOEX ver;
memset(&ver, 0, sizeof(OSVERSIONINFOEX));
if(!GetVersionEx((OSVERSIONINFO*)&ver))
{
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
}
GetVersionEx((OSVERSIONINFO*)&ver);
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
return ver.dwMinorVersion;
}
tstring WinUtil::getNicks(const CID& cid) throw() {
return Text::toT(Util::toString(ClientManager::getInstance()->getNicks(cid)));
}
pair<tstring, bool> WinUtil::getHubNames(const CID& cid) throw() {
StringList hubs = ClientManager::getInstance()->getHubNames(cid);
if(hubs.empty()) {
return make_pair(TSTRING(OFFLINE), false);
} else {
return make_pair(Text::toT(Util::toString(hubs)), true);
}
}
void WinUtil::getContextMenuPos(CListViewCtrl& aList, POINT& aPt) {
int pos = aList.GetNextItem(-1, LVNI_SELECTED | LVNI_FOCUSED);
if(pos >= 0) {
CRect lrc;
aList.GetItemRect(pos, &lrc, LVIR_LABEL);
aPt.x = lrc.left;
aPt.y = lrc.top + (lrc.Height() / 2);
} else {
aPt.x = aPt.y = 0;
}
aList.ClientToScreen(&aPt);
}
void WinUtil::getContextMenuPos(CTreeViewCtrl& aTree, POINT& aPt) {
CRect trc;
HTREEITEM ht = aTree.GetSelectedItem();
if(ht) {
aTree.GetItemRect(ht, &trc, TRUE);
aPt.x = trc.left;
aPt.y = trc.top + (trc.Height() / 2);
} else {
aPt.x = aPt.y = 0;
}
aTree.ClientToScreen(&aPt);
}
void WinUtil::getContextMenuPos(CEdit& aEdit, POINT& aPt) {
CRect erc;
aEdit.GetRect(&erc);
aPt.x = erc.Width() / 2;
aPt.y = erc.Height() / 2;
aEdit.ClientToScreen(&aPt);
}
void WinUtil::openFolder(const tstring& file) {
if (File::getSize(Text::fromT(file)) != -1)
::ShellExecute(NULL, NULL, Text::toT("explorer.exe").c_str(), Text::toT("/e, /select, \"" + (Text::fromT(file)) + "\"").c_str(), NULL, SW_SHOWNORMAL);
else
::ShellExecute(NULL, NULL, Text::toT("explorer.exe").c_str(), Text::toT("/e, \"" + Util::getFilePath(Text::fromT(file)) + "\"").c_str(), NULL, SW_SHOWNORMAL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -