mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
win open with menu done, lang string for 0.7.9 added
This commit is contained in:
parent
6302eeeb2b
commit
781c531964
6 changed files with 212 additions and 20 deletions
|
@ -452,11 +452,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_authorization" = "{name},\nWe detected a login into your account from a new device on {day}, {date} at {time}\n\nDevice: {device}\nLocation: {location}\n\nIf this wasn't you, you can go to Settings — Terminate other sessions.\n\nThanks,\nThe Telegram Team";
|
"lng_new_authorization" = "{name},\nWe detected a login into your account from a new device on {day}, {date} at {time}\n\nDevice: {device}\nLocation: {location}\n\nIf this wasn't you, you can go to Settings — Terminate other sessions.\n\nThanks,\nThe Telegram Team";
|
||||||
|
|
||||||
"lng_new_version7007" = "Telegram Desktop was updated to version {version}\n\n — Tray icon added in Ubuntu\n\nFull version history is available here:\n{link}";
|
"lng_new_version7009" = "Telegram Desktop was updated to version {version}\n\n — Added Korean language\n — Quick «open with» menu on Windows and OS X\n\nFull version history is available here:\n{link}";
|
||||||
"lng_new_version7006_appstore" = "Telegram Desktop was updated to version {version}\n\n — Stickers support\n — Local caching for voice messages\n — Added new languages\n\nFull version history is available here:\n{link}";
|
"lng_new_version7006_appstore" = "Telegram Desktop was updated to version {version}\n\n — Stickers support\n — Local caching for voice messages\n — Added new languages\n\nFull version history is available here:\n{link}";
|
||||||
|
|
||||||
|
// Wnd specific
|
||||||
|
|
||||||
|
"lng_wnd_choose_program_menu" = "Choose default program...";
|
||||||
|
|
||||||
// Mac specific
|
// Mac specific
|
||||||
|
|
||||||
|
"lng_mac_choose_program_menu" = "Other...";
|
||||||
|
|
||||||
"lng_mac_choose_app" = "Choose Application";
|
"lng_mac_choose_app" = "Choose Application";
|
||||||
"lng_mac_choose_text" = "Choose an application to open the document \"{file}\".";
|
"lng_mac_choose_text" = "Choose an application to open the document \"{file}\".";
|
||||||
"lng_mac_enable_filter" = "Enable:";
|
"lng_mac_enable_filter" = "Enable:";
|
||||||
|
|
|
@ -699,8 +699,8 @@ void Application::startApp() {
|
||||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||||
if (Local::oldMapVersion() < AppVersion) {
|
if (Local::oldMapVersion() < AppVersion) {
|
||||||
psRegisterCustomScheme();
|
psRegisterCustomScheme();
|
||||||
if (Local::oldMapVersion() && Local::oldMapVersion() < 7007 && (cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64)) {
|
if (Local::oldMapVersion() && Local::oldMapVersion() < 7009) {
|
||||||
QString versionFeatures(lng_new_version7007(lt_version, QString::fromStdWString(AppVersionStr), lt_link, qsl("https://desktop.telegram.org/#changelog")));
|
QString versionFeatures(lng_new_version7009(lt_version, QString::fromStdWString(AppVersionStr), lt_link, qsl("https://desktop.telegram.org/#changelog")));
|
||||||
if (!versionFeatures.isEmpty()) {
|
if (!versionFeatures.isEmpty()) {
|
||||||
window->serviceNotification(versionFeatures);
|
window->serviceNotification(versionFeatures);
|
||||||
}
|
}
|
||||||
|
|
|
@ -685,6 +685,8 @@ void MTPautoConnection::onSocketDisconnected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::sendData(mtpBuffer &buffer) {
|
void MTPautoConnection::sendData(mtpBuffer &buffer) {
|
||||||
|
if (status == FinishedWork) return;
|
||||||
|
|
||||||
if (buffer.size() < 3) {
|
if (buffer.size() < 3) {
|
||||||
LOG(("TCP Error: writing bad packet, len = %1").arg(buffer.size() * sizeof(mtpPrime)));
|
LOG(("TCP Error: writing bad packet, len = %1").arg(buffer.size() * sizeof(mtpPrime)));
|
||||||
TCP_LOG(("TCP Error: bad packet %1").arg(mb(&buffer[0], buffer.size() * sizeof(mtpPrime)).str()));
|
TCP_LOG(("TCP Error: bad packet %1").arg(mb(&buffer[0], buffer.size() * sizeof(mtpPrime)).str()));
|
||||||
|
@ -722,6 +724,8 @@ void MTPautoConnection::httpSend(mtpBuffer &buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::disconnectFromServer() {
|
void MTPautoConnection::disconnectFromServer() {
|
||||||
|
if (status == FinishedWork) return;
|
||||||
|
|
||||||
Requests copy = requests;
|
Requests copy = requests;
|
||||||
requests.clear();
|
requests.clear();
|
||||||
for (Requests::const_iterator i = copy.cbegin(), e = copy.cend(); i != e; ++i) {
|
for (Requests::const_iterator i = copy.cbegin(), e = copy.cend(); i != e; ++i) {
|
||||||
|
@ -737,7 +741,7 @@ void MTPautoConnection::disconnectFromServer() {
|
||||||
sock.close();
|
sock.close();
|
||||||
|
|
||||||
httpStartTimer.stop();
|
httpStartTimer.stop();
|
||||||
status = WaitingBoth;
|
status = FinishedWork;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
|
void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
|
||||||
|
@ -758,10 +762,12 @@ void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MTPautoConnection::isConnected() {
|
bool MTPautoConnection::isConnected() {
|
||||||
return !address.isEmpty();
|
return status != FinishedWork && !address.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::requestFinished(QNetworkReply *reply) {
|
void MTPautoConnection::requestFinished(QNetworkReply *reply) {
|
||||||
|
if (status == FinishedWork) return;
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
requests.remove(reply);
|
requests.remove(reply);
|
||||||
|
@ -820,6 +826,8 @@ void MTPautoConnection::requestFinished(QNetworkReply *reply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
||||||
|
if (status == FinishedWork) return;
|
||||||
|
|
||||||
mtpBuffer data = _handleTcpResponse(packet, size);
|
mtpBuffer data = _handleTcpResponse(packet, size);
|
||||||
if (data.size() == 1) {
|
if (data.size() == 1) {
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
|
@ -884,6 +892,8 @@ QString MTPautoConnection::transport() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::socketError(QAbstractSocket::SocketError e) {
|
void MTPautoConnection::socketError(QAbstractSocket::SocketError e) {
|
||||||
|
if (status == FinishedWork) return;
|
||||||
|
|
||||||
_handleTcpError(e, sock);
|
_handleTcpError(e, sock);
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
status = WaitingHttp;
|
status = WaitingHttp;
|
||||||
|
@ -2498,8 +2508,8 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
|
||||||
}
|
}
|
||||||
|
|
||||||
if (badTime) {
|
if (badTime) {
|
||||||
DEBUG_LOG(("Message Error: bad time in updates cons"));
|
DEBUG_LOG(("Message Error: bad time in updates cons, must create new session"));
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtpBuffer update(end - from);
|
mtpBuffer update(end - from);
|
||||||
|
|
|
@ -213,6 +213,7 @@ private:
|
||||||
HttpReady,
|
HttpReady,
|
||||||
UsingHttp,
|
UsingHttp,
|
||||||
UsingTcp,
|
UsingTcp,
|
||||||
|
FinishedWork
|
||||||
};
|
};
|
||||||
Status status;
|
Status status;
|
||||||
MTPint128 tcpNonce, httpNonce;
|
MTPint128 tcpNonce, httpNonce;
|
||||||
|
|
|
@ -520,7 +520,7 @@ int64 objc_idleTime() { // taken from https://github.com/trueinteractions/tint/i
|
||||||
}
|
}
|
||||||
[menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
|
[menu insertItem:[NSMenuItem separatorItem] atIndex:index++];
|
||||||
}
|
}
|
||||||
NSMenuItem *item = [menu insertItemWithTitle:@"Other..." action:@selector(itemChosen:) keyEquivalent:@"" atIndex:index++];
|
NSMenuItem *item = [menu insertItemWithTitle:objc_lang(lng_mac_choose_program_menu).s() action:@selector(itemChosen:) keyEquivalent:@"" atIndex:index++];
|
||||||
[item setTarget:self];
|
[item setTarget:self];
|
||||||
|
|
||||||
[menu popUpMenuPositioningItem:nil atLocation:CGPointMake(x, y) inView:nil];
|
[menu popUpMenuPositioningItem:nil atLocation:CGPointMake(x, y) inView:nil];
|
||||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
#include <Shobjidl.h>
|
#include <Shobjidl.h>
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
#include <Strsafe.h>
|
#include <Strsafe.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <Windowsx.h>
|
#include <Windowsx.h>
|
||||||
|
@ -56,6 +57,7 @@ namespace {
|
||||||
bool frameless = true;
|
bool frameless = true;
|
||||||
bool useDWM = false;
|
bool useDWM = false;
|
||||||
bool useTheme = false;
|
bool useTheme = false;
|
||||||
|
bool useOpenWith = false;
|
||||||
bool useOpenAs = false;
|
bool useOpenAs = false;
|
||||||
bool themeInited = false;
|
bool themeInited = false;
|
||||||
bool finished = true;
|
bool finished = true;
|
||||||
|
@ -605,22 +607,31 @@ namespace {
|
||||||
QColor _shActive(0, 0, 0), _shInactive(0, 0, 0);
|
QColor _shActive(0, 0, 0), _shInactive(0, 0, 0);
|
||||||
|
|
||||||
typedef BOOL (FAR STDAPICALLTYPE *f_dwmDefWindowProc)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, _Out_ LRESULT *plResult);
|
typedef BOOL (FAR STDAPICALLTYPE *f_dwmDefWindowProc)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, _Out_ LRESULT *plResult);
|
||||||
f_dwmDefWindowProc dwmDefWindowProc;
|
f_dwmDefWindowProc dwmDefWindowProc = 0;
|
||||||
|
|
||||||
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmSetWindowAttribute)(HWND hWnd, DWORD dwAttribute, _In_ LPCVOID pvAttribute, DWORD cbAttribute);
|
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmSetWindowAttribute)(HWND hWnd, DWORD dwAttribute, _In_ LPCVOID pvAttribute, DWORD cbAttribute);
|
||||||
f_dwmSetWindowAttribute dwmSetWindowAttribute;
|
f_dwmSetWindowAttribute dwmSetWindowAttribute = 0;
|
||||||
|
|
||||||
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset);
|
typedef HRESULT (FAR STDAPICALLTYPE *f_dwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset);
|
||||||
f_dwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea;
|
f_dwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea = 0;
|
||||||
|
|
||||||
typedef HRESULT (FAR STDAPICALLTYPE *f_setWindowTheme)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
|
typedef HRESULT (FAR STDAPICALLTYPE *f_setWindowTheme)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
|
||||||
f_setWindowTheme setWindowTheme;
|
f_setWindowTheme setWindowTheme = 0;
|
||||||
|
|
||||||
typedef HRESULT (FAR STDAPICALLTYPE *f_openAs_RunDLL)(HWND hWnd, HINSTANCE hInstance, LPCWSTR lpszCmdLine, int nCmdShow);
|
typedef HRESULT (FAR STDAPICALLTYPE *f_openAs_RunDLL)(HWND hWnd, HINSTANCE hInstance, LPCWSTR lpszCmdLine, int nCmdShow);
|
||||||
f_openAs_RunDLL openAs_RunDLL;
|
f_openAs_RunDLL openAs_RunDLL = 0;
|
||||||
|
|
||||||
typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo);
|
typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo);
|
||||||
f_shOpenWithDialog shOpenWithDialog;
|
f_shOpenWithDialog shOpenWithDialog = 0;
|
||||||
|
|
||||||
|
typedef HRESULT (FAR STDAPICALLTYPE *f_shAssocEnumHandlers)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler);
|
||||||
|
f_shAssocEnumHandlers shAssocEnumHandlers = 0;
|
||||||
|
|
||||||
|
typedef HRESULT(FAR STDAPICALLTYPE *f_shCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
|
||||||
|
f_shCreateItemFromParsingName shCreateItemFromParsingName = 0;
|
||||||
|
|
||||||
|
typedef HRESULT(FAR STDAPICALLTYPE *f_shLoadIndirectString)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved);
|
||||||
|
f_shLoadIndirectString shLoadIndirectString = 0;
|
||||||
|
|
||||||
template <typename TFunction>
|
template <typename TFunction>
|
||||||
bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) {
|
bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) {
|
||||||
|
@ -638,7 +649,7 @@ namespace {
|
||||||
frameless = !useDWM;
|
frameless = !useDWM;
|
||||||
|
|
||||||
setupUx();
|
setupUx();
|
||||||
setupOpenAs();
|
setupShell();
|
||||||
}
|
}
|
||||||
void setupDWM() {
|
void setupDWM() {
|
||||||
HINSTANCE procId = LoadLibrary(L"DWMAPI.DLL");
|
HINSTANCE procId = LoadLibrary(L"DWMAPI.DLL");
|
||||||
|
@ -654,9 +665,20 @@ namespace {
|
||||||
if (!loadFunction(procId, "SetWindowTheme", setWindowTheme)) return;
|
if (!loadFunction(procId, "SetWindowTheme", setWindowTheme)) return;
|
||||||
useTheme = true;
|
useTheme = true;
|
||||||
}
|
}
|
||||||
void setupOpenAs() {
|
void setupShell() {
|
||||||
HINSTANCE procId = LoadLibrary(L"SHELL32.DLL");
|
HINSTANCE procId = LoadLibrary(L"SHELL32.DLL");
|
||||||
|
setupOpenWith(procId);
|
||||||
|
setupOpenAs(procId);
|
||||||
|
}
|
||||||
|
void setupOpenWith(HINSTANCE procId) {
|
||||||
|
if (!loadFunction(procId, "SHAssocEnumHandlers", shAssocEnumHandlers)) return;
|
||||||
|
if (!loadFunction(procId, "SHCreateItemFromParsingName", shCreateItemFromParsingName)) return;
|
||||||
|
useOpenWith = true;
|
||||||
|
|
||||||
|
HINSTANCE otherProcId = LoadLibrary(L"SHLWAPI.DLL");
|
||||||
|
if (otherProcId) loadFunction(otherProcId, "SHLoadIndirectString", shLoadIndirectString);
|
||||||
|
}
|
||||||
|
void setupOpenAs(HINSTANCE procId) {
|
||||||
if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return;
|
if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return;
|
||||||
useOpenAs = true;
|
useOpenAs = true;
|
||||||
}
|
}
|
||||||
|
@ -998,6 +1020,7 @@ void PsMainWindow::psUpdateWorkmode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HICON qt_pixmapToWinHICON(const QPixmap &);
|
HICON qt_pixmapToWinHICON(const QPixmap &);
|
||||||
|
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &, int hbitmapFormat);
|
||||||
static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) {
|
static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) {
|
||||||
if (!icon.isNull()) {
|
if (!icon.isNull()) {
|
||||||
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
|
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
|
||||||
|
@ -2170,6 +2193,162 @@ void psPostprocessFile(const QString &name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct OpenWithApp {
|
||||||
|
OpenWithApp(const QString &name, HBITMAP icon, IAssocHandler *handler) : name(name), icon(icon), handler(handler) {
|
||||||
|
}
|
||||||
|
OpenWithApp(const QString &name, IAssocHandler *handler) : name(name), icon(0), handler(handler) {
|
||||||
|
}
|
||||||
|
void destroy() {
|
||||||
|
if (icon) DeleteBitmap(icon);
|
||||||
|
if (handler) handler->Release();
|
||||||
|
}
|
||||||
|
QString name;
|
||||||
|
HBITMAP icon;
|
||||||
|
IAssocHandler *handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool OpenWithAppLess(const OpenWithApp &a, const OpenWithApp &b) {
|
||||||
|
return a.name < b.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP _iconToBitmap(LPWSTR icon, int iconindex) {
|
||||||
|
if (!icon) return 0;
|
||||||
|
WCHAR tmpIcon[4096];
|
||||||
|
if (icon[0] == L'@' && shLoadIndirectString && SUCCEEDED(shLoadIndirectString(icon, tmpIcon, 4096, 0))) {
|
||||||
|
icon = tmpIcon;
|
||||||
|
}
|
||||||
|
int32 w = GetSystemMetrics(SM_CXSMICON), h = GetSystemMetrics(SM_CYSMICON);
|
||||||
|
|
||||||
|
HICON ico = ExtractIcon(0, icon, iconindex);
|
||||||
|
if (!ico) {
|
||||||
|
if (!iconindex) { // try to read image
|
||||||
|
QImage img(QString::fromWCharArray(icon));
|
||||||
|
if (!img.isNull()) {
|
||||||
|
return qt_pixmapToWinHBITMAP(QPixmap::fromImage(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), /* HBitmapAlpha */ 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HDC screenDC = GetDC(0), hdc = CreateCompatibleDC(screenDC);
|
||||||
|
HBITMAP result = CreateCompatibleBitmap(screenDC, w, h);
|
||||||
|
HGDIOBJ was = SelectObject(hdc, result);
|
||||||
|
DrawIconEx(hdc, 0, 0, ico, w, h, 0, NULL, DI_NORMAL);
|
||||||
|
SelectObject(hdc, was);
|
||||||
|
DeleteDC(hdc);
|
||||||
|
ReleaseDC(0, screenDC);
|
||||||
|
|
||||||
|
DestroyIcon(ico);
|
||||||
|
|
||||||
|
return (HBITMAP)CopyImage(result, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
|
||||||
|
// return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool psShowOpenWithMenu(int x, int y, const QString &file) {
|
||||||
|
if (!useOpenWith || !App::wnd()) return false;
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
QList<OpenWithApp> handlers;
|
||||||
|
IShellItem* pItem = nullptr;
|
||||||
|
if (SUCCEEDED(shCreateItemFromParsingName(QDir::toNativeSeparators(file).toStdWString().c_str(), nullptr, IID_PPV_ARGS(&pItem)))) {
|
||||||
|
IEnumAssocHandlers *assocHandlers = 0;
|
||||||
|
if (SUCCEEDED(pItem->BindToHandler(nullptr, BHID_EnumAssocHandlers, IID_PPV_ARGS(&assocHandlers)))) {
|
||||||
|
HRESULT hr = S_FALSE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
IAssocHandler *handler = 0;
|
||||||
|
ULONG ulFetched = 0;
|
||||||
|
hr = assocHandlers->Next(1, &handler, &ulFetched);
|
||||||
|
if (FAILED(hr) || hr == S_FALSE || !ulFetched) break;
|
||||||
|
|
||||||
|
LPWSTR name = 0;
|
||||||
|
if (SUCCEEDED(handler->GetUIName(&name))) {
|
||||||
|
LPWSTR icon = 0;
|
||||||
|
int iconindex = 0;
|
||||||
|
if (SUCCEEDED(handler->GetIconLocation(&icon, &iconindex)) && icon) {
|
||||||
|
handlers.push_back(OpenWithApp(QString::fromWCharArray(name), _iconToBitmap(icon, iconindex), handler));
|
||||||
|
CoTaskMemFree(icon);
|
||||||
|
} else {
|
||||||
|
handlers.push_back(OpenWithApp(QString::fromWCharArray(name), handler));
|
||||||
|
}
|
||||||
|
CoTaskMemFree(name);
|
||||||
|
} else {
|
||||||
|
handler->Release();
|
||||||
|
}
|
||||||
|
} while (hr != S_FALSE);
|
||||||
|
assocHandlers->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handlers.isEmpty()) {
|
||||||
|
HMENU menu = CreatePopupMenu();
|
||||||
|
std::sort(handlers.begin(), handlers.end(), OpenWithAppLess);
|
||||||
|
for (int32 i = 0, l = handlers.size(); i < l; ++i) {
|
||||||
|
MENUITEMINFO menuInfo = { 0 };
|
||||||
|
menuInfo.cbSize = sizeof(menuInfo);
|
||||||
|
menuInfo.fMask = MIIM_STRING | MIIM_DATA | MIIM_ID;
|
||||||
|
menuInfo.fType = MFT_STRING;
|
||||||
|
menuInfo.wID = i + 1;
|
||||||
|
if (handlers.at(i).icon) {
|
||||||
|
menuInfo.fMask |= MIIM_BITMAP;
|
||||||
|
menuInfo.hbmpItem = handlers.at(i).icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name = handlers.at(i).name;
|
||||||
|
if (name.size() > 512) name = name.mid(0, 512);
|
||||||
|
WCHAR nameArr[1024];
|
||||||
|
name.toWCharArray(nameArr);
|
||||||
|
nameArr[name.size()] = 0;
|
||||||
|
menuInfo.dwTypeData = nameArr;
|
||||||
|
InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &menuInfo);
|
||||||
|
}
|
||||||
|
MENUITEMINFO sepInfo = { 0 };
|
||||||
|
sepInfo.cbSize = sizeof(sepInfo);
|
||||||
|
sepInfo.fMask = MIIM_STRING | MIIM_DATA;
|
||||||
|
sepInfo.fType = MFT_SEPARATOR;
|
||||||
|
InsertMenuItem(menu, GetMenuItemCount(menu), true, &sepInfo);
|
||||||
|
|
||||||
|
MENUITEMINFO menuInfo = { 0 };
|
||||||
|
menuInfo.cbSize = sizeof(menuInfo);
|
||||||
|
menuInfo.fMask = MIIM_STRING | MIIM_DATA | MIIM_ID;
|
||||||
|
menuInfo.fType = MFT_STRING;
|
||||||
|
menuInfo.wID = handlers.size() + 1;
|
||||||
|
|
||||||
|
QString name = lang(lng_wnd_choose_program_menu);
|
||||||
|
if (name.size() > 512) name = name.mid(0, 512);
|
||||||
|
WCHAR nameArr[1024];
|
||||||
|
name.toWCharArray(nameArr);
|
||||||
|
nameArr[name.size()] = 0;
|
||||||
|
menuInfo.dwTypeData = nameArr;
|
||||||
|
InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &menuInfo);
|
||||||
|
|
||||||
|
int sel = TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, x, y, 0, App::wnd()->psHwnd(), 0);
|
||||||
|
DestroyMenu(menu);
|
||||||
|
|
||||||
|
if (sel > 0) {
|
||||||
|
if (sel <= handlers.size()) {
|
||||||
|
IDataObject *dataObj = 0;
|
||||||
|
IEnumAssocHandlers *assocHandlers = 0;
|
||||||
|
if (SUCCEEDED(pItem->BindToHandler(nullptr, BHID_DataObject, IID_PPV_ARGS(&dataObj))) && dataObj) {
|
||||||
|
handlers.at(sel - 1).handler->Invoke(dataObj);
|
||||||
|
dataObj->Release();
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
for (int i = 0, l = handlers.size(); i < l; ++i) {
|
||||||
|
handlers[i].destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pItem->Release();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void psOpenFile(const QString &name, bool openWith) {
|
void psOpenFile(const QString &name, bool openWith) {
|
||||||
std::wstring wname = QDir::toNativeSeparators(name).toStdWString();
|
std::wstring wname = QDir::toNativeSeparators(name).toStdWString();
|
||||||
|
|
||||||
|
@ -2305,10 +2484,6 @@ void psExecTelegram() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool psShowOpenWithMenu(int x, int y, const QString &file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args, const wchar_t *description) {
|
void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args, const wchar_t *description) {
|
||||||
WCHAR startupFolder[MAX_PATH];
|
WCHAR startupFolder[MAX_PATH];
|
||||||
HRESULT hres = SHGetFolderPath(0, path_csidl, 0, SHGFP_TYPE_CURRENT, startupFolder);
|
HRESULT hres = SHGetFolderPath(0, path_csidl, 0, SHGFP_TYPE_CURRENT, startupFolder);
|
||||||
|
|
Loading…
Add table
Reference in a new issue