Outlook Add in not properly initialised when called from "Send to" Windows contextual menu - outlook

I work on an Outlook 2016 add-in (C# visual studio 2017 on Windows 10).
The add-in do its job perfectly when a new message is created and then sent from the "Write new message" window launched from the Outlook main menu (or toolbar) : the add-in displays its own ribbon with some radiobuttons to configure the message to be sent and that's all.
But when a new message window is created from the Windows contextual menu "Send to" on a file (to be sent as an attachement), the add-in is ignored : the radio buttons, even if they trigger their respective callbacks and so configure the underlying model, let the new message unchanged :-(
The main difference observed under debugger is :
from the outlook menu : the "ThisAddIn" class seems to retrieve a wrapper for the new message window and so the configuration is taken into account when the message is sent :-)
from the Windows contextual menu : only a "GetCustomUI" callback is triggered and so the message is sent unchanged when the "Send" button is clicked :-(
Any help (examples, documentation, howto, ...) appreciated ...
JF

Not all event handlers are triggered when users try to send files using the context menu Send To.
If the GetCustomUI is triggered when a user sends files from a folder (using a context menu) you can add a custom ribbon UI with your radio buttons to configure the message to be sent. I suppose that is all what your add-in does.
You just need to use Ribbon XML to create a custom UI and use the GetCustomUI function to return it back. Read more about that in the Walkthrough: Create a custom tab by using Ribbon XML article.
In the ribbon event handlers you need to make sure you get access to the item through the Context passed as an argument. For example, the onAction callback has the following signature:
C#: void OnAction(IRibbonControl control)
VBA: Sub OnAction(control As IRibbonControl)
C++: HRESULT OnAction([in] IRibbonControl *pControl)
Visual Basic: Sub OnAction(control As IRibbonControl)
The IRibbonControl interface instance provides the Context property which represents the active window containing the Ribbon user interface that triggers a callback procedure. So, you may cast it to the Inspector or Explorer for retrieving the actual mail item you have to deal with.

Related

VSTO Outlook: Opening Outlook from a mailto link does not create custom task pane

I have an VSTO Outlook Addin which shows always an Outlook custom task pane in all windows, explorers and inspectors. This is working perfectly, I mean, custom task pane is always show, except one particular use case, e.g. when you open outlook by clicking in a mailto link in a web page for example. In this case no explorer is open, instead only one knspector window is open, in this case the reply/compose window. So I need to handle when outlook is open through a mailto link and show my custom task pane in the reply/compose window, so which event do i need to handle? It looks like in this case i am not calling the logic to show my custom task pane when there are 0 explorers opened. I want to handle that event , check if numbers of explorers opened are 0 and then in this case show my ctp. Any help please?
If you are using Inspectors.NewInspector event, it won't fire for the mailto links. What you can do, is create a timer (use the Timer object from the Form namespace - it fires on the same thread) that checks the Application.Inspectors collection periodically and verifies that your task pane has been added to that inspector. You can create an Inspector wrapper class that handles Inspector.Close to remove itself from the parent list maintained by your code as well as contains a pointer to your task pane. When looping through the Outlook's inspectors collection, you can match OOM's Inspector object to your wrapper by comparing the HWND of an Inspector object to that stored by your wrapper. The window handle (HWND) can be retrieved using the IOleWindow interface - cast the Inspector object to IOleWindow and call IOleWindow.GetWindow

OWA Addin code written gives a pane within the mail, but i need it to pop a window and display the webpage in default browser

FormSettings>
Form xsi:type="ItemRead">
DesktopSettings>
SourceLocation DefaultValue="https://www.google.com"/>
RequestedWidth>800/RequestedWidth>
RequestedHeight>800/RequestedHeight>
/DesktopSettings>
/Form>
/FormSettings>
what has to be used in order to get a pop up browser on clicking that hyperlink
If you also want the task pane to open, you can start with an add-in command that only executes a JavaScript function. See an overview and an example.
Then either call the displayDialogAsync API to open a window that can communicate with the add-in (the kind of window depends on the client), or call window.open to open an external web page in the default browser.
When the add-in's JavaScript has finished executing, remember to call event.completed() per the first example to stop the add-in.

How to disable copy/paste commands in the Windows edit control context menu?

How can I disable those 3 standard cut/copy/paste commands in the context menu of the native Windows OS edit control?
I also need to disable the equivalent clipboard-related commands like CTRL+C/CTRL+V.
Is there a special edit control style or anything else we can use to disable all copy/paste operations with one easy setting?
Typically, when a control displays a popup menu, a WM_INITPOPUPMENU message is generated which "allows an application to modify the menu before it is displayed, without changing the entire menu."
Unfortunately, a standard Win32 Edit control does not generate that message for its default popup menu, as confirmed in a November 2000 article of MSDN Magazine (the link on MSDN itself is dead, but this link is from the Internet Archive):
MSDN Magazine, November 2000, C++ Q&A:
Q: Why isn't a WM_INITMENUPOPUP message generated when you right-click an edit control?
A: I can't tell you why there isn't one, but I can confirm it's true ... edit controls don't send WM_INITMENUPOPUP. The edit control must be calling TrackPopupMenu with a null HWND handle and/or TPM_NONOTIFY, which tells the menu not to send notifications. It's possible (and again I'm only guessing) that the authors were trying to improve performance by reducing message traffic ... In any case, suppose you want to add your own menu items to the edit control context menu. How do you do it? Alas, you have no choice but to reinvent the wheel
So the only option available is to subclass the edit control and handle the WM_CONTEXTMENU message instead, creating and displaying your own custom popup menu as needed. Which means you have to manually duplicate the functionality of any standard menu items that you want to appear in your custom menu.
Update: there is a way to access and modify the edit control's standard popup menu after all (I just tested it and it worked). TecMan provided a link to a VBForums discussion that talks about it, however it gets a few details wrong. I got the correct details from a PureBasic forum discussion.
The correct approach is as follows:
subclass the edit control to intercept the WM_CONTEXTMENU message. Either SetWindowSubClass() or SetWindowLongPtr(GWL_WNDPROC) can be used, though the first is preferred.
when the WM_CONTEXTMENU message is received, call SetWindowsHookEx() to install a thread-local hook (use 0 for the hMod parameter and GetCurrentThreadId() for the dwThreadId parameter). Either a WH_CBT or WH_CALLWNDPROC hook can be used. Then dispatch WM_CONTENTMENU to the default message handler via DefSubclassProc() or CallWindowProc() to invoke the standard popup menu.
inside the hook procedure, when a HCBT_CREATEWND (WH_CBT hook) or WM_CREATE (WH_CALLWNDPROC hook) notification is received, pass the provided HWND to GetClassName(). If the class name is #32768 (the standard window class name for menus, as documented on MSDN), post (very important!) a custom window message using PostMessage(), specifying the menu window's HWND in the message's WPARAM or LPARAM parameter, to any HWND that you control, such as your main window, or even the edit control itself (since it is already subclassed). You will need the menu's HWND in the next step. You can optionally now uninstall the hook at this time, or wait for DefSubclassProc()/CallWindowProc() to exit (it will exit after the menu has been dismissed). You need to use PostMessage() because the menu window has not created its HMENU yet at this time. PostMessage() delays the next step until after the HMENU is ready.
when the custom window message is received, send a MN_GETMENU message via SendMessage() to the menu's HWND that you obtained from the hook. You now have the menu's HMENU and can do whatever you want with it.
to disable the Cut, Copy, and Paste menu items, call EnableMenuItem(). Their menu item identifiers are the same values as the WM_CUT, WM_COPY and WM_PASTE messages, respectively (this is not documented by Microsoft, but is consistent across Windows versions).
Update: I just found a much simpler solution (which also worked when I tested it).
subclass the edit control to intercept WM_CONTEXTMENU, as described above.
when the message is received, call SetWinEventHook() to install a thread-local event hook (set the hmodWinEventProc parameter to 0, the idProcess parameter to GetCurrentProcessId(), the idThread parameter to GetCurrentThreadId(), and the dwFlags parameter to 0 - not WINEVENT_INCONTEXT!). Set the eventMin and eventMax parameters both to EVENT_SYSTEM_MENUPOPUPSTART so that it is the only event you receive. Then dispatch the message to the default handler to invoke the popup menu.
when your event callback is called, the menu has already been fully initialized, so you can send the MN_GETMENU message to the provided HWND, which will be the menu's window (the callback's idObject parameter will be OBJID_CLIENT and the idChild parameter will be 0).
manipulate the HMENU as needed.
unhook the event hook when done using it, as described above.
As you can see here, this does work.
Before modifying the menu:
After disabling the menu items:
Even deleting the menu items:
You could leave the options visible but lock the clipboard from usage.
If this solution suits you all you need to do is make a program that opens the clipboard by calling OpenClipboard(NULL). In order to release the clipboard call CloseClipboard().
One approach (similar to hypmir's idea but not quite as intrusive) is to simply overwrite the clipboard with "DATA REMOVED BY TecMan" whenever it is updated. You could do this as a registered clipboard viewer.
Open the clipboard, clear all formats, add CF_TEXT with the notice, close it.
I would use a short delay (maybe a timer callback) so that you make your update AFTER the first update has been processed by any other registered clipboard viewers on the system.
Your mileage may vary.
Abusing the clipboard like this is never a good idea.
I found one interesting idea of how to get the handle of the edit control's context menu on vbforums.com:
http://www.vbforums.com/showthread.php?776385-RESOLVED-Modify-right-click-context-menu-in-standard-controls
It demonstrates how to add custom context menu items to the standard OS context menu. I think, this idea can be used to modify the menu too. Theoretically I need to enumerate the menu items and disable the items related to the copy/paste commands. The question is how to know whether a menu item is related to copy/paste? Getting the menu item text is a bad idea ;)
Another problem of that code is that it is based on some Windows features that are not documented. I've checked the solution, it still works in Windows 10, but who knows how the edit control context menu may be changed in the future updates of the OS...

