In Outlook Interop, how do I tell if an AppointmentItem has been saved (and not simply closed without saving)? - outlook

I have some code that needs to run whenever a user saves or sends an Outlook appointment.
Currently I register a close event to the Inspector and run my code within that event:
((Outlook.InspectorEvents_Event)_inspector).Close += InspectorWrapper_Close;
For the most part this is okay unless the user closes the inspector window without saving their changes. In that case, it is critical that my code does not run.
I have been searching for either a save event to which I can register my appointment or any kind of flag to indicate if the item was actually saved.
The AppointmentItem object has a .Saved property, but it always returns false.
Any help is appreciated.

Use AppointmentItem.Write / AfterWrite events. Keep in mind that Outlook can autosave an appointment.

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

Event raised when closing or opening a CodePane

I'm writing a VBE/VBIDE add-in and I have a tool window that changes based on the open CodePane objects. Is there an event I can monitor when a code pane is added or removed from the CodePanes collection?
The CodePanes collection itself appears to have no Events associated with it.
If there is no event available, I'm open to other workarounds. Polling would be a reliable fallback, but I'd rather not go that route if I could avoid it.

Check visibility or status change of a window

I have to enumerate all process running on my machine and notify if some changement will happen (for example: change of visibility of windows, open a new window, close a window).
To enumerate all processes I can use this function provided by MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspxI thought that I need to save a list of running processes and check (how without polling?) if it changes. Can I do it without saving current running processes?
For the visibility changes here https://msdn.microsoft.com/it-it/library/windows/desktop/ms646274(v=vs.85).aspx I found that VM_ACTIVATE message is sent to both windows. How can I catch it? Can I do it in another way?
For whom is interested in this topic, I found that to check if a window is created or destroyed I've to use SetWinEventHook(), like in the example of its MSDN page. I simply check if event value is EVENT_OBJECT_CREATE or EVENT_OBJECT_DESTROY. For other events, check the event constants list.

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...

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