Modifying current email item visually - c#

I'd like to ask if there is any possibility to modify the currently selected item's sender visually only. I just want to visualize text next to the sender's email.
I'm applying image to visualize what I am trying to achieve
What I have tried so far is using the ActiveInspector and modifying the current item's Sender.Address value.
public static void test(MailItem item)
{
var currItem = item.GetInspector.CurrentItem;
if(currItem == Microsoft.Office.Interop.Outlook.OlObjectClass.olMail)
{
currItem.Sender.Address += "test";
}
}
Any ideas? I've seen that the currentItem is System.__ComObject.

There is no trivial way for customizing the sender's information without changing the underlying properties of Outlook items.
You may try using Windows API functions for subclassing Outlook windows and injecting your own form on top of built-in ones. See SetWindowsHookEx for more information, it installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread.
Also you may consider using the replacement-all form region layout. A replacement form region is a page that replaces the default page of a standard form, and a replace-all form region replaces all pages in a standard Outlook form.
As the last resort, you may consider using Add-in Express layouts where you can hide the sender's pane and show your own.

Related

Invoke on click on a button using UI Automation with no InvokePattern or clickablePoint

i'm try to send click message to (or invoke) a button in another application .
i used UISpy.exe and could find the element which i need.
but it has no id,no clickablePoint and no Invoke pattern.
i tried following code:
var processStartInfo = new ProcessStartInfo(#"tdesktop\Program.exe");
var proc = Process.Start(processStartInfo);
Thread.Sleep(3000);
AutomationElement mainWin = AutomationElement.RootElement.FindChildByProcessId(proc.Id);
List<AutomationElement> elmList= GetChildren(mainWin);
//MessageBox.Show(elmList.Count.ToString());
if (elmList.Count == 7)
{
List<AutomationElement> menubar= GetChildren(elmList[6]);
AutomationElement elementNode = menubar[1];
double x = elementNode.GetClickablePoint().X;
double y = elementNode.GetClickablePoint().Y;
win32 w = new win32();
w.move_left_click((UInt32)x, (UInt32)y);
}
it throws an exception in elementNode.GetClickablePoint().X that the Autumation Element has no clickable point.
i tried also TryGetInvokePattern() but still throws execption it has no InvokePattern.
i use VS2012 and .net 4.5
is there any way to make this?
As was already suggested, I'd strongly recommend pointing the Inspect SDK tool to the UI you're interested in. The tool (inspect.exe) be found in places like "C:\Program Files (x86)\Windows Kits\8.1\bin\x64".
By using the tool, you can see how the UI element of interest is being exposed programmatically. For example, is it exposed as a single UIA element, or it is part of a larger UIA element which represents a set of UI elements shown visually, and what UIA patterns does it support? As a test, I just pointed Inspect to an arrow shape in Paint. The results are shown below.
So I can tell that the arrow is exposed programmatically as a single UIA element, and that it supports the Invoke pattern. This means I can programmatically invoke the button through UIA. (And I can call the pattern methods on the element from inside Inspect’s Action menu, which is pretty handy.) If the UIA element didn't support any patterns that would allow me to programmatically control it, I can find its BoundingRectangle property through UIA, and simulate a mouse click in the middle of that to invoke it. (And I'm assuming the button's not obscured when I simulate the mouse click.)
But if I look at another group of elements shown visually on the screen, using Inspect I can learn that the whole set is exposed through UIA as a single UIA element. So in the image of Inspect shown below, I can learn that I'm not able to programmatically invoke a specific color in that group.
So in that case, I'd probably have to assume I know the size and layout of the UI elements shown visually in that group, and simulate a mouse click at some point which I think is appropriate based on the color I want to invoke.
By using Inspect, I can get a good understanding of what my options are. Ideally a single element shown visually on the screen will be exposed through UIA as a single element that I can control through whatever patterns are relevant, (for example, Invoke, Toggle, SelectionItem etc). But if useful patterns aren't supported, then I could consider simulating mouse clicks instead, based on whatever ClickablePoint or BoundingRectangle data's exposed.
Thanks,
Guy
A menu bar doesn't expose the InvokePattern (see UI Automation Support for the MenuBar Control Type). However, a menu item can be Invoked (see UI Automation Support for the MenuItem Control Type).
The following code illustrates how to generate a list of menu items:
AutomationElementCollection items = menubar.FindAll(
TreeScope.Children,
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.MenuItem));

In vsto C#, when copying(no pasting) a range, how to know this range(row/col/rect info)?

Example in excel 2013,
I select range A1:C3 and ctrl-c or right click copy.
Noticing there will be an animation moving arounding this range, meaning you just copied it.
Now I just want to get this range in my code.
I just hooked the copy invent in windows message. And how can I get this range?
pls help.
Example code:
private override onCopy(Excel.Range source){
//...
base.onCopy(source);
//Now I can get the source range when copy happens.
//But in vsto, there is no such method.
//Help me to work around
}
You can use the Selection object to get the current selection. But it may return another selection, not just copied.
To get the copied Seletion object you need to set a keyboard hook for intercepting the Ctrl+C keyboard buttons and/or repurspose the ribbon controls.
See Using shortcut keys to call a function in an Office Add-in to get started with Windows Hooks.
Most probably repurposing the ribbon controls will be enough (context menus use the Ribbon UI). See Temporarily Repurpose Commands on the Office Fluent Ribbon for more information.

Create a view, similar to mail list, inside a windows form for an outlook add-in

I'm trying to create an Outlook Add-in, where there will be a Windows form. Inside that form will be a list of mail messages i.e. just a different view from the inbox.
I'm doing this for MS Outlook 2010/2013, using C# [VS 2010 Outlook 2010 Add-in].
I already tried exploring the following but it doesn't seem to suit or I'm missing something:
Table view (It seems to apply only on an active explorer/inspector and not something showable/displayable inside a windows form.)
Form region
Outlook view control (I can't seem to find a reference to ViewCtl or AxMicrosoft)
I'm now thinking of just using something like a grid view and then fill it with the mail items. But I'm wondering if there's better way than this and if anyone can point me where else to look?
Thanks :)
now thinking of just using something like a grid view and then fill it with the mail items.
I don't think that keeping another list view (using the grid view control, for example) will be an easy task.
Form region
They are for inspector windows only. You need to subclass Outlook windows using Windows API functions to inject your own form into the Explorer window. See Adjacent Windows In Outlook for more information.
You can use the [WebViewURL][2] property of the Folder class which allows to set a string indicating the URL of the Web page that is assigned to a folder.
Sub SetupFolderHomePage()
Dim nsp As Outlook.NameSpace
Dim mpfInbox As Outlook.Folder
Dim mpfNew As Outlook.Folder
Set nsp = Application.GetNamespace("MAPI")
Set mpfInbox = nsp.GetDefaultFolder(olFolderInbox)
Set mpfNew = mpfInbox.Folders.Add("MyFolderHomePage")
mpfNew.WebViewURL = "http://www.microsoft.com"
mpfNew.WebViewOn = True
End Sub
Be aware, you need to set NonDefaultStoreScript key in the windows registry to get the WebView properties working in Outlook. See You cannot add a URL to the Address box on the Home Page tab in Outlook 2007 for more information.
As an alternative consider using the WebViewPane layout from ADX. The solution is based on the WebViewURL property and requires the windows registry key as well, but provides a more convinient way to set up a windows form with .net controls. See the [similar][3] forum thread for more information.
Also you can customize the current view in the explorer window. The Outlook object model provides the CurrentView property for the Explorer and Folder classes. The View object represents a customizable view used to sort, group, and view data. Views are defined and customized using the View object's XML property. The XML property allows you to create and set a customized XML schema that defines the various features of a view.

Outlook 2013 Form Region and the Delete Key

So, I've finally had to deal with this annoying issue. It seems that it's a known "bug" and there doesn't seem to be a great work-around. I was wondering what seems to be the best work around for this.
A little bit of info. In my form region I have a Winform control and a WPF control. The user can't do certain key combinations on the Winform control (Ctrl-A to select all, Delete key deletes email instead of highlighted text), but everything works fine on the WPF control.
I've tried adding the Winform control to the WPF control using a WindowsFormHost, but that made it worse as it wouldn't register the backspace key after that. I tried capturing the delete event for the email, but I can't get the .BeforeDelete to trigger. Same for the Explorer.BeforeItemCut event. Currently I'm trying to capture the WndProc event to re-direct the key events, but it seems like there should be a better/easier way.
Not sure how to continue from here. Any help in direction is welcomed. Below is my how I'm trying to capture email delete event.
Outlook.MailItem _selEmail;
// This does get triggered
private void Explorer_SelectionChange()
{
var actExplorer = this.Application.ActiveExplorer();
if(this.Application.ActiveExplorer().Selection.Count > 0)
{
var selObject = actExplorer.Selection[1];
if(selObject is Outlook.MailItem)
{
_selEmail = selObject as Outlook.MailItem;
_selEmail.BeforeEmailDelete -=
new Outlook.ItemEvents_10_BeforeDeleteEventHandler(Email_BeforeDelete);
_selEmail.BeforeEmailDelete +=
new Outlook.ItemEvents_10_BeforeDeleteEventHandler(Email_BeforeDelete);
}
}
}
// Haven't gotten this to trigger. The Console.Write("") is there
// only for a breakpoint;
private void Email_BeforeDelete(object sender, ref bool cancel)
{
Console.WriteLine("");
}
First of all, I'd suggest breaking the chain of property and method calls and declare each property or method call on a separate line of code. Thus, you will be able to release underlying COM objects inplace. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. You can read more about that in the Systematically Releasing Objects article in MSDN.
Try to turn off the Single key reading using the space bar option in Outlook which allows you to move quickly through your messages in the Reading Pane. The space bar scrolls the current item. At the end of the item, it jumps to the next unread item in your message list.
Finally, using WPF controls on Outlook forms produce a well-known issue. Outlook has a habit of swallowing various keys and not sending them along to your code or form region. The spacebar, tab, backspace keys are among those affected when the keys are pressed in the reading pane. You can find a similar forum thread.

Set ADXOlExplorerLayout as DockRight

I am developing an Outlook plugin using add-in-express. I have added an adxOlFormsManager there. Which contains a Forms collection named ‘adxOlFormsCollectionItem1’. I have set the form class name to as “FlowOutlook.Plugins.Chat.ChatExplorerPane”. Yes, ChatExplorerPane is my ADXOlForm.
I implement a custom event for the my ADXOlform using following code:
private void AddinModule_AddinStartupComplete(object sender, EventArgs e)
{
try
{
var currentChatTypeForm = AddinModule.CurrentInstance.adxOlFormsCollectionItem1.FormInstances(0) as ChatExplorerPane;
currentChatTypeForm.OnChatTypeSelected += currentChatTypeForm_OnChatTypeSelected;
}
catch (Exception ex)
{
Debug.DebugMessage(2, "AddinModule : Error in AddinModule_AddinStartupComplete() : " + ex.Message);
}
}
My Problem is :
If I explorer layout as “RightSubpane” this works fine. But after I changing the explorer layout as dock right (using Properties window), adxOlFormsCollectionItem1.FormInstanceCount is 0. (Which means “currentChatTypeForm” will be null).
What I am supposed to do :
private void ChangeExplorerLayout(AddinExpress.OL.ADXOlForm form)
{
if (form == null) return;
form.XXX = AddinExpress.OL.ADXOlExplorerLayout.DockRight;
}
I wrote above method to change the explorer layout by code. I hope I may be able to call that safely inside AddinModule_AddinStartupComplete, after initializing my custom method. But I need to know the code for replacing ‘XXX’ to complete the method and have a try.
Please advice me to change explorer layout as dock right according to my requirements.
Kushan Randima.
Below is a citation from the manual - see section Accessing a Form Instance in the PDF file in the folder {Add-in Express}\Docs on your development PC.
It is essential that Add-in Express panes are built on the windowing of the host application, not on the events of the application's object model. This means that getting an instance of an Add-in Express pane in a certain event may result in getting null (Nothing in VB.NET) if the call is issued before the pane is shown or after it is hidden. For instance, it is often the case with WindowActivate/WindowDeactivate in Excel, Word, and PowerPoint.
...
So, you may encounter a problem if your add-in retrieves a pane instance in an event above. To bypass this problem, we suggest modifying the code of the add-in so that it gets notified about a pane instance being shown or hidden (instead of getting the pane instance by handling the events above). Use the ADXBeforeTaskPaneShow event of the task pane class (Excel, Word, and PowerPoint) and the ADXOlForm.ADXBeforeFormShow (Outlook) event to be notified about the specified pane instance being shown. When the form becomes hidden, you'll get ADXOlForm.ADXAfterFormHide (Outlook) and the ADXAfterTaskPaneHide event of the task pane class (Excel, Word, and PowerPoint).
That is, instead of getting a form instance in the AddinStartupcomplete event, you can handle the ADXOlForm.ADXBeforeFormShow event.
Hope this helps.

Categories

Resources