New feature: Opens file in its default viewer

This feature has the same effect as double-clicking this file in Windows Explorer.

Closes #3577, fixes #3576
This commit is contained in:
Cyrillev 2017-07-30 09:10:36 +02:00 committed by Don HO
parent 2593d64fbb
commit fbbe9344d9
11 changed files with 107 additions and 31 deletions

View File

@ -91,7 +91,7 @@
<Item id="41017" name="Rename..."/>
<Item id="41021" name="Restore Recent Closed File"/>
<Item id="41022" name="Open Folder as &amp;Workspace"/>
<Item id="41023" name="Open in Default Viewer"/>
<Item id="42001" name="Cu&amp;t"/>
<Item id="42002" name="&amp;Copy"/>
<Item id="42003" name="&amp;Undo"/>
@ -334,6 +334,7 @@
<Item CMID="18" name="Close All to the Right"/>
<Item CMID="19" name="Open Containing Folder in Explorer"/>
<Item CMID="20" name="Open Containing Folder in cmd"/>
<Item CMID="21" name="Open in Default Viewer"/>
</TabBar>
</Menu>

View File

@ -95,6 +95,7 @@
<Item id="41017" name="Renommer..."/>
<Item id="41021" name="Ouvrir le dernier fichier fermé"/>
<Item id="41022" name="Ouvrir Dossier en tant qu'Espace de travail"/>
<Item id="41023" name="Ouvrir dans l'application par défaut"/>
<Item id="42001" name="Cou&amp;per"/>
<Item id="42002" name="&amp;Copier"/>
<Item id="42003" name="&amp;Annuler"/>
@ -331,6 +332,7 @@
<Item CMID="18" name="Fermer les onglets sur la droite"/>
<Item CMID="19" name="Ouvrir le répertoire du fichier en cours dans Explorer"/>
<Item CMID="20" name="Ouvrir le répertoire du fichier en cours dans cmd"/>
<Item CMID="21" name="Ouvrir dans l'application par défaut"/>
</TabBar>
</Menu>
<Dialog>

View File

@ -1101,3 +1101,28 @@ bool isCertificateValidated(const generic_string & fullFilePath, const generic_s
return isOK;
}
bool isAssoCommandExisting(LPCTSTR FullPathName)
{
bool isAssoCommandExisting = false;
bool isFileExisting = PathFileExists(FullPathName) != FALSE;
if (isFileExisting)
{
PTSTR ext = PathFindExtension(FullPathName);
HRESULT hres;
wchar_t buffer[MAX_PATH] = TEXT("");
DWORD bufferLen = MAX_PATH;
// check if association exist
hres = AssocQueryString(ASSOCF_VERIFY|ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_COMMAND, ext, NULL, buffer, &bufferLen);
isAssoCommandExisting = (hres == S_OK) // check if association exist and no error
&& (buffer != NULL) // check if buffer is not NULL
&& (wcsstr(buffer, TEXT("notepad++.exe")) == NULL); // check association with notepad++
}
return isAssoCommandExisting;
}

View File

@ -187,3 +187,4 @@ generic_string uintToString(unsigned int val);
HWND CreateToolTip(int toolID, HWND hDlg, HINSTANCE hInst, const PTSTR pszText);
bool isCertificateValidated(const generic_string & fullFilePath, const generic_string & subjectName2check);
bool isAssoCommandExisting(LPCTSTR FullPathName);

View File

@ -49,6 +49,7 @@
#include "functionListPanel.h"
#include "fileBrowser.h"
#include "LongRunningOperation.h"
#include "Common.h"
using namespace std;
@ -1943,6 +1944,8 @@ void Notepad_plus::checkDocState()
enableCommand(IDM_FILE_OPEN_FOLDER, isFileExisting, MENU);
enableCommand(IDM_FILE_RELOAD, isFileExisting, MENU);
enableCommand(IDM_FILE_OPEN_DEFAULT_VIEWER, isAssoCommandExisting(curBuf->getFullPathName()), MENU);
enableConvertMenuItems(curBuf->getEolFormat());
checkUnicodeMenuItems();
checkLangsMenu(-1);

View File

@ -222,6 +222,7 @@ BEGIN
MENUITEM "Explorer", IDM_FILE_OPEN_FOLDER
MENUITEM "cmd", IDM_FILE_OPEN_CMD
END
MENUITEM "Open in Default Viewer" IDM_FILE_OPEN_DEFAULT_VIEWER
MENUITEM "Open Folder as Workspace...", IDM_FILE_OPENFOLDERASWORSPACE
MENUITEM "Re&load from Disk", IDM_FILE_RELOAD
MENUITEM "&Save", IDM_FILE_SAVE

