Files
Common.Native/WinEvent.cs
2014-04-30 17:00:26 -04:00

436 lines
20 KiB
C#

using System;
using System.Runtime.InteropServices;
namespace Common.Native
{
public class WinEvent
{
public enum Event
{
Min = 0x00000001,
Max = 0x7FFFFFFF,
/*
* EVENT_SYSTEM_SOUND
* Sent when a sound is played. Currently nothing is generating this, we
* this event when a system sound (for menus, etc) is played. Apps
* generate this, if accessible, when a private sound is played. For
* example, if Mail plays a "New Mail" sound.
*
* System Sounds:
* (Generated by PlaySoundEvent in USER itself)
* hwnd is NULL
* idObject is OBJID_SOUND
* idChild is sound child ID if one
* App Sounds:
* (PlaySoundEvent won't generate notification; up to app)
* hwnd + idObject gets interface pointer to Sound object
* idChild identifies the sound in question
* are going to be cleaning up the SOUNDSENTRY feature in the control panel
* and will use this at that time. Applications implementing WinEvents
* are perfectly welcome to use it. Clients of IAccessible* will simply
* turn around and get back a non-visual object that describes the sound.
*/
SystemSound = 0x0001,
/*
* EVENT_SYSTEM_ALERT
* System Alerts:
* (Generated by MessageBox() calls for example)
* hwnd is hwndMessageBox
* idObject is OBJID_ALERT
* App Alerts:
* (Generated whenever)
* hwnd+idObject gets interface pointer to Alert
*/
SystemAlert = 0x0002,
/*
* EVENT_SYSTEM_FOREGROUND
* Sent when the foreground (active) window changes, even if it is changing
* to another window in the same thread as the previous one.
* hwnd is hwndNewForeground
* idObject is OBJID_WINDOW
* idChild is INDEXID_OBJECT
*/
SystemForeground = 0x0003,
/*
* Menu
* hwnd is window (top level window or popup menu window)
* idObject is ID of control (OBJID_MENU, OBJID_SYSMENU, OBJID_SELF for popup)
* idChild is CHILDID_SELF
*
* EVENT_SYSTEM_MENUSTART
* EVENT_SYSTEM_MENUEND
* For MENUSTART, hwnd+idObject+idChild refers to the control with the menu bar,
* or the control bringing up the context menu.
*
* Sent when entering into and leaving from menu mode (system, app bar, and
* track popups).
*/
SystemMenuStart = 0x0004,
SystemMenuEnd = 0x0005,
/*
* EVENT_SYSTEM_MENUPOPUPSTART
* EVENT_SYSTEM_MENUPOPUPEND
* Sent when a menu popup comes up and just before it is taken down. Note
* that for a call to TrackPopupMenu(), a client will see EVENT_SYSTEM_MENUSTART
* followed almost immediately by EVENT_SYSTEM_MENUPOPUPSTART for the popup
* being shown.
*
* For MENUPOPUP, hwnd+idObject+idChild refers to the NEW popup coming up, not the
* parent item which is hierarchical. You can get the parent menu/popup by
* asking for the accParent object.
*/
SystemMenuPopupStart = 0x0006,
SystemMenuPopupEnd = 0x0007,
/*
* EVENT_SYSTEM_CAPTURESTART
* EVENT_SYSTEM_CAPTUREEND
* Sent when a window takes the capture and releases the capture.
*/
SystemCaptureStart = 0x0008,
SystemCaptureEnd = 0x0009,
/*
* Move Size
* EVENT_SYSTEM_MOVESIZESTART
* EVENT_SYSTEM_MOVESIZEEND
* Sent when a window enters and leaves move-size dragging mode.
*/
SystemMoveSizeStart = 0x000A,
SystemMoveSizeEnd = 0x000B,
/*
* Context Help
* EVENT_SYSTEM_CONTEXTHELPSTART
* EVENT_SYSTEM_CONTEXTHELPEND
* Sent when a window enters and leaves context sensitive help mode.
*/
SystemContextHelpStart = 0x000C,
EventSystemContextHelpEnd = 0x000D,
/*
* Drag & Drop
* EVENT_SYSTEM_DRAGDROPSTART
* EVENT_SYSTEM_DRAGDROPEND
* Send the START notification just before going into drag&drop loop. Send
* the END notification just after canceling out.
* Note that it is up to apps and OLE to generate this, since the system
* doesn't know. Like EVENT_SYSTEM_SOUND, it will be a while before this
* is prevalent.
*/
SystemDragDropStart = 0x000E,
SystemDragdropEnd = 0x000F,
/*
* Dialog
* Send the START notification right after the dialog is completely
* initialized and visible. Send the END right before the dialog
* is hidden and goes away.
* EVENT_SYSTEM_DIALOGSTART
* EVENT_SYSTEM_DIALOGEND
*/
SystemDialogStart = 0x0010,
SystemDialogEnd = 0x0011,
/*
* EVENT_SYSTEM_SCROLLING
* EVENT_SYSTEM_SCROLLINGSTART
* EVENT_SYSTEM_SCROLLINGEND
* Sent when beginning and ending the tracking of a scrollbar in a window,
* and also for scrollbar controls.
*/
SystemScrollingStart = 0x0012,
SystemScrollingEnd = 0x0013,
/*
* Alt-Tab Window
* Send the START notification right after the switch window is initialized
* and visible. Send the END right before it is hidden and goes away.
* EVENT_SYSTEM_SWITCHSTART
* EVENT_SYSTEM_SWITCHEND
*/
SystemSwitchStart = 0x0014,
SystemSwitchEnd = 0x0015,
/*
* EVENT_SYSTEM_MINIMIZESTART
* EVENT_SYSTEM_MINIMIZEEND
* Sent when a window minimizes and just before it restores.
*/
SystemMinimizeStart = 0x0016,
SystemMinimizeEnd = 0x0017,
SystemDesktopSwitch = 0x0020,
EventSystemEnd = 0x00FF,
OemDefinedStart = 0x0101,
OemDefinedEnd = 0x01FF,
UiaEventIdStart = 0x4E00,
UiaEventIdEnd = 0x4EFF,
UiaPropIdStart = 0x7500,
UiaPropIdEnd = 0x75FF,
ConsoleCaret = 0x4001,
ConsoleUpdateRegion = 0x4002,
ConsoleUpdateSimple = 0x4003,
ConsoleUpdateScroll = 0x4004,
ConsoleLayout = 0x4005,
ConsoleStartApplication = 0x4006,
ConsoleEndApplication = 0x4007,
ConsoleEnd = 0x40FF,
/*
* Object events
*
* The system AND apps generate these. The system generates these for
* real windows. Apps generate these for objects within their window which
* act like a separate control, e.g. an item in a list view.
*
* When the system generate them, dwParam2 is always WMOBJID_SELF. When
* apps generate them, apps put the has-meaning-to-the-app-only ID value
* in dwParam2.
* For all events, if you want detailed accessibility information, callers
* should
* * Call AccessibleObjectFromWindow() with the hwnd, idObject parameters
* of the event, and IID_IAccessible as the REFIID, to get back an
* IAccessible* to talk to
* * Initialize and fill in a VARIANT as VT_I4 with lVal the idChild
* parameter of the event.
* * If idChild isn't zero, call get_accChild() in the container to see
* if the child is an object in its own right. If so, you will get
* back an IDispatch* object for the child. You should release the
* parent, and call QueryInterface() on the child object to get its
* IAccessible*. Then you talk directly to the child. Otherwise,
* if get_accChild() returns you nothing, you should continue to
* use the child VARIANT. You will ask the container for the properties
* of the child identified by the VARIANT. In other words, the
* child in this case is accessible but not a full-blown object.
* Like a button on a titlebar which is 'small' and has no children.
*/
/*
* For all EVENT_OBJECT events,
* hwnd is the dude to Send the WM_GETOBJECT message to (unless NULL,
* see above for system things)
* idObject is the ID of the object that can resolve any queries a
* client might have. It's a way to deal with windowless controls,
* controls that are just drawn on the screen in some larger parent
* window (like SDM), or standard frame elements of a window.
* idChild is the piece inside of the object that is affected. This
* allows clients to access things that are too small to have full
* blown objects in their own right. Like the thumb of a scrollbar.
* The hwnd/idObject pair gets you to the container, the dude you
* probably want to talk to most of the time anyway. The idChild
* can then be passed into the acc properties to get the name/value
* of it as needed.
*
* Example #1:
* System propagating a listbox selection change
* EVENT_OBJECT_SELECTION
* hwnd == listbox hwnd
* idObject == OBJID_WINDOW
* idChild == new selected item, or CHILDID_SELF if
* nothing now selected within container.
* Word '97 propagating a listbox selection change
* hwnd == SDM window
* idObject == SDM ID to get at listbox 'control'
* idChild == new selected item, or CHILDID_SELF if
* nothing
*
* Example #2:
* System propagating a menu item selection on the menu bar
* EVENT_OBJECT_SELECTION
* hwnd == top level window
* idObject == OBJID_MENU
* idChild == ID of child menu bar item selected
*
* Example #3:
* System propagating a dropdown coming off of said menu bar item
* EVENT_OBJECT_CREATE
* hwnd == popup item
* idObject == OBJID_WINDOW
* idChild == CHILDID_SELF
*
* Example #4:
*
* For EVENT_OBJECT_REORDER, the object referred to by hwnd/idObject is the
* PARENT container in which the zorder is occurring. This is because if
* one child is zordering, all of them are changing their relative zorder.
*/
ObjectCreate = 0x8000, // hwnd + ID + idChild is created item
ObjectDestroy = 0x8001, // hwnd + ID + idChild is destroyed item
ObjectShow = 0x8002, // hwnd + ID + idChild is shown item
ObjectHide = 0x8003, // hwnd + ID + idChild is hidden item
ObjectReorder = 0x8004, // hwnd + ID + idChild is parent of zordering children
/*
* NOTE:
* Minimize the number of notifications!
*
* When you are hiding a parent object, obviously all child objects are no
* longer visible on screen. They still have the same "visible" status,
* but are not truly visible. Hence do not send HIDE notifications for the
* children also. One implies all. The same goes for SHOW.
*/
ObjectFocus = 0x8005, // hwnd + ID + idChild is focused item
ObjectSelection = 0x8006, // hwnd + ID + idChild is selected item (if only one), or idChild is OBJID_WINDOW if complex
ObjectSelectionAdd = 0x8007, // hwnd + ID + idChild is item added
ObjectSelectionRemove = 0x8008, // hwnd + ID + idChild is item removed
ObjectSelectionWithin = 0x8009, // hwnd + ID + idChild is parent of changed selected items
/*
* NOTES:
* There is only one "focused" child item in a parent. This is the place
* keystrokes are going at a given moment. Hence only send a notification
* about where the NEW focus is going. A NEW item getting the focus already
* implies that the OLD item is losing it.
*
* SELECTION however can be multiple. Hence the different SELECTION
* notifications. Here's when to use each:
*
* (1) Send a SELECTION notification in the simple single selection
* case (like the focus) when the item with the selection is
* merely moving to a different item within a container. hwnd + ID
* is the container control, idChildItem is the new child with the
* selection.
*
* (2) Send a SELECTIONADD notification when a new item has simply been added
* to the selection within a container. This is appropriate when the
* number of newly selected items is very small. hwnd + ID is the
* container control, idChildItem is the new child added to the selection.
*
* (3) Send a SELECTIONREMOVE notification when a new item has simply been
* removed from the selection within a container. This is appropriate
* when the number of newly selected items is very small, just like
* SELECTIONADD. hwnd + ID is the container control, idChildItem is the
* new child removed from the selection.
*
* (4) Send a SELECTIONWITHIN notification when the selected items within a
* control have changed substantially. Rather than propagate a large
* number of changes to reflect removal for some items, addition of
* others, just tell somebody who cares that a lot happened. It will
* be faster an easier for somebody watching to just turn around and
* query the container control what the new bunch of selected items
* are.
*/
ObjectStateChange = 0x800A, // hwnd + ID + idChild is item w/ state change
/*
* Examples of when to send an EVENT_OBJECT_STATECHANGE include
* * It is being enabled/disabled (USER does for windows)
* * It is being pressed/released (USER does for buttons)
* * It is being checked/unchecked (USER does for radio/check buttons)
*/
ObjectLocationChange = 0x800B, // hwnd + ID + idChild is moved/sized item
/*
* Note:
* A LOCATIONCHANGE is not sent for every child object when the parent
* changes shape/moves. Send one notification for the topmost object
* that is changing. For example, if the user resizes a top level window,
* USER will generate a LOCATIONCHANGE for it, but not for the menu bar,
* title bar, scrollbars, etc. that are also changing shape/moving.
*
* In other words, it only generates LOCATIONCHANGE notifications for
* real windows that are moving/sizing. It will not generate a LOCATIONCHANGE
* for every non-floating child window when the parent moves (the children are
* logically moving also on screen, but not relative to the parent).
*
* Now, if the app itself resizes child windows as a result of being
* sized, USER will generate LOCATIONCHANGEs for those dudes also because
* it doesn't know better.
*
* Note also that USER will generate LOCATIONCHANGE notifications for two
* non-window sys objects:
* (1) System caret
* (2) Cursor
*/
ObjectNameChange = 0x800C, // hwnd + ID + idChild is item w/ name change
ObjectDescriptionChange = 0x800D, // hwnd + ID + idChild is item w/ desc change
ObjectValueChange = 0x800E, // hwnd + ID + idChild is item w/ value change
ObjectParentChange = 0x800F, // hwnd + ID + idChild is item w/ new parent
ObjectHelpChange = 0x8010, // hwnd + ID + idChild is item w/ help change
ObjectDefaultActionChange = 0x8011, // hwnd + ID + idChild is item w/ def action change
ObjectAcceleratorChange = 0x8012, // hwnd + ID + idChild is item w/ keybd accel change
ObjectInvoked = 0x8013, // hwnd + ID + idChild is item invoked
ObjectTextSelectionChanged = 0x8014, // hwnd + ID + idChild is item w? test selection change
/*
* EVENT_OBJECT_CONTENTSCROLLED
* Sent when ending the scrolling of a window object.
*
* Unlike the similar event (EVENT_SYSTEM_SCROLLEND), this event will be
* associated with the scrolling window itself. There is no difference
* between horizontal or vertical scrolling.
*
* This event should be posted whenever scroll action is completed, including
* when it is scrolled by scroll bars, mouse wheel, or keyboard navigations.
*
* example:
* hwnd == window that is scrolling
* idObject == OBJID_CLIENT
* idChild == CHILDID_SELF
*/
ObjectContentScrolled = 0x8015,
SystemArrangmentPreview = 0x8016,
ObjectEnd = 0x80FF,
AiaStart = 0xA000,
AiaEnd = 0xAFFF
}
public enum ObjectIdentifier : uint
{
Window = 0x00000000,
SystemMenu = 0xFFFFFFFF,
TitleBar = 0xFFFFFFFE,
Menu = 0xFFFFFFFD,
Client = 0xFFFFFFFC,
VerticalScroll = 0xFFFFFFFB,
HorizontalScroll = 0xFFFFFFFA,
SizeGrip = 0xFFFFFFF9,
Caret = 0xFFFFFFF8,
Cursor = 0xFFFFFFF7,
Alert = 0xFFFFFFF6,
Sound = 0xFFFFFFF5
}
public enum ChildIdentifier
{
Self = 0
}
[Flags]
public enum SetWinEventHookFlags : uint
{
OutOfContext = 0x0000, // Events are ASYNC
SkipOwnThread = 0x0001, // Don't call back for events on installer's thread
SkipOwnProcess = 0x0002, // Don't call back for events on installer's process
InContext = 0x0004, // Events are SYNC, this causes your dll to be injected into every process
}
public delegate void WinEventDelegate(IntPtr hWinEventHook, Event eventType, IntPtr hwnd, ObjectIdentifier idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(Event eventMin, Event eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, SetWinEventHookFlags dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
}
}