[skip ci] Backport of office code from master, also added a solution for OneNote export problems in the log. This should be described in a FAQ... http://microsoftmercenary.com/wp/outlook-excel-interop-calls-breaking-solved/

This commit is contained in:
RKrom 2014-12-21 00:11:29 +01:00
commit cf00c408ff
3 changed files with 83 additions and 94 deletions

View file

@ -38,9 +38,14 @@ namespace GreenshotOfficePlugin {
public string EmailCC; public string EmailCC;
[IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")] [IniProperty("EmailBCC", Description = "Default value for the BCC in emails that are created", DefaultValue = "")]
public string EmailBCC; public string EmailBCC;
[IniProperty("OutlookAllowExportInMeetings", Description = "Allow export in meeting items", DefaultValue = "False")] [IniProperty("OutlookAllowExportInMeetings", Description = "For Outlook: Allow export in meeting items", DefaultValue = "False")]
public bool OutlookAllowExportInMeetings; public bool OutlookAllowExportInMeetings;
[IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")] [IniProperty("WordLockAspectRatio", Description = "For Word: Lock the aspect ratio of the image", DefaultValue = "True")]
public bool WordLockAspectRatio; public bool WordLockAspectRatio;
[IniProperty("PowerpointLockAspectRatio", Description = "For Powerpoint: Lock the aspect ratio of the image", DefaultValue = "True")]
public bool PowerpointLockAspectRatio;
[IniProperty("PowerpointSlideLayout", Description = "For Powerpoint: Slide layout, changing this to a wrong value will fallback on ppLayoutBlank!!", DefaultValue = "ppLayoutPictureWithCaption")]
public PPSlideLayout PowerpointSlideLayout;
} }
} }

View file

@ -19,6 +19,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Greenshot.Plugin; using Greenshot.Plugin;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using System; using System;
@ -181,17 +183,17 @@ namespace Greenshot.Interop.Office {
OneNoteSection currentSection = null; OneNoteSection currentSection = null;
OneNoteNotebook currentNotebook = null; OneNoteNotebook currentNotebook = null;
while (xmlReader.Read()) { while (xmlReader.Read()) {
if("one:Notebook".Equals(xmlReader.Name)) { if ("one:Notebook".Equals(xmlReader.Name)) {
string id = xmlReader.GetAttribute("ID"); string id = xmlReader.GetAttribute("ID");
if(id != null && (currentNotebook == null || !id.Equals(currentNotebook.ID))) { if (id != null && (currentNotebook == null || !id.Equals(currentNotebook.ID))) {
currentNotebook = new OneNoteNotebook(); currentNotebook = new OneNoteNotebook();
currentNotebook.ID = xmlReader.GetAttribute("ID"); currentNotebook.ID = xmlReader.GetAttribute("ID");
currentNotebook.Name = xmlReader.GetAttribute("name"); currentNotebook.Name = xmlReader.GetAttribute("name");
} }
} }
if("one:Section".Equals(xmlReader.Name)) { if ("one:Section".Equals(xmlReader.Name)) {
string id = xmlReader.GetAttribute("ID"); string id = xmlReader.GetAttribute("ID");
if(id != null && (currentSection == null || !id.Equals(currentSection.ID))) { if (id != null && (currentSection == null || !id.Equals(currentSection.ID))) {
currentSection = new OneNoteSection(); currentSection = new OneNoteSection();
currentSection.ID = xmlReader.GetAttribute("ID"); currentSection.ID = xmlReader.GetAttribute("ID");
currentSection.Name = xmlReader.GetAttribute("name"); currentSection.Name = xmlReader.GetAttribute("name");
@ -200,14 +202,14 @@ namespace Greenshot.Interop.Office {
} }
if ("one:Page".Equals(xmlReader.Name)) { if ("one:Page".Equals(xmlReader.Name)) {
// Skip deleted items // Skip deleted items
if("true".Equals(xmlReader.GetAttribute("isInRecycleBin"))) { if ("true".Equals(xmlReader.GetAttribute("isInRecycleBin"))) {
continue; continue;
} }
OneNotePage page = new OneNotePage(); OneNotePage page = new OneNotePage();
page.Parent = currentSection; page.Parent = currentSection;
page.Name = xmlReader.GetAttribute("name"); page.Name = xmlReader.GetAttribute("name");
page.ID = xmlReader.GetAttribute("ID"); page.ID = xmlReader.GetAttribute("ID");
if(page.ID == null || page.Name == null) { if (page.ID == null || page.Name == null) {
continue; continue;
} }
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed")); page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
@ -223,8 +225,13 @@ namespace Greenshot.Interop.Office {
} }
} }
} }
} 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) { } catch (Exception ex) {
LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex); LOG.Warn("Problem retrieving onenote destinations, ignoring: ", ex);
} }
pages.Sort(delegate(OneNotePage p1, OneNotePage p2) { pages.Sort(delegate(OneNotePage p1, OneNotePage p2) {
if(p1.IsCurrentlyViewed || p2.IsCurrentlyViewed) { if(p1.IsCurrentlyViewed || p2.IsCurrentlyViewed) {

View file

@ -18,20 +18,21 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Greenshot.IniFile;
using GreenshotOfficePlugin;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Text;
using Greenshot.Interop;
namespace Greenshot.Interop.Office { namespace Greenshot.Interop.Office {
public class PowerpointExporter { public class PowerpointExporter {
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PowerpointExporter)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PowerpointExporter));
private static Version powerpointVersion; private static Version _powerpointVersion;
private static readonly OfficeConfiguration officeConfiguration = IniConfig.GetIniSection<OfficeConfiguration>();
public static bool isAfter2003() { private static bool IsAfter2003() {
return powerpointVersion.Major > (int)OfficeVersion.OFFICE_2003; return _powerpointVersion.Major > (int)OfficeVersion.OFFICE_2003;
} }
/// <summary> /// <summary>
@ -39,7 +40,7 @@ namespace Greenshot.Interop.Office {
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static List<string> GetPowerpointPresentations() { public static List<string> GetPowerpointPresentations() {
List<string> foundPresentations = new System.Collections.Generic.List<string>(); List<string> foundPresentations = new List<string>();
try { try {
using (IPowerpointApplication powerpointApplication = GetPowerpointApplication()) { using (IPowerpointApplication powerpointApplication = GetPowerpointApplication()) {
if (powerpointApplication == null) { if (powerpointApplication == null) {
@ -56,7 +57,7 @@ namespace Greenshot.Interop.Office {
if (presentation.ReadOnly == MsoTriState.msoTrue) { if (presentation.ReadOnly == MsoTriState.msoTrue) {
continue; continue;
} }
if (isAfter2003()) { if (IsAfter2003()) {
if (presentation.Final) { if (presentation.Final) {
continue; continue;
} }
@ -117,55 +118,49 @@ namespace Greenshot.Interop.Office {
/// <param name="imageSize"></param> /// <param name="imageSize"></param>
/// <param name="title"></param> /// <param name="title"></param>
private static void AddPictureToPresentation(IPresentation presentation, string tmpFile, Size imageSize, string title) { private static void AddPictureToPresentation(IPresentation presentation, string tmpFile, Size imageSize, string title) {
if (presentation == null) { if (presentation != null) {
return; //ISlide slide = presentation.Slides.AddSlide( presentation.Slides.Count + 1, PPSlideLayout.ppLayoutPictureWithCaption);
} ISlide slide;
ISlide slide; float left = (presentation.PageSetup.SlideWidth / 2) - (imageSize.Width / 2f);
float left = (presentation.PageSetup.SlideWidth / 2) - (imageSize.Width / 2) ; float top = (presentation.PageSetup.SlideHeight / 2) - (imageSize.Height / 2f);
float top = (presentation.PageSetup.SlideHeight / 2) - (imageSize.Height / 2); float width = imageSize.Width;
float width = imageSize.Width; float height = imageSize.Height;
float height = imageSize.Height; IShape shapeForCaption = null;
bool isLayoutPictureWithCaption = false; bool hasScaledWidth = false;
IShape shapeForCaption = null; bool hasScaledHeight = false;
bool hasScaledWidth = false;
bool hasScaledHeight = false;
// Try to create the slide
using (ISlides slides = presentation.Slides) {
try { try {
slide = slides.Add(slides.Count + 1, (int)PPSlideLayout.ppLayoutPictureWithCaption); slide = presentation.Slides.Add(presentation.Slides.Count + 1, (int)officeConfiguration.PowerpointSlideLayout);
isLayoutPictureWithCaption = true;
// Shapes[2] is the image shape on this layout. // Shapes[2] is the image shape on this layout.
shapeForCaption = slide.Shapes.item(1); shapeForCaption = slide.Shapes.item(1);
using (IShape shapeForLocation = slide.Shapes.item(2)) { IShape shapeForLocation = slide.Shapes.item(2);
if (width > shapeForLocation.Width) {
width = shapeForLocation.Width;
left = shapeForLocation.Left;
hasScaledWidth = true;
} else {
shapeForLocation.Left = left;
}
shapeForLocation.Width = imageSize.Width;
if (height > shapeForLocation.Height) { if (width > shapeForLocation.Width) {
height = shapeForLocation.Height; width = shapeForLocation.Width;
top = shapeForLocation.Top; left = shapeForLocation.Left;
hasScaledHeight = true; hasScaledWidth = true;
} else { } else {
top = (shapeForLocation.Top + (shapeForLocation.Height / 2)) - (imageSize.Height / 2); shapeForLocation.Left = left;
}
shapeForLocation.Height = imageSize.Height;
} }
shapeForLocation.Width = imageSize.Width;
if (height > shapeForLocation.Height) {
height = shapeForLocation.Height;
top = shapeForLocation.Top;
hasScaledHeight = true;
} else {
top = (shapeForLocation.Top + (shapeForLocation.Height / 2)) - (imageSize.Height / 2f);
}
shapeForLocation.Height = imageSize.Height;
} catch (Exception e) { } catch (Exception e) {
LOG.Error(e); LOG.Error(e);
// didn't work. Use simple slide layout slide = presentation.Slides.Add(presentation.Slides.Count + 1, (int)PPSlideLayout.ppLayoutBlank);
slide = slides.Add(slides.Count + 1, (int)PPSlideLayout.ppLayoutBlank); }
IShape shape = slide.Shapes.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height);
if (officeConfiguration.PowerpointLockAspectRatio) {
shape.LockAspectRatio = MsoTriState.msoTrue;
} else {
shape.LockAspectRatio = MsoTriState.msoFalse;
} }
}
// Make sure the picture is added and correctly scaled
using (IShape shape = slide.Shapes.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height)) {
shape.LockAspectRatio = MsoTriState.msoTrue;
shape.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle); shape.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
shape.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle); shape.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
if (hasScaledWidth) { if (hasScaledWidth) {
@ -177,34 +172,17 @@ namespace Greenshot.Interop.Office {
shape.Left = left; shape.Left = left;
shape.Top = top; shape.Top = top;
shape.AlternativeText = title; shape.AlternativeText = title;
} if (shapeForCaption != null) {
// Try settings the caption
if (shapeForCaption != null) {
if (isLayoutPictureWithCaption) {
try { try {
// Using try/catch to make sure problems with the text range don't give an exception. // Using try/catch to make sure problems with the text range don't give an exception.
using (ITextFrame textFrame = shapeForCaption.TextFrame) { ITextFrame textFrame = shapeForCaption.TextFrame;
textFrame.TextRange.Text = title; textFrame.TextRange.Text = title;
}
} catch (Exception ex) { } catch (Exception ex) {
LOG.Warn("Problem setting the title to a text-range", ex); LOG.Warn("Problem setting the title to a text-range", ex);
} }
} }
shapeForCaption.Dispose(); presentation.Application.ActiveWindow.View.GotoSlide(slide.SlideNumber);
} presentation.Application.Activate();
// Show the window, and show the new slide
using (IPowerpointApplication application = presentation.Application) {
using (IPowerpointWindow activeWindow = application.ActiveWindow) {
using (IPowerpointView view = activeWindow.View) {
view.GotoSlide(slide.SlideNumber);
}
}
application.Activate();
}
if (slide != null) {
slide.Dispose();
} }
} }
@ -218,17 +196,16 @@ namespace Greenshot.Interop.Office {
public static bool InsertIntoNewPresentation(string tmpFile, Size imageSize, string title) { public static bool InsertIntoNewPresentation(string tmpFile, Size imageSize, string title) {
bool isPictureAdded = false; bool isPictureAdded = false;
using (IPowerpointApplication powerpointApplication = GetOrCreatePowerpointApplication()) { using (IPowerpointApplication powerpointApplication = GetOrCreatePowerpointApplication()) {
if (powerpointApplication == null) { if (powerpointApplication != null) {
return isPictureAdded; powerpointApplication.Visible = true;
} using (IPresentations presentations = powerpointApplication.Presentations) {
powerpointApplication.Visible = true; using (IPresentation presentation = presentations.Add(MsoTriState.msoTrue)) {
using (IPresentations presentations = powerpointApplication.Presentations) { try {
using (IPresentation presentation = presentations.Add(MsoTriState.msoTrue)) { AddPictureToPresentation(presentation, tmpFile, imageSize, title);
try { isPictureAdded = true;
AddPictureToPresentation(presentation, tmpFile, imageSize, title); } catch (Exception e) {
isPictureAdded = true; LOG.Error(e);
} catch (Exception e) { }
LOG.Error(e);
} }
} }
} }
@ -261,16 +238,16 @@ namespace Greenshot.Interop.Office {
/// </summary> /// </summary>
/// <param name="powerpointApplication">IPowerpointApplication</param> /// <param name="powerpointApplication">IPowerpointApplication</param>
private static void InitializeVariables(IPowerpointApplication powerpointApplication) { private static void InitializeVariables(IPowerpointApplication powerpointApplication) {
if (powerpointApplication == null || powerpointVersion != null) { if (powerpointApplication == null || _powerpointVersion != null) {
return; return;
} }
try { try {
powerpointVersion = new Version(powerpointApplication.Version); _powerpointVersion = new Version(powerpointApplication.Version);
LOG.InfoFormat("Using Powerpoint {0}", powerpointVersion); LOG.InfoFormat("Using Powerpoint {0}", _powerpointVersion);
} catch (Exception exVersion) { } catch (Exception exVersion) {
LOG.Error(exVersion); LOG.Error(exVersion);
LOG.Warn("Assuming Powerpoint version 1997."); LOG.Warn("Assuming Powerpoint version 1997.");
powerpointVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0); _powerpointVersion = new Version((int)OfficeVersion.OFFICE_97, 0, 0, 0);
} }
} }