mirror of
https://github.com/greenshot/greenshot.git
synced 2025-01-24 14:12:52 -08:00
307 lines
14 KiB
C#
307 lines
14 KiB
C#
// Greenshot - a free and open source screenshot tool
|
|
// Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
|
//
|
|
// For more information see: http://getgreenshot.org/
|
|
// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Xml;
|
|
using GreenshotOfficePlugin.Com;
|
|
using GreenshotOfficePlugin.OfficeExport.Entities;
|
|
using GreenshotPlugin.Core;
|
|
using GreenshotPlugin.Interfaces;
|
|
using GreenshotPlugin.Interfaces.Plugin;
|
|
using Microsoft.Office.Interop.OneNote;
|
|
|
|
namespace GreenshotOfficePlugin.OfficeExport
|
|
{
|
|
/// <summary>
|
|
/// OneNote exporter
|
|
/// More details about OneNote: http://msdn.microsoft.com/en-us/magazine/ff796230.aspx
|
|
/// </summary>
|
|
public class OneNoteExporter
|
|
{
|
|
private const string XmlImageContent = "<one:Image format=\"png\"><one:Size width=\"{1}.0\" height=\"{2}.0\" isSetByUser=\"true\" /><one:Data>{0}</one:Data></one:Image>";
|
|
private const string XmlOutline = "<?xml version=\"1.0\"?><one:Page xmlns:one=\"{2}\" ID=\"{1}\"><one:Title><one:OE><one:T><![CDATA[{3}]]></one:T></one:OE></one:Title>{0}</one:Page>";
|
|
private const string OnenoteNamespace2010 = "http://schemas.microsoft.com/office/onenote/2010/onenote";
|
|
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OneNoteExporter));
|
|
|
|
/// <summary>
|
|
/// Create a new page in the "unfiled notes section", with the title of the capture, and export the capture there.
|
|
/// </summary>
|
|
/// <param name="surfaceToUpload">ISurface</param>
|
|
/// <returns>bool true if export worked</returns>
|
|
public bool ExportToNewPage(ISurface surfaceToUpload)
|
|
{
|
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
|
var newPage = new OneNotePage();
|
|
string unfiledNotesSectionId = GetSectionId(oneNoteApplication, SpecialLocation.slUnfiledNotesSection);
|
|
if (unfiledNotesSectionId == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string pageId;
|
|
oneNoteApplication.ComObject.CreateNewPage(unfiledNotesSectionId, out pageId, NewPageStyle.npsDefault);
|
|
newPage.Id = pageId;
|
|
// Set the new name, this is automatically done in the export to page
|
|
newPage.Name = surfaceToUpload.CaptureDetails.Title;
|
|
return ExportToPage(oneNoteApplication, surfaceToUpload, newPage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Export the capture to the specified page
|
|
/// </summary>
|
|
/// <param name="surfaceToUpload">ISurface</param>
|
|
/// <param name="page">OneNotePage</param>
|
|
/// <returns>bool true if everything worked</returns>
|
|
public bool ExportToPage(ISurface surfaceToUpload, OneNotePage page)
|
|
{
|
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
|
return ExportToPage(oneNoteApplication, surfaceToUpload, page);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Export the capture to the specified page
|
|
/// </summary>
|
|
/// <param name="oneNoteApplication">IOneNoteApplication</param>
|
|
/// <param name="surfaceToUpload">ISurface</param>
|
|
/// <param name="page">OneNotePage</param>
|
|
/// <returns>bool true if everything worked</returns>
|
|
private bool ExportToPage(IDisposableCom<Application> oneNoteApplication, ISurface surfaceToUpload, OneNotePage page)
|
|
{
|
|
if (oneNoteApplication == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
using var pngStream = new MemoryStream();
|
|
var pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
|
|
ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
|
|
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
|
|
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Image.Width, surfaceToUpload.Image.Height);
|
|
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
|
|
LOG.InfoFormat("Sending XML: {0}", pageChangesXml);
|
|
oneNoteApplication.ComObject.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false);
|
|
try
|
|
{
|
|
oneNoteApplication.ComObject.NavigateTo(page.Id, null, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Warn("Unable to navigate to the target page", ex);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call this to get the running Excel application, returns null if there isn't any.
|
|
/// </summary>
|
|
/// <returns>ComDisposable for Excel.Application or null</returns>
|
|
private IDisposableCom<Application> GetOneNoteApplication()
|
|
{
|
|
IDisposableCom<Application> oneNoteApplication;
|
|
try
|
|
{
|
|
oneNoteApplication = OleAut32Api.GetActiveObject<Application>("OneNote.Application");
|
|
}
|
|
catch
|
|
{
|
|
// Ignore, probably no OneNote running
|
|
return null;
|
|
}
|
|
return oneNoteApplication;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call this to get the running OneNote application, or create a new instance
|
|
/// </summary>
|
|
/// <returns>ComDisposable for OneNote.Application</returns>
|
|
private IDisposableCom<Application> GetOrCreateOneNoteApplication()
|
|
{
|
|
var oneNoteApplication = GetOneNoteApplication();
|
|
if (oneNoteApplication == null)
|
|
{
|
|
oneNoteApplication = DisposableCom.Create(new Application());
|
|
}
|
|
return oneNoteApplication;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the captions of all the open word documents
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IList<OneNotePage> GetPages()
|
|
{
|
|
var pages = new List<OneNotePage>();
|
|
try
|
|
{
|
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
|
if (oneNoteApplication != null)
|
|
{
|
|
// ReSharper disable once RedundantAssignment
|
|
string notebookXml = "";
|
|
oneNoteApplication.ComObject.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
|
|
if (!string.IsNullOrEmpty(notebookXml))
|
|
{
|
|
LOG.Debug(notebookXml);
|
|
StringReader reader = null;
|
|
try
|
|
{
|
|
reader = new StringReader(notebookXml);
|
|
using var xmlReader = new XmlTextReader(reader);
|
|
reader = null;
|
|
OneNoteSection currentSection = null;
|
|
OneNoteNotebook currentNotebook = null;
|
|
while (xmlReader.Read())
|
|
{
|
|
if ("one:Notebook".Equals(xmlReader.Name))
|
|
{
|
|
string id = xmlReader.GetAttribute("ID");
|
|
if ((id != null) && ((currentNotebook == null) || !id.Equals(currentNotebook.Id)))
|
|
{
|
|
currentNotebook = new OneNoteNotebook
|
|
{
|
|
Id = xmlReader.GetAttribute("ID"),
|
|
Name = xmlReader.GetAttribute("name")
|
|
};
|
|
}
|
|
}
|
|
if ("one:Section".Equals(xmlReader.Name))
|
|
{
|
|
string id = xmlReader.GetAttribute("ID");
|
|
if (id != null && (currentSection == null || !id.Equals(currentSection.Id)))
|
|
{
|
|
currentSection = new OneNoteSection
|
|
{
|
|
Id = xmlReader.GetAttribute("ID"),
|
|
Name = xmlReader.GetAttribute("name"),
|
|
Parent = currentNotebook
|
|
};
|
|
}
|
|
}
|
|
if ("one:Page".Equals(xmlReader.Name))
|
|
{
|
|
// Skip deleted items
|
|
if ("true".Equals(xmlReader.GetAttribute("isInRecycleBin")))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var page = new OneNotePage
|
|
{
|
|
Parent = currentSection,
|
|
Name = xmlReader.GetAttribute("name"),
|
|
Id = xmlReader.GetAttribute("ID")
|
|
};
|
|
if ((page.Id == null) || (page.Name == null))
|
|
{
|
|
continue;
|
|
}
|
|
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
|
|
pages.Add(page);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (reader != null)
|
|
{
|
|
reader.Dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (COMException cEx)
|
|
{
|
|
if (cEx.ErrorCode == unchecked((int)0x8002801D))
|
|
{
|
|
LOG.Warn("Wrong registry keys, to solve this remove the OneNote key as described here: http://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/");
|
|
}
|
|
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", cEx);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex);
|
|
}
|
|
pages.Sort((page1, page2) =>
|
|
{
|
|
if (page1.IsCurrentlyViewed || page2.IsCurrentlyViewed)
|
|
{
|
|
return page2.IsCurrentlyViewed.CompareTo(page1.IsCurrentlyViewed);
|
|
}
|
|
return string.Compare(page1.DisplayName, page2.DisplayName, StringComparison.Ordinal);
|
|
});
|
|
return pages;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve the Section ID for the specified special location
|
|
/// </summary>
|
|
/// <param name="oneNoteApplication"></param>
|
|
/// <param name="specialLocation">SpecialLocation</param>
|
|
/// <returns>string with section ID</returns>
|
|
private string GetSectionId(IDisposableCom<Application> oneNoteApplication, SpecialLocation specialLocation)
|
|
{
|
|
if (oneNoteApplication == null)
|
|
{
|
|
return null;
|
|
}
|
|
// ReSharper disable once RedundantAssignment
|
|
string unfiledNotesPath = "";
|
|
oneNoteApplication.ComObject.GetSpecialLocation(specialLocation, out unfiledNotesPath);
|
|
|
|
// ReSharper disable once RedundantAssignment
|
|
string notebookXml = "";
|
|
oneNoteApplication.ComObject.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
|
|
if (!string.IsNullOrEmpty(notebookXml))
|
|
{
|
|
LOG.Debug(notebookXml);
|
|
StringReader reader = null;
|
|
try
|
|
{
|
|
reader = new StringReader(notebookXml);
|
|
using var xmlReader = new XmlTextReader(reader);
|
|
while (xmlReader.Read())
|
|
{
|
|
if (!"one:Section".Equals(xmlReader.Name))
|
|
{
|
|
continue;
|
|
}
|
|
string id = xmlReader.GetAttribute("ID");
|
|
string path = xmlReader.GetAttribute("path");
|
|
if (unfiledNotesPath.Equals(path))
|
|
{
|
|
return id;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (reader != null)
|
|
{
|
|
reader.Dispose();
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
} |