Outlook addin has failed to find Office control by ID

I've just built an MS Outlook Add In using Visual Studio and Office 2010. I've installed it ok on 4 machines, but one user is getting the following error -
Error found in Custom UI XML of "...."
...
...
Failed to find Office control by ID
Everyone is running Windows 7 and Outlook 2010 - not sure why this person is having a problem. Can anyone suggest how to diagnose this?
For those having similar issues, you don't have to remove any add-in.
What is happening is: Outlook will try to load all ribbons (found in your ribbon xml) into any window the user goes to. Then it'll complain about not finding ID x or y.
Just make sure your GetCustomUI method in Ribbon.cs does not load the entire ribbon XML at once but rather loads it per fragment.
If you're not sure what IDs you need to target, use a breakpoint in GetCustomUI then start Outlook, surf different views (main, new email, new appointment, calendar...etc) in order to gather the IDs for the views wherein you need to show you add-in.
In my case, I needed Microsoft.Outlook.Explorer, Microsoft.Outlook.Mail.Compose and Microsoft.Outlook.Appointment.
Therefore I changed my GetCustomUI to:
public string GetCustomUI(string ribbonID)
{
switch (ribbonID)
{
case "Microsoft.Outlook.Explorer":
return GetResourceText("MyAddin.RibbonsForOutlookExplorer.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("MyAddin.RibbonForOutlookMailCompose.xml");
case "Microsoft.Outlook.Appointment":
return GetResourceText("MyAddin.RibbonForOutlookAppointment.xml");
default:
return null;
}
}
Of course, I had to break down my Ribbon.xml into the three XML files mentioned above. The result: Outlook will ONLY load the fragment needed for a given screen (appointment, new email ...) and will not complain about "not finding an ID on screen X or Y".
Finally, for those who are not sure why some users get that error while others don't: it's because of "Show add-in user interface errors" option (in Options -> Advanced). If that is unchecked then Outlook will ignore the malformed ribbon XML errors. If it checked, users will get related errors about your add-in (if any exists) and also about other add-ins.
If it works for everyone except one user. As #Brijesh Mishra mentioned check if the user has got any other addin and if he is having own quick access tool bar customized.
If he has got any of this then, remove the other addins and try to install or reset the quick access tool bar customization.
For all of you that use a Designer-based VSTO plugin, and not the XML solution.
I searched all the web for this problem, but only found XML-based solutions.
There's nothing for Visual Designer on the web, because in this case you don't have to override the "GetCustomUI" method.
Ribbons designed by using the Visual Designer return a RibbonManager by default.
This RibbonManager object represents all Ribbon (Visual Designer) items in the project and is automatically handled in background through the active window inspector.
So you don't have to write any special code to handle different windows.
To configure it correctly you just have to:
Add one extra Visual Designer Ribbon for every window the user goes to
in the Ribbon Object go under "RibbonType", open the checkbox list an only activate the corresponding window, where the ribbon should appear.
If there is more than one window checked in the list, Outlook trys to insert the ribbon in all the marked windows. Even if the corresponding window is currently not opened. That's the reason, why the error "Failed to find control ID" appears.
the actual fix for me was to separate the ribbon XML files containing the customUI and redirecting to the correct one in the GetCustomUI method (implemented using Office.IRibbonExtensibility)
in example:
public string GetCustomUI(string RibbonID)
{
switch (RibbonID)
{
case "Microsoft.Outlook.Mail.Read":
return GetResourceText("namespace.type1.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("namespace.type2.xml");
default:
return null;
}
}

Why are some events not shown in the Visual Studio properties window?

I wanted to add an event for a textbox to handle when it loses focus. I was sure I remembered some sort of LostFocus event, but I didn't see it in the Properties grid. But sure enough, the event exists if I access it programmatically. I'm using VS2008 - any reason why this event (and maybe others?) wasn't shown in the Properties grid?
Control.LostFocus is marked with [BrowsableAttribute(false)]. This means it will not be shown in the Properties window. For details see BrowsableAttribute.
Here's the declaration:
[BrowsableAttribute(false)]
public event EventHandler LostFocus
LostFocus is a troublesome event, this is the fine print from the SDK docs for WM_KILLFOCUS, the underlying Windows message:
While processing this message, do not make any function calls that display or activate a window. This causes the thread to yield control and can cause the application to stop responding to messages. For more information, see Message Deadlocks.
Use the Leave event instead.

Resources