mirror of
https://github.com/ckaczor/Common.Native.git
synced 2026-01-27 01:25:44 -05:00
Initial commit
This commit is contained in:
436
WinEvent.cs
Normal file
436
WinEvent.cs
Normal file
@@ -0,0 +1,436 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user