View File

@ -105,6 +105,34 @@ void Notepad_plus::command(int id)
}
break;
case IDM_FILE_OPEN_DEFAULT_VIEWER:
{
// Opens file in its default viewer.
// Has the same effect as doubleclicking this file in Windows Explorer.
BufferID buf = _pEditView->getCurrentBufferID();
HINSTANCE res = ::ShellExecute(NULL, TEXT("open"), buf->getFullPathName(), NULL, NULL, SW_SHOW);
// As per MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx)
// If the function succeeds, it returns a value greater than 32.
// If the function fails, it returns an error value that indicates the cause of the failure.
int retResult = reinterpret_cast<int>(res);
if (retResult <= 32)
{
generic_string errorMsg;
errorMsg += GetLastErrorAsString(retResult);
errorMsg += TEXT("An attempt was made to execute the below command.");
errorMsg += TEXT("\n----------------------------------------------------------");
errorMsg += TEXT("\nCommand: ");
errorMsg += buf->getFullPathName();
errorMsg += TEXT("\nError Code: ");
errorMsg += intToString(retResult);
errorMsg += TEXT("\n----------------------------------------------------------");
::MessageBox(_pPublicInterface->getHSelf(), errorMsg.c_str(), TEXT("ShellExecute - ERROR"), MB_ICONINFORMATION | MB_APPLMODAL);
}
}
break;
case IDM_FILE_OPENFOLDERASWORSPACE:
{
generic_string folderPath = folderBrowser(_pPublicInterface->getHSelf(), TEXT("Select a folder to add in Folder as Workspace panel"));

View File

@ -32,6 +32,7 @@
#include "VerticalFileSwitcher.h"
#include "ProjectPanel.h"
#include "documentMap.h"
#include "Common.h"
#include <stack>
using namespace std;
@ -514,7 +515,8 @@ BOOL Notepad_plus::notify(SCNotification *notification)
if (!_tabPopupMenu.isCreated())
{
std::vector<MenuItemUnit> itemUnitArray;
// IMPORTANT: If list below is modified, you have to change the value of tabContextMenuItemPos[] in localization.cpp file
std::vector<MenuItemUnit> itemUnitArray;
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_CLOSE, TEXT("Close")));
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_CLOSEALL_BUT_CURRENT, TEXT("Close All BUT This")));
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_CLOSEALL_TOLEFT, TEXT("Close All to the Left")));
@ -529,6 +531,8 @@ BOOL Notepad_plus::notify(SCNotification *notification)
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_OPEN_FOLDER, TEXT("Open Containing Folder in Explorer")));
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_OPEN_CMD, TEXT("Open Containing Folder in cmd")));
itemUnitArray.push_back(MenuItemUnit(0, NULL));
itemUnitArray.push_back(MenuItemUnit(IDM_FILE_OPEN_DEFAULT_VIEWER, TEXT("Open in Default Viewer")));
itemUnitArray.push_back(MenuItemUnit(0, NULL));
itemUnitArray.push_back(MenuItemUnit(IDM_EDIT_SETREADONLY, TEXT("Read-Only")));
itemUnitArray.push_back(MenuItemUnit(IDM_EDIT_CLEARREADONLY, TEXT("Clear Read-Only Flag")));
itemUnitArray.push_back(MenuItemUnit(0, NULL));
@ -540,6 +544,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
itemUnitArray.push_back(MenuItemUnit(IDM_VIEW_CLONE_TO_ANOTHER_VIEW, TEXT("Clone to Other View")));
itemUnitArray.push_back(MenuItemUnit(IDM_VIEW_GOTO_NEW_INSTANCE, TEXT("Move to New Instance")));
itemUnitArray.push_back(MenuItemUnit(IDM_VIEW_LOAD_IN_NEW_INSTANCE, TEXT("Open in New Instance")));
// IMPORTANT: If list above is modified, you have to change the value of tabContextMenuItemPos[] in localization.cpp file
_tabPopupMenu.create(_pPublicInterface->getHSelf(), itemUnitArray);
_nativeLangSpeaker.changeLangTabContextMenu(_tabPopupMenu.getMenuHandle());
@ -560,6 +565,8 @@ BOOL Notepad_plus::notify(SCNotification *notification)
_tabPopupMenu.enableItem(IDM_FILE_DELETE, isFileExisting);
_tabPopupMenu.enableItem(IDM_FILE_RENAME, isFileExisting);
_tabPopupMenu.enableItem(IDM_FILE_OPEN_DEFAULT_VIEWER, isAssoCommandExisting(buf->getFullPathName()));
bool isDirty = buf->isDirty();
bool isUntitled = buf->isUntitled();
_tabPopupMenu.enableItem(IDM_VIEW_GOTO_NEW_INSTANCE, !(isDirty||isUntitled));

View File

@ -81,6 +81,7 @@ static const WinMenuKeyDefinition winKeyDefs[] =
{ VK_O, IDM_FILE_OPEN, true, false, false, nullptr },
{ VK_NULL, IDM_FILE_OPEN_FOLDER, false, false, false, nullptr },
{ VK_NULL, IDM_FILE_OPEN_CMD, false, false, false, nullptr },
{ VK_NULL, IDM_FILE_OPEN_DEFAULT_VIEWER, false, false, false, nullptr },
{ VK_NULL, IDM_FILE_OPENFOLDERASWORSPACE, false, false, false, nullptr },
{ VK_NULL, IDM_FILE_RELOAD, false, false, false, nullptr },
{ VK_S, IDM_FILE_SAVE, true, false, false, nullptr },

View File

@ -364,27 +364,32 @@ void NativeLangSpeaker::changeMenuLang(HMENU menuHandle, generic_string & plugin
static const int tabContextMenuItemPos[] =
{
// +-------------- The order in tab menu (NppNotification.cpp : if (!_tabPopupMenu.isCreated())
// |
// | +------ Number in english.xml (<language>.xml) : <TabBar>
// | |
0, // 0 : Close
1, // 1 : Close ALL BUT This
4, // 2 : Save
5, // 3 : Save As
9, // 4 : Print
21, // 5 : Move to Other View
22, // 6 : Clone to Other View
17, // 7 : Full File Path to Clipboard
18, // 8 : Filename to Clipboard
19, // 9 : Current Dir. Path to Clipboard
23, // 5 : Move to Other View
24, // 6 : Clone to Other View
19, // 7 : Full File Path to Clipboard
20, // 8 : Filename to Clipboard
21, // 9 : Current Dir. Path to Clipboard
6, // 10: Rename
7, // 11: Move to Recycle Bin
14, // 12: Read-Only
15, // 13: Clear Read-Only Flag
23, // 14: Move to New Instance
24, // 15: Open to New Instance
16, // 12: Read-Only
17, // 13: Clear Read-Only Flag
25, // 14: Move to New Instance
26, // 15: Open to New Instance
8, // 16: Reload
2, // 17: Close ALL to the Left
3, // 18: Close ALL to the Right
11, // 19: Open Containing Folder in Explorer
12, // 20: Open Containing Folder in cmd
14, // 21: Open in Default Viewer
-1 //-------End
};

View File

@ -56,10 +56,11 @@
#define IDM_FILE_OPEN_CMD (IDM_FILE + 20)
#define IDM_FILE_RESTORELASTCLOSEDFILE (IDM_FILE + 21)
#define IDM_FILE_OPENFOLDERASWORSPACE (IDM_FILE + 22)
#define IDM_FILE_OPEN_DEFAULT_VIEWER (IDM_FILE + 23)
// IMPORTANT: If list above is modified, you have to change the following values:
// To be updated if new menu item(s) is (are) added in menu "File"
#define IDM_FILEMENU_LASTONE IDM_FILE_OPENFOLDERASWORSPACE
#define IDM_FILEMENU_LASTONE IDM_FILE_OPEN_DEFAULT_VIEWER
// 0 based position of command "Exit" including the bars in the file menu
// and without counting "Recent files history" items
@ -68,25 +69,26 @@
// 1 Open...
// 2 Open Containing Folder
// 3 Open Folder as Workspace
// 4 Reload from Disk
// 5 Save
// 6 Save As...
// 7 Save a Copy As...
// 8 Save All
// 9 Rename...
//10 Close
//11 Close All
//12 Close More
//13 Move to Recycle Bin
//14 --------
//15 Load Session...
//16 Save Session...
//17 --------
//18 Print...
//19 Print Now
//20 --------
//21 Exit
#define IDM_FILEMENU_EXISTCMDPOSITION 21
// 4 Open in Default Viewer
// 5 Reload from Disk
// 6 Save
// 7 Save As...
// 8 Save a Copy As...
// 9 Save All
//10 Rename...
//11 Close
//12 Close All
//13 Close More
//14 Move to Recycle Bin
//15 --------
//16 Load Session...
//17 Save Session...
//18 --------
//19 Print...
//20 Print Now
//21 --------
//22 Exit
#define IDM_FILEMENU_EXISTCMDPOSITION 22
#define IDM_EDIT (IDM + 2000)