diff --git a/Outlook2013TodoAddIn/AppointmentsControl.Designer.cs b/Outlook2013TodoAddIn/AppointmentsControl.Designer.cs index 2cbedcf..76fabda 100644 --- a/Outlook2013TodoAddIn/AppointmentsControl.Designer.cs +++ b/Outlook2013TodoAddIn/AppointmentsControl.Designer.cs @@ -31,7 +31,7 @@ this.components = new System.ComponentModel.Container(); this.numRangeDays = new System.Windows.Forms.NumericUpDown(); this.lblRangeDays = new System.Windows.Forms.Label(); - this.apptCalendar = new System.Windows.Forms.MonthCalendar(); + this.apptCalendar = new Outlook2013TodoAddIn.DoubleClickMonthCalendar(); this.ctxMenuAppointments = new System.Windows.Forms.ContextMenuStrip(this.components); this.mnuItemReplyAllEmail = new System.Windows.Forms.ToolStripMenuItem(); this.hdrDate = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -86,6 +86,7 @@ this.apptCalendar.MaxSelectionCount = 1; this.apptCalendar.Name = "apptCalendar"; this.apptCalendar.TabIndex = 4; + this.apptCalendar.DoubleClickEx += new System.EventHandler(this.apptCalendar_DoubleClickEx); this.apptCalendar.DateChanged += new System.Windows.Forms.DateRangeEventHandler(this.monthCalendar1_DateChanged); // // ctxMenuAppointments @@ -186,7 +187,7 @@ private System.Windows.Forms.NumericUpDown numRangeDays; private System.Windows.Forms.Label lblRangeDays; - private System.Windows.Forms.MonthCalendar apptCalendar; + private DoubleClickMonthCalendar apptCalendar; private System.Windows.Forms.ContextMenuStrip ctxMenuAppointments; private System.Windows.Forms.ToolStripMenuItem mnuItemReplyAllEmail; private System.Windows.Forms.ColumnHeader hdrDate; diff --git a/Outlook2013TodoAddIn/AppointmentsControl.cs b/Outlook2013TodoAddIn/AppointmentsControl.cs index 9cdbd68..4f1da8d 100644 --- a/Outlook2013TodoAddIn/AppointmentsControl.cs +++ b/Outlook2013TodoAddIn/AppointmentsControl.cs @@ -7,22 +7,38 @@ using Outlook = Microsoft.Office.Interop.Outlook; namespace Outlook2013TodoAddIn { + /// User control to hold the calendar, etc... + /// public partial class AppointmentsControl : UserControl { + #region "Variables" + /// + + /// + /// Used to retrieve the email address of a contact + /// private const string PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"; + #endregion "Variables" + + #region "Properties" + + /// + /// Number of days (including today) to retrieve appointments from in the future + /// public decimal NumDays { - get - { - return this.numRangeDays.Value; - } - set - { - this.numRangeDays.Value = value; - } + get { return this.numRangeDays.Value; } + set { this.numRangeDays.Value = value; } } + #endregion "Properties" + + #region "Methods" + + /// + /// Default constructor + /// public AppointmentsControl() { InitializeComponent(); @@ -43,22 +59,40 @@ namespace Outlook2013TodoAddIn // MessageBox.Show("Test"); //} + /// + /// Respond to calendar changes + /// + /// Sender + /// DateRangeEventArgs private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e) { this.RetrieveAppointments(); } + /// + /// Change days to retrieve appointments in the future + /// + /// Sender + /// EventArgs private void numRangeDays_ValueChanged(object sender, EventArgs e) { Properties.Settings.Default.NumDays = this.numRangeDays.Value; this.RetrieveAppointments(); } + /// + /// Manual refresh + /// + /// Sender + /// EventArgs private void btnRefresh_Click(object sender, EventArgs e) { this.RetrieveAppointments(); } + /// + /// Retrieve all appointments for the current configurations + /// public void RetrieveAppointments() { // Get the Outlook folder for the calendar to retrieve the appointments @@ -123,20 +157,15 @@ namespace Outlook2013TodoAddIn case Outlook.OlBusyStatus.olBusy: current.ForeColor = Color.Purple; break; - case Outlook.OlBusyStatus.olFree: break; - case Outlook.OlBusyStatus.olOutOfOffice: current.ForeColor = Color.Brown; break; - case Outlook.OlBusyStatus.olTentative: break; - case Outlook.OlBusyStatus.olWorkingElsewhere: break; - default: break; } @@ -159,11 +188,11 @@ namespace Outlook2013TodoAddIn } /// - /// Get recurring appointments in date range. + /// Get recurring appointments in a date range. /// - /// - /// - /// + /// Outlook folder + /// Start time + /// End time /// Outlook.Items private Outlook.Items GetAppointmentsInRange(Outlook.Folder folder, DateTime startTime, DateTime endTime) { @@ -190,6 +219,11 @@ namespace Outlook2013TodoAddIn catch { return null; } } + /// + /// Open the appointment, having in mind it might be a recurring event + /// + /// Sender + /// EventArgs private void listView1_DoubleClick(object sender, EventArgs e) { if (this.listView1.SelectedIndices.Count != 0) @@ -222,13 +256,17 @@ namespace Outlook2013TodoAddIn // Open up the appointment in a new window appt.Display(true); // Modal yes/no } - // At the end, synchronously "refresh" items in case they have changed this.RetrieveAppointments(); } } } + /// + /// Creates a new mail item to reply all recipients of an appointment (except the current user) + /// + /// Sender + /// EventArgs private void mnuItemReplyAllEmail_Click(object sender, EventArgs e) { if (this.listView1.SelectedIndices.Count != 0) @@ -237,7 +275,6 @@ namespace Outlook2013TodoAddIn if (appt != null) { Outlook.MailItem mail = Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem; - string curUserAddress = GetEmailAddress(Globals.ThisAddIn.Application.Session.CurrentUser); foreach (Outlook.Recipient rcpt in appt.Recipients) { @@ -245,8 +282,6 @@ namespace Outlook2013TodoAddIn if (curUserAddress != smtpAddress) { mail.Recipients.Add(smtpAddress); - - //mail.Recipients.Add(rcpt.AddressEntry.Name); } } mail.Body = Environment.NewLine + Environment.NewLine + appt.Body; @@ -256,10 +291,44 @@ namespace Outlook2013TodoAddIn } } + /// + /// Resolves Outlook recipient email address + /// + /// Recipient + /// Email address of the contact private string GetEmailAddress(Outlook.Recipient rcpt) { Outlook.PropertyAccessor pa = rcpt.PropertyAccessor; return pa.GetProperty(PR_SMTP_ADDRESS).ToString(); } + + /// + /// Switch to the calendar view when double-clicking a date + /// + /// Sender + /// EventArgs + private void apptCalendar_DoubleClickEx(object sender, EventArgs e) + { + // TODO: Clicking in days outside of the current month will cause the calendar to refresh to that day, reposition all days and + // select the wrong one + //MessageBox.Show(this.apptCalendar.SelectionStart.ToShortDateString()); + + // Get the Outlook folder for the calendar to retrieve the appointments + Outlook.Folder calFolder = + Globals.ThisAddIn.Application.Session.GetDefaultFolder( + Outlook.OlDefaultFolders.olFolderCalendar) + as Outlook.Folder; + + //Outlook.View view = Globals.ThisAddIn.Application.ActiveExplorer().CurrentView; + + foreach (Outlook.View view in Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder.Views) + { + MessageBox.Show("New view: {0}", view.Name); + } + + //calFolder.Display(); + } + + #endregion "Methods" } } \ No newline at end of file diff --git a/Outlook2013TodoAddIn/DoubleClickMonthCalendar.cs b/Outlook2013TodoAddIn/DoubleClickMonthCalendar.cs new file mode 100644 index 0000000..e4261be --- /dev/null +++ b/Outlook2013TodoAddIn/DoubleClickMonthCalendar.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Outlook2013TodoAddIn +{ + public class DoubleClickMonthCalendar : MonthCalendar + { + public event EventHandler DoubleClickEx; + + public DoubleClickMonthCalendar() + { + lastClickTick = Environment.TickCount - SystemInformation.DoubleClickTime; + } + + protected override void OnMouseDown(MouseEventArgs e) + { + int tick = Environment.TickCount; + if (tick - lastClickTick <= SystemInformation.DoubleClickTime) + { + EventHandler handler = DoubleClickEx; + if (handler != null) handler(this, EventArgs.Empty); + } + else + { + base.OnMouseDown(e); + lastClickTick = tick; + } + } + + private int lastClickTick; + } +} \ No newline at end of file diff --git a/Outlook2013TodoAddIn/FormRecurringOpen.cs b/Outlook2013TodoAddIn/FormRecurringOpen.cs index 863d159..61d6de6 100644 --- a/Outlook2013TodoAddIn/FormRecurringOpen.cs +++ b/Outlook2013TodoAddIn/FormRecurringOpen.cs @@ -2,21 +2,33 @@ namespace Outlook2013TodoAddIn { + /// + /// Mimic Outlook's popup to open one instance or the whole series + /// public partial class FormRecurringOpen : Form { - public DialogResult ButtonPressed { get; set; } + #region "Properties" + /// + /// Whether the user wants to retrieve all instances or not + /// public bool OpenRecurring { - get - { - return this.rbtnAll.Checked; - } + get { return this.rbtnAll.Checked; } } + #endregion "Properties" + + #region "Methods" + + /// + /// Open the form + /// public FormRecurringOpen() { InitializeComponent(); } + + #endregion "Methods" } } \ No newline at end of file diff --git a/Outlook2013TodoAddIn/Outlook2013TodoAddIn.csproj b/Outlook2013TodoAddIn/Outlook2013TodoAddIn.csproj index 72e91f8..1ecb855 100644 --- a/Outlook2013TodoAddIn/Outlook2013TodoAddIn.csproj +++ b/Outlook2013TodoAddIn/Outlook2013TodoAddIn.csproj @@ -178,6 +178,7 @@ can be found. --> + Form diff --git a/Outlook2013TodoAddIn/ThisAddIn.cs b/Outlook2013TodoAddIn/ThisAddIn.cs index b1f1a36..7d0e29d 100644 --- a/Outlook2013TodoAddIn/ThisAddIn.cs +++ b/Outlook2013TodoAddIn/ThisAddIn.cs @@ -5,69 +5,69 @@ using Office = Microsoft.Office.Core; namespace Outlook2013TodoAddIn { + /// + /// Class for the add-in + /// public partial class ThisAddIn { - private AppointmentsControl appControl; + #region "Properties" + /// + /// Control with calendar, etc... + /// + public AppointmentsControl AppControl { get; set; } + + /// + /// Custom task pane + /// public Microsoft.Office.Tools.CustomTaskPane ToDoTaskPane { get; set; } - //private Dictionary inspectorWrappersValue = new Dictionary(); - //private Outlook.Inspectors inspectors; + #endregion "Properties" - //void Inspectors_NewInspector(Outlook.Inspector Inspector) - //{ - // if (Inspector.CurrentItem is Outlook.MailItem) - // { - // inspectorWrappersValue.Add(Inspector, new InspectorWrapper(Inspector)); - // } - //} - - //public Dictionary InspectorWrappers - //{ - // get - // { - // return inspectorWrappersValue; - // } - //} + #region "Methods" + /// + /// Initialize settings upon add-in startup + /// + /// Sender + /// EventArgs private void ThisAddIn_Startup(object sender, System.EventArgs e) { - //inspectors = this.Application.Inspectors; - //inspectors.NewInspector += - // new Outlook.InspectorsEvents_NewInspectorEventHandler( - // Inspectors_NewInspector); + this.AddRegistryNotification(); - //foreach (Outlook.Inspector inspector in inspectors) - //{ - // Inspectors_NewInspector(inspector); - //} + this.AppControl = new AppointmentsControl(); + this.AppControl.NumDays = Properties.Settings.Default.NumDays; // Setting the value will load the appointments + this.AppControl.RetrieveAppointments(); - appControl = new AppointmentsControl(); - appControl.NumDays = Properties.Settings.Default.NumDays; // Setting the value will load the appointments - - //Properties.Settings.Default.Properties[] - // appControl.Dock = System.Windows.Forms.DockStyle.Right; - ToDoTaskPane = this.CustomTaskPanes.Add(appControl, "Appointments"); - ToDoTaskPane.Visible = Properties.Settings.Default.Visible; - - //ToDoTaskPane.Visible = true; - //ToDoTaskPane.Width = 285; // appControl.Width; + ToDoTaskPane = this.CustomTaskPanes.Add(this.AppControl, "Appointments"); + // TODO: Fix this + // ToDoTaskPane.Visible = Properties.Settings.Default.Visible; + ToDoTaskPane.Visible = true; ToDoTaskPane.Width = Properties.Settings.Default.Width; ToDoTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight; ToDoTaskPane.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoHorizontal; ToDoTaskPane.VisibleChanged += ToDoTaskPane_VisibleChanged; - appControl.SizeChanged += appControl_SizeChanged; - - this.AddRegistryNotification(); + this.AppControl.SizeChanged += appControl_SizeChanged; } + /// + /// Store the new size setting upon resizing + /// + /// Sender + /// EventArgs private void appControl_SizeChanged(object sender, EventArgs e) { Properties.Settings.Default.Width = ToDoTaskPane.Width; } + /// + /// Toggle ribbon button's status + /// + /// Sender + /// EventArgs private void ToDoTaskPane_VisibleChanged(object sender, EventArgs e) { + // TODO: Save visibility ONLY when not closing the form // Properties.Settings.Default.Visible = ToDoTaskPane.Visible; TodoRibbonAddIn rbn = Globals.Ribbons.FirstOrDefault(r => r is TodoRibbonAddIn) as TodoRibbonAddIn; if (rbn != null) @@ -77,45 +77,42 @@ namespace Outlook2013TodoAddIn } /// - /// This is NEVER executed anymore + /// This is not executed by default /// http://msdn.microsoft.com/en-us/library/office/ee720183.aspx#OL2010AdditionalShutdownChanges_AddinShutdownChangesinOL2010Beta - /// We MANUALLY add notification to the registry of each user + /// We MANUALLY add notification to the registry of each user below /// - /// - /// + /// Sender + /// EventArgs private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { - //inspectors.NewInspector -= - // new Outlook.InspectorsEvents_NewInspectorEventHandler( - // Inspectors_NewInspector); - //inspectors = null; - //inspectorWrappersValue = null; - // Can't call these because the object is already disposed. Settings will be set while the app is running - //Properties.Settings.Default.Visible = ToDoTaskPane.Visible; - //Properties.Settings.Default.Width = ToDoTaskPane.Width; - //Properties.Settings.Default.NumDays = appControl.NumDays; + // Can't call property setters such as: Properties.Settings.Default.NumDays = XXX because the pane is already disposed. + // Settings will be set while the app is running and saved here. Properties.Settings.Default.Save(); } + /// + /// Implement shutdown notification for this particular add-in + /// http://msdn.microsoft.com/en-us/library/office/ee720183.aspx#OL2010AdditionalShutdownChanges_AddinShutdownChangesinOL2010Beta + /// HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\Addins\\[RequireShutdownNotification]=dword:0x1 + /// private void AddRegistryNotification() { - // http://msdn.microsoft.com/en-us/library/office/ee720183.aspx#OL2010AdditionalShutdownChanges_AddinShutdownChangesinOL2010Beta - // HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\Addins\\[RequireShutdownNotification]=dword:0x1 - + // TODO: Make sure there are no memory leaks (dispose COM obejcts) + // TODO: See if this works the first time (if the entry is not there when Outlook loads, it will NOT notify the add-in) string subKey = @"Software\Microsoft\Office\Outlook\Addins\Outlook2013TodoAddIn"; RegistryKey rk = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(subKey, true); - if (rk == null) { rk = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(subKey); } - if ((int)rk.GetValue("RequireShutdownNotification", 0) == 0) { rk.SetValue("RequireShutdownNotification", 1, RegistryValueKind.DWord); // "dword:0x1" } } + #endregion "Methods" + #region VSTO generated code /// diff --git a/Outlook2013TodoAddIn/TodoRibbonAddIn.Designer.cs b/Outlook2013TodoAddIn/TodoRibbonAddIn.Designer.cs index 38a6676..a9ed7ab 100644 --- a/Outlook2013TodoAddIn/TodoRibbonAddIn.Designer.cs +++ b/Outlook2013TodoAddIn/TodoRibbonAddIn.Designer.cs @@ -67,7 +67,6 @@ this.Name = "TodoRibbonAddIn"; this.RibbonType = "Microsoft.Outlook.Explorer"; this.Tabs.Add(this.tab1); - this.Load += new Microsoft.Office.Tools.Ribbon.RibbonUIEventHandler(this.TodoRibbonAddIn_Load); this.tab1.ResumeLayout(false); this.tab1.PerformLayout(); this.group1.ResumeLayout(false); diff --git a/Outlook2013TodoAddIn/TodoRibbonAddIn.cs b/Outlook2013TodoAddIn/TodoRibbonAddIn.cs index e66c965..f34252d 100644 --- a/Outlook2013TodoAddIn/TodoRibbonAddIn.cs +++ b/Outlook2013TodoAddIn/TodoRibbonAddIn.cs @@ -2,15 +2,23 @@ namespace Outlook2013TodoAddIn { + /// + /// Adds a button to the add-in placeholder in the ribbon + /// public partial class TodoRibbonAddIn { - private void TodoRibbonAddIn_Load(object sender, RibbonUIEventArgs e) - { - } + #region "Methods" + /// + /// Change visibility of the pane + /// + /// Sender + /// RibbonControlEventArgs private void toggleButton1_Click(object sender, RibbonControlEventArgs e) { Globals.ThisAddIn.ToDoTaskPane.Visible = this.toggleButton1.Checked; } + + #endregion } } \ No newline at end of file