From cbd2d6c8daf27d893bb89b4be8a1d2d2076dcc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Fri, 5 Jul 2013 12:05:49 +0200 Subject: [PATCH] Issue #123 better context menu integration (Windows) --- .../com/jpexs/decompiler/flash/gui/Main.java | 126 +++++++++++++----- .../jpexs/decompiler/flash/gui/MainFrame.java | 10 +- 2 files changed, 94 insertions(+), 42 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index ee573fb97..eae68c22f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -48,6 +48,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Properties; +import java.util.TreeMap; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Level; @@ -110,9 +111,10 @@ public class Main { } /** - * Dump tags to stdout + * Get title of the file + * + * @return file title */ - // public static String getFileTitle() { if (maskURL != null) { return maskURL; @@ -449,8 +451,8 @@ public class Main { boolean offered = (Boolean) Configuration.getConfig("offeredAssociation", Boolean.FALSE); if (!offered) { if (Platform.isWindows()) { - if ((!isAssociated()) && JOptionPane.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { - associate(true); + if ((!isAddedToContextMenu()) && JOptionPane.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { + addToContextMenu(true); } } } @@ -459,6 +461,7 @@ public class Main { /** * @param args the command line arguments + * @throws IOException */ public static void main(String[] args) throws IOException { loadProperties(); @@ -478,10 +481,10 @@ public class Main { offerAssociation(); showModeFrame(); } else { - if (args[pos].equals("-unassociate")) { - associate(false); - } else if (args[pos].equals("-associate")) { - associate(true); + if (args[pos].equals("-removefromcontextmenu")) { + addToContextMenu(false); + } else if (args[pos].equals("-addtocontextmenu")) { + addToContextMenu(true); } else if (args[pos].equals("-proxy")) { int port = 55555; for (int i = pos; i < args.length; i++) { @@ -983,18 +986,19 @@ public class Main { return getFFDecHome() + CONFIG_NAME; } - public static boolean isAssociated() { + public static boolean isAddedToContextMenu() { if (!Platform.isWindows()) { return false; } - if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, ".swf")) { + final String classesPath = "Software\\Classes\\"; + if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf")) { return false; } - String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_CLASSES_ROOT, ".swf", ""); + String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf", ""); if (clsName == null) { return false; } - return Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec"); + return Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); } public static String getAppDir() { @@ -1010,51 +1014,99 @@ public class Main { return appDir; } - public static boolean associate(boolean value) { - if (value == isAssociated()) { + public static boolean addToContextMenu(boolean add) { + if (add == isAddedToContextMenu()) { return true; } String appDir = getAppDir(); + String exeName = "ffdec.exe"; + final String classesPath = "Software\\Classes\\"; try { - if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, ".swf")) { - Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, ".swf"); - Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, ".swf", "", "ShockwaveFlash.ShockwaveFlash"); + // 1) Add to context menu of SWF + if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf")) { + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf"); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf", "", "ShockwaveFlash.ShockwaveFlash"); } - String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_CLASSES_ROOT, ".swf", ""); - if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, clsName)) { - Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, clsName); - Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, clsName, "", "Flash Movie"); + String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf", ""); + if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName)) { + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName, "", "Flash Movie"); } - if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell")) { - Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell"); + if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell")) { + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell"); } - boolean exists = Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec"); + boolean exists = Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); - //String shellName = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\" + clsName + "\\shell\\ffdec", ""); - if ((!exists) && value) { - Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec"); - Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec", "", "Open with FFDec"); - Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec\\command"); - Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec\\command", "", "\"" + appDir + "ffdec.exe\" \"%1\""); - return true; - } - if (exists && (!value)) { //unassociate - Advapi32Util.registryDeleteKey(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec\\command"); - Advapi32Util.registryDeleteKey(WinReg.HKEY_CLASSES_ROOT, clsName + "\\shell\\ffdec"); + if ((!exists) && add) { //add + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec", "", "Open with FFDec"); + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec\\command"); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec\\command", "", "\"" + appDir + exeName + "\" \"%1\""); + } + if (exists && (!add)) { //remove + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec\\command"); + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); + } + + exists = Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName); + if ((!exists) && add) { //add + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName); + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell"); + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open"); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open", "", "Open with FFDec"); + Advapi32Util.registryCreateKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open\\command"); + Advapi32Util.registrySetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open\\command", "", "\"" + appDir + "ffdec.exe\" \"%1\""); + + } + if (exists && (!add)) { //remove + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open\\command"); + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell\\open"); + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName + "\\shell"); + Advapi32Util.registryDeleteKey(WinReg.HKEY_LOCAL_MACHINE, classesPath + "Applications\\" + exeName); + } + //2) Add to OpenWith list + String mruList = Advapi32Util.registryGetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "MRUList"); + if (mruList != null) { + exists = false; + char appChar = 0; + for (int i = 0; i < mruList.length(); i++) { + String app = Advapi32Util.registryGetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "" + mruList.charAt(i)); + if (app.equals(exeName)) { + appChar = mruList.charAt(i); + exists = true; + break; + } + } + if ((!exists) && add) { //add + for (int c = 'a'; c <= 'z'; c++) { + if (mruList.indexOf(c) == -1) { + mruList += (char) c; + Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "" + (char) c, exeName); + Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "MRUList", mruList); + break; + } + } + } + if (exists && (!add)) { //remove + mruList = mruList.replace("" + appChar, ""); + Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "MRUList", mruList); + Advapi32Util.registryDeleteValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.swf\\OpenWithList", "" + appChar); + } return true; } + } catch (Exception ex) { //Updating registry failed, try elevating rights SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO(); sei.fMask = 0x00000040; sei.lpVerb = new WString("runas"); - sei.lpFile = new WString(appDir + "ffdec.exe"); - sei.lpParameters = new WString(value ? "-associate" : "-unassociate"); + sei.lpFile = new WString(appDir + exeName); + sei.lpParameters = new WString(add ? "-addtocontextmenu" : "-removefromcontextmenu"); sei.nShow = WinUser.SW_NORMAL; Shell32.INSTANCE.ShellExecuteEx(sei); //Wait till exit diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 43efcd5cf..15ae53813 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -27,7 +27,7 @@ import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import static com.jpexs.decompiler.flash.gui.Main.isAssociated; +import static com.jpexs.decompiler.flash.gui.Main.isAddedToContextMenu; import com.jpexs.decompiler.flash.gui.abc.ABCPanel; import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; @@ -462,7 +462,7 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection miAssociate = new JCheckBoxMenuItem(translate("menu.settings.addtocontextmenu")); miAssociate.setActionCommand("ASSOCIATE"); miAssociate.addActionListener(this); - miAssociate.setState(isAssociated()); + miAssociate.setState(isAddedToContextMenu()); JMenuItem miLanguage = new JMenuItem(translate("menu.settings.language")); @@ -1537,16 +1537,16 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection doFilter(); break; case "ASSOCIATE": - if (miAssociate.getState() == Main.isAssociated()) { + if (miAssociate.getState() == Main.isAddedToContextMenu()) { return; } - Main.associate(miAssociate.getState()); + Main.addToContextMenu(miAssociate.getState()); //Update checkbox menuitem accordingly (User can cancel rights elevation) new Timer().schedule(new TimerTask() { @Override public void run() { - miAssociate.setState(Main.isAssociated()); + miAssociate.setState(Main.isAddedToContextMenu()); } }, 500); //It takes some time registry change to apply break;