mirror of
https://github.com/ckaczor/Common.Native.git
synced 2026-01-14 01:25:44 -05:00
436 lines
20 KiB
C#
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);
|
|
}
|
|
} |