diff --git a/LanguageMaster.xml b/LanguageMaster.xml
index 05e6389b5..fe27b25a9 100644
--- a/LanguageMaster.xml
+++ b/LanguageMaster.xml
@@ -2042,6 +2042,7 @@ can edit in same subtitle file (collaboration)
Word lists
ASS/SSA Style
Network
+ File type associations
Rules
Show tool bar buttons
New
@@ -2506,6 +2507,8 @@ Continue?
OCR
Edit
Shortcuts: Allow single letter/number in text box
+ Update file type associations
+ File type associations updated
Download mpv lib
diff --git a/build.bat b/build.bat
index a7f35a1a8..48ad47d4e 100644
--- a/build.bat
+++ b/build.bat
@@ -172,7 +172,8 @@ IF NOT EXIST "temp_zip" MD "temp_zip"
IF NOT EXIST "temp_zip\Languages" MD "temp_zip\Languages"
IF NOT EXIST "temp_zip\Dictionaries" MD "temp_zip\Dictionaries"
IF NOT EXIST "temp_zip\Ocr" MD "temp_zip\Ocr"
-IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302"
+IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302"
+IF NOT EXIST "temp_zip\Icons" MD "temp_zip\Icons"
ECHO.
COPY /Y /V "..\..\..\..\LICENSE.txt" "temp_zip\"
@@ -193,6 +194,7 @@ COPY /Y /V "Languages\*.xml" "temp_zip\Languages\"
COPY /Y /V "..\..\..\..\Dictionaries\*.*" "temp_zip\Dictionaries\"
COPY /Y /V "..\..\..\..\Ocr\*.*" "temp_zip\Ocr\"
XCOPY /Y /V "..\..\..\..\Tesseract302\*.*" "temp_zip\Tesseract302\" /S
+COPY /Y /V "..\..\..\..\Icons\*.ico" "temp_zip\Icons\"
PUSHD "temp_zip"
START "" /B /WAIT "%SEVENZIP%" a -tzip -mx=9 "SubtitleEdit-%VERSION%.zip" * >NUL
diff --git a/build_beta.bat b/build_beta.bat
index df9b64fa0..9fa1baff5 100644
--- a/build_beta.bat
+++ b/build_beta.bat
@@ -160,7 +160,8 @@ IF NOT EXIST "temp_zip" MD "temp_zip"
IF NOT EXIST "temp_zip\Languages" MD "temp_zip\Languages"
IF NOT EXIST "temp_zip\Dictionaries" MD "temp_zip\Dictionaries"
IF NOT EXIST "temp_zip\Ocr" MD "temp_zip\Ocr"
-IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302"
+IF NOT EXIST "temp_zip\Tesseract302" MD "temp_zip\Tesseract302"
+IF NOT EXIST "temp_zip\Icons" MD "temp_zip\Icons"
ECHO.
COPY /Y /V "..\..\..\..\LICENSE.txt" "temp_zip\"
@@ -181,6 +182,7 @@ COPY /Y /V "Languages\*.xml" "temp_zip\Languages\"
COPY /Y /V "..\..\..\..\Dictionaries\*.*" "temp_zip\Dictionaries\"
COPY /Y /V "..\..\..\..\Ocr\*.*" "temp_zip\Ocr\"
XCOPY /Y /V "..\..\..\..\Tesseract302\*.*" "temp_zip\Tesseract302\" /S
+COPY /Y /V "..\..\..\..\Icons\*.ico" "temp_zip\Icons\"
PUSHD "temp_zip"
START "" /B /WAIT "%SEVENZIP%" a -tzip -mx=9 "SubtitleEditBeta.zip" * >NUL
diff --git a/installer/Subtitle_Edit_installer.iss b/installer/Subtitle_Edit_installer.iss
index e4fa073c3..234fe5b76 100644
--- a/installer/Subtitle_Edit_installer.iss
+++ b/installer/Subtitle_Edit_installer.iss
@@ -435,55 +435,55 @@ Filename: {win}\Microsoft.NET\Framework64\v4.0.30319\ngen.exe; Parameters: "unin
[Registry]
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""
-Root: HKA ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\SubtitleEdit.EXE,0";
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""
+Root: HKCU ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\SubtitleEdit.EXE,0";
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
-Root: HKA ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}.ass"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ass.ico"; Check: DoSystemAssoc('ass')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
+Root: HKCU ; Subkey: "Software\Classes\.ass"; ValueData: "{#SetupSetting('AppName')}.ass"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ass')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ass\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ass.ico"; Check: DoSystemAssoc('ass')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
-Root: HKA ; Subkey: "Software\Classes\.dfxp"; ValueData: "{#SetupSetting('AppName')}.dfxp"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\dfxp.ico"; Check: DoSystemAssoc('dfxp')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
+Root: HKCU ; Subkey: "Software\Classes\.dfxp"; ValueData: "{#SetupSetting('AppName')}.dfxp"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('dfxp')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.dfxp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\dfxp.ico"; Check: DoSystemAssoc('dfxp')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
-Root: HKA ; Subkey: "Software\Classes\.sbv"; ValueData: "{#SetupSetting('AppName')}.sbv"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sbv.ico"; Check: DoSystemAssoc('sbv')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
+Root: HKCU ; Subkey: "Software\Classes\.sbv"; ValueData: "{#SetupSetting('AppName')}.sbv"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sbv')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sbv\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sbv.ico"; Check: DoSystemAssoc('sbv')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
-Root: HKA ; Subkey: "Software\Classes\.srt"; ValueData: "{#SetupSetting('AppName')}.srt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\srt.ico"; Check: DoSystemAssoc('srt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
+Root: HKCU ; Subkey: "Software\Classes\.srt"; ValueData: "{#SetupSetting('AppName')}.srt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('srt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.srt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\srt.ico"; Check: DoSystemAssoc('srt')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
-Root: HKA ; Subkey: "Software\Classes\.ssa"; ValueData: "{#SetupSetting('AppName')}.ssa"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ssa.ico"; Check: DoSystemAssoc('ssa')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
+Root: HKCU ; Subkey: "Software\Classes\.ssa"; ValueData: "{#SetupSetting('AppName')}.ssa"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('ssa')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.ssa\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\ssa.ico"; Check: DoSystemAssoc('ssa')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
-Root: HKA ; Subkey: "Software\Classes\.stl"; ValueData: "{#SetupSetting('AppName')}.stl"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\stl.ico"; Check: DoSystemAssoc('stl')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
+Root: HKCU ; Subkey: "Software\Classes\.stl"; ValueData: "{#SetupSetting('AppName')}.stl"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('stl')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.stl\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\stl.ico"; Check: DoSystemAssoc('stl')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
-Root: HKA ; Subkey: "Software\Classes\.sub"; ValueData: "{#SetupSetting('AppName')}.sub"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sub.ico"; Check: DoSystemAssoc('sub')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
+Root: HKCU ; Subkey: "Software\Classes\.sub"; ValueData: "{#SetupSetting('AppName')}.sub"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sub')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sub\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sub.ico"; Check: DoSystemAssoc('sub')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
-Root: HKA ; Subkey: "Software\Classes\.sup"; ValueData: "{#SetupSetting('AppName')}.sup"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sup.ico"; Check: DoSystemAssoc('sup')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
+Root: HKCU ; Subkey: "Software\Classes\.sup"; ValueData: "{#SetupSetting('AppName')}.sup"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('sup')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.sup\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\sup.ico"; Check: DoSystemAssoc('sup')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
-Root: HKA ; Subkey: "Software\Classes\.vtt"; ValueData: "{#SetupSetting('AppName')}.vtt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
-Root: HKA ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\vtt.ico"; Check: DoSystemAssoc('vtt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt"; ValueData: "{app}\{#SetupSetting('AppExeName')}"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\shell\open\command"; ValueData: """{app}\SubtitleEdit.exe"" ""%1"""; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
+Root: HKCU ; Subkey: "Software\Classes\.vtt"; ValueData: "{#SetupSetting('AppName')}.vtt"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Check: DoSystemAssoc('vtt')
+Root: HKCU ; Subkey: "Software\Classes\{#SetupSetting('AppName')}.vtt\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\Icons\vtt.ico"; Check: DoSystemAssoc('vtt')
; Add .ass (Advanced SubStation Alpha) to the SE-supported file types
Root: HKLM; Subkey: "{#keyApps}\SubtitleEdit.exe\SupportedTypes"; ValueType: string; ValueName: ".ass"; ValueData: ""; Check: HklmKeyExists('{#keyApps}')
@@ -556,11 +556,11 @@ var
CurrentProgId, MyProgId, KeyName: String;
begin
KeyName := '{#keyCl}\.' + FileType;
- if RegQueryStringValue(HKEY_LOCAL_MACHINE, KeyName, '', CurrentProgId) then
+ if RegQueryStringValue(HKEY_CURRENT_USER, KeyName, '', CurrentProgId) then
begin
MyProgId := 'SubtitleEdit.' + FileType;
if CompareText(CurrentProgId, MyProgId) = 0 then
- RegWriteStringValue(HKEY_LOCAL_MACHINE, KeyName, '', '');
+ RegWriteStringValue(HKEY_CURRENT_USER, KeyName, '', '');
end;
Result := IsTaskSelected('associate_common');
end;
diff --git a/src/ui/Forms/Options/Settings.Designer.cs b/src/ui/Forms/Options/Settings.Designer.cs
index 8af4026b4..5a29a0685 100644
--- a/src/ui/Forms/Options/Settings.Designer.cs
+++ b/src/ui/Forms/Options/Settings.Designer.cs
@@ -415,6 +415,12 @@
this.buttonReset = new System.Windows.Forms.Button();
this.toolTipContinuationPreview = new System.Windows.Forms.ToolTip(this.components);
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
+ this.panelFileTypeAssociations = new System.Windows.Forms.Panel();
+ this.labelUpdateFileTypeAssociationsStatus = new System.Windows.Forms.Label();
+ this.buttonUpdateFileTypeAssociations = new System.Windows.Forms.Button();
+ this.listViewFileTypeAssociations = new System.Windows.Forms.ListView();
+ this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.imageListFileTypeAssociations = new System.Windows.Forms.ImageList(this.components);
this.panelGeneral.SuspendLayout();
this.groupBoxMiscellaneous.SuspendLayout();
this.groupBoxGeneralRules.SuspendLayout();
@@ -487,6 +493,7 @@
this.groupBoxNetworkSession.SuspendLayout();
this.groupBoxProxySettings.SuspendLayout();
this.groupBoxProxyAuthentication.SuspendLayout();
+ this.panelFileTypeAssociations.SuspendLayout();
this.SuspendLayout();
//
// buttonOK
@@ -529,7 +536,8 @@
"Wordlists",
"Toolbar",
"Font",
- "Network"});
+ "Network",
+ "File type associations"});
this.listBoxSection.Location = new System.Drawing.Point(10, 10);
this.listBoxSection.Name = "listBoxSection";
this.listBoxSection.Size = new System.Drawing.Size(214, 516);
@@ -5009,11 +5017,60 @@
this.toolTipContinuationPreview.InitialDelay = 500;
this.toolTipContinuationPreview.ReshowDelay = 100;
//
+ // panelFileTypeAssociations
+ //
+ this.panelFileTypeAssociations.Controls.Add(this.labelUpdateFileTypeAssociationsStatus);
+ this.panelFileTypeAssociations.Controls.Add(this.buttonUpdateFileTypeAssociations);
+ this.panelFileTypeAssociations.Controls.Add(this.listViewFileTypeAssociations);
+ this.panelFileTypeAssociations.Location = new System.Drawing.Point(230, 6);
+ this.panelFileTypeAssociations.Name = "panelFileTypeAssociations";
+ this.panelFileTypeAssociations.Size = new System.Drawing.Size(852, 521);
+ this.panelFileTypeAssociations.TabIndex = 16;
+ //
+ // labelUpdateFileTypeAssociationsStatus
+ //
+ this.labelUpdateFileTypeAssociationsStatus.AutoSize = true;
+ this.labelUpdateFileTypeAssociationsStatus.Location = new System.Drawing.Point(16, 294);
+ this.labelUpdateFileTypeAssociationsStatus.Name = "labelUpdateFileTypeAssociationsStatus";
+ this.labelUpdateFileTypeAssociationsStatus.Size = new System.Drawing.Size(35, 13);
+ this.labelUpdateFileTypeAssociationsStatus.TabIndex = 24;
+ this.labelUpdateFileTypeAssociationsStatus.Text = "label2";
+ //
+ // buttonUpdateFileTypeAssociations
+ //
+ this.buttonUpdateFileTypeAssociations.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonUpdateFileTypeAssociations.Location = new System.Drawing.Point(16, 260);
+ this.buttonUpdateFileTypeAssociations.Name = "buttonUpdateFileTypeAssociations";
+ this.buttonUpdateFileTypeAssociations.Size = new System.Drawing.Size(218, 23);
+ this.buttonUpdateFileTypeAssociations.TabIndex = 23;
+ this.buttonUpdateFileTypeAssociations.Text = "Update file type associations";
+ this.buttonUpdateFileTypeAssociations.UseVisualStyleBackColor = true;
+ this.buttonUpdateFileTypeAssociations.Click += new System.EventHandler(this.buttonUpdateFileTypeAssociations_Click);
+ //
+ // listViewFileTypeAssociations
+ //
+ this.listViewFileTypeAssociations.CheckBoxes = true;
+ this.listViewFileTypeAssociations.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader1});
+ this.listViewFileTypeAssociations.HideSelection = false;
+ this.listViewFileTypeAssociations.Location = new System.Drawing.Point(0, 4);
+ this.listViewFileTypeAssociations.Name = "listViewFileTypeAssociations";
+ this.listViewFileTypeAssociations.Size = new System.Drawing.Size(849, 241);
+ this.listViewFileTypeAssociations.TabIndex = 22;
+ this.listViewFileTypeAssociations.UseCompatibleStateImageBehavior = false;
+ //
+ // imageListFileTypeAssociations
+ //
+ this.imageListFileTypeAssociations.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+ this.imageListFileTypeAssociations.ImageSize = new System.Drawing.Size(32, 32);
+ this.imageListFileTypeAssociations.TransparentColor = System.Drawing.Color.Transparent;
+ //
// Settings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1092, 574);
+ this.Controls.Add(this.panelFileTypeAssociations);
this.Controls.Add(this.panelFont);
this.Controls.Add(this.panelWaveform);
this.Controls.Add(this.panelTools);
@@ -5147,6 +5204,8 @@
this.groupBoxProxySettings.PerformLayout();
this.groupBoxProxyAuthentication.ResumeLayout(false);
this.groupBoxProxyAuthentication.PerformLayout();
+ this.panelFileTypeAssociations.ResumeLayout(false);
+ this.panelFileTypeAssociations.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -5540,5 +5599,11 @@
private System.Windows.Forms.Label labelBDOpensIn;
private System.Windows.Forms.CheckBox checkBoxShortcutsAllowLetterOrNumberInTextBox;
private System.Windows.Forms.CheckBox checkBoxWaveformAutoGen;
+ private System.Windows.Forms.Panel panelFileTypeAssociations;
+ private System.Windows.Forms.ListView listViewFileTypeAssociations;
+ private System.Windows.Forms.ColumnHeader columnHeader1;
+ private System.Windows.Forms.ImageList imageListFileTypeAssociations;
+ private System.Windows.Forms.Button buttonUpdateFileTypeAssociations;
+ private System.Windows.Forms.Label labelUpdateFileTypeAssociationsStatus;
}
}
\ No newline at end of file
diff --git a/src/ui/Forms/Options/Settings.cs b/src/ui/Forms/Options/Settings.cs
index aa42470b6..f38bc5ca9 100644
--- a/src/ui/Forms/Options/Settings.cs
+++ b/src/ui/Forms/Options/Settings.cs
@@ -33,6 +33,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
private const int ToolbarSection = 8;
private const int AppearanceSection = 9;
private const int NetworkSection = 10;
+ private const int FileTypeAssociationSection = 11;
private string _listBoxSearchString = string.Empty;
private DateTime _listBoxSearchStringLastUsed = DateTime.UtcNow;
@@ -47,6 +48,8 @@ namespace Nikse.SubtitleEdit.Forms.Options
private List _rulesProfiles;
private List _pluginShortcuts;
+ private IEnumerable GetSubtitleFormats() => SubtitleFormat.AllSubtitleFormats.Where(format => !format.IsVobSubIndexFile).Select(format => format.FriendlyName);
+
private class ComboBoxLanguage
{
public CultureInfo CultureInfo { get; set; }
@@ -115,6 +118,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
UiUtil.FixFonts(this);
UiUtil.FixLargeFonts(this, buttonOK);
Init();
+ FillFileTypeAssociationsListView();
}
public void Init()
@@ -343,6 +347,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
listBoxSection.Items[ToolbarSection] = language.Toolbar;
listBoxSection.Items[AppearanceSection] = language.Appearance;
listBoxSection.Items[NetworkSection] = language.Network;
+ listBoxSection.Items[FileTypeAssociationSection] = language.FileTypeAssociations;
Text = language.Title;
panelGeneral.Text = language.General;
@@ -1152,6 +1157,9 @@ namespace Nikse.SubtitleEdit.Forms.Options
_oldListViewShowWpm = Configuration.Settings.Tools.ListViewShowColumnWordsPerMin;
labelPlatform.Text = (IntPtr.Size * 8) + "-bit";
+
+ buttonUpdateFileTypeAssociations.Text = language.UpdateFileTypeAssociations;
+ labelUpdateFileTypeAssociationsStatus.Text = string.Empty;
}
private void SetDialogStyle(DialogType dialogStyle)
@@ -2634,6 +2642,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
panelToolBar.Visible = false;
panelFont.Visible = false;
panelNetwork.Visible = false;
+ panelFileTypeAssociations.Visible = false;
var section = panelGeneral;
switch (listBoxSection.SelectedIndex)
@@ -2668,6 +2677,9 @@ namespace Nikse.SubtitleEdit.Forms.Options
case NetworkSection:
section = panelNetwork;
break;
+ case FileTypeAssociationSection:
+ section = panelFileTypeAssociations;
+ break;
}
section.Visible = true;
@@ -3955,6 +3967,50 @@ namespace Nikse.SubtitleEdit.Forms.Options
listBoxFavoriteSubtitleFormats.SetSelected(listBoxFavoriteSubtitleFormats.Items.Count - 1, true);
}
- private IEnumerable GetSubtitleFormats() => SubtitleFormat.AllSubtitleFormats.Where(format => !format.IsVobSubIndexFile).Select(format => format.FriendlyName);
+ private void FillFileTypeAssociationsListView()
+ {
+ var iconDir = Path.Combine(Configuration.BaseDirectory, "Icons");
+ if (!Directory.Exists(iconDir))
+ {
+ return;
+ }
+
+ var iconFileNames = Directory.GetFiles(iconDir, "*.ico");
+ listViewFileTypeAssociations.LargeImageList = imageListFileTypeAssociations;
+ foreach (var iconFileName in iconFileNames)
+ {
+ var friendlyName = "." + Path.GetFileNameWithoutExtension(iconFileName).ToUpperInvariant();
+ var icon = new Icon(iconFileName);
+ imageListFileTypeAssociations.Images.Add(icon);
+ var item = new ListViewItem(friendlyName);
+ item.ImageIndex = imageListFileTypeAssociations.Images.Count - 1;
+ item.Checked = FileTypeAssociations.GetChecked("." + Path.GetFileNameWithoutExtension(iconFileName).ToLowerInvariant(), "Subtitle Edit");
+ item.Tag = iconFileName;
+ listViewFileTypeAssociations.Items.Add(item);
+ }
+ listViewFileTypeAssociations.Refresh();
+ }
+
+ private void buttonUpdateFileTypeAssociations_Click(object sender, EventArgs e)
+ {
+ var exeFileName = Assembly.GetEntryAssembly().Location;
+ foreach (ListViewItem item in listViewFileTypeAssociations.Items)
+ {
+ var ext = item.Text.ToLowerInvariant();
+ if (item.Checked)
+ {
+ var iconFileName = (string)item.Tag;
+ FileTypeAssociations.SetFileAssociationViaRegistry(ext, exeFileName, iconFileName, "Subtitle Edit");
+ }
+ else
+ {
+ FileTypeAssociations.DeleteFileAssociationViaRegistry(ext, "Subtitle Edit");
+ }
+ }
+
+ labelUpdateFileTypeAssociationsStatus.Text = LanguageSettings.Current.Settings.FileTypeAssociationsUpdated;
+ FileTypeAssociations.Refresh();
+ System.Threading.SynchronizationContext.Current.Post(TimeSpan.FromMilliseconds(3000), () => labelUpdateFileTypeAssociationsStatus.Text = string.Empty);
+ }
}
}
diff --git a/src/ui/Forms/Options/Settings.resx b/src/ui/Forms/Options/Settings.resx
index b551e3d64..33d62c9d6 100644
--- a/src/ui/Forms/Options/Settings.resx
+++ b/src/ui/Forms/Options/Settings.resx
@@ -118,21 +118,24 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- 17, 17
+ 232, 17
- 592, 17
+ 807, 17
- 253, 17
+ 468, 17
- 415, 17
+ 630, 17
- 792, 17
+ 1007, 17
- 17, 56
+ 1210, 17
+
+
+ 17, 17
\ No newline at end of file
diff --git a/src/ui/Logic/FileTypeAssociations.cs b/src/ui/Logic/FileTypeAssociations.cs
new file mode 100644
index 000000000..56d1592f6
--- /dev/null
+++ b/src/ui/Logic/FileTypeAssociations.cs
@@ -0,0 +1,80 @@
+using Microsoft.Win32;
+using System;
+using System.IO;
+
+namespace Nikse.SubtitleEdit.Logic
+{
+ internal static class FileTypeAssociations
+ {
+ [System.Runtime.InteropServices.DllImport("Shell32.dll")]
+ private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
+
+ internal static bool GetChecked(string ext, string appName)
+ {
+ using (RegistryKey key = Registry.CurrentUser.OpenSubKey($"Software\\Classes\\{appName}{ext}"))
+ {
+ if (key == null)
+ {
+ return false;
+ }
+
+ var defaultIcon = key.OpenSubKey("DefaultIcon");
+ if (defaultIcon == null)
+ {
+ return false;
+ }
+
+ var iconFileNameObject = defaultIcon.GetValue("");
+ if (iconFileNameObject == null || !(iconFileNameObject is string iconFileName) || !File.Exists(iconFileName))
+ {
+ return false;
+ }
+
+ var cmd = key.OpenSubKey("shell\\open\\command");
+ if (cmd == null)
+ {
+ return false;
+ }
+
+ var cmdObject = cmd.GetValue("");
+ if (cmdObject != null && cmdObject is string cmdString)
+ {
+ var ix = cmdString.IndexOf("SubtitleEdit.exe");
+ if (ix >= 0)
+ {
+ var exeFileName = cmdString.Substring(0, ix + "SubtitleEdit.exe".Length).Trim('"');
+ return File.Exists(exeFileName);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ internal static void SetFileAssociationViaRegistry(string ext, string exeFileName, string iconFileName, string appName)
+ {
+ Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}", "", $"{ext.TrimStart('.')} subtitle file");
+ Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}\\DefaultIcon", "", iconFileName);
+ // Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}", "FriendlyTypeName", "My Friendly Type Name");
+ Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{appName}{ext}\\shell\\open\\command", "", $"\"{exeFileName.Trim('"')}\" \"%1\"");
+ Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Classes\\{ext}", "", $"{appName}{ext}");
+ }
+
+ internal static void DeleteFileAssociationViaRegistry(string ext, string appName)
+ {
+ using (RegistryKey regkey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\", true))
+ {
+ if (regkey != null && regkey.OpenSubKey($"{appName}{ext}") != null)
+ {
+ regkey.DeleteSubKeyTree($"{appName}{ext}");
+ }
+ }
+ }
+
+ internal static void Refresh()
+ {
+ //this call notifies Windows that it needs to redo the file associations and icons
+ SHChangeNotify(0x08000000, 0x2000, IntPtr.Zero, IntPtr.Zero);
+ }
+ }
+}
diff --git a/src/ui/Logic/Language.cs b/src/ui/Logic/Language.cs
index b82fb9581..480acd8f0 100644
--- a/src/ui/Logic/Language.cs
+++ b/src/ui/Logic/Language.cs
@@ -2369,6 +2369,7 @@ can edit in same subtitle file (collaboration)",
WordLists = "Word lists",
SsaStyle = "ASS/SSA Style",
Network = "Network",
+ FileTypeAssociations = "File type associations",
Rules = "Rules",
NetworkSessionSettings = "Network session settings",
NetworkSessionNewSound = "Play sound file when new message arrives",
@@ -2833,6 +2834,8 @@ can edit in same subtitle file (collaboration)",
BDOpensInOcr = "OCR",
BDOpensInEdit = "Edit",
ShortcutsAllowSingleLetterOrNumberInTextBox = "Shortcuts: Allow single letter/number in text box",
+ UpdateFileTypeAssociations = "Update file type associations",
+ FileTypeAssociationsUpdated = "File type associations updated",
};
SettingsMpv = new LanguageStructure.SettingsMpv
diff --git a/src/ui/Logic/LanguageDeserializer.cs b/src/ui/Logic/LanguageDeserializer.cs
index fdee5edb5..87d041f8e 100644
--- a/src/ui/Logic/LanguageDeserializer.cs
+++ b/src/ui/Logic/LanguageDeserializer.cs
@@ -5503,6 +5503,9 @@ namespace Nikse.SubtitleEdit.Logic
case "Settings/Network":
language.Settings.Network = reader.Value;
break;
+ case "Settings/FileTypeAssociations":
+ language.Settings.FileTypeAssociations = reader.Value;
+ break;
case "Settings/Rules":
language.Settings.Rules = reader.Value;
break;
@@ -6883,6 +6886,12 @@ namespace Nikse.SubtitleEdit.Logic
case "Settings/ShortcutsAllowSingleLetterOrNumberInTextBox":
language.Settings.ShortcutsAllowSingleLetterOrNumberInTextBox = reader.Value;
break;
+ case "Settings/UpdateFileTypeAssociations":
+ language.Settings.UpdateFileTypeAssociations = reader.Value;
+ break;
+ case "Settings/FileTypeAssociationsUpdated":
+ language.Settings.FileTypeAssociationsUpdated = reader.Value;
+ break;
case "SettingsMpv/DownloadMpv":
language.SettingsMpv.DownloadMpv = reader.Value;
break;
diff --git a/src/ui/Logic/LanguageStructure.cs b/src/ui/Logic/LanguageStructure.cs
index 0d6f8a641..0776789ff 100644
--- a/src/ui/Logic/LanguageStructure.cs
+++ b/src/ui/Logic/LanguageStructure.cs
@@ -2218,6 +2218,7 @@
public string WordLists { get; set; }
public string SsaStyle { get; set; }
public string Network { get; set; }
+ public string FileTypeAssociations { get; set; }
public string Rules { get; set; }
public string ShowToolBarButtons { get; set; }
public string New { get; set; }
@@ -2684,6 +2685,8 @@
public string BDOpensInOcr { get; set; }
public string BDOpensInEdit { get; set; }
public string ShortcutsAllowSingleLetterOrNumberInTextBox { get; set; }
+ public string UpdateFileTypeAssociations { get; set; }
+ public string FileTypeAssociationsUpdated { get; set; }
}
public class SettingsMpv
diff --git a/src/ui/SubtitleEdit.csproj b/src/ui/SubtitleEdit.csproj
index 51d6ea739..2ed7027f7 100644
--- a/src/ui/SubtitleEdit.csproj
+++ b/src/ui/SubtitleEdit.csproj
@@ -1237,6 +1237,7 @@
+