├── .gitattributes ├── .gitignore ├── CodePreviewHandler.cs ├── CodePreviewHandler.csproj ├── CodePreviewHandler.sln ├── CodePreviewHandlerSetup ├── CodePreviewHandlerSetup.isl ├── CodePreviewHandlerSetup.isl.774 └── CodePreviewHandlerSetup.isproj ├── CppFormat.cs ├── CsharpFormat.cs ├── CssFormat.cs ├── HtmlViewer ├── Element.cs ├── FontUnit.cs ├── HtmlCommandInfo.cs ├── HtmlControl.cs ├── HtmlDocument.cs ├── HtmlEditor.cs ├── HtmlFontSize.cs ├── HtmlFormat.cs ├── HtmlSelection.cs ├── HtmlSelectionType.cs ├── HtmlTextFormatting.cs ├── Interop.cs └── MSHTMLSite.cs ├── Installer.cs ├── Libraries ├── CSharpFormat.dll └── TimHeuer.ManagedPreviewHandler.dll ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── README.md ├── Registration.cs └── UpgradeLog.htm /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## THIS PROJECT SPECIFICS 3 | ################# 4 | CodePreviewHandlerSetup/CodePreviewHandlerSetup/ 5 | 6 | ################# 7 | ## Eclipse 8 | ################# 9 | 10 | *.pydevproject 11 | .project 12 | .metadata 13 | bin/ 14 | tmp/ 15 | *.tmp 16 | *.bak 17 | *.swp 18 | *~.nib 19 | local.properties 20 | .classpath 21 | .settings/ 22 | .loadpath 23 | 24 | # External tool builders 25 | .externalToolBuilders/ 26 | 27 | # Locally stored "Eclipse launch configurations" 28 | *.launch 29 | 30 | # CDT-specific 31 | .cproject 32 | 33 | # PDT-specific 34 | .buildpath 35 | 36 | 37 | ################# 38 | ## Visual Studio 39 | ################# 40 | 41 | ## Ignore Visual Studio temporary files, build results, and 42 | ## files generated by popular Visual Studio add-ons. 43 | 44 | # User-specific files 45 | *.suo 46 | *.user 47 | *.sln.docstates 48 | 49 | # Build results 50 | [Dd]ebug/ 51 | [Rr]elease/ 52 | *_i.c 53 | *_p.c 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.vspscc 68 | .builds 69 | *.dotCover 70 | 71 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 72 | #packages/ 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opensdf 79 | *.sdf 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper* 87 | 88 | # Installshield output folder 89 | [Ee]xpress 90 | 91 | # DocProject is a documentation generator add-in 92 | DocProject/buildhelp/ 93 | DocProject/Help/*.HxT 94 | DocProject/Help/*.HxC 95 | DocProject/Help/*.hhc 96 | DocProject/Help/*.hhk 97 | DocProject/Help/*.hhp 98 | DocProject/Help/Html2 99 | DocProject/Help/html 100 | 101 | # Click-Once directory 102 | publish 103 | 104 | # Others 105 | [Bb]in 106 | [Oo]bj 107 | sql 108 | TestResults 109 | *.Cache 110 | ClientBin 111 | stylecop.* 112 | ~$* 113 | *.dbmdl 114 | Generated_Code #added for RIA/Silverlight projects 115 | 116 | # Backup & report files from converting an old project file to a newer 117 | # Visual Studio version. Backup files are not needed, because we have git ;-) 118 | _UpgradeReport_Files/ 119 | Backup*/ 120 | UpgradeLog*.XML 121 | 122 | 123 | 124 | ############ 125 | ## Windows 126 | ############ 127 | 128 | # Windows image file caches 129 | Thumbs.db 130 | 131 | # Folder config file 132 | Desktop.ini 133 | 134 | 135 | ############# 136 | ## Python 137 | ############# 138 | 139 | *.py[co] 140 | 141 | # Packages 142 | *.egg 143 | *.egg-info 144 | dist 145 | build 146 | eggs 147 | parts 148 | bin 149 | var 150 | sdist 151 | develop-eggs 152 | .installed.cfg 153 | 154 | # Installer logs 155 | pip-log.txt 156 | 157 | # Unit test / coverage reports 158 | .coverage 159 | .tox 160 | 161 | #Translations 162 | *.mo 163 | 164 | #Mr Developer 165 | .mr.developer.cfg 166 | 167 | # Mac crap 168 | .DS_Store 169 | -------------------------------------------------------------------------------- /CodePreviewHandler.cs: -------------------------------------------------------------------------------- 1 | // timheuer.com 2 | // adapted from the MSDN Magazine samples January 2007 VOL 22 NO 1 edition 3 | 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Windows.Forms; 7 | using TimHeuer.ManagedPreviewHandler; 8 | using TimHeuer.PreviewHandlers.Properties; 9 | 10 | namespace TimHeuer.PreviewHandlers 11 | { 12 | [PreviewHandler("Source Code Preview Handler", ".json;.yml;.yaml;.cs;.vb;.sql;.js;.xaml;.xml;.uix;.htm;.html;.cpp;.h;.hpp;.targets;.target", "{93E38957-78C4-40e2-9B1D-E202B43C6D23}")] 13 | [ProgId("TimHeuer.PreviewHandlers.CodePreviewHandler")] 14 | [Guid("0E1B4233-AEB5-4c5b-BF31-21766492B301")] 15 | [ClassInterface(ClassInterfaceType.None)] 16 | [ComVisible(true)] 17 | public sealed class CodePreviewHandler : FileBasedPreviewHandler 18 | { 19 | protected override PreviewHandlerControl CreatePreviewHandlerControl() 20 | { 21 | return new CodePreviewHandlerControl(); 22 | } 23 | 24 | private sealed class CodePreviewHandlerControl : FileBasedPreviewHandlerControl 25 | { 26 | public override void Load(FileInfo file) 27 | { 28 | StreamReader rdr = file.OpenText(); 29 | string previewCode = rdr.ReadToEnd(); 30 | string formattedCode = FormatCode(previewCode, file.Extension.ToLowerInvariant()); 31 | 32 | HtmlApp.Html.HtmlControl html = new HtmlApp.Html.HtmlControl(); 33 | html.LoadHtml(string.Format("{1}", Resources.CssString, formattedCode)); 34 | html.Dock = DockStyle.Fill; 35 | 36 | Controls.Add(html); 37 | } 38 | 39 | private string FormatCode(string sourceCode, string codeType) 40 | { 41 | string formatted = string.Empty; 42 | 43 | switch (codeType) 44 | { 45 | case ".h": 46 | case ".cpp": 47 | case ".hpp": 48 | CppFormat cpp = new CppFormat(); 49 | formatted = cpp.FormatCode(sourceCode); 50 | break; 51 | case ".cs": 52 | CSharpFormat cs = new CSharpFormat(); 53 | formatted = cs.FormatCode(sourceCode); 54 | break; 55 | case ".vb": 56 | Manoli.Utils.CSharpFormat.VisualBasicFormat vb = new Manoli.Utils.CSharpFormat.VisualBasicFormat(); 57 | formatted = vb.FormatCode(sourceCode); 58 | break; 59 | case ".js": 60 | Manoli.Utils.CSharpFormat.JavaScriptFormat js = new Manoli.Utils.CSharpFormat.JavaScriptFormat(); 61 | formatted = js.FormatCode(sourceCode); 62 | break; 63 | case ".sql": 64 | Manoli.Utils.CSharpFormat.TsqlFormat sql = new Manoli.Utils.CSharpFormat.TsqlFormat(); 65 | formatted = sql.FormatCode(sourceCode); 66 | break; 67 | case ".xaml": 68 | case ".xml": 69 | case ".html": 70 | case ".htm": 71 | case ".target": 72 | case ".targets": 73 | case ".uix": 74 | Manoli.Utils.CSharpFormat.HtmlFormat xml = new Manoli.Utils.CSharpFormat.HtmlFormat(); 75 | formatted = xml.FormatCode(sourceCode); 76 | break; 77 | case ".json": 78 | case ".yml": 79 | case ".yaml": 80 | Manoli.Utils.CSharpFormat.SourceFormat src = new Manoli.Utils.CSharpFormat.MshFormat(); 81 | formatted = src.FormatCode(sourceCode); 82 | break; 83 | } 84 | 85 | return formatted; 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /CodePreviewHandler.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {2B886813-EC35-476B-B14C-BC6F0459BEC6} 9 | Library 10 | Properties 11 | TimHeuer.PreviewHandlers 12 | TimHeuer.CodePreviewHandler 13 | false 14 | 15 | 16 | v2.0 17 | 18 | 19 | 20 | 21 | 2.0 22 | publish\ 23 | true 24 | Disk 25 | false 26 | Foreground 27 | 7 28 | Days 29 | false 30 | false 31 | true 32 | 0 33 | 1.0.0.%2a 34 | false 35 | false 36 | true 37 | 38 | 39 | true 40 | full 41 | false 42 | bin\Debug\ 43 | DEBUG;TRACE 44 | prompt 45 | 4 46 | 47 | 48 | pdbonly 49 | true 50 | bin\Release\ 51 | TRACE 52 | prompt 53 | 4 54 | 55 | 56 | 57 | False 58 | Libraries\CSharpFormat.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | False 68 | Libraries\TimHeuer.ManagedPreviewHandler.dll 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Component 81 | 82 | 83 | 84 | Component 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Component 95 | 96 | 97 | 98 | True 99 | True 100 | Resources.resx 101 | 102 | 103 | 104 | 105 | 106 | Designer 107 | ResXFileCodeGenerator 108 | Resources.Designer.cs 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | False 120 | .NET Framework 3.5 SP1 Client Profile 121 | false 122 | 123 | 124 | False 125 | .NET Framework 3.5 SP1 126 | true 127 | 128 | 129 | 130 | 137 | -------------------------------------------------------------------------------- /CodePreviewHandler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodePreviewHandler", "CodePreviewHandler.csproj", "{2B886813-EC35-476B-B14C-BC6F0459BEC6}" 5 | EndProject 6 | Project("{6141683F-8A12-4E36-9623-2EB02B2C2303}") = "CodePreviewHandlerSetup", "CodePreviewHandlerSetup\CodePreviewHandlerSetup.isproj", "{C641CC2B-1732-4654-A37E-2C0ADF11E491}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | CD_ROM|Any CPU = CD_ROM|Any CPU 11 | Debug|Any CPU = Debug|Any CPU 12 | DVD-5|Any CPU = DVD-5|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | SingleImage|Any CPU = SingleImage|Any CPU 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU 18 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.CD_ROM|Any CPU.Build.0 = Release|Any CPU 19 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU 22 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.DVD-5|Any CPU.Build.0 = Debug|Any CPU 23 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU 26 | {2B886813-EC35-476B-B14C-BC6F0459BEC6}.SingleImage|Any CPU.Build.0 = Release|Any CPU 27 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.CD_ROM|Any CPU.ActiveCfg = CD_ROM 28 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.CD_ROM|Any CPU.Build.0 = CD_ROM 29 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.Debug|Any CPU.ActiveCfg = DVD-5 30 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.Debug|Any CPU.Build.0 = DVD-5 31 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.DVD-5|Any CPU.ActiveCfg = DVD-5 32 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.DVD-5|Any CPU.Build.0 = DVD-5 33 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.Release|Any CPU.ActiveCfg = SingleImage 34 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.Release|Any CPU.Build.0 = SingleImage 35 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.SingleImage|Any CPU.ActiveCfg = SingleImage 36 | {C641CC2B-1732-4654-A37E-2C0ADF11E491}.SingleImage|Any CPU.Build.0 = SingleImage 37 | EndGlobalSection 38 | GlobalSection(SolutionProperties) = preSolution 39 | HideSolutionNode = FALSE 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /CodePreviewHandlerSetup/CodePreviewHandlerSetup.isproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Express 6 | 7 | Debug 8 | $(Configuration) 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 33 | CodePreviewHandler 34 | {2B886813-EC35-476B-B14C-BC6F0459BEC6} 35 | 36 | 37 | -------------------------------------------------------------------------------- /CppFormat.cs: -------------------------------------------------------------------------------- 1 | namespace TimHeuer.PreviewHandlers 2 | { 3 | public class CppFormat : Manoli.Utils.CSharpFormat.CSharpFormat 4 | { 5 | protected override string Keywords 6 | { 7 | get 8 | { 9 | string str = base.Keywords + "auto static_cast reinterpret_cast dynamic_cast safe_cast nullptr"; 10 | return str; 11 | } 12 | } 13 | 14 | protected override string Preprocessors 15 | { 16 | get 17 | { 18 | return "#if #else #elif #endif #define #undef #warning " 19 | + "#error #line #region #endregion #pragma #include"; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CsharpFormat.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace TimHeuer.PreviewHandlers 3 | { 4 | public class CSharpFormat : Manoli.Utils.CSharpFormat.CSharpFormat 5 | { 6 | protected override string Keywords 7 | { 8 | get 9 | { 10 | string str = base.Keywords + " await async"; 11 | return str; 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CssFormat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace TimHeuer.PreviewHandlers 6 | { 7 | public class CssFormat : Manoli.Utils.CSharpFormat.HtmlFormat 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /HtmlViewer/Element.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | using System.ComponentModel; 13 | using System.Diagnostics; 14 | using System.Drawing; 15 | using System.Globalization; 16 | using System.Collections; 17 | using System.Reflection; 18 | 19 | /// 20 | /// The base class for all element wrappers. These provide information for populating 21 | /// the property grid. 22 | /// 23 | [ 24 | DesignOnly(true) 25 | ] 26 | public class Element { 27 | public static Element GetWrapperFor(Interop.IHTMLElement element, HtmlControl owner) { 28 | Element wrapperElement = new Element(element); 29 | wrapperElement.SetOwner(owner); 30 | return wrapperElement; 31 | } 32 | 33 | private Interop.IHTMLElement _peer; 34 | private HtmlControl _owner; 35 | 36 | internal Element(Interop.IHTMLElement peer) { 37 | Debug.Assert(peer != null); 38 | _peer = peer; 39 | } 40 | 41 | [Browsable(false)] 42 | public string InnerHtml { 43 | get { 44 | try { 45 | return _peer.GetInnerHTML(); 46 | } 47 | catch (Exception e) { 48 | Debug.Fail(e.ToString(), "Could not get Element InnerHTML"); 49 | 50 | return String.Empty; 51 | } 52 | } 53 | set { 54 | try { 55 | _peer.SetInnerHTML(value); 56 | } 57 | catch (Exception e) { 58 | Debug.Fail(e.ToString(), "Could not set Element InnerHTML"); 59 | } 60 | } 61 | } 62 | 63 | [Browsable(false)] 64 | public string OuterHtml { 65 | get { 66 | try { 67 | return _peer.GetOuterHTML(); 68 | } 69 | catch (Exception e) { 70 | Debug.Fail(e.ToString(), "Could not get Element OuterHTML"); 71 | 72 | return String.Empty; 73 | } 74 | } 75 | set { 76 | try { 77 | _peer.SetOuterHTML(value); 78 | } 79 | catch (Exception e) { 80 | Debug.Fail(e.ToString(), "Could not set Element OuterHTML"); 81 | } 82 | } 83 | } 84 | 85 | [Browsable(false)] 86 | public string TagName { 87 | get { 88 | try { 89 | return _peer.GetTagName(); 90 | } 91 | catch (Exception e) { 92 | Debug.Fail(e.ToString(), "Could not get Element TagName" + e.ToString()); 93 | 94 | return String.Empty; 95 | } 96 | } 97 | } 98 | 99 | internal Interop.IHTMLElement Peer { 100 | get { 101 | return _peer; 102 | } 103 | } 104 | 105 | public object GetAttribute(string attribute) { 106 | try { 107 | object[] obj = new object[1]; 108 | 109 | _peer.GetAttribute(attribute, 0, obj); 110 | 111 | object o = obj[0]; 112 | if (o is DBNull) { 113 | o = null; 114 | } 115 | return o; 116 | } 117 | catch (Exception e) { 118 | Debug.Fail(e.ToString(), "Call to IHTMLElement::GetAttribute failed in Element"); 119 | 120 | return null; 121 | } 122 | } 123 | 124 | protected internal bool GetBooleanAttribute(string attribute) { 125 | object o = GetAttribute(attribute); 126 | 127 | if (o == null) { 128 | return false; 129 | } 130 | 131 | Debug.Assert(o is bool, "Attribute " + attribute + " is not of type Boolean"); 132 | if (o is bool) { 133 | return (bool)o; 134 | } 135 | 136 | return false; 137 | } 138 | 139 | protected internal Color GetColorAttribute(string attribute) { 140 | string color = GetStringAttribute(attribute); 141 | 142 | if (color.Length == 0) { 143 | return Color.Empty; 144 | } 145 | else { 146 | return ColorTranslator.FromHtml(color); 147 | } 148 | } 149 | 150 | protected internal Enum GetEnumAttribute(string attribute, Enum defaultValue) { 151 | Type enumType = defaultValue.GetType(); 152 | 153 | object o = GetAttribute(attribute); 154 | if (o == null) { 155 | return defaultValue; 156 | } 157 | 158 | Debug.Assert(o is string, "Attribute " + attribute + " is not of type String"); 159 | string s = o as string; 160 | if ((s == null) || (s.Length == 0)) { 161 | return defaultValue; 162 | } 163 | 164 | try { 165 | return (Enum)Enum.Parse(enumType, s, true); 166 | } 167 | catch { 168 | return defaultValue; 169 | } 170 | } 171 | 172 | protected internal int GetIntegerAttribute(string attribute, int defaultValue) { 173 | object o = GetAttribute(attribute); 174 | 175 | if (o == null) { 176 | return defaultValue; 177 | } 178 | if (o is int) { 179 | return (int)o; 180 | } 181 | if (o is short) { 182 | return (short)o; 183 | } 184 | if (o is string) { 185 | string s = (string)o; 186 | if ((s.Length != 0) && (Char.IsDigit(s[0]))) { 187 | try { 188 | return Int32.Parse((string)o); 189 | } 190 | catch { 191 | } 192 | } 193 | } 194 | 195 | Debug.Fail("Attribute " + attribute + " is not an integer"); 196 | return defaultValue; 197 | } 198 | 199 | public Element GetChild(int index) { 200 | Interop.IHTMLElementCollection children = (Interop.IHTMLElementCollection)_peer.GetChildren(); 201 | Interop.IHTMLElement child = (Interop.IHTMLElement)children.Item(null, index); 202 | 203 | return Element.GetWrapperFor(child, _owner); 204 | } 205 | 206 | public Element GetChild(string name) { 207 | Interop.IHTMLElementCollection children = (Interop.IHTMLElementCollection)_peer.GetChildren(); 208 | Interop.IHTMLElement child = (Interop.IHTMLElement)children.Item(name, null); 209 | 210 | return Element.GetWrapperFor(child, _owner); 211 | } 212 | 213 | public Element GetParent() { 214 | Interop.IHTMLElement parent = (Interop.IHTMLElement)_peer.GetParentElement(); 215 | return Element.GetWrapperFor(parent, _owner); 216 | } 217 | 218 | protected string GetRelativeUrl(string absoluteUrl) { 219 | if ((absoluteUrl == null) || (absoluteUrl.Length == 0)) { 220 | return String.Empty; 221 | } 222 | 223 | string s = absoluteUrl; 224 | if (_owner != null) { 225 | string ownerUrl = _owner.Url; 226 | 227 | if (ownerUrl.Length != 0) { 228 | try { 229 | Uri ownerUri = new Uri(ownerUrl); 230 | Uri imageUri = new Uri(s); 231 | 232 | s = ownerUri.MakeRelative(imageUri); 233 | } 234 | catch { 235 | } 236 | } 237 | } 238 | 239 | return s; 240 | } 241 | 242 | protected internal string GetStringAttribute(string attribute) { 243 | return GetStringAttribute(attribute, String.Empty); 244 | } 245 | 246 | protected internal string GetStringAttribute(string attribute, string defaultValue) { 247 | object o = GetAttribute(attribute); 248 | 249 | if (o == null) { 250 | return defaultValue; 251 | } 252 | if (o is string) { 253 | return (string)o; 254 | } 255 | 256 | return defaultValue; 257 | } 258 | 259 | public void RemoveAttribute(string attribute) { 260 | try { 261 | _peer.RemoveAttribute(attribute, 0); 262 | } 263 | catch (Exception e) { 264 | Debug.Fail(e.ToString(), "Call to IHTMLElement::RemoveAttribute failed in Element"); 265 | } 266 | } 267 | 268 | public void SetAttribute(string attribute, object value) { 269 | try { 270 | _peer.SetAttribute(attribute, value, 0); 271 | } 272 | catch (Exception e) { 273 | Debug.Fail(e.ToString(), "Call to IHTMLElement::SetAttribute failed in Element"); 274 | } 275 | } 276 | 277 | protected internal void SetBooleanAttribute(string attribute, bool value) { 278 | if (value) { 279 | SetAttribute(attribute, true); 280 | } 281 | else { 282 | RemoveAttribute(attribute); 283 | } 284 | } 285 | 286 | protected internal void SetColorAttribute(string attribute, Color value) { 287 | if (value.IsEmpty) { 288 | RemoveAttribute(attribute); 289 | } 290 | else { 291 | SetAttribute(attribute, ColorTranslator.ToHtml(value)); 292 | } 293 | } 294 | 295 | protected internal void SetEnumAttribute(string attribute, Enum value, Enum defaultValue) { 296 | Debug.Assert(value.GetType().Equals(defaultValue.GetType())); 297 | 298 | if (value.Equals(defaultValue)) { 299 | RemoveAttribute(attribute); 300 | } 301 | else { 302 | SetAttribute(attribute, value.ToString(CultureInfo.InvariantCulture)); 303 | } 304 | } 305 | 306 | protected internal void SetIntegerAttribute(string attribute, int value, int defaultValue) { 307 | if (value == defaultValue) { 308 | RemoveAttribute(attribute); 309 | } 310 | else { 311 | SetAttribute(attribute, value); 312 | } 313 | } 314 | 315 | internal void SetOwner(HtmlControl owner) { 316 | _owner = owner; 317 | } 318 | 319 | protected internal void SetStringAttribute(string attribute, string value) { 320 | SetStringAttribute(attribute, value, String.Empty); 321 | } 322 | 323 | protected internal void SetStringAttribute(string attribute, string value, string defaultValue) { 324 | if ((value == null) || value.Equals(defaultValue)) { 325 | RemoveAttribute(attribute); 326 | } 327 | else { 328 | SetAttribute(attribute, value); 329 | } 330 | } 331 | 332 | public override string ToString() { 333 | if (_peer != null) { 334 | try { 335 | return "<" + _peer.GetTagName() + ">"; 336 | } 337 | catch { 338 | } 339 | } 340 | return String.Empty; 341 | } 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /HtmlViewer/FontUnit.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | 13 | public enum FontUnit { 14 | Empty, 15 | Smaller, 16 | Larger, 17 | Type, 18 | XXSmall, 19 | XSmall, 20 | Small, 21 | Medium, 22 | Large, 23 | XLarge, 24 | XXLarge, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlCommandInfo.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | 12 | using System; 13 | 14 | [Flags] 15 | public enum HtmlCommandInfo { 16 | Enabled = 1, 17 | Checked = 2 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlControl.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | 12 | using System; 13 | using System.Collections; 14 | using System.Collections.Specialized; 15 | using System.Diagnostics; 16 | using System.Drawing; 17 | using System.IO; 18 | using System.Runtime.InteropServices; 19 | using System.Text; 20 | using System.Windows; 21 | using System.Windows.Forms; 22 | 23 | using STATSTG = Interop.STATSTG; 24 | 25 | /// 26 | /// An HTML rendering control based on MSHTML 27 | /// 28 | public class HtmlControl : Control { 29 | 30 | private static readonly object EventShowContextMenu = new object(); 31 | private static readonly object _readyStateCompleteEvent = new object(); 32 | 33 | private bool _scrollBarsEnabled; 34 | private bool _flatScrollBars; 35 | private bool _border3d; 36 | private bool _scriptEnabled; 37 | private bool _allowInPlaceNavigation; 38 | private bool _fullDocumentMode; 39 | 40 | private bool _firstActivation; 41 | private bool _isReady; 42 | private bool _isCreated; 43 | 44 | //These allow a user to load the document before displaying 45 | private bool _loadDesired; 46 | private string _desiredContent; 47 | private string _desiredUrl; 48 | 49 | private bool _focusDesired; 50 | 51 | private string _url; 52 | private object _scriptObject; 53 | 54 | private MSHTMLSite _site; 55 | 56 | private static IDictionary _urlMap; 57 | 58 | /// 59 | /// 60 | public HtmlControl() : this(true) { 61 | } 62 | 63 | /// 64 | /// 65 | /// 66 | public HtmlControl(bool fullDocumentMode) { 67 | _firstActivation = true; 68 | _fullDocumentMode = fullDocumentMode; 69 | 70 | // Scroll bars should be enabled by default 71 | _scrollBarsEnabled = true; 72 | } 73 | 74 | public bool AllowInPlaceNavigation { 75 | get { 76 | return _allowInPlaceNavigation; 77 | } 78 | set { 79 | _allowInPlaceNavigation = value; 80 | } 81 | } 82 | 83 | /// 84 | /// Indicates if the Interop.HTMLDocument2 is created 85 | /// 86 | protected bool IsCreated { 87 | get { 88 | return _isCreated; 89 | } 90 | } 91 | 92 | internal bool IsFullDocumentMode { 93 | get { 94 | return _fullDocumentMode; 95 | } 96 | } 97 | 98 | /// 99 | /// Indicates if the control is ready for use 100 | /// 101 | public bool IsReady { 102 | get { 103 | return _isReady; 104 | } 105 | } 106 | 107 | protected internal Interop.IHTMLDocument2 MSHTMLDocument { 108 | get { 109 | return _site.MSHTMLDocument; 110 | } 111 | } 112 | 113 | protected internal Interop.IOleCommandTarget CommandTarget { 114 | get { 115 | return _site.MSHTMLCommandTarget; 116 | } 117 | } 118 | 119 | public bool Border3d { 120 | get { 121 | return _border3d; 122 | } 123 | set { 124 | _border3d = value; 125 | } 126 | } 127 | 128 | /// 129 | /// Indicates if the current selection can be copied 130 | /// 131 | public bool CanCopy { 132 | get { 133 | return IsCommandEnabled(Interop.IDM_COPY); 134 | } 135 | } 136 | 137 | /// 138 | /// Indicates if the current selection can be cut 139 | /// 140 | public bool CanCut { 141 | get { 142 | return IsCommandEnabled(Interop.IDM_CUT); 143 | } 144 | } 145 | 146 | /// 147 | /// Indicates if the current selection can be pasted to 148 | /// 149 | public bool CanPaste { 150 | get { 151 | return IsCommandEnabled(Interop.IDM_PASTE); 152 | } 153 | } 154 | 155 | /// 156 | /// Indicates if the editor can redo 157 | /// 158 | public bool CanRedo { 159 | get { 160 | return IsCommandEnabled(Interop.IDM_REDO); 161 | } 162 | } 163 | 164 | /// 165 | /// Indicates if the editor can undo 166 | /// 167 | public bool CanUndo { 168 | get { 169 | return IsCommandEnabled(Interop.IDM_UNDO); 170 | } 171 | } 172 | 173 | public bool FlatScrollBars { 174 | get { 175 | return _flatScrollBars; 176 | } 177 | set { 178 | _flatScrollBars = value; 179 | } 180 | } 181 | 182 | 183 | public event EventHandler ReadyStateComplete { 184 | add { 185 | Events.AddHandler(_readyStateCompleteEvent, value); 186 | } 187 | remove { 188 | Events.RemoveHandler(_readyStateCompleteEvent, value); 189 | } 190 | } 191 | 192 | public bool ScriptEnabled { 193 | get { 194 | return _scriptEnabled; 195 | } 196 | set { 197 | _scriptEnabled = value; 198 | } 199 | } 200 | 201 | public object ScriptObject { 202 | get { 203 | return _scriptObject; 204 | } 205 | set { 206 | _scriptObject = value; 207 | } 208 | } 209 | 210 | public bool ScrollBarsEnabled { 211 | get { 212 | return _scrollBarsEnabled; 213 | } 214 | set { 215 | _scrollBarsEnabled = value; 216 | } 217 | } 218 | 219 | /// 220 | /// Gets the url of the document contained in the control 221 | /// 222 | public virtual string Url { 223 | get { 224 | return _url; 225 | } 226 | } 227 | 228 | internal static IDictionary UrlMap { 229 | get { 230 | if (_urlMap == null) { 231 | _urlMap = new HybridDictionary(true); 232 | } 233 | return _urlMap; 234 | } 235 | } 236 | 237 | /// 238 | /// Copy the current selection 239 | /// 240 | public void Copy() { 241 | if (!CanCopy) { 242 | throw new Exception("HtmlControl.Copy : Not in able to copy the current selection!"); 243 | } 244 | Exec(Interop.IDM_COPY); 245 | } 246 | 247 | protected virtual string CreateHtmlContent(string content, string style) { 248 | return "" + style + "" + content + ""; 249 | } 250 | 251 | /// 252 | /// Cut the current selection 253 | /// 254 | public void Cut() { 255 | if (!CanCut) { 256 | throw new Exception("HtmlControl.Cut : Not in able to cut the current selection!"); 257 | } 258 | Exec(Interop.IDM_CUT); 259 | } 260 | 261 | /// 262 | protected override void Dispose(bool disposing) { 263 | if (disposing) { 264 | if (_url != null) { 265 | UrlMap[_url] = null; 266 | } 267 | } 268 | base.Dispose(disposing); 269 | } 270 | 271 | /// 272 | /// Executes the specified command in MSHTML 273 | /// 274 | /// 275 | protected internal void Exec(int command) { 276 | Exec(command, null); 277 | } 278 | 279 | /// 280 | /// Executes the specified command in MSHTML with the specified argument 281 | /// 282 | /// 283 | protected internal void Exec(int command, object argument) { 284 | object[] args = new object[] { argument }; 285 | 286 | //Execute the command 287 | int hr = CommandTarget.Exec(ref Interop.Guid_MSHTML, command, Interop.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, args, null); 288 | if (hr != Interop.S_OK) { 289 | throw new Exception("MSHTMLHelper.Exec : Command "+command+" did not return S_OK"); 290 | } 291 | } 292 | 293 | /// 294 | /// Executes the specified command in MSHTML with the specified argument 295 | /// 296 | /// 297 | protected internal void ExecPrompt(int command) { 298 | object[] args = new object[] { null }; 299 | 300 | //Execute the command 301 | int hr = CommandTarget.Exec(ref Interop.Guid_MSHTML, command, Interop.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER, args, null); 302 | if (hr != Interop.S_OK) { 303 | throw new Exception("MSHTMLHelper.Exec : Command "+command+" did not return S_OK"); 304 | } 305 | } 306 | 307 | /// 308 | /// Executes the specified command in MSHTML and returns the result 309 | /// 310 | /// 311 | /// object result - The result of the command 312 | protected internal object ExecResult(int command) { 313 | object[] retVal = new object[1]; 314 | 315 | //Execute the command 316 | int hr = CommandTarget.Exec(ref Interop.Guid_MSHTML, command, Interop.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, null, retVal); 317 | if (hr != Interop.S_OK) { 318 | throw new Exception("MSHTMLHelper.ExecResult : Command "+command+" did not return S_OK"); 319 | } 320 | return retVal[0]; 321 | } 322 | 323 | /// 324 | /// Queries MSHTML for the command info (enabled and checked) for the specified command 325 | /// 326 | /// 327 | /// 328 | protected internal HtmlCommandInfo GetCommandInfo(int command) { 329 | //First query the command target for the command status 330 | int info; 331 | Interop.tagOLECMD oleCommand = new Interop.tagOLECMD(); 332 | 333 | //Create an tagOLDCMD to store the command and receive the result 334 | oleCommand.cmdID = command; 335 | int hr = CommandTarget.QueryStatus(ref Interop.Guid_MSHTML, 1, oleCommand, 0); 336 | Debug.Assert(hr == Interop.S_OK,"IOleCommand.QueryStatus did not return S_OK"); 337 | 338 | //Then translate the response from the command status 339 | //We can just right shift by one to eliminate the supported flag from OLECMDF 340 | info = oleCommand.cmdf; 341 | //REVIEW: Do we want to do a mapping instead of playing with the bits? 342 | return (HtmlCommandInfo)(info>>1) & (HtmlCommandInfo.Enabled | HtmlCommandInfo.Checked); 343 | } 344 | 345 | /// 346 | /// Indicates if the specified command is checked 347 | /// 348 | /// 349 | /// 350 | protected internal bool IsCommandChecked(int command) { 351 | return ((GetCommandInfo(command) & HtmlCommandInfo.Checked) != 0); 352 | } 353 | 354 | /// 355 | /// Indicates if the specified command is enabled 356 | /// 357 | /// 358 | /// 359 | protected internal bool IsCommandEnabled(int command) { 360 | return ((GetCommandInfo(command) & HtmlCommandInfo.Enabled) != 0); 361 | } 362 | 363 | /// 364 | /// Indicates if the specified command is enabled 365 | /// 366 | /// 367 | /// 368 | protected internal bool IsCommandEnabledAndChecked(int command) { 369 | HtmlCommandInfo info = GetCommandInfo(command); 370 | return (((info & HtmlCommandInfo.Enabled) != 0) && ((info & HtmlCommandInfo.Checked) != 0)); 371 | } 372 | 373 | /// 374 | /// Loads HTML content from a stream into this control 375 | /// 376 | /// 377 | public void LoadHtml(Stream stream) { 378 | if (stream == null) { 379 | throw new ArgumentNullException("LoadHtml : You must specify a non-null stream for content"); 380 | } 381 | StreamReader reader = new StreamReader(stream); 382 | LoadHtml(reader.ReadToEnd()); 383 | } 384 | 385 | /// 386 | /// Loads HTML content from a string into this control 387 | /// 388 | /// 389 | public void LoadHtml(string content) { 390 | LoadHtml(content, null, null); 391 | } 392 | 393 | public void LoadHtml(string content, string url) { 394 | LoadHtml(content, url, null); 395 | } 396 | 397 | //REVIEW: Add a load method for stream and url 398 | 399 | /// 400 | /// Loads HTML content from a string into this control identified by the specified URL. 401 | /// If MSHTML has not yet been created, the loading is postponed until MSHTML has been created. 402 | /// 403 | /// 404 | /// 405 | public void LoadHtml(string content, string url, string style) { 406 | if (content == null) { 407 | content = ""; 408 | } 409 | 410 | if (!_isCreated) { 411 | _desiredContent = content; 412 | _desiredUrl = url; 413 | _loadDesired = true; 414 | return; 415 | } 416 | 417 | if (_fullDocumentMode == false) { 418 | content = CreateHtmlContent(content, style); 419 | } 420 | 421 | OnBeforeLoad(); 422 | 423 | Interop.IStream stream = null; 424 | 425 | //First we create a COM stream 426 | IntPtr hglobal = Marshal.StringToHGlobalUni(content); 427 | Interop.CreateStreamOnHGlobal(hglobal, true, out stream); 428 | 429 | // Initialize a new document if there is nothing to load 430 | if (stream == null) { 431 | Interop.IPersistStreamInit psi = (Interop.IPersistStreamInit)_site.MSHTMLDocument; 432 | Debug.Assert(psi != null, "Expected IPersistStreamInit"); 433 | psi.InitNew(); 434 | psi = null; 435 | } 436 | else { 437 | Interop.IHTMLDocument2 document = _site.MSHTMLDocument; 438 | //If there is no specified URL load the document from the stream 439 | if (url == null) { 440 | Interop.IPersistStreamInit psi = (Interop.IPersistStreamInit)document; 441 | Debug.Assert(psi != null, "Expected IPersistStreamInit"); 442 | psi.Load(stream); 443 | psi = null; 444 | } 445 | else { 446 | //Otherwise we create a moniker and load the stream to that moniker 447 | } 448 | } 449 | _url = url; 450 | 451 | OnAfterLoad(); 452 | } 453 | 454 | /// 455 | /// Allow editors to perform actions after HTML content is loaded to the control 456 | /// 457 | protected virtual void OnAfterLoad() { 458 | } 459 | 460 | /// 461 | /// 462 | protected virtual void OnAfterSave() { 463 | } 464 | 465 | /// 466 | /// Allow editors to perform actions before HTML content is loaded to the control 467 | /// 468 | protected virtual void OnBeforeLoad() { 469 | } 470 | 471 | /// 472 | /// 473 | protected virtual void OnBeforeSave() { 474 | } 475 | 476 | /// 477 | /// Allow editors to perform actions when the MSHTML document is created 478 | /// and before it's activated 479 | /// 480 | /// 481 | protected virtual void OnCreated(EventArgs args) { 482 | } 483 | 484 | /// 485 | /// On focus, we have to also return focus to MSHTML 486 | /// 487 | protected override void OnGotFocus(EventArgs e) { 488 | base.OnGotFocus(e); 489 | 490 | //TODO: Fill this in with the right code 491 | if (IsReady) { 492 | // REVIEW: Not sure if we need to do this... It seems to work without it. 493 | //_site.ActivateMSHTML(); 494 | _site.SetFocus(); 495 | } 496 | else { 497 | _focusDesired = true; 498 | } 499 | } 500 | 501 | /// 502 | /// We can only activate the MSHTML after our handle has been created, 503 | /// so upon creating the handle, we create and activate Interop. 504 | /// 505 | /// If LoadHtml was called prior to this, we do the loading now 506 | /// 507 | /// 508 | protected override void OnHandleCreated(EventArgs args) { 509 | base.OnHandleCreated(args); 510 | if (_firstActivation) { 511 | _site = new MSHTMLSite(this); 512 | _site.CreateMSHTML(); 513 | 514 | _isCreated = true; 515 | 516 | OnCreated(new EventArgs()); 517 | 518 | _site.ActivateMSHTML(); 519 | _firstActivation = false; 520 | 521 | if (_loadDesired) { 522 | LoadHtml(_desiredContent, _desiredUrl); 523 | _loadDesired = false; 524 | } 525 | } 526 | } 527 | 528 | /// 529 | /// Called when the control has just become ready 530 | /// 531 | /// 532 | protected internal virtual void OnReadyStateComplete(EventArgs e) { 533 | _isReady = true; 534 | 535 | EventHandler handler = (EventHandler)Events[_readyStateCompleteEvent]; 536 | if (handler != null) { 537 | handler(this, e); 538 | } 539 | 540 | if (_focusDesired) { 541 | _focusDesired = false; 542 | _site.ActivateMSHTML(); 543 | _site.SetFocus(); 544 | } 545 | } 546 | 547 | /// 548 | /// Cut the current selection 549 | /// 550 | public void Paste() { 551 | if (!CanPaste) { 552 | throw new Exception("HtmlControl.Paste : Not in able to paste the current selection!"); 553 | } 554 | Exec(Interop.IDM_PASTE); 555 | } 556 | 557 | /// 558 | /// We need to process keystrokes in order to pass them to MSHTML 559 | /// 560 | public override bool PreProcessMessage(ref Message m) { 561 | bool handled = false; 562 | if ((m.Msg >= Interop.WM_KEYFIRST) && (m.Msg <= Interop.WM_KEYLAST)) { 563 | // If it's a key down, first see if the key combo is a command key 564 | 565 | if (m.Msg == Interop.WM_KEYDOWN) { 566 | handled = ProcessCmdKey(ref m, (Keys)(int)m.WParam | ModifierKeys); 567 | } 568 | 569 | if (!handled) { 570 | int keyCode = (int)m.WParam; 571 | // Don't let Trident eat Ctrl-PgUp/PgDn 572 | if (((keyCode != (int)Keys.PageUp) && (keyCode != (int)Keys.PageDown)) || ((ModifierKeys & Keys.Control) == 0)) { 573 | Interop.COMMSG cm = new Interop.COMMSG(); 574 | 575 | cm.hwnd = m.HWnd; 576 | cm.message = m.Msg; 577 | cm.wParam = m.WParam; 578 | cm.lParam = m.LParam; 579 | handled = _site.TranslateAccelarator(cm); 580 | } 581 | else { 582 | // WndProc for Ctrl-PgUp/PgDn is never called so call it directly here 583 | WndProc(ref m); 584 | handled = true; 585 | } 586 | } 587 | } 588 | 589 | if (!handled) { 590 | handled = base.PreProcessMessage(ref m); 591 | } 592 | 593 | return handled; 594 | } 595 | 596 | public void Redo() { 597 | if (!CanRedo) { 598 | throw new Exception("HtmlControl.Redo : Not in able to redo!"); 599 | } 600 | Exec(Interop.IDM_REDO); 601 | } 602 | 603 | /// 604 | /// Saves the HTML contained in control to a string and return it. 605 | /// 606 | /// string - The HTML in the control 607 | public string SaveHtml() { 608 | if (!IsCreated) { 609 | throw new Exception("HtmlControl.SaveHtml : No HTML to save!"); 610 | } 611 | 612 | string content = String.Empty; 613 | 614 | try { 615 | OnBeforeSave(); 616 | 617 | Interop.IHTMLDocument2 document = _site.MSHTMLDocument; 618 | 619 | if (_fullDocumentMode) { 620 | // First save the document to a stream 621 | Interop.IPersistStreamInit psi = (Interop.IPersistStreamInit)document; 622 | Debug.Assert(psi != null, "Expected IPersistStreamInit"); 623 | 624 | Interop.IStream stream = null; 625 | Interop.CreateStreamOnHGlobal(Interop.NullIntPtr, true, out stream); 626 | 627 | psi.Save(stream, 1); 628 | 629 | // Now copy the stream to the string 630 | STATSTG stat = new STATSTG(); 631 | stream.Stat(stat, 1); 632 | int length = (int)stat.cbSize; 633 | byte[] bytes = new byte[length]; 634 | 635 | IntPtr hglobal; 636 | Interop.GetHGlobalFromStream(stream, out hglobal); 637 | Debug.Assert(hglobal != Interop.NullIntPtr, "Failed in GetHGlobalFromStream"); 638 | 639 | // First copy the stream to a byte array 640 | IntPtr pointer = Interop.GlobalLock(hglobal); 641 | if (pointer != Interop.NullIntPtr) { 642 | Marshal.Copy(pointer, bytes, 0, length); 643 | 644 | Interop.GlobalUnlock(hglobal); 645 | 646 | // Then create the string from the byte array (use a StreamReader to eat the preamble in the UTF8 encoding case) 647 | StreamReader streamReader = null; 648 | try { 649 | streamReader = new StreamReader(new MemoryStream(bytes), Encoding.Default); 650 | content = streamReader.ReadToEnd(); 651 | } 652 | finally { 653 | if (streamReader != null) { 654 | streamReader.Close(); 655 | } 656 | } 657 | } 658 | } 659 | else { 660 | // Save only the contents of the tag 661 | Interop.IHTMLElement bodyElement = document.GetBody(); 662 | Debug.Assert(bodyElement != null, "Could not get BODY element from document"); 663 | 664 | if (bodyElement != null) { 665 | content = SavePartialHtml(Element.GetWrapperFor(bodyElement, this)); 666 | } 667 | } 668 | } 669 | catch (Exception e) { 670 | Debug.Fail("HtmlControl.SaveHtml" + e.ToString()); 671 | content = String.Empty; 672 | } 673 | finally { 674 | OnAfterSave(); 675 | } 676 | 677 | if (content == null) { 678 | content = String.Empty; 679 | } 680 | return content; 681 | } 682 | 683 | // REVIEW: Come up with better names to unify _fullDocumentMode, CreateHtmlContent, and SavePartialHtml 684 | protected virtual string SavePartialHtml(Element bodyElement) { 685 | return bodyElement.InnerHtml; 686 | } 687 | 688 | /// 689 | /// Saves the HTML contained in the control to a stream 690 | /// 691 | /// 692 | public void SaveHtml(Stream stream) { 693 | if (stream == null) { 694 | throw new ArgumentNullException("SaveHtml : Must specify a non-null stream to which to save"); 695 | } 696 | 697 | string content = SaveHtml(); 698 | 699 | StreamWriter writer = new StreamWriter(stream, Encoding.UTF8); 700 | writer.Write(content); 701 | writer.Flush(); 702 | } 703 | 704 | public void Undo() { 705 | if (!CanUndo) { 706 | throw new Exception("HtmlControl.Undo : Not in able to undo!"); 707 | } 708 | Exec(Interop.IDM_UNDO); 709 | } 710 | } 711 | } 712 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlDocument.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | 13 | /// 14 | /// Summary description for HtmlDocument. 15 | /// 16 | public class HtmlDocument { 17 | 18 | private HtmlEditor _editor; 19 | 20 | public HtmlDocument(HtmlEditor editor) { 21 | _editor = editor; 22 | } 23 | 24 | /// 25 | /// Indicates if a button can be inserted 26 | /// 27 | public bool CanInsertButton { 28 | get { 29 | return _editor.IsCommandEnabled(Interop.IDM_BUTTON); 30 | } 31 | } 32 | 33 | /// 34 | /// Indicates if a listbox can be inserted 35 | /// 36 | public bool CanInsertListBox { 37 | get { 38 | return _editor.IsCommandEnabled(Interop.IDM_LISTBOX); 39 | } 40 | } 41 | 42 | /// 43 | /// Indicates if HTML can be inserted 44 | /// 45 | public bool CanInsertHtml { 46 | get { 47 | if (Selection.Type == HtmlSelectionType.ElementSelection) { 48 | //If this is a control range, we can only insert HTML if we're in a div or span 49 | Interop.IHtmlControlRange controlRange = (Interop.IHtmlControlRange)Selection.MSHTMLSelection; 50 | int selectedItemCount = controlRange.GetLength(); 51 | if (selectedItemCount == 1) { 52 | Interop.IHTMLElement element = controlRange.Item(0); 53 | if ((String.Compare(element.GetTagName(), "div", true) == 0) || 54 | (String.Compare(element.GetTagName(), "td", true) == 0)) { 55 | return true; 56 | } 57 | } 58 | } 59 | else { 60 | //If this is a text range, we can definitely insert HTML 61 | return true; 62 | } 63 | return false; 64 | } 65 | } 66 | 67 | /// 68 | /// Indicates if an hyperlink can be inserted 69 | /// 70 | public bool CanInsertHyperlink { 71 | get { 72 | if (((Selection.Type == HtmlSelectionType.TextSelection) || (Selection.Type == HtmlSelectionType.Empty)) && 73 | (Selection.Length == 0)) { 74 | return CanInsertHtml; 75 | } 76 | else { 77 | return _editor.IsCommandEnabled(Interop.IDM_HYPERLINK); 78 | } 79 | } 80 | } 81 | 82 | /// 83 | /// Indicates if a radio button can be inserted 84 | /// 85 | public bool CanInsertRadioButton { 86 | get { 87 | 88 | return _editor.IsCommandEnabled(Interop.IDM_RADIOBUTTON); 89 | } 90 | } 91 | 92 | /// 93 | /// Indicates if a text area can be inserted 94 | /// 95 | public bool CanInsertTextArea { 96 | get { 97 | return _editor.IsCommandEnabled(Interop.IDM_TEXTAREA); 98 | } 99 | } 100 | 101 | /// 102 | /// Indicates if a textbox can be inserted 103 | /// 104 | public bool CanInsertTextBox { 105 | get { 106 | return _editor.IsCommandEnabled(Interop.IDM_TEXTBOX); 107 | } 108 | } 109 | 110 | /// 111 | /// The current selection in the editor 112 | /// 113 | protected HtmlSelection Selection { 114 | get { 115 | return _editor.Selection; 116 | } 117 | } 118 | 119 | /// 120 | /// Inserts a button 121 | /// 122 | public void InsertButton() { 123 | _editor.Exec(Interop.IDM_BUTTON); 124 | } 125 | 126 | /// 127 | /// Inserts the specified string into the html over the current selection 128 | /// 129 | /// 130 | public void InsertHtml(string html) { 131 | Selection.SynchronizeSelection(); 132 | if (Selection.Type == HtmlSelectionType.ElementSelection) { 133 | //If it's a control range, we can only insert if we are in a div or td 134 | Interop.IHtmlControlRange controlRange = (Interop.IHtmlControlRange)Selection.MSHTMLSelection; 135 | int selectedItemCount = controlRange.GetLength(); 136 | if (selectedItemCount == 1) { 137 | Interop.IHTMLElement element = controlRange.Item(0); 138 | if ((String.Compare(element.GetTagName(), "div", true) == 0) || 139 | (String.Compare(element.GetTagName(), "td", true) == 0)) { 140 | element.InsertAdjacentHTML("beforeEnd", html); 141 | } 142 | } 143 | } 144 | else { 145 | Interop.IHTMLTxtRange textRange = (Interop.IHTMLTxtRange)Selection.MSHTMLSelection; 146 | textRange.PasteHTML(html); 147 | } 148 | } 149 | 150 | /// 151 | /// Inserts a hyperlink with the specified URL and description 152 | /// 153 | /// 154 | /// 155 | public void InsertHyperlink(string url, string description) { 156 | Selection.SynchronizeSelection(); 157 | if (url == null) { 158 | try { 159 | _editor.ExecPrompt(Interop.IDM_HYPERLINK); 160 | } 161 | catch {} // don't care if it fails! 162 | } 163 | else { 164 | if (((Selection.Type == HtmlSelectionType.TextSelection) || (Selection.Type == HtmlSelectionType.Empty)) && 165 | (Selection.Length == 0)) { 166 | InsertHtml(""+description+""); 167 | /*Interop.IHTMLTxtRange textRange = (Interop.IHTMLTxtRange)Selection.MSHTMLSelection; 168 | textRange.PasteHTML(""+description+"");*/ 169 | } 170 | else { 171 | _editor.Exec(Interop.IDM_HYPERLINK, url); 172 | } 173 | } 174 | } 175 | 176 | /// 177 | /// Inserts a list box 178 | /// 179 | public void InsertListBox() { 180 | _editor.Exec(Interop.IDM_LISTBOX); 181 | } 182 | 183 | /// 184 | /// Inserts a radio button 185 | /// 186 | public void InsertRadioButton() { 187 | _editor.Exec(Interop.IDM_RADIOBUTTON); 188 | } 189 | 190 | /// 191 | /// Inserts a text area 192 | /// 193 | public void InsertTextArea() { 194 | _editor.Exec(Interop.IDM_TEXTAREA); 195 | } 196 | 197 | /// 198 | /// Inserts a text box 199 | /// 200 | public void InsertTextBox() { 201 | _editor.Exec(Interop.IDM_TEXTBOX); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlEditor.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | using System.Collections; 13 | using System.Diagnostics; 14 | using System.ComponentModel.Design; 15 | using System.Runtime.InteropServices; 16 | using System.Windows.Forms; 17 | 18 | /// 19 | /// Summary description for HtmlEditor. 20 | /// 21 | public class HtmlEditor : HtmlControl { 22 | private bool _absolutePositioningEnabled; 23 | private bool _absolutePositioningDesired; 24 | 25 | private bool _bordersVisible; 26 | private bool _bordersDesired; 27 | 28 | private bool _designModeEnabled; 29 | private bool _designModeDesired; 30 | 31 | private bool _multipleSelectionEnabled; 32 | private bool _multipleSelectionDesired; 33 | 34 | private HtmlTextFormatting textFormatting; 35 | private HtmlDocument document; 36 | private HtmlSelection _selection; 37 | 38 | Interop.IPersistStreamInit _persistStream; 39 | 40 | private Interop.IOleUndoManager _undoManager; 41 | 42 | private Interop.IHTMLEditServices _editServices; 43 | 44 | public HtmlEditor() : this(true) { 45 | } 46 | 47 | internal HtmlEditor(bool fullDocumentMode) : base(fullDocumentMode) { 48 | } 49 | 50 | /// 51 | /// Enables or disables absolute position for the entire editor 52 | /// 53 | public bool AbsolutePositioningEnabled { 54 | get { 55 | return _absolutePositioningEnabled; 56 | } 57 | set { 58 | //If the control isn't ready to be put into abs pos mode, 59 | //set a flag and put it in abs pos mode when it is ready 60 | _absolutePositioningDesired = value; 61 | if (!IsCreated) { 62 | return; 63 | } 64 | else { 65 | //Turn abs pos mode on or off depending on the new value 66 | _absolutePositioningEnabled = value; 67 | object[] args = new object[] { _absolutePositioningEnabled }; 68 | Exec(Interop.IDM_2D_POSITION, args); 69 | } 70 | } 71 | } 72 | 73 | public bool BordersVisible { 74 | get { 75 | return _bordersVisible; 76 | } 77 | set { 78 | _bordersDesired = value; 79 | if (!IsReady) { 80 | return; 81 | } 82 | if (_bordersVisible != _bordersDesired) { 83 | _bordersVisible = value; 84 | object[] args = new object[] { _bordersVisible }; 85 | Exec(Interop.IDM_SHOWZEROBORDERATDESIGNTIME,args); 86 | } 87 | } 88 | } 89 | 90 | /// 91 | /// Indicates if the editor is in design mode 92 | /// Also places MSHTML into design mode if set to true 93 | /// 94 | public bool DesignModeEnabled { 95 | get { 96 | return _designModeEnabled; 97 | } 98 | set { 99 | //Only execute this if we aren't already in design mode 100 | if (_designModeEnabled != value) { 101 | //If the control isn't ready to be put into design mode, 102 | //set a flag and put it in design mode when it is ready 103 | if (!IsCreated) { 104 | _designModeDesired = value; 105 | } 106 | else { 107 | //Turn design mode on or off depending on the new value 108 | _designModeEnabled = value; 109 | MSHTMLDocument.SetDesignMode((_designModeEnabled ? "on" : "off")); 110 | } 111 | } 112 | } 113 | } 114 | 115 | /// 116 | /// Returns the document object for doing insertions 117 | /// 118 | public HtmlDocument Document { 119 | get { 120 | if (!IsReady) { 121 | throw new Exception("HtmlDocument not ready yet!"); 122 | } 123 | if (document == null) { 124 | document = new HtmlDocument(this); 125 | } 126 | return document; 127 | } 128 | } 129 | 130 | private Interop.IHTMLEditServices MSHTMLEditServices { 131 | get { 132 | if (_editServices==null) { 133 | Interop.IServiceProvider serviceProvider = MSHTMLDocument as Interop.IServiceProvider; 134 | Debug.Assert(serviceProvider != null); 135 | Guid shtmlGuid = new Guid(0x3050f7f9,0x98b5,0x11cf,0xbb,0x82,0x00,0xaa,0x00,0xbd,0xce,0x0b); 136 | Guid intGuid = (typeof(Interop.IHTMLEditServices)).GUID; 137 | 138 | IntPtr editServicePtr = Interop.NullIntPtr; 139 | int hr = serviceProvider.QueryService(ref shtmlGuid, ref intGuid, out editServicePtr); 140 | Debug.Assert((hr == Interop.S_OK) && (editServicePtr != Interop.NullIntPtr), "Did not get IHTMLEditService"); 141 | if ((hr == Interop.S_OK) && (editServicePtr != Interop.NullIntPtr)) { 142 | _editServices = (Interop.IHTMLEditServices) Marshal.GetObjectForIUnknown(editServicePtr); 143 | Marshal.Release(editServicePtr); 144 | } 145 | } 146 | return _editServices; 147 | } 148 | } 149 | /// 150 | /// Indicates if the contents of the editor have been modified 151 | /// 152 | public virtual bool IsDirty { 153 | get { 154 | if (DesignModeEnabled && IsReady) { 155 | if (_persistStream != null) { 156 | //TODO: After a load, this is no longer true, what do we do??? 157 | if (_persistStream.IsDirty() == Interop.S_OK) { 158 | return true; 159 | } 160 | } 161 | } 162 | return false; 163 | } 164 | } 165 | 166 | /// 167 | /// Indicates if multiple selection is enabled in the editor 168 | /// Also places MSHTML into multiple selection mode if set to true 169 | /// 170 | public bool MultipleSelectionEnabled { 171 | get { 172 | return _multipleSelectionEnabled; 173 | } 174 | set { 175 | //If the control isn't ready yet, postpone setting multiple selection 176 | _multipleSelectionDesired = value; 177 | if (!IsReady) { 178 | return; 179 | } 180 | else { 181 | //Create an objects array to pass parameters to the MSHTML command target 182 | _multipleSelectionEnabled = value; 183 | object[] args = new object[] { _multipleSelectionEnabled }; 184 | int hr = CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_MULTIPLESELECTION, 0, args, null); 185 | Debug.Assert(hr == Interop.S_OK); 186 | } 187 | } 188 | } 189 | 190 | /// 191 | /// The current selection in the editor 192 | /// 193 | public HtmlSelection Selection { 194 | get { 195 | if (_selection == null) { 196 | _selection = CreateSelection(); 197 | } 198 | return _selection; 199 | } 200 | } 201 | 202 | /// 203 | /// The text formatting element of the editor 204 | /// 205 | public HtmlTextFormatting TextFormatting { 206 | get { 207 | if (!IsReady) { 208 | throw new Exception("HtmlDocument not ready yet!"); 209 | } 210 | if (textFormatting == null) { 211 | textFormatting = new HtmlTextFormatting(this); 212 | } 213 | return textFormatting; 214 | } 215 | } 216 | 217 | private Interop.IOleUndoManager UndoManager { 218 | get { 219 | if (_undoManager == null) { 220 | Interop.IServiceProvider serviceProvider = MSHTMLDocument as Interop.IServiceProvider; 221 | Debug.Assert(serviceProvider != null); 222 | Guid undoManagerGuid = typeof(Interop.IOleUndoManager).GUID; 223 | Guid undoManagerGuid2 = typeof(Interop.IOleUndoManager).GUID; 224 | IntPtr undoManagerPtr = Interop.NullIntPtr; 225 | int hr = serviceProvider.QueryService(ref undoManagerGuid2, ref undoManagerGuid, out undoManagerPtr); 226 | if ((hr == Interop.S_OK) && (undoManagerPtr != Interop.NullIntPtr)) { 227 | _undoManager = (Interop.IOleUndoManager)Marshal.GetObjectForIUnknown(undoManagerPtr); 228 | Marshal.Release(undoManagerPtr); 229 | } 230 | } 231 | return _undoManager; 232 | } 233 | } 234 | 235 | /// 236 | /// 237 | public void ClearDirtyState() { 238 | if (!IsReady) 239 | return; 240 | Exec(Interop.IDM_SETDIRTY,false); 241 | } 242 | 243 | /// 244 | /// 245 | protected virtual HtmlSelection CreateSelection() { 246 | return new HtmlSelection(this); 247 | } 248 | 249 | protected override void OnAfterSave() { 250 | // In non-full document mode, we don't actually save the IPersistInitStream, so 251 | // clear the dirty bit here 252 | if (!IsFullDocumentMode) { 253 | ClearDirtyState(); 254 | } 255 | } 256 | 257 | /// 258 | /// Overridden to remove the grid behavior before loading 259 | /// 260 | protected override void OnBeforeLoad() { 261 | //are already visible 262 | if (BordersVisible) { 263 | BordersVisible = false; 264 | _bordersDesired = true; 265 | } 266 | } 267 | /// 268 | /// Overridden to activate design and multiple selection modes 269 | /// 270 | /// 271 | protected override void OnCreated(EventArgs args) { 272 | if (args == null) { 273 | throw new ArgumentNullException("You must specify a non-null EventArgs for OnCreated"); 274 | } 275 | 276 | base.OnCreated(args); 277 | 278 | object[] mshtmlArgs = new object[1]; 279 | 280 | mshtmlArgs[0] = true; 281 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_PERSISTDEFAULTVALUES, 0, mshtmlArgs, null); 282 | 283 | mshtmlArgs[0] = true; 284 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_PROTECTMETATAGS, 0, mshtmlArgs, null); 285 | 286 | mshtmlArgs[0] = true; 287 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_PRESERVEUNDOALWAYS, 0, mshtmlArgs, null); 288 | 289 | mshtmlArgs[0] = true; 290 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_NOACTIVATENORMALOLECONTROLS, 0, mshtmlArgs, null); 291 | 292 | mshtmlArgs[0] = true; 293 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_NOACTIVATEDESIGNTIMECONTROLS, 0, mshtmlArgs, null); 294 | 295 | mshtmlArgs[0] = true; 296 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_NOACTIVATEJAVAAPPLETS, 0, mshtmlArgs, null); 297 | 298 | mshtmlArgs[0] = true; 299 | CommandTarget.Exec(ref Interop.Guid_MSHTML, Interop.IDM_NOFIXUPURLSONPASTE, 0, mshtmlArgs, null); 300 | 301 | //Set the design mode to the last desired design mode 302 | if (_designModeDesired) { 303 | DesignModeEnabled = _designModeDesired; 304 | _designModeDesired = false; 305 | } 306 | 307 | } 308 | 309 | /// 310 | /// Overridden to set the design mode to the last desired design mode and multiple selection flag 311 | /// to the last desired multiple selection flag 312 | /// 313 | /// 314 | protected override internal void OnReadyStateComplete(EventArgs args) { 315 | base.OnReadyStateComplete(args); 316 | 317 | _persistStream = (Interop.IPersistStreamInit)MSHTMLDocument; 318 | 319 | Selection.SynchronizeSelection(); 320 | 321 | //Set the mutiple selection mode to the last desired multiple selection mode 322 | if (_multipleSelectionDesired) { 323 | MultipleSelectionEnabled = _multipleSelectionDesired; 324 | } 325 | 326 | //Set the absolute positioning mode to the last desired absolute position mode 327 | if (_absolutePositioningDesired) { 328 | AbsolutePositioningEnabled = _absolutePositioningDesired; 329 | } 330 | 331 | //Set the absolute positioning mode to the last desired absolute position mode 332 | if (_bordersDesired) { 333 | BordersVisible = _bordersDesired; 334 | } 335 | 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlFontSize.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | 12 | public enum HtmlFontSize { 13 | Smallest = 1, 14 | Smaller = 2, 15 | Small = 3, 16 | Medium = 4, 17 | Large = 5, 18 | Larger = 6, 19 | Largest = 7 20 | } 21 | } -------------------------------------------------------------------------------- /HtmlViewer/HtmlFormat.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | 13 | public enum HtmlFormat { 14 | Normal = 0, 15 | Formatted = 1, 16 | Heading1 = 2, 17 | Heading2 = 3, 18 | Heading3 = 4, 19 | Heading4 = 5, 20 | Heading5 = 6, 21 | Heading6 = 7, 22 | Paragraph = 8, 23 | OrderedList = 9, 24 | UnorderedList = 10 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlSelection.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | using System.Diagnostics; 13 | using System.Collections; 14 | using System.Runtime.InteropServices; 15 | 16 | /// 17 | /// Summary description for HtmlSelection. 18 | /// 19 | public class HtmlSelection { 20 | 21 | public static readonly string DesignTimeLockAttribute = "Design_Time_Lock"; 22 | 23 | private EventHandler _selectionChangedHandler; 24 | 25 | private HtmlEditor _editor; 26 | private Interop.IHTMLDocument2 _document; 27 | private HtmlSelectionType _type; 28 | private int _selectionLength; 29 | private string _text; 30 | private object _mshtmlSelection; 31 | private ArrayList _items; 32 | private ArrayList _elements; 33 | private bool _sameParentValid; 34 | private int _maxZIndex; 35 | 36 | public HtmlSelection(HtmlEditor editor) { 37 | _editor = editor; 38 | _maxZIndex = 99; 39 | } 40 | 41 | /// 42 | /// Indicates if the current selection can be aligned 43 | /// 44 | public bool CanAlign { 45 | get { 46 | if (_items.Count < 2) { 47 | return false; 48 | } 49 | if (_type == HtmlSelectionType.ElementSelection) { 50 | foreach (Interop.IHTMLElement elem in _items) { 51 | //First check if they are all absolutely positioned 52 | if (!IsElement2DPositioned(elem)) { 53 | return false; 54 | } 55 | 56 | //Then check if none of them are locked 57 | if (IsElementLocked(elem)) { 58 | return false; 59 | } 60 | } 61 | //Then check if they all have the same parent 62 | if (!SameParent) { 63 | return false; 64 | } 65 | return true; 66 | } 67 | return false; 68 | } 69 | } 70 | 71 | /// 72 | /// Indicates if the current selection can be size-matched 73 | /// 74 | public bool CanMatchSize { 75 | get { 76 | if (_items.Count < 2) { 77 | return false; 78 | } 79 | if (_type == HtmlSelectionType.ElementSelection) { 80 | foreach (Interop.IHTMLElement elem in _items) { 81 | //Then check if none of them are locked 82 | if (IsElementLocked(elem)) { 83 | return false; 84 | } 85 | } 86 | //Then check if they all have the same parent 87 | if (!SameParent) { 88 | return false; 89 | } 90 | return true; 91 | } 92 | return false; 93 | } 94 | } 95 | 96 | /// 97 | /// Indicates if the current selection can have it's hyperlink removed 98 | /// 99 | public bool CanRemoveHyperlink { 100 | get { 101 | return _editor.IsCommandEnabled(Interop.IDM_UNLINK); 102 | } 103 | } 104 | 105 | /// 106 | /// Indicates if the current selection have it's z-index modified 107 | /// 108 | public bool CanChangeZIndex { 109 | get { 110 | if (_items.Count == 0) { 111 | return false; 112 | } 113 | if (_type == HtmlSelectionType.ElementSelection) { 114 | foreach (Interop.IHTMLElement elem in _items) { 115 | //First check if they are all absolutely positioned 116 | if (!IsElement2DPositioned(elem)) { 117 | return false; 118 | } 119 | } 120 | //Then check if they all have the same parent 121 | if (!SameParent) { 122 | return false; 123 | } 124 | return true; 125 | } 126 | return false; 127 | } 128 | } 129 | 130 | /// 131 | /// Indicates if the current selection can be wrapped in HTML tags 132 | /// 133 | public bool CanWrapSelection { 134 | get { 135 | if ((_selectionLength != 0) && (Type == HtmlSelectionType.TextSelection)) { 136 | return true; 137 | } 138 | return false; 139 | } 140 | } 141 | 142 | protected HtmlEditor Editor { 143 | get { 144 | return _editor; 145 | } 146 | } 147 | 148 | public ICollection Elements { 149 | get { 150 | if (_elements == null) { 151 | _elements = new ArrayList(); 152 | foreach (Interop.IHTMLElement element in _items) { 153 | object wrapper = CreateElementWrapper(element); 154 | if (wrapper != null) { 155 | _elements.Add(wrapper); 156 | } 157 | } 158 | } 159 | return _elements; 160 | } 161 | } 162 | 163 | /// 164 | /// All selected items 165 | /// 166 | internal ICollection Items { 167 | get { 168 | return _items; 169 | } 170 | } 171 | 172 | public int Length { 173 | get { 174 | return _selectionLength; 175 | } 176 | } 177 | 178 | /// 179 | /// Indicates if all items in the selection have the same parent element 180 | /// 181 | private bool SameParent { 182 | get { 183 | if (!_sameParentValid) { 184 | IntPtr primaryParentElementPtr = Interop.NullIntPtr; 185 | 186 | foreach (Interop.IHTMLElement elem in _items) { 187 | //Check if all items have the same parent by doing pointer equality 188 | Interop.IHTMLElement parentElement = elem.GetParentElement(); 189 | IntPtr parentElementPtr = Marshal.GetIUnknownForObject(parentElement); 190 | //If we haven't gotten a primary parent element (ie, this is the first time through the loop) 191 | //Remember what the this parent element is 192 | if (primaryParentElementPtr == Interop.NullIntPtr) { 193 | primaryParentElementPtr = parentElementPtr; 194 | } 195 | else { 196 | //Check the pointers 197 | if (primaryParentElementPtr != parentElementPtr) { 198 | Marshal.Release(parentElementPtr); 199 | if (primaryParentElementPtr != Interop.NullIntPtr) { 200 | Marshal.Release(primaryParentElementPtr); 201 | } 202 | _sameParentValid = false; 203 | return _sameParentValid; 204 | } 205 | Marshal.Release(parentElementPtr); 206 | } 207 | } 208 | if (primaryParentElementPtr != Interop.NullIntPtr) { 209 | Marshal.Release(primaryParentElementPtr); 210 | } 211 | _sameParentValid = true; 212 | } 213 | return _sameParentValid; 214 | } 215 | } 216 | 217 | public event EventHandler SelectionChanged { 218 | add { 219 | _selectionChangedHandler = (EventHandler)Delegate.Combine(_selectionChangedHandler, value); 220 | } 221 | remove { 222 | if (_selectionChangedHandler != null) { 223 | _selectionChangedHandler = (EventHandler)Delegate.Remove(_selectionChangedHandler, value); 224 | } 225 | } 226 | } 227 | 228 | /// 229 | /// Returns the MSHTML selection object (IHTMLTxtRange or IHTMLControlRange) 230 | /// Does not synchronize the selection!!! Uses the selection from the last synchronization 231 | /// 232 | protected internal object MSHTMLSelection { 233 | get { 234 | return _mshtmlSelection; 235 | } 236 | } 237 | 238 | /// 239 | /// Returns the text contained in the selection if there is a text selection 240 | /// 241 | public string Text { 242 | get { 243 | if (_type == HtmlSelectionType.TextSelection) { 244 | return _text; 245 | } 246 | return null; 247 | } 248 | } 249 | 250 | /// 251 | /// The HtmlSelectionType of the selection 252 | /// 253 | public HtmlSelectionType Type { 254 | get { 255 | return _type; 256 | } 257 | } 258 | 259 | public void ClearSelection() { 260 | _editor.Exec(Interop.IDM_CLEARSELECTION); 261 | } 262 | 263 | protected virtual object CreateElementWrapper(Interop.IHTMLElement element) { 264 | return Element.GetWrapperFor(element, _editor); 265 | } 266 | 267 | /// 268 | /// Returns info about the absolute positioning of the selection 269 | /// 270 | /// 271 | public HtmlCommandInfo GetAbsolutePositionInfo() { 272 | return _editor.GetCommandInfo(Interop.IDM_ABSOLUTE_POSITION); 273 | } 274 | 275 | /// 276 | /// Returns info about the design time lock state of the selection 277 | /// 278 | /// 279 | public HtmlCommandInfo GetLockInfo() { 280 | if (_type == HtmlSelectionType.ElementSelection) { 281 | foreach (Interop.IHTMLElement elem in _items) { 282 | //We only need to check that all elements are absolutely positioned 283 | if (!IsElement2DPositioned(elem)) { 284 | return (HtmlCommandInfo)0; 285 | } 286 | 287 | if (IsElementLocked(elem)) { 288 | return HtmlCommandInfo.Checked | HtmlCommandInfo.Enabled; 289 | } 290 | return HtmlCommandInfo.Enabled; 291 | } 292 | } 293 | return (HtmlCommandInfo)0; 294 | } 295 | 296 | public string GetOuterHtml() { 297 | Debug.Assert(Items.Count == 1, "Can't get OuterHtml of more than one element"); 298 | 299 | string outerHtml = String.Empty; 300 | try { 301 | outerHtml = ((Interop.IHTMLElement)_items[0]).GetOuterHTML(); 302 | 303 | // Call this twice because, in the first call, Trident will call OnContentSave, which calls SetInnerHtml, but 304 | // the outer HTML it returns does not include that new inner HTML. 305 | outerHtml = ((Interop.IHTMLElement)_items[0]).GetOuterHTML(); 306 | } 307 | catch { 308 | } 309 | 310 | return outerHtml; 311 | } 312 | 313 | public ArrayList GetParentHierarchy(object o) { 314 | Interop.IHTMLElement current = GetIHtmlElement(o); 315 | if (current == null) { 316 | return null; 317 | } 318 | 319 | string tagName = current.GetTagName().ToLower(); 320 | if (tagName.Equals("body")) { 321 | return null; 322 | } 323 | 324 | ArrayList ancestors = new ArrayList(); 325 | 326 | current = current.GetParentElement(); 327 | while ((current != null) && (current.GetTagName().ToLower().Equals("body") == false)) { 328 | Element element = Element.GetWrapperFor(current, _editor); 329 | if (IsSelectableElement(element)) { 330 | ancestors.Add(element); 331 | } 332 | current = current.GetParentElement(); 333 | } 334 | 335 | // Don't add the body tag to the hierarchy if we aren't in full document mode 336 | if (current != null) { 337 | Element element = Element.GetWrapperFor(current, _editor); 338 | if (IsSelectableElement(element)) { 339 | ancestors.Add(element); 340 | } 341 | } 342 | 343 | return ancestors; 344 | } 345 | 346 | protected virtual Interop.IHTMLElement GetIHtmlElement(object o) { 347 | if (o is Element) { 348 | return ((Element)o).Peer; 349 | } 350 | return null; 351 | } 352 | 353 | /// 354 | /// Convenience method for checking if the specified element is absolutely positioned 355 | /// 356 | /// 357 | /// 358 | private bool IsElement2DPositioned(Interop.IHTMLElement elem) { 359 | Interop.IHTMLElement2 elem2 = (Interop.IHTMLElement2) elem; 360 | Interop.IHTMLCurrentStyle style = elem2.GetCurrentStyle(); 361 | string position = style.GetPosition(); 362 | if ((position == null) || (String.Compare(position, "absolute", true) != 0)) { 363 | return false; 364 | } 365 | return true; 366 | } 367 | 368 | /// 369 | /// Convenience method for checking if the specified element has a design time lock 370 | /// 371 | /// 372 | /// 373 | private bool IsElementLocked(Interop.IHTMLElement elem) { 374 | object[] attribute = new object[1]; 375 | elem.GetAttribute(DesignTimeLockAttribute,0,attribute); 376 | if (attribute[0] == null) { 377 | Interop.IHTMLStyle style = elem.GetStyle(); 378 | attribute[0] = style.GetAttribute(DesignTimeLockAttribute,0); 379 | } 380 | if ((attribute[0] == null) || !(attribute[0] is string)) { 381 | return false; 382 | } 383 | return true; 384 | } 385 | 386 | protected virtual bool IsSelectableElement(Element element) { 387 | return (_editor.IsFullDocumentMode || (element.TagName.ToLower() != "body")); 388 | } 389 | 390 | protected virtual void OnSelectionChanged() { 391 | if (_selectionChangedHandler != null) { 392 | _selectionChangedHandler.Invoke(this, EventArgs.Empty); 393 | } 394 | } 395 | 396 | public bool SelectElement(object o) { 397 | ArrayList list = new ArrayList(1); 398 | list.Add(o); 399 | return SelectElements(list); 400 | } 401 | 402 | public bool SelectElements(ICollection elements) { 403 | Interop.IHTMLElement body = _editor.MSHTMLDocument.GetBody(); 404 | Interop.IHTMLTextContainer container = body as Interop.IHTMLTextContainer; 405 | Debug.Assert(container != null); 406 | object controlRange = container.createControlRange(); 407 | 408 | Interop.IHtmlControlRange htmlControlRange = controlRange as Interop.IHtmlControlRange; 409 | Debug.Assert(htmlControlRange != null); 410 | if (htmlControlRange == null) { 411 | return false; 412 | } 413 | 414 | Interop.IHtmlControlRange2 htmlControlRange2 = controlRange as Interop.IHtmlControlRange2; 415 | Debug.Assert(htmlControlRange2 != null); 416 | if (htmlControlRange2 == null) { 417 | return false; 418 | } 419 | 420 | 421 | int hr = 0; 422 | foreach (object o in elements) { 423 | Interop.IHTMLElement element = GetIHtmlElement(o); 424 | if (element == null) { 425 | return false; 426 | } 427 | hr = htmlControlRange2.addElement(element); 428 | if (hr != Interop.S_OK) { 429 | break; 430 | } 431 | } 432 | if (hr == Interop.S_OK) { 433 | //If it succeeded, simply select the control range 434 | htmlControlRange.Select(); 435 | } 436 | else { 437 | // elements like DIV and SPAN, w/o layout, cannot be added to a control selelction. 438 | Interop.IHtmlBodyElement bodyElement = (Interop.IHtmlBodyElement)body; 439 | Interop.IHTMLTxtRange textRange = bodyElement.createTextRange(); 440 | if (textRange != null) { 441 | foreach (object o in elements) { 442 | try { 443 | Interop.IHTMLElement element = GetIHtmlElement(o); 444 | if (element == null) { 445 | return false; 446 | } 447 | textRange.MoveToElementText(element); 448 | } 449 | catch { 450 | } 451 | } 452 | textRange.Select(); 453 | } 454 | } 455 | return true; 456 | } 457 | 458 | // /// 459 | // /// Sends all selected items to the back 460 | // /// 461 | // public void SendToBack() { 462 | // //TODO: How do we compress the ZIndexes so they never go out of the range of an int 463 | // SynchronizeSelection(); 464 | // if (_type == HtmlSelectionType.ElementSelection) { 465 | // if (_items.Count > 1) { 466 | // //We have to move all items to the back, and maintain their ordering, so 467 | // //Find the maximum ZIndex in the group 468 | // int max = _minZIndex; 469 | // int count = _items.Count; 470 | // Interop.IHTMLStyle[] styles = new Interop.IHTMLStyle[count]; 471 | // int[] zIndexes = new int[count]; 472 | // for (int i = 0; i < count; i++) { 473 | // Interop.IHTMLElement elem = (Interop.IHTMLElement)_items[i]; 474 | // styles[i] = elem.GetStyle(); 475 | // zIndexes[i] = (int)styles[i].GetZIndex(); 476 | // if (zIndexes[i] > max) { 477 | // max = zIndexes[i]; 478 | // } 479 | // } 480 | // //Calculate how far the first element has to be moved in order to be in the back 481 | // int offset = max - (_minZIndex - 1); 482 | // BatchedUndoUnit unit = _editor.OpenBatchUndo("Align Left"); 483 | // try { 484 | // //Then send all items in the selection that far back 485 | // for (int i = 0; i < count; i++) { 486 | // int newPos = zIndexes[i] - offset; 487 | // if (zIndexes[i] == _maxZIndex) { 488 | // _maxZIndex--; 489 | // } 490 | // styles[i].SetZIndex(newPos); 491 | // if (newPos < _minZIndex) { 492 | // _minZIndex = newPos; 493 | // } 494 | // } 495 | // } 496 | // catch (Exception e) { 497 | // System.Windows.Forms.MessageBox.Show(e.ToString(),"Exception"); 498 | // } 499 | // finally { 500 | // unit.Close(); 501 | // } 502 | // } 503 | // else { 504 | // Interop.IHTMLElement elem = (Interop.IHTMLElement)_items[0]; 505 | // object zIndex = elem.GetStyle().GetZIndex(); 506 | // if ((zIndex != null) && !(zIndex is DBNull)) { 507 | // if ((int)zIndex == _minZIndex) { 508 | // // if the element is already in the back do nothing. 509 | // return; 510 | // } 511 | // 512 | // if ((int)zIndex == _maxZIndex) { 513 | // _maxZIndex--; 514 | // } 515 | // } 516 | // elem.GetStyle().SetZIndex(--_minZIndex); 517 | // } 518 | // } 519 | // } 520 | 521 | public void SetOuterHtml(string outerHtml) { 522 | Debug.Assert(Items.Count == 1, "Can't get OuterHtml of more than one element"); 523 | ((Interop.IHTMLElement)_items[0]).SetOuterHTML(outerHtml); 524 | } 525 | 526 | /// 527 | /// Synchronizes the selection state held in this object with the selection state in MSHTML 528 | /// 529 | /// true if the selection has changed 530 | public bool SynchronizeSelection() { 531 | //Get the selection object from the MSHTML document 532 | if (_document == null) { 533 | _document = _editor.MSHTMLDocument; 534 | } 535 | Interop.IHTMLSelectionObject selectionObj = _document.GetSelection(); 536 | 537 | //Get the current selection from that selection object 538 | object currentSelection = null; 539 | try { 540 | currentSelection = selectionObj.CreateRange(); 541 | } 542 | catch { 543 | } 544 | 545 | ArrayList oldItems = _items; 546 | HtmlSelectionType oldType = _type; 547 | int oldLength = _selectionLength; 548 | //Default to an empty selection 549 | _type = HtmlSelectionType.Empty; 550 | _selectionLength = 0; 551 | if (currentSelection != null) { 552 | _mshtmlSelection = currentSelection; 553 | _items = new ArrayList(); 554 | //If it's a text selection 555 | if (currentSelection is Interop.IHTMLTxtRange) { 556 | Interop.IHTMLTxtRange textRange = (Interop.IHTMLTxtRange) currentSelection; 557 | //IntPtr ptr = Marshal.GetIUnknownForObject(textRange); 558 | Interop.IHTMLElement parentElement = textRange.ParentElement(); 559 | // If the document is in full document mode or we're selecting a non-body tag, allow it to select 560 | // otherwise, leave the selection as empty (since we don't want the body tag to be selectable on an ASP.NET 561 | // User Control 562 | if (IsSelectableElement(Element.GetWrapperFor(parentElement, _editor))) { 563 | //Add the parent of the text selection 564 | if (parentElement != null) { 565 | _text = textRange.GetText(); 566 | if (_text != null) { 567 | _selectionLength = _text.Length; 568 | } 569 | else { 570 | _selectionLength = 0; 571 | } 572 | _type = HtmlSelectionType.TextSelection; 573 | _items.Add(parentElement); 574 | } 575 | } 576 | } 577 | //If it's a control selection 578 | else if (currentSelection is Interop.IHtmlControlRange) { 579 | Interop.IHtmlControlRange controlRange = (Interop.IHtmlControlRange) currentSelection; 580 | int selectedCount = controlRange.GetLength(); 581 | //Add all elements selected 582 | if (selectedCount > 0) { 583 | _type = HtmlSelectionType.ElementSelection; 584 | for (int i = 0; i < selectedCount; i++) { 585 | Interop.IHTMLElement currentElement = controlRange.Item(i); 586 | _items.Add(currentElement); 587 | } 588 | _selectionLength = selectedCount; 589 | } 590 | } 591 | } 592 | _sameParentValid = false; 593 | 594 | bool selectionChanged = false; 595 | //Now check if there was a change of selection 596 | //If the two selections have different lengths, then the selection has changed 597 | if (_type != oldType) { 598 | selectionChanged = true; 599 | } 600 | else if (_selectionLength != oldLength) { 601 | selectionChanged = true; 602 | } 603 | else { 604 | if (_items != null) { 605 | //If the two selections have a different element, then the selection has changed 606 | for (int i = 0; i < _items.Count; i++) { 607 | if (_items[i] != oldItems[i]) { 608 | selectionChanged = true; 609 | break; 610 | } 611 | } 612 | } 613 | } 614 | if (selectionChanged) { 615 | //Set _elements to null so no one can retrieve a dirty copy of the selection element wrappers 616 | _elements = null; 617 | 618 | OnSelectionChanged(); 619 | return true; 620 | } 621 | 622 | return false; 623 | } 624 | /// 625 | /// Toggle the absolute positioning state of the selected items 626 | /// 627 | public void ToggleAbsolutePosition() { 628 | _editor.Exec(Interop.IDM_ABSOLUTE_POSITION, !((GetAbsolutePositionInfo() & HtmlCommandInfo.Checked) != 0)); 629 | SynchronizeSelection(); 630 | if (_type == HtmlSelectionType.ElementSelection) { 631 | foreach (Interop.IHTMLElement elem in _items) { 632 | elem.GetStyle().SetZIndex(++_maxZIndex); 633 | } 634 | } 635 | } 636 | 637 | /// 638 | /// Toggle the design time lock state of the selected items 639 | /// 640 | public void ToggleLock() { 641 | //Switch the lock on each item 642 | foreach (Interop.IHTMLElement elem in _items) { 643 | Interop.IHTMLStyle style = elem.GetStyle(); 644 | if (IsElementLocked(elem)) { 645 | //We need to remove attributes off the element and the style because of a bug in Trident 646 | elem.RemoveAttribute(DesignTimeLockAttribute,0); 647 | style.RemoveAttribute(DesignTimeLockAttribute,0); 648 | } 649 | else { 650 | //We need to add attributes to the element and the style because of a bug in Trident 651 | elem.SetAttribute(DesignTimeLockAttribute,"true",0); 652 | style.SetAttribute(DesignTimeLockAttribute,"true",0); 653 | } 654 | } 655 | } 656 | 657 | public void WrapSelection(string tag) { 658 | WrapSelection(tag, null); 659 | } 660 | 661 | public void WrapSelection(string tag, IDictionary attributes) { 662 | //Create a string for all the attributes 663 | string attributeString = String.Empty; 664 | if (attributes != null) { 665 | foreach (string key in attributes.Keys) { 666 | attributeString+=key+"=\""+attributes[key]+"\" "; 667 | } 668 | } 669 | SynchronizeSelection(); 670 | if (_type == HtmlSelectionType.TextSelection) { 671 | Interop.IHTMLTxtRange textRange = (Interop.IHTMLTxtRange)MSHTMLSelection; 672 | string oldText = textRange.GetHtmlText(); 673 | if (oldText == null) { 674 | oldText = String.Empty; 675 | } 676 | string newText = "<"+tag+" "+attributeString+">"+oldText+""; 677 | textRange.PasteHTML(newText); 678 | } 679 | } 680 | 681 | public void WrapSelectionInDiv() { 682 | WrapSelection("div"); 683 | } 684 | 685 | public void WrapSelectionInSpan() { 686 | WrapSelection("span"); 687 | } 688 | 689 | public void WrapSelectionInBlockQuote() { 690 | WrapSelection("blockquote"); 691 | } 692 | 693 | public void WrapSelectionInHyperlink(string url) { 694 | _editor.Exec(Interop.IDM_HYPERLINK,url); 695 | } 696 | 697 | public void RemoveHyperlink() { 698 | _editor.Exec(Interop.IDM_UNLINK); 699 | } 700 | } 701 | } 702 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlSelectionType.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | using System; 12 | 13 | public enum HtmlSelectionType { 14 | Empty = 0, 15 | TextSelection = 1, 16 | ElementSelection = 2 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /HtmlViewer/HtmlTextFormatting.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | 12 | using System; 13 | using System.ComponentModel; 14 | using System.Diagnostics; 15 | using System.Drawing; 16 | 17 | /// 18 | /// Summary description for HtmlTextFormatting. 19 | /// 20 | public class HtmlTextFormatting { 21 | 22 | /// 23 | /// Array of the names of HTML formats that MSHTML accepts 24 | /// These need to be in the same order as the enum HtmlFormat 25 | /// 26 | private static readonly string[] formats = 27 | new string[] { 28 | "Normal", // Normal 29 | "Formatted", // PreFormatted 30 | "Heading 1", // Heading1 31 | "Heading 2", // Heading2 32 | "Heading 3", // Heading3 33 | "Heading 4", // Heading4 34 | "Heading 5", // Heading5 35 | "Heading 6", // Heading6 36 | "Paragraph", // Paragraph 37 | "Numbered List", // OrderedList 38 | "Bulleted List" // UnorderedList 39 | }; 40 | 41 | public HtmlEditor editor; 42 | 43 | /// 44 | /// Constructor which simply takes an HtmlEditor to interface with MSHTML 45 | /// 46 | /// 47 | public HtmlTextFormatting(HtmlEditor editor) { 48 | this.editor = editor; 49 | } 50 | 51 | /// 52 | /// The background color of the current text 53 | /// 54 | public Color BackColor { 55 | get { 56 | //Query MSHTML, convert the result, and return the color 57 | return ConvertMSHTMLColor(editor.ExecResult(Interop.IDM_BACKCOLOR)); 58 | } 59 | set { 60 | //Translate the color and execute the command 61 | string color = ColorTranslator.ToHtml(value); 62 | editor.Exec(Interop.IDM_BACKCOLOR, color); 63 | } 64 | } 65 | 66 | /// 67 | /// Indicates if the current text can be indented 68 | /// 69 | public bool CanIndent { 70 | get { 71 | return editor.IsCommandEnabled(Interop.IDM_INDENT); 72 | } 73 | } 74 | 75 | /// 76 | /// Indicates if the background color can be set 77 | /// 78 | public bool CanSetBackColor { 79 | get { 80 | return editor.IsCommandEnabled(Interop.IDM_BACKCOLOR); 81 | } 82 | } 83 | 84 | /// 85 | /// Indicates if the font face can be set 86 | /// 87 | public bool CanSetFontName { 88 | get { 89 | return editor.IsCommandEnabled(Interop.IDM_FONTNAME); 90 | } 91 | } 92 | 93 | /// 94 | /// Indicates if the font size can get set 95 | /// 96 | public bool CanSetFontSize { 97 | get { 98 | return editor.IsCommandEnabled(Interop.IDM_FONTSIZE); 99 | } 100 | } 101 | 102 | /// 103 | /// Indicates if the foreground color can be set 104 | /// 105 | public bool CanSetForeColor { 106 | get { 107 | return editor.IsCommandEnabled(Interop.IDM_FORECOLOR); 108 | } 109 | } 110 | 111 | /// 112 | /// Indicates if the Html format (eg ordered lists, paragraph, heading) can be set 113 | /// 114 | public bool CanSetHtmlFormat { 115 | get { 116 | return editor.IsCommandEnabled(Interop.IDM_BLOCKFMT); 117 | } 118 | } 119 | 120 | /// 121 | /// Indicates if the current text can be unindented 122 | /// 123 | public bool CanUnindent { 124 | get { 125 | return editor.IsCommandEnabled(Interop.IDM_OUTDENT); 126 | } 127 | } 128 | 129 | /// 130 | /// Gets and sets the font name of the current text 131 | /// 132 | public string FontName { 133 | get { 134 | return (editor.ExecResult(Interop.IDM_FONTNAME) as string); 135 | } 136 | set { 137 | editor.Exec(Interop.IDM_FONTNAME, value); 138 | } 139 | } 140 | 141 | /// 142 | /// Gets and sets the font size of the current text 143 | /// 144 | public HtmlFontSize FontSize { 145 | get { 146 | object o = editor.ExecResult(Interop.IDM_FONTSIZE); 147 | if (o == null) { 148 | return HtmlFontSize.Medium; 149 | } 150 | else { 151 | return (HtmlFontSize)o; 152 | } 153 | } 154 | set { 155 | editor.Exec(Interop.IDM_FONTSIZE, (int)value); 156 | } 157 | } 158 | 159 | /// 160 | /// The foreground color of the current text 161 | /// 162 | public Color ForeColor { 163 | get { 164 | //Query MSHTML, convert the result, and return the color 165 | return ConvertMSHTMLColor(editor.ExecResult(Interop.IDM_FORECOLOR)); 166 | } 167 | set { 168 | //Translate the color and execute the command 169 | string color = ColorTranslator.ToHtml(value); 170 | editor.Exec(Interop.IDM_FORECOLOR, color); 171 | } 172 | } 173 | 174 | /// 175 | /// Converts an MSHTML color to a Frameworks color 176 | /// 177 | /// object colorValue - The color value returned from MSHTML 178 | /// 179 | private Color ConvertMSHTMLColor(object colorValue) { 180 | if (colorValue != null) { 181 | Type colorType = colorValue.GetType(); 182 | if (colorType == typeof(int)) { 183 | //If the colorValue is an int, it's a Win32 color 184 | return ColorTranslator.FromWin32((int)colorValue); 185 | } 186 | else if (colorType == typeof(string)) { 187 | //Otherwise, it's a string, so convert that 188 | return ColorTranslator.FromHtml((string)colorValue); 189 | } 190 | Debug.Fail("Unexpected color type : " + colorType.FullName); 191 | } 192 | return Color.Empty; 193 | } 194 | 195 | /// 196 | /// Gets the current state of the bold command (enabled and/or checked) 197 | /// 198 | /// 199 | public HtmlCommandInfo GetBoldInfo() { 200 | return editor.GetCommandInfo(Interop.IDM_BOLD); 201 | } 202 | 203 | public HtmlFormat GetHtmlFormat() { 204 | string formatString = editor.ExecResult(Interop.IDM_BLOCKFMT) as string; 205 | if (formatString != null) { 206 | for (int i = 0; i < formats.Length; i++) { 207 | if (formatString.Equals(formats[i])) { 208 | return (HtmlFormat)i; 209 | } 210 | } 211 | } 212 | return HtmlFormat.Normal; 213 | } 214 | 215 | /// 216 | /// Gets the current state of the italics command (enabled and/or checked) 217 | /// 218 | /// 219 | public HtmlCommandInfo GetItalicsInfo() { 220 | return editor.GetCommandInfo(Interop.IDM_ITALIC); 221 | } 222 | 223 | /// 224 | /// Gets the current state of the strikethrough command (enabled and/or checked) 225 | /// 226 | /// 227 | public HtmlCommandInfo GetStrikethroughInfo() { 228 | return editor.GetCommandInfo(Interop.IDM_STRIKETHROUGH); 229 | } 230 | 231 | /// 232 | /// Gets the current state of the Subscript command (enabled and/or checked) 233 | /// 234 | /// 235 | public HtmlCommandInfo GetSubscriptInfo() { 236 | return editor.GetCommandInfo(Interop.IDM_SUBSCRIPT); 237 | } 238 | 239 | /// 240 | /// Gets the current state of the Superscript command (enabled and/or checked) 241 | /// 242 | /// 243 | public HtmlCommandInfo GetSuperscriptInfo() { 244 | return editor.GetCommandInfo(Interop.IDM_SUPERSCRIPT); 245 | } 246 | 247 | /// 248 | /// Gets the current state of the Underline command (enabled and/or checked) 249 | /// 250 | /// 251 | public HtmlCommandInfo GetUnderlineInfo() { 252 | return editor.GetCommandInfo(Interop.IDM_UNDERLINE); 253 | } 254 | 255 | /// 256 | /// Indents the current text 257 | /// 258 | public void Indent() { 259 | editor.Exec(Interop.IDM_INDENT); 260 | } 261 | /// 262 | /// Sets the HTML format (eg ordered list, paragraph, etc.) of the current text 263 | /// 264 | /// 265 | public void SetHtmlFormat(HtmlFormat format) { 266 | editor.Exec(Interop.IDM_BLOCKFMT, formats[(int)format]); 267 | } 268 | 269 | /// 270 | /// Gets the current state of the bold command 271 | /// 272 | /// 273 | public void ToggleBold() { 274 | editor.Exec(Interop.IDM_BOLD); 275 | } 276 | 277 | /// 278 | /// Toggles the current state of the italics command 279 | /// 280 | /// 281 | public void ToggleItalics() { 282 | editor.Exec(Interop.IDM_ITALIC); 283 | } 284 | 285 | /// 286 | /// Toggles the current state of the strikethrough command 287 | /// 288 | /// 289 | public void ToggleStrikethrough() { 290 | editor.Exec(Interop.IDM_STRIKETHROUGH); 291 | } 292 | 293 | /// 294 | /// Toggles the current state of the Subscript command 295 | /// 296 | /// 297 | public void ToggleSubscript() { 298 | editor.Exec(Interop.IDM_SUBSCRIPT); 299 | } 300 | 301 | /// 302 | /// Toggles the current state of the Superscript command 303 | /// 304 | /// 305 | public void ToggleSuperscript() { 306 | editor.Exec(Interop.IDM_SUPERSCRIPT); 307 | } 308 | 309 | /// 310 | /// Toggles the current state of the Underline command 311 | /// 312 | /// 313 | public void ToggleUnderline() { 314 | editor.Exec(Interop.IDM_UNDERLINE); 315 | } 316 | 317 | /// 318 | /// Unindents the current text 319 | /// 320 | public void Unindent() { 321 | editor.Exec(Interop.IDM_OUTDENT); 322 | } 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /HtmlViewer/MSHTMLSite.cs: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // HTML Control and HTML Editor Sample 3 | // Copyright 2003, Nikhil Kothari. All Rights Reserved. 4 | // 5 | // Provided as is, in sample form with no associated warranties. 6 | // For more information on usage, see the accompanying 7 | // License.txt file. 8 | /////////////////////////////////////////////////////////////////////////////// 9 | 10 | namespace HtmlApp.Html { 11 | 12 | using System; 13 | using System.ComponentModel; 14 | using System.Diagnostics; 15 | using System.Drawing; 16 | using System.Runtime.InteropServices; 17 | using System.Windows.Forms; 18 | 19 | [ 20 | ClassInterface(ClassInterfaceType.None) 21 | ] 22 | internal class MSHTMLSite : 23 | Interop.IOleClientSite, 24 | Interop.IOleContainer, 25 | Interop.IOleDocumentSite, 26 | Interop.IOleInPlaceSite, 27 | Interop.IOleInPlaceFrame, 28 | Interop.IDocHostUIHandler, 29 | Interop.IPropertyNotifySink, 30 | Interop.IAdviseSink, 31 | Interop.IOleServiceProvider { 32 | 33 | /// the Control used to host (and parent) the mshtml window 34 | private HtmlControl hostControl; 35 | 36 | /// the mshtml instance and various related objects 37 | private Interop.IOleObject tridentOleObject; 38 | private Interop.IHTMLDocument2 tridentDocument; 39 | private Interop.IOleCommandTarget tridentCmdTarget; 40 | private Interop.IOleDocumentView tridentView; 41 | private Interop.IOleInPlaceActiveObject activeObject; 42 | 43 | // cookie representing our sink 44 | private Interop.ConnectionPointCookie propNotifyCookie; 45 | private int adviseSinkCookie; 46 | 47 | // private DropTarget _dropTarget; 48 | 49 | /// 50 | /// 51 | public MSHTMLSite(HtmlControl hostControl) { 52 | if ((hostControl == null) || (hostControl.IsHandleCreated == false)) { 53 | throw new ArgumentException(); 54 | } 55 | 56 | this.hostControl = hostControl; 57 | hostControl.Resize += new EventHandler(this.OnParentResize); 58 | } 59 | 60 | /// 61 | /// 62 | public Interop.IOleCommandTarget MSHTMLCommandTarget { 63 | get { 64 | return tridentCmdTarget; 65 | } 66 | } 67 | 68 | /// 69 | /// 70 | public Interop.IHTMLDocument2 MSHTMLDocument { 71 | get { 72 | return tridentDocument; 73 | } 74 | } 75 | 76 | /// 77 | /// 78 | public void ActivateMSHTML() { 79 | Debug.Assert(tridentOleObject != null, "How'd we get here when trident is null!"); 80 | 81 | try { 82 | Interop.COMRECT r = new Interop.COMRECT(); 83 | 84 | Interop.GetClientRect(hostControl.Handle, r); 85 | tridentOleObject.DoVerb(Interop.OLEIVERB_UIACTIVATE, Interop.NullIntPtr, (Interop.IOleClientSite)this, 86 | 0, hostControl.Handle, r); 87 | } 88 | catch (Exception e) { 89 | Debug.Fail(e.ToString()); 90 | } 91 | } 92 | 93 | /// 94 | /// 95 | public void CloseMSHTML() { 96 | hostControl.Resize -= new EventHandler(this.OnParentResize); 97 | 98 | try { 99 | if (propNotifyCookie != null) { 100 | propNotifyCookie.Disconnect(); 101 | propNotifyCookie = null; 102 | } 103 | 104 | if (tridentDocument != null) { 105 | tridentView = null; 106 | tridentDocument = null; 107 | tridentCmdTarget = null; 108 | activeObject = null; 109 | 110 | if (adviseSinkCookie != 0) { 111 | tridentOleObject.Unadvise(adviseSinkCookie); 112 | adviseSinkCookie = 0; 113 | } 114 | 115 | tridentOleObject.Close(Interop.OLECLOSE_NOSAVE); 116 | tridentOleObject.SetClientSite(null); 117 | tridentOleObject = null; 118 | } 119 | } 120 | catch (Exception e) { 121 | Debug.Fail(e.ToString()); 122 | } 123 | } 124 | 125 | /// 126 | /// 127 | public void CreateMSHTML() { 128 | Debug.Assert(tridentDocument == null, "Must call CloseMSHTML before recreating."); 129 | 130 | bool created = false; 131 | try { 132 | // create the trident instance 133 | tridentDocument = (Interop.IHTMLDocument2)new Interop.HTMLDocument(); 134 | tridentOleObject = (Interop.IOleObject)tridentDocument; 135 | 136 | // hand it our Interop.IOleClientSite implementation 137 | tridentOleObject.SetClientSite((Interop.IOleClientSite)this); 138 | 139 | created = true; 140 | 141 | propNotifyCookie = new Interop.ConnectionPointCookie(tridentDocument, this, typeof(Interop.IPropertyNotifySink), false); 142 | 143 | tridentOleObject.Advise((Interop.IAdviseSink)this, out adviseSinkCookie); 144 | Debug.Assert(adviseSinkCookie != 0); 145 | 146 | tridentCmdTarget = (Interop.IOleCommandTarget)tridentDocument; 147 | } 148 | finally { 149 | if (created == false) { 150 | tridentDocument = null; 151 | tridentOleObject = null; 152 | tridentCmdTarget = null; 153 | } 154 | } 155 | } 156 | 157 | /// 158 | /// 159 | public void DeactivateMSHTML() { 160 | // TODO: Implement this... once I know how to do it! 161 | } 162 | 163 | /// 164 | /// 165 | private void OnParentResize(object src, EventArgs e) { 166 | if (tridentView != null) { 167 | Interop.COMRECT r = new Interop.COMRECT(); 168 | 169 | Interop.GetClientRect(hostControl.Handle, r); 170 | tridentView.SetRect(r); 171 | } 172 | } 173 | 174 | /// 175 | /// 176 | private void OnReadyStateChanged() { 177 | string readyState = tridentDocument.GetReadyState(); 178 | if (String.Compare(readyState, "complete", true) == 0) { 179 | OnReadyStateComplete(); 180 | } 181 | } 182 | 183 | /// 184 | /// 185 | private void OnReadyStateComplete() { 186 | hostControl.OnReadyStateComplete(EventArgs.Empty); 187 | } 188 | 189 | internal void SetFocus() { 190 | if (activeObject != null) { 191 | IntPtr hWnd = IntPtr.Zero; 192 | if (activeObject.GetWindow(out hWnd) == Interop.S_OK) { 193 | Debug.Assert(hWnd != IntPtr.Zero); 194 | Interop.SetFocus(hWnd); 195 | } 196 | } 197 | } 198 | 199 | /// 200 | /// 201 | public bool TranslateAccelarator(Interop.COMMSG msg) { 202 | if (activeObject != null) { 203 | int hr = activeObject.TranslateAccelerator(msg); 204 | if (hr != Interop.S_FALSE) { 205 | return true; 206 | } 207 | } 208 | return false; 209 | } 210 | 211 | 212 | /////////////////////////////////////////////////////////////////////////// 213 | // Interop.IOleClientSite Implementation 214 | 215 | public int SaveObject() { 216 | return Interop.S_OK; 217 | } 218 | 219 | public int GetMoniker(int dwAssign, int dwWhichMoniker, out object ppmk) { 220 | ppmk = null; 221 | return Interop.E_NOTIMPL; 222 | } 223 | 224 | public int GetContainer(out Interop.IOleContainer ppContainer) { 225 | ppContainer = (Interop.IOleContainer)this; 226 | return Interop.S_OK; 227 | } 228 | 229 | public int ShowObject() { 230 | return Interop.S_OK; 231 | } 232 | 233 | public int OnShowWindow(int fShow) { 234 | return Interop.S_OK; 235 | } 236 | 237 | public int RequestNewObjectLayout() { 238 | return Interop.S_OK; 239 | } 240 | 241 | 242 | /////////////////////////////////////////////////////////////////////////// 243 | // Interop.IOleContainer Implementation 244 | 245 | public void ParseDisplayName(object pbc, string pszDisplayName, int[] pchEaten, object[] ppmkOut) { 246 | Debug.Fail("ParseDisplayName - " + pszDisplayName); 247 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 248 | } 249 | 250 | public void EnumObjects(int grfFlags, object[] ppenum) { 251 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 252 | } 253 | 254 | public void LockContainer(int fLock) { 255 | } 256 | 257 | 258 | /////////////////////////////////////////////////////////////////////////// 259 | // Interop.IOleDocumentSite Implementation 260 | 261 | public int ActivateMe(Interop.IOleDocumentView pViewToActivate) { 262 | Debug.Assert(pViewToActivate != null, 263 | "Expected the view to be non-null"); 264 | if (pViewToActivate == null) 265 | return Interop.E_INVALIDARG; 266 | 267 | Interop.COMRECT r = new Interop.COMRECT(); 268 | 269 | Interop.GetClientRect(hostControl.Handle, r); 270 | 271 | tridentView = pViewToActivate; 272 | tridentView.SetInPlaceSite((Interop.IOleInPlaceSite)this); 273 | tridentView.UIActivate(1); 274 | tridentView.SetRect(r); 275 | tridentView.Show(1); 276 | 277 | return Interop.S_OK; 278 | } 279 | 280 | 281 | /////////////////////////////////////////////////////////////////////////// 282 | // Interop.IOleInPlaceSite Implementation 283 | 284 | public IntPtr GetWindow() { 285 | return hostControl.Handle; 286 | } 287 | 288 | public void ContextSensitiveHelp(int fEnterMode) { 289 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 290 | } 291 | 292 | public int CanInPlaceActivate() { 293 | return Interop.S_OK; 294 | } 295 | 296 | public void OnInPlaceActivate() { 297 | } 298 | 299 | public void OnUIActivate() { 300 | } 301 | 302 | public void GetWindowContext(out Interop.IOleInPlaceFrame ppFrame, out Interop.IOleInPlaceUIWindow ppDoc, Interop.COMRECT lprcPosRect, Interop.COMRECT lprcClipRect, Interop.tagOIFI lpFrameInfo) { 303 | ppFrame = (Interop.IOleInPlaceFrame)this; 304 | ppDoc = null; 305 | 306 | Interop.GetClientRect(hostControl.Handle, lprcPosRect); 307 | Interop.GetClientRect(hostControl.Handle, lprcClipRect); 308 | 309 | lpFrameInfo.cb = Marshal.SizeOf(typeof(Interop.tagOIFI)); 310 | lpFrameInfo.fMDIApp = 0; 311 | lpFrameInfo.hwndFrame = hostControl.Handle; 312 | lpFrameInfo.hAccel = Interop.NullIntPtr; 313 | lpFrameInfo.cAccelEntries = 0; 314 | } 315 | 316 | public int Scroll(Interop.tagSIZE scrollExtant) { 317 | return Interop.E_NOTIMPL; 318 | } 319 | 320 | public void OnUIDeactivate(int fUndoable) { 321 | // NOTE, nikhilko, 7/99: Don't return E_NOTIMPL. Somehow doing nothing and returning S_OK 322 | // fixes trident hosting in Win2000. 323 | } 324 | 325 | public void OnInPlaceDeactivate() { 326 | } 327 | 328 | public void DiscardUndoState() { 329 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 330 | } 331 | 332 | public void DeactivateAndUndo() { 333 | } 334 | 335 | public int OnPosRectChange(Interop.COMRECT lprcPosRect) { 336 | return Interop.S_OK; 337 | } 338 | 339 | 340 | /////////////////////////////////////////////////////////////////////////// 341 | // Interop.IOleInPlaceFrame Implementation 342 | 343 | public void GetBorder(Interop.COMRECT lprectBorder) { 344 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 345 | } 346 | 347 | public void RequestBorderSpace(Interop.COMRECT pborderwidths) { 348 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 349 | } 350 | 351 | public void SetBorderSpace(Interop.COMRECT pborderwidths) { 352 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 353 | } 354 | 355 | public void SetActiveObject(Interop.IOleInPlaceActiveObject pActiveObject, string pszObjName) { 356 | this.activeObject = pActiveObject; 357 | } 358 | 359 | public void InsertMenus(IntPtr hmenuShared, Interop.tagOleMenuGroupWidths lpMenuWidths) { 360 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 361 | } 362 | 363 | public void SetMenu(IntPtr hmenuShared, IntPtr holemenu, IntPtr hwndActiveObject) { 364 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 365 | } 366 | 367 | public void RemoveMenus(IntPtr hmenuShared) { 368 | throw new COMException(String.Empty, Interop.E_NOTIMPL); 369 | } 370 | 371 | public void SetStatusText(string pszStatusText) { 372 | } 373 | 374 | public void EnableModeless(int fEnable) { 375 | } 376 | 377 | public int TranslateAccelerator(Interop.COMMSG lpmsg, short wID) { 378 | return Interop.S_FALSE; 379 | } 380 | 381 | 382 | /////////////////////////////////////////////////////////////////////////// 383 | // IDocHostUIHandler Implementation 384 | 385 | public int ShowContextMenu(int dwID, Interop.POINT pt, object pcmdtReserved, object pdispReserved) { 386 | // Point location = hostControl.PointToClient(new Point(pt.x, pt.y)); 387 | // 388 | // ShowContextMenuEventArgs e = new ShowContextMenuEventArgs(location, false); 389 | // 390 | // try { 391 | // hostControl.OnShowContextMenu(e); 392 | // } 393 | // catch { 394 | // // Make sure we return Interop.S_OK 395 | // } 396 | // 397 | return Interop.S_OK; 398 | } 399 | 400 | public int GetHostInfo(Interop.DOCHOSTUIINFO info) { 401 | info.dwDoubleClick = Interop.DOCHOSTUIDBLCLICK_DEFAULT; 402 | int flags = 0; 403 | if (hostControl.AllowInPlaceNavigation) { 404 | flags |= Interop.DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION; 405 | } 406 | if (!hostControl.Border3d) { 407 | flags |= Interop.DOCHOSTUIFLAG_NO3DBORDER; 408 | } 409 | if (!hostControl.ScriptEnabled) { 410 | flags |= Interop.DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE; 411 | } 412 | if (!hostControl.ScrollBarsEnabled) { 413 | flags |= Interop.DOCHOSTUIFLAG_SCROLL_NO; 414 | } 415 | if (hostControl.FlatScrollBars) { 416 | flags |= Interop.DOCHOSTUIFLAG_FLAT_SCROLLBAR; 417 | } 418 | info.dwFlags = flags; 419 | return Interop.S_OK; 420 | } 421 | 422 | public int EnableModeless(bool fEnable) { 423 | return Interop.S_OK; 424 | } 425 | 426 | public int ShowUI(int dwID, Interop.IOleInPlaceActiveObject activeObject, Interop.IOleCommandTarget commandTarget, Interop.IOleInPlaceFrame frame, Interop.IOleInPlaceUIWindow doc) { 427 | return Interop.S_OK; 428 | } 429 | 430 | public int HideUI() { 431 | return Interop.S_OK; 432 | } 433 | 434 | public int UpdateUI() { 435 | return Interop.S_OK; 436 | } 437 | 438 | public int OnDocWindowActivate(bool fActivate) { 439 | return Interop.E_NOTIMPL; 440 | } 441 | 442 | public int OnFrameWindowActivate(bool fActivate) { 443 | return Interop.E_NOTIMPL; 444 | } 445 | 446 | public int ResizeBorder(Interop.COMRECT rect, Interop.IOleInPlaceUIWindow doc, bool fFrameWindow) { 447 | return Interop.E_NOTIMPL; 448 | } 449 | 450 | public int GetOptionKeyPath(string[] pbstrKey, int dw) { 451 | pbstrKey[0] = null; 452 | return Interop.S_OK; 453 | } 454 | 455 | public int GetDropTarget(Interop.IOleDropTarget pDropTarget, out Interop.IOleDropTarget ppDropTarget) { 456 | ppDropTarget = null; 457 | return Interop.E_NOTIMPL; 458 | } 459 | 460 | public int GetExternal(out object ppDispatch) { 461 | ppDispatch = hostControl.ScriptObject; 462 | if (ppDispatch != null) { 463 | return Interop.S_OK; 464 | } 465 | else { 466 | return Interop.E_NOTIMPL; 467 | } 468 | } 469 | 470 | public int TranslateAccelerator(Interop.COMMSG msg, ref Guid group, int nCmdID) { 471 | return Interop.S_FALSE; 472 | } 473 | 474 | public int TranslateUrl(int dwTranslate, string strURLIn, out string pstrURLOut) { 475 | pstrURLOut = null; 476 | return Interop.E_NOTIMPL; 477 | } 478 | 479 | public int FilterDataObject(Interop.IOleDataObject pDO, out Interop.IOleDataObject ppDORet) { 480 | ppDORet = null; 481 | return Interop.E_NOTIMPL; 482 | } 483 | 484 | 485 | /////////////////////////////////////////////////////////////////////////// 486 | // IPropertyNotifySink Implementation 487 | 488 | public void OnChanged(int dispID) { 489 | if (dispID == Interop.DISPID_READYSTATE) { 490 | OnReadyStateChanged(); 491 | } 492 | } 493 | 494 | public void OnRequestEdit(int dispID) { 495 | } 496 | 497 | 498 | /////////////////////////////////////////////////////////////////////////// 499 | // IAdviseSink Implementation 500 | 501 | public void OnDataChange(Interop.FORMATETC pFormat, Interop.STGMEDIUM pStg) { 502 | } 503 | 504 | public void OnViewChange(int dwAspect, int index) { 505 | } 506 | 507 | public void OnRename(object pmk) { 508 | } 509 | 510 | public void OnSave() { 511 | } 512 | 513 | public void OnClose() { 514 | } 515 | 516 | 517 | /////////////////////////////////////////////////////////////////////////// 518 | // Interop.IOleServiceProvider 519 | 520 | public int QueryService(ref Guid sid, ref Guid iid, out IntPtr ppvObject) { 521 | int hr = Interop.E_NOINTERFACE; 522 | ppvObject = Interop.NullIntPtr; 523 | 524 | // object service = hostControl.GetService(ref sid); 525 | // if (service != null) { 526 | // if (iid.Equals(Interop.IID_IUnknown)) { 527 | // ppvObject = Marshal.GetIUnknownForObject(service); 528 | // } 529 | // else { 530 | // IntPtr pUnk = Marshal.GetIUnknownForObject(service); 531 | // 532 | // hr = Marshal.QueryInterface(pUnk, ref iid, out ppvObject); 533 | // Marshal.Release(pUnk); 534 | // } 535 | // } 536 | 537 | return hr; 538 | } 539 | 540 | } 541 | } 542 | 543 | -------------------------------------------------------------------------------- /Installer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.ComponentModel; 4 | using System.Configuration.Install; 5 | using System.Runtime.InteropServices; 6 | using System.Diagnostics; 7 | 8 | namespace TimHeuer.PreviewHandlers 9 | { 10 | [RunInstaller(true)] 11 | public class ComInstaller : Installer 12 | { 13 | public override void Install(IDictionary stateSaver) 14 | { 15 | try 16 | { 17 | base.Install(stateSaver); 18 | RegistrationServices regsrv = new RegistrationServices(); 19 | if (!regsrv.RegisterAssembly(this.GetType().Assembly, AssemblyRegistrationFlags.SetCodeBase)) 20 | { 21 | throw new InstallException("Failed to register for COM interop."); 22 | } 23 | } 24 | catch (Exception exc) 25 | { 26 | Trace.WriteLine(exc.ToString()); 27 | throw; 28 | } 29 | } 30 | 31 | public override void Uninstall(IDictionary savedState) 32 | { 33 | base.Uninstall(savedState); 34 | RegistrationServices regsrv = new RegistrationServices(); 35 | if (!regsrv.UnregisterAssembly(this.GetType().Assembly)) 36 | { 37 | throw new InstallException("Failed to unregister for COM interop."); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Libraries/CSharpFormat.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timheuer/CodePreviewHandler/92c2b34e7f79255c3426d43ab6bce1c5c5541c2f/Libraries/CSharpFormat.dll -------------------------------------------------------------------------------- /Libraries/TimHeuer.ManagedPreviewHandler.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timheuer/CodePreviewHandler/92c2b34e7f79255c3426d43ab6bce1c5c5541c2f/Libraries/TimHeuer.ManagedPreviewHandler.dll -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CodePreviewHandler")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CodePreviewHandler")] 13 | [assembly: AssemblyCopyright("Copyright © 2006")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1bc56a14-e380-4c1f-bc04-0cdce01593da")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18033 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TimHeuer.PreviewHandlers.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimHeuer.PreviewHandlers.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to .csharpcode, .csharpcode pre 65 | ///{ 66 | /// font-size: small; 67 | /// color: black; 68 | /// font-family: Consolas, "Courier New", Courier, Monospace; 69 | /// background-color: #ffffff; 70 | /// /*white-space: pre;*/ 71 | ///} 72 | /// 73 | ///.csharpcode pre { margin: 0em; } 74 | /// 75 | ///.csharpcode .rem { color: #008000; } 76 | /// 77 | ///.csharpcode .kwrd { color: #0000ff; } 78 | /// 79 | ///.csharpcode .str { color: #006080; } 80 | /// 81 | ///.csharpcode .op { color: #0000c0; } 82 | /// 83 | ///.csharpcode .preproc { color: #cc6633; } 84 | /// 85 | ///.csharpcode .asp { background-color: #ffff00; } 86 | /// 87 | ///.csharpcode .html { color: #800000 [rest of string was truncated]";. 88 | /// 89 | internal static string CssString { 90 | get { 91 | return ResourceManager.GetString("CssString", resourceCulture); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | .csharpcode, .csharpcode pre 122 | { 123 | font-size: small; 124 | color: black; 125 | font-family: Consolas, "Courier New", Courier, Monospace; 126 | background-color: #ffffff; 127 | /*white-space: pre;*/ 128 | } 129 | 130 | .csharpcode pre { margin: 0em; } 131 | 132 | .csharpcode .rem { color: #008000; } 133 | 134 | .csharpcode .kwrd { color: #0000ff; } 135 | 136 | .csharpcode .str { color: #006080; } 137 | 138 | .csharpcode .op { color: #0000c0; } 139 | 140 | .csharpcode .preproc { color: #cc6633; } 141 | 142 | .csharpcode .asp { background-color: #ffff00; } 143 | 144 | .csharpcode .html { color: #800000; } 145 | 146 | .csharpcode .attr { color: #ff0000; } 147 | 148 | .csharpcode .alt 149 | { 150 | background-color: #f4f4f4; 151 | width: 100%; 152 | margin: 0em; 153 | } 154 | 155 | .csharpcode .lnum { color: #606060; } 156 | 157 | Embedded CSS styles 158 | 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CodePreviewHandler 2 | ================== 3 | 4 | [![Build status](http://ci.appveyor.com/api/projects/status/ni43t86jj5d3ql5t)](http://ci.appveyor.com/project/TimHeuer/codepreviewhandler) 5 | 6 | This is code for a Windows PreviewHandler file association. 7 | This enables you to have a preview window in Explorer or Outlook when selecting a file and it will show code-highlighting for the file without opening into some editor. 8 | 9 | See http://timheuer.com/blog/archive/2006/12/13/13945.aspx for some history. 10 | -------------------------------------------------------------------------------- /Registration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using TimHeuer.ManagedPreviewHandler; 4 | 5 | namespace TimHeuer.PreviewHandlers 6 | { 7 | internal static class PreviewHandlerRegistration 8 | { 9 | [ComRegisterFunction] 10 | private static void Register(Type t) { PreviewHandler.Register(t); } 11 | 12 | [ComUnregisterFunction] 13 | private static void Unregister(Type t) { PreviewHandler.Unregister(t); } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UpgradeLog.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timheuer/CodePreviewHandler/92c2b34e7f79255c3426d43ab6bce1c5c5541c2f/UpgradeLog.htm --------------------------------------------------------------------------------