Thread: [Mwinapi-commits] SF.net SVN: mwinapi:[76] trunk/ManagedWinapi
Status: Beta
Brought to you by:
schierlm
From: <sch...@us...> - 2008-08-28 22:23:16
|
Revision: 76 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=76&view=rev Author: schierlm Date: 2008-08-28 22:23:10 +0000 (Thu, 28 Aug 2008) Log Message: ----------- Add COMTypeInformation class Modified Paths: -------------- trunk/ManagedWinapi/ManagedWinapi.csproj Added Paths: ----------- trunk/ManagedWinapi/COMTypeInformation.cs Added: trunk/ManagedWinapi/COMTypeInformation.cs =================================================================== --- trunk/ManagedWinapi/COMTypeInformation.cs (rev 0) +++ trunk/ManagedWinapi/COMTypeInformation.cs 2008-08-28 22:23:10 UTC (rev 76) @@ -0,0 +1,137 @@ +/* + * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to + * access native API by managed code. http://mwinapi.sourceforge.net/ + * Copyright (C) 2008 Michael Schierl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. if not, visit + * http://www.gnu.org/licenses/lgpl.html or write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices.ComTypes; +using ComTypes = System.Runtime.InteropServices.ComTypes; +using System.Runtime.InteropServices; + +namespace ManagedWinapi +{ + /// <summary> + /// This class contains methods to identify type name, functions and variables + /// of a wrapped COM object (that appears as System.__COMObject in the debugger). + /// </summary> + public class COMTypeInformation + { + IDispatch dispatch; + ITypeInfo typeInfo; + + /// <summary> + /// Create a new COMTypeInformation object for the given COM Object. + /// </summary> + public COMTypeInformation(object comObject) + { + dispatch = comObject as IDispatch; + if (dispatch == null) throw new Exception("Object is not a COM Object"); + int typeInfoCount; + int hr = dispatch.GetTypeInfoCount(out typeInfoCount); + if (hr < 0) throw new COMException("GetTypeInfoCount failed", hr); + if (typeInfoCount != 1) throw new Exception("No TypeInfo present"); + hr = dispatch.GetTypeInfo(0, LCID_US_ENGLISH, out typeInfo); + if (hr < 0) throw new COMException("GetTypeInfo failed", hr); + } + + /// <summary> + /// The type name of the COM object. + /// </summary> + public string TypeName + { + get + { + string name, dummy1, dummy3; + int dummy2; + typeInfo.GetDocumentation(-1, out name, out dummy1, out dummy2, out dummy3); + return name; + } + } + + /// <summary> + /// The names of the exported functions of this COM object. + /// </summary> + public IList<string> FunctionNames + { + get + { + List<string> result = new List<String>(); + for (int jj = 0; ; jj++) + { + IntPtr fncdesc; + try + { + typeInfo.GetFuncDesc(jj, out fncdesc); + } + catch (COMException) { break; } + ComTypes.FUNCDESC fd = (ComTypes.FUNCDESC)Marshal.PtrToStructure(fncdesc, typeof(ComTypes.FUNCDESC)); + string[] tmp = new string[1]; + int cnt; + typeInfo.GetNames(fd.memid, tmp, tmp.Length, out cnt); + if (cnt == 1) + result.Add(tmp[0]); + typeInfo.ReleaseFuncDesc(fncdesc); + } + return result; + } + } + + /// <summary> + /// The names of the exported variables of this COM object. + /// </summary> + public IList<string> VariableNames + { + get + { + List<string> result = new List<String>(); + for (int jj = 0; ; jj++) + { + IntPtr vardesc; + try + { + typeInfo.GetVarDesc(jj, out vardesc); + } + catch (COMException) { break; } + ComTypes.VARDESC vd = (ComTypes.VARDESC)Marshal.PtrToStructure(vardesc, typeof(ComTypes.VARDESC)); + string[] tmp = new string[1]; + int cnt; + typeInfo.GetNames(vd.memid, tmp, tmp.Length, out cnt); + if (cnt == 1) + result.Add(tmp[0]); + typeInfo.ReleaseFuncDesc(vardesc); + } + return result; + } + } + + #region PInvoke Declarations + + private const int LCID_US_ENGLISH = 0x409; + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")] + private interface IDispatch + { + [PreserveSig] + int GetTypeInfoCount(out int count); + [PreserveSig] + int GetTypeInfo(int index, int lcid, [MarshalAs(UnmanagedType.Interface)] out ITypeInfo pTypeInfo); + } + #endregion + } +} Modified: trunk/ManagedWinapi/ManagedWinapi.csproj =================================================================== --- trunk/ManagedWinapi/ManagedWinapi.csproj 2008-06-14 20:18:49 UTC (rev 75) +++ trunk/ManagedWinapi/ManagedWinapi.csproj 2008-08-28 22:23:10 UTC (rev 76) @@ -44,6 +44,7 @@ <Compile Include="AccessibleObjectListener.cs"> <SubType>Component</SubType> </Compile> + <Compile Include="COMTypeInformation.cs" /> <Compile Include="Contents\AccessibleWindowParser.cs" /> <Compile Include="ExtendedFileInfo.cs" /> <Compile Include="CodepointRange.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2009-01-17 14:29:01
|
Revision: 78 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=78&view=rev Author: schierlm Date: 2009-01-17 14:28:47 +0000 (Sat, 17 Jan 2009) Log Message: ----------- Use WM_GETTEXT to receive text content of text boxes, which works better than GetWindowText. Modified Paths: -------------- trunk/ManagedWinapi/Contents/ListParser.cs trunk/ManagedWinapi/Contents/TextFieldParser.cs trunk/ManagedWinapi/SystemWindow.cs Modified: trunk/ManagedWinapi/Contents/ListParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/ListParser.cs 2009-01-17 14:28:01 UTC (rev 77) +++ trunk/ManagedWinapi/Contents/ListParser.cs 2009-01-17 14:28:47 UTC (rev 78) @@ -184,7 +184,7 @@ { values[i] = slb[i]; } - return new ListContent("ComboBox", -1, sw.Title, values); + return new ListContent("ComboBox", -1, sw.Text, values); } } @@ -340,7 +340,8 @@ { List<string> treeNodes = new List<string>(); int selected = -1; - foreach(SystemAccessibleObject n in sao.Children) { + foreach (SystemAccessibleObject n in sao.Children) + { if (n.RoleIndex == 36) { if ((n.State & 0x2) != 0) Modified: trunk/ManagedWinapi/Contents/TextFieldParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/TextFieldParser.cs 2009-01-17 14:28:01 UTC (rev 77) +++ trunk/ManagedWinapi/Contents/TextFieldParser.cs 2009-01-17 14:28:47 UTC (rev 78) @@ -104,13 +104,13 @@ } else { - return sw.Title != ""; + return sw.Text != ""; } } internal override WindowContent ParseContent(SystemWindow sw) { - return new TextContent(sw.Title, sw.PasswordCharacter != 0, strict); + return new TextContent(sw.Text, sw.PasswordCharacter != 0, strict); } } } Modified: trunk/ManagedWinapi/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/SystemWindow.cs 2009-01-17 14:28:01 UTC (rev 77) +++ trunk/ManagedWinapi/SystemWindow.cs 2009-01-17 14:28:47 UTC (rev 78) @@ -508,6 +508,22 @@ } /// <summary> + /// The text inside of this window (by sending a <c>WM_GETTEXT</c> message). + /// For child windows of other applications, this is more reliable + /// than the <see cref="Title"/> function. + /// </summary> + public string Text + { + get + { + int length = SendGetMessage(WM_GETTEXTLENGTH); + StringBuilder sb = new StringBuilder(length + 1); + SendMessage(new HandleRef(this, HWnd), WM_GETTEXT, new IntPtr(sb.Capacity), sb); + return sb.ToString(); + } + } + + /// <summary> /// The name of the window class (by the <c>GetClassName</c> API function). /// This class has nothing to do with classes in C# or other .NET languages. /// </summary> @@ -1306,7 +1322,7 @@ [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hWnd); - private const int WM_CLOSE = 16; + private const int WM_CLOSE = 16, WM_GETTEXT = 13, WM_GETTEXTLENGTH = 14; private enum GetWindow_Cmd { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2009-06-26 14:05:09
|
Revision: 83 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=83&view=rev Author: schierlm Date: 2009-06-26 13:30:47 +0000 (Fri, 26 Jun 2009) Log Message: ----------- - Add WinForms-like MouseDown/Up/Move/Wheel events to LowLevelMouseHook - Add DomainName and DnsDomainName properties to MachineIdentifiers [submitted by Duncan Smart <duncan dot smart at gmail dot com>] Modified Paths: -------------- trunk/ManagedWinapi/LowLevelHook.cs trunk/ManagedWinapi/MachineIdentifiers.cs Modified: trunk/ManagedWinapi/LowLevelHook.cs =================================================================== --- trunk/ManagedWinapi/LowLevelHook.cs 2009-04-13 15:35:03 UTC (rev 82) +++ trunk/ManagedWinapi/LowLevelHook.cs 2009-06-26 13:30:47 UTC (rev 83) @@ -177,6 +177,18 @@ /// </summary> public event LowLevelMessageCallback MessageIntercepted; + /// <summary>Occurs when the mouse pointer is moved.</summary> + public event EventHandler<MouseEventArgs> MouseMove; + + /// <summary>Occurs when a mouse button is pressed.</summary> + public event EventHandler<MouseEventArgs> MouseDown; + + /// <summary>Occurs when a mouse button is released.</summary> + public event EventHandler<MouseEventArgs> MouseUp; + + /// <summary>Occurs when the mouse wheel moves.</summary> + public event EventHandler<MouseEventArgs> MouseWheel; + /// <summary> /// Represents a method that handles an intercepted mouse action. /// </summary> @@ -206,6 +218,9 @@ if (code == HC_ACTION) { MSLLHOOKSTRUCT llh = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); + + fireMouseEvents(wParam, llh.pt, llh.mouseData); + bool handled = false; if (MouseIntercepted != null) { @@ -224,6 +239,76 @@ return 0; } + private void fireMouseEvents(IntPtr wParam, POINT pt, int mouseData) + { + const int WM_MOUSEMOVE = 0x200, + WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202, + WM_RBUTTONDOWN = 0x204, WM_RBUTTONUP = 0x205, + WM_MBUTTONDOWN = 0x207, WM_MBUTTONUP = 0x208, + WM_MOUSEWHEEL = 0x20A, + WM_XBUTTONDOWN = 0x020B, WM_XBUTTONUP = 0x020C; + + switch ((int)wParam) + { + case WM_MOUSEMOVE: + if (MouseMove != null) + MouseMove(this, new MouseEventArgs(MouseButtons.None, 0, pt.X, pt.Y, 0)); + break; + + case WM_LBUTTONDOWN: + if (MouseDown != null) + MouseDown(this, new MouseEventArgs(MouseButtons.Left, 1, pt.X, pt.Y, 0)); + break; + case WM_LBUTTONUP: + if (MouseUp != null) + MouseUp(this, new MouseEventArgs(MouseButtons.Left, 1, pt.X, pt.Y, 0)); + break; + + case WM_RBUTTONDOWN: + if (MouseDown != null) + MouseDown(this, new MouseEventArgs(MouseButtons.Right, 1, pt.X, pt.Y, 0)); + break; + case WM_RBUTTONUP: + if (MouseUp != null) + MouseUp(this, new MouseEventArgs(MouseButtons.Right, 1, pt.X, pt.Y, 0)); + break; + + case WM_MBUTTONDOWN: + if (MouseDown != null) + MouseDown(this, new MouseEventArgs(MouseButtons.Middle, 1, pt.X, pt.Y, 0)); + break; + case WM_MBUTTONUP: + if (MouseUp != null) + MouseUp(this, new MouseEventArgs(MouseButtons.Middle, 1, pt.X, pt.Y, 0)); + break; + + case WM_MOUSEWHEEL: + if (MouseWheel != null) + MouseWheel(this, new MouseEventArgs(MouseButtons.None, 0, pt.X, pt.Y, hiWord(mouseData))); + break; + + case WM_XBUTTONDOWN: + if (MouseDown != null) + { + MouseButtons xbutton = hiWord(mouseData) == 1 ? MouseButtons.XButton1 : MouseButtons.XButton2; + MouseDown(this, new MouseEventArgs(xbutton, 1, pt.X, pt.Y, 0)); + } + break; + case WM_XBUTTONUP: + if (MouseUp != null) + { + MouseButtons xbutton = hiWord(mouseData) == 1 ? MouseButtons.XButton1 : MouseButtons.XButton2; + MouseUp(this, new MouseEventArgs(xbutton, 1, pt.X, pt.Y, 0)); + } + break; + } + } + + private static short hiWord(int n) + { + return (short)((n >> 0x10) & 0xFFFF); + } + #region PInvoke Declarations [StructLayout(LayoutKind.Sequential)] Modified: trunk/ManagedWinapi/MachineIdentifiers.cs =================================================================== --- trunk/ManagedWinapi/MachineIdentifiers.cs 2009-04-13 15:35:03 UTC (rev 82) +++ trunk/ManagedWinapi/MachineIdentifiers.cs 2009-06-26 13:30:47 UTC (rev 83) @@ -25,6 +25,7 @@ using System.Net.NetworkInformation; using System.IO; using System.Net; +using System.ComponentModel; namespace ManagedWinapi { @@ -64,6 +65,24 @@ [DllImport("advapi32.dll", SetLastError = true, PreserveSig = false)] private static extern void LsaClose(IntPtr ObjectHandle); + [DllImport("netapi32.dll", CharSet = CharSet.Auto)] + private static extern int NetWkstaGetInfo(string server, + int level, + out WKSTA_INFO_100 info); + + [DllImport("netapi32.dll")] + private static extern int NetApiBufferFree(WKSTA_INFO_100 info); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + private class WKSTA_INFO_100 + { + public int wki100_platform_id; + public string wki100_computername; + public string wki100_langroup; + public int wki100_ver_major; + public int wki100_ver_minor; + } + /// <summary> /// The security identifier of this machine. This id is generated at /// installation time (or when running tools like SysPrep or NewSid) @@ -90,6 +109,37 @@ } /// <summary> + /// The NetBIOS name of the domain to which this machine is joined, or the LAN workgroup name if not. + /// For the Active Directory DNS domain name, see <see cref="DnsDomainName"/>. + /// </summary> + public static string DomainName + { + get + { + WKSTA_INFO_100 wkstaInfo; + int result = NetWkstaGetInfo(null, 100, out wkstaInfo); + if (result != 0) + throw new Win32Exception(result); + string domainName = wkstaInfo.wki100_langroup; + NetApiBufferFree(wkstaInfo); + return domainName; + } + } + + /// <summary> + /// The Active Directory DNS domain of which this machine is a member. + /// For the NetBIOS domain name see <see cref="DomainName"/>. + /// </summary> + public static string DnsDomainName + { + get + { + IPGlobalProperties ipGlobalProps = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties(); + return ipGlobalProps.DomainName; + } + } + + /// <summary> /// The DNS host name of this machine. Can be easily changed. /// </summary> public static string HostName This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2010-02-14 14:15:03
|
Revision: 92 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=92&view=rev Author: schierlm Date: 2010-02-14 14:14:56 +0000 (Sun, 14 Feb 2010) Log Message: ----------- - WindowContentParser: Add an option to parse only the short description (faster) - Speed up parsing of details list views enormously Modified Paths: -------------- trunk/ManagedWinapi/Contents/ListParser.cs trunk/ManagedWinapi/Contents/WindowContentParser.cs trunk/ManagedWinapi/SystemWindow.cs Modified: trunk/ManagedWinapi/Contents/ListParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/ListParser.cs 2010-01-02 19:08:51 UTC (rev 91) +++ trunk/ManagedWinapi/Contents/ListParser.cs 2010-02-14 14:14:56 UTC (rev 92) @@ -155,6 +155,12 @@ return SystemListBox.FromSystemWindow(sw) != null; } + internal override WindowContent ParsePreviewContent(SystemWindow sw) + { + SystemListBox slb = SystemListBox.FromSystemWindow(sw); + return new ListContent("ListBox", slb.SelectedIndex, slb.SelectedItem, new string[0]); + } + internal override WindowContent ParseContent(SystemWindow sw) { SystemListBox slb = SystemListBox.FromSystemWindow(sw); @@ -175,6 +181,11 @@ return SystemComboBox.FromSystemWindow(sw) != null; } + internal override WindowContent ParsePreviewContent(SystemWindow sw) + { + return new ListContent("ComboBox", -1, sw.Text, new string[0]); + } + internal override WindowContent ParseContent(SystemWindow sw) { SystemComboBox slb = SystemComboBox.FromSystemWindow(sw); @@ -198,11 +209,81 @@ return cnt != 0; } + internal override WindowContent ParsePreviewContent(SystemWindow sw) + { + uint LVM_GETITEMCOUNT = (0x1000 + 4); + int cnt = sw.SendGetMessage(LVM_GETITEMCOUNT); + if (cnt == 0) throw new Exception(); + SystemAccessibleObject o = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); + if (o.RoleIndex == 33) + { + return new ListContent("DetailsListView", -1, null, new string[0]); + } + else + { + return new ListContent("EmptyListView", -1, null, new string[0]); + } + } + internal override WindowContent ParseContent(SystemWindow sw) { uint LVM_GETITEMCOUNT = (0x1000 + 4); int cnt = sw.SendGetMessage(LVM_GETITEMCOUNT); if (cnt == 0) throw new Exception(); + try + { + SystemListView slv = SystemListView.FromSystemWindow(sw); + // are there column headers? + string[] hdr = null; + SystemListViewColumn[] columns = slv.Columns; + if (columns.Length > 0) + { + hdr = new string[columns.Length]; + for (int i = 0; i < hdr.Length; i++) + { + hdr[i] = columns[i].Title; + } + } + int itemCount = slv.Count; + List<string> values = new List<string>(); + for (int i = 0; i < itemCount; i++) + { + SystemListViewItem item = slv[i]; + string name = item.Title; + if (hdr != null) + { + for (int j = 1; j < hdr.Length; j++) + { + SystemListViewItem subitem = slv[i, j]; + name += "\t" + subitem.Title; + } + } + values.Add(name); + } + if (hdr != null) + { + string lines = "", headers = ""; + foreach (string h in hdr) + { + if (lines.Length > 0) lines += "\t"; + if (headers.Length > 0) headers += "\t"; + headers += h; + lines += ListContent.Repeat('~', h.Length); + } + values.Insert(0, lines); + values.Insert(0, headers); + return new ListContent("DetailsListView", -1, null, values.ToArray()); + } + else + { + return new ListContent("ListView", -1, null, values.ToArray()); + } + } + catch + { + // fallback to slower accessible object method + if (true) throw; + } SystemAccessibleObject o = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); if (o.RoleIndex == 33) { @@ -333,6 +414,16 @@ return cnt != 0; } + internal override WindowContent ParsePreviewContent(SystemWindow sw) + { + SystemAccessibleObject sao = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); + if (sao.RoleIndex == 35) + { + return new ListContent("TreeView", -1, null, new string[0]); + } + return new ListContent("EmptyTreeView", -1, null, new string[0]); + } + internal override WindowContent ParseContent(SystemWindow sw) { SystemAccessibleObject sao = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); Modified: trunk/ManagedWinapi/Contents/WindowContentParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/WindowContentParser.cs 2010-01-02 19:08:51 UTC (rev 91) +++ trunk/ManagedWinapi/Contents/WindowContentParser.cs 2010-02-14 14:14:56 UTC (rev 92) @@ -26,11 +26,26 @@ internal abstract bool CanParseContent(SystemWindow sw); internal abstract WindowContent ParseContent(SystemWindow sw); + /// <summary> + /// Parse enough content so that the <see cref="WindowContent.ShortDescription"/> is accurate. + /// </summary> + internal virtual WindowContent ParsePreviewContent(SystemWindow sw) + { + return ParseContent(sw); + } + internal static WindowContent Parse(SystemWindow sw) { WindowContentParser parser = ContentParserRegistry.Instance.GetParser(sw); if (parser == null) return null; return parser.ParseContent(sw); } + + internal static WindowContent ParsePreview(SystemWindow sw) + { + WindowContentParser parser = ContentParserRegistry.Instance.GetParser(sw); + if (parser == null) return null; + return parser.ParsePreviewContent(sw); + } } } Modified: trunk/ManagedWinapi/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/SystemWindow.cs 2010-01-02 19:08:51 UTC (rev 91) +++ trunk/ManagedWinapi/SystemWindow.cs 2010-02-14 14:14:56 UTC (rev 92) @@ -996,6 +996,21 @@ } /// <summary> + /// A preview of the content of this window. Is only supported for some + /// kinds of controls (like text or list boxes). This method can be a lot + /// faster than the <see cref="Content"/> method, but will only + /// guarantee that the <see cref="WindowContent.ShortDescription"/> field is + /// filled accurately. + /// </summary> + public WindowContent PreviewContent + { + get + { + return WindowContentParser.ParsePreview(this); + } + } + + /// <summary> /// Whether this control, which is a check box or radio button, is checked. /// </summary> public CheckState CheckState This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-01-02 20:33:42
|
Revision: 97 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=97&view=rev Author: schierlm Date: 2011-01-02 20:33:36 +0000 (Sun, 02 Jan 2011) Log Message: ----------- - Remove debug code in ListParser - disable a warning in MixerControl Modified Paths: -------------- trunk/ManagedWinapi/Contents/ListParser.cs trunk/ManagedWinapi/MixerControl.cs Modified: trunk/ManagedWinapi/Contents/ListParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/ListParser.cs 2011-01-01 22:53:58 UTC (rev 96) +++ trunk/ManagedWinapi/Contents/ListParser.cs 2011-01-02 20:33:36 UTC (rev 97) @@ -282,7 +282,6 @@ catch { // fallback to slower accessible object method - if (true) throw; } SystemAccessibleObject o = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); if (o.RoleIndex == 33) Modified: trunk/ManagedWinapi/MixerControl.cs =================================================================== --- trunk/ManagedWinapi/MixerControl.cs 2011-01-01 22:53:58 UTC (rev 96) +++ trunk/ManagedWinapi/MixerControl.cs 2011-01-02 20:33:36 UTC (rev 97) @@ -274,6 +274,7 @@ public int fValue; } +#pragma warning disable 649 internal struct MIXERCONTROLDETAILS_LISTTEXT { public int dwParam1; @@ -282,6 +283,7 @@ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szName; } +#pragma warning restore 649 private static readonly int MIXER_GETLINECONTROLSF_ALL = 0x0; private static readonly uint MIXERCONTROL_CT_CLASS_MASK = 0xF0000000; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-01-12 22:19:49
|
Revision: 98 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=98&view=rev Author: schierlm Date: 2011-01-12 22:19:42 +0000 (Wed, 12 Jan 2011) Log Message: ----------- Add a class for creating special screenshots (like screenshots of non-rectangular windows or of scrollable regions). The current scrolling implementation leaves a lot of room for speed optimizations, but it can handle a lot of cases where other freeware scrolling screenshot implementations fail. Modified Paths: -------------- trunk/ManagedWinapi/ManagedWinapi.csproj trunk/ManagedWinapi/SystemWindow.cs Added Paths: ----------- trunk/ManagedWinapi/Screenshot.cs Modified: trunk/ManagedWinapi/ManagedWinapi.csproj =================================================================== --- trunk/ManagedWinapi/ManagedWinapi.csproj 2011-01-02 20:33:36 UTC (rev 97) +++ trunk/ManagedWinapi/ManagedWinapi.csproj 2011-01-12 22:19:42 UTC (rev 98) @@ -62,6 +62,7 @@ <Compile Include="MachineIdentifiers.cs" /> <Compile Include="ProcessMemoryChunk.cs" /> <Compile Include="ProcessTree.cs" /> + <Compile Include="Screenshot.cs" /> <Compile Include="ShortcutBox.cs"> <SubType>Component</SubType> </Compile> Added: trunk/ManagedWinapi/Screenshot.cs =================================================================== --- trunk/ManagedWinapi/Screenshot.cs (rev 0) +++ trunk/ManagedWinapi/Screenshot.cs 2011-01-12 22:19:42 UTC (rev 98) @@ -0,0 +1,607 @@ +using System; +/* + * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to + * access native API by managed code. http://mwinapi.sourceforge.net/ + * Copyright (C) 2011 Michael Schierl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. if not, visit + * http://www.gnu.org/licenses/lgpl.html or write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows.Forms; +using ManagedWinapi.Accessibility; + +namespace ManagedWinapi.Windows +{ + /// <summary> + /// Provides methods to obtain screenshots of different targets. + /// </summary> + public static class Screenshot + { + + /// <summary> + /// Take a screenshot of the full screen. + /// </summary> + /// <param name="includeCursor">Whether to include the mouse cursor.</param> + public static Bitmap TakeScreenshot(bool includeCursor) + { + Rectangle rect = Screen.PrimaryScreen.Bounds; + foreach (Screen screen in Screen.AllScreens) + rect = Rectangle.Union(rect, screen.Bounds); + return TakeScreenshot(rect, includeCursor, null); + } + + /// <summary> + /// Take a screenshot of a given window or object. + /// </summary> + /// <param name="window">Window to take the screenshot from.</param> + /// <param name="clientAreaOnly">Whether to include only the client area or also the decoration (title bar).</param> + /// <param name="includeCursor">Whether to include the mouse cursor.</param> + /// <param name="keepShape">Whether to keep the shape (transparency region) of the window.</param> + public static Bitmap TakeScreenshot(SystemWindow window, bool clientAreaOnly, bool includeCursor, bool keepShape) + { + Region shape = null; + if (keepShape) + { + shape = window.Region; + if (shape != null && clientAreaOnly) + { + shape.Translate(window.Rectangle.Left - window.ClientRectangle.Left, window.Rectangle.Top - window.ClientRectangle.Top); + } + } + return TakeScreenshot(clientAreaOnly ? window.ClientRectangle : window.Rectangle, includeCursor, shape); + } + + /// <summary> + /// Take a screenshot of a given accessible object + /// </summary> + /// <param name="accessibleObject">Accessible object to take the screenshot from.</param> + /// <param name="includeCursor">Whether to include the mouse cursor.</param> + /// <param name="keepShape">Whether to keep the shape (transparency region) of the window.</param> + public static Bitmap TakeScreenshot(SystemAccessibleObject accessibleObject, bool includeCursor, bool keepShape) + { + Region shape = null; + if (keepShape) + { + shape = accessibleObject.Window.Region; + shape.Translate(accessibleObject.Window.Rectangle.Left - accessibleObject.Location.Left, accessibleObject.Window.Rectangle.Top - accessibleObject.Location.Top); + } + return TakeScreenshot(accessibleObject.Location, includeCursor, shape); + } + + /// <summary> + /// Take a screenshot of an arbitrary rectangle on the screen. Optionally a region + /// can be used for clipping the rectangle. The mouse cursor, if included, + /// is not affected by clipping. + /// </summary> + /// <param name="rect">Rectangle to include.</param> + /// <param name="includeCursor">Whether to include the mouse cursor.</param> + /// <param name="shape">Shape (region) used for clipping.</param> + public static Bitmap TakeScreenshot(Rectangle rect, bool includeCursor, Region shape) + { + Bitmap result = new Bitmap(rect.Width, rect.Height); + + using (Graphics g = Graphics.FromImage(result)) + { + g.CopyFromScreen(rect.Location, Point.Empty, rect.Size); + } + if (shape != null) + { + for (int i = 0; i < result.Width; i++) + { + for (int j = 0; j < result.Height; j++) + { + if (!shape.IsVisible(new Point(i, j))) + { + result.SetPixel(i, j, Color.Transparent); + } + } + } + } + if (includeCursor) + { + // Cursors may use XOR operations http://support.microsoft.com/kb/311221 + CURSORINFO ci; + ci.cbSize = Marshal.SizeOf(typeof(CURSORINFO)); + ApiHelper.FailIfZero(GetCursorInfo(out ci)); + if ((ci.flags & CURSOR_SHOWING) != 0) + { + using (Cursor c = new Cursor(ci.hCursor)) + { + Point cursorLocation = new Point(ci.ptScreenPos.X - rect.X - c.HotSpot.X, ci.ptScreenPos.Y - rect.Y - c.HotSpot.Y); + // c.Draw() does not work with XOR cursors (like the default text cursor) + DrawCursor(ref result, c, cursorLocation); + } + } + } + return result; + } + + private static void DrawCursor(ref Bitmap bitmap, Cursor cursor, Point cursorLocation) + { + // http://support.microsoft.com/kb/311221 + // http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/291990e0-fb68-4e0a-ae12-835d43b9275b/ + + IntPtr compatibleHDC; + using (Graphics g = Graphics.FromImage(bitmap)) + { + IntPtr hDC = g.GetHdc(); + compatibleHDC = CreateCompatibleDC(hDC); + g.ReleaseHdc(); + } + IntPtr hBmp = bitmap.GetHbitmap(); + SelectObject(compatibleHDC, hBmp); + DrawIcon(compatibleHDC, cursorLocation.X, cursorLocation.Y, cursor.Handle); + bitmap.Dispose(); + bitmap = Image.FromHbitmap(hBmp); + DeleteObject(hBmp); + } + + /// <summary> + /// Take a screenshot of a window which has a larger display area than on screen (i. e. it has scroll bars). + /// This will send a <code>WM_PRINT</code> or <code>WM_PRINTCLIENT</code> message to the window to try to print it into an + /// offscreen image. This will be repeated with larger images until a transparent border remains. + /// This operation will only work with windows that explicitly support it. + /// </summary> + /// <param name="window">Window to take the screenshot of</param> + /// <param name="clientAreaOnly">Whether to send WM_PRINTCLIENT message</param> + public static Bitmap TakeOverlargeScreenshot(SystemWindow window, bool clientAreaOnly) + { + Rectangle position = window.Position; + int width = position.Width + 1; + int height = position.Height + 1; + while (true) + { + Bitmap result = TakeOverlargeScreenshot(window, clientAreaOnly, width, height); + if (result.GetPixel(0, height - 1).A != 0) + height *= 2; + else if (result.GetPixel(width - 1, 0).A != 0) + width *= 2; + else + return result; + if (width * height > 256 * 1048576) // 1 gigabyte! + return result; + } + } + + /// <summary> + /// Take a screenshot of a window which has a larger display area than on screen (i. e. it has scroll bars). + /// This will send a <code>WM_PRINT</code> or <code>WM_PRINTCLIENT</code> message to the window to try to print it into an + /// offscreen image of the given width and height. + /// </summary> + /// <param name="window">Window to take the screenshot of</param> + /// <param name="clientAreaOnly">Whether to send WM_PRINTCLIENT message</param> + /// <param name="width">Width of the bitmap</param> + /// <param name="height">Height of the bitmap</param> + public static Bitmap TakeOverlargeScreenshot(SystemWindow window, bool clientAreaOnly, int width, int height) + { + Bitmap bmp = new Bitmap(width, height); + Graphics g = Graphics.FromImage(bmp); + IntPtr pTarget = g.GetHdc(); + IntPtr pSource = CreateCompatibleDC(pTarget); + IntPtr pOrig = SelectObject(pSource, bmp.GetHbitmap()); + PrintWindow(window.HWnd, pTarget, clientAreaOnly ? (uint)1 : (uint)0); + IntPtr pNew = SelectObject(pSource, pOrig); + DeleteObject(pNew); + DeleteObject(pSource); + g.ReleaseHdc(pTarget); + g.Dispose(); + return bmp; + } + + /// <summary> + /// Take a screenshot from a vertically scrolling window. The scrolling can be done either by simulating mouse wheel events, + /// or by simulating mouse click events on the scrollbar button. The operation stops when scrolling does not result in any + /// new content or when the mouse is moved by the user. + /// </summary> + /// <param name="scrollPoint">Point inside the window that is inside the scrolling region and that might be used for sending scroll wheel events at</param> + /// <param name="window">Window to take the screenshot of</param> + /// <param name="clickPoint">Point above the scrollbar to click, if desired</param> + public static Bitmap TakeVerticalScrollingScreenshot(Point scrollPoint, SystemWindow window, Point? clickPoint) + { + return TakeVerticalScrollingScreenshot(scrollPoint, window.Rectangle, clickPoint); + } + + /// <summary> + /// Take a screenshot from a vertically scrolling region. The scrolling can be done either by simulating mouse wheel events, + /// or by simulating mouse click events on the scrollbar button. The operation stops when scrolling does not result in any + /// new content or when the mouse is moved by the user. + /// </summary> + /// <param name="scrollPoint">Point inside the window that is inside the scrolling region and that might be used for sending scroll wheel events at</param> + /// <param name="rect">Rectangle to take the screenshot of</param> + /// <param name="clickPoint">Point above the scrollbar to click, if desired</param> + public static Bitmap TakeVerticalScrollingScreenshot(Point scrollPoint, Rectangle rect, Point? clickPoint) + { + int scrollCount; + return TakeScrollingScreenshot(scrollPoint, rect, clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => TakeScreenshot(r, false, null), out scrollCount); + } + + /// <summary> + /// Take a screenshot from a horizontally scrolling window. The scrolling can be done either by simulating mouse wheel events, + /// or by simulating mouse click events on the scrollbar button. The operation stops when scrolling does not result in any + /// new content or when the mouse is moved by the user. + /// </summary> + /// <param name="scrollPoint">Point inside the window that is inside the scrolling region and that might be used for sending scroll wheel events at</param> + /// <param name="window">Window to take the screenshot of</param> + /// <param name="clickPoint">Point above the scrollbar to click, if desired</param> + /// <returns></returns> + public static Bitmap TakeHorizontalScrollingScreenshot(Point scrollPoint, SystemWindow window, Point? clickPoint) + { + return TakeHorizontalScrollingScreenshot(scrollPoint, window.Rectangle, clickPoint); + } + + /// <summary> + /// Take a screenshot from a horizontally scrolling region. The scrolling can be done either by simulating mouse wheel events, + /// or by simulating mouse click events on the scrollbar button. The operation stops when scrolling does not result in any + /// new content or when the mouse is moved by the user. + /// </summary> + /// <param name="scrollPoint">Point inside the window that is inside the scrolling region and that might be used for sending scroll wheel events at</param> + /// <param name="rect">Rectangle to take the screenshot of</param> + /// <param name="clickPoint">Point above the scrollbar to click, if desired</param> + /// <returns></returns> + public static Bitmap TakeHorizontalScrollingScreenshot(Point scrollPoint, Rectangle rect, Point? clickPoint) + { + int scrollCount; + return FlipRotate(TakeScrollingScreenshot(new Point(scrollPoint.Y, scrollPoint.X), FlipRotate(rect), clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => FlipRotate(TakeScreenshot(FlipRotate(r), false, null)), out scrollCount)); + } + + private delegate Bitmap ScreenshotFunction(Rectangle rect); + + private static Bitmap TakeScrollingScreenshot(Point centerPoint, Rectangle rect, Point mousePoint, bool click, ScreenshotFunction screenshot, out int scrollCount) + { + scrollCount = 0; + Cursor.Position = mousePoint; + Bitmap buffer = screenshot(rect); + int usedHeight = buffer.Height; + buffer = ResizeBitmap(buffer, buffer.Height * 4); + while (Cursor.Position == mousePoint) + { + scrollCount++; + if (click) + { + KeyboardKey.InjectMouseEvent(0x0002, 0, 0, 0, UIntPtr.Zero); + KeyboardKey.InjectMouseEvent(0x0004, 0, 0, 0, UIntPtr.Zero); + } + else + { + KeyboardKey.InjectMouseEvent(0x0800, 0, 0, unchecked((uint)-120), UIntPtr.Zero); + } + Application.DoEvents(); + Bitmap nextPart = screenshot(rect); + int scrollHeight = AppendBelow(buffer, usedHeight, nextPart); + foreach (int delay in new int[] { 0, 2, 10, 100, 200, 1000 }) + { + if (scrollHeight > 0 || Cursor.Position != mousePoint) + break; + Thread.Sleep(delay); + Application.DoEvents(); + nextPart = screenshot(rect); + scrollHeight = AppendBelow(buffer, usedHeight, nextPart); + } + if (scrollHeight == -1) + { + CropToSimilarRange(centerPoint, ref rect, ref buffer, ref usedHeight, ref nextPart); + scrollHeight = AppendBelow(buffer, usedHeight, nextPart); + } + if (scrollHeight <= 0) + break; + usedHeight += scrollHeight; + if (buffer.Height - usedHeight < rect.Height) + buffer = ResizeBitmap(buffer, buffer.Height * 2); + } + return ResizeBitmap(buffer, usedHeight); + } + + private static void CropToSimilarRange(Point centerPoint, ref Rectangle rect, ref Bitmap buffer, ref int usedHeight, ref Bitmap nextPart) + { + Point mousePoint = Cursor.Position; + int offs = usedHeight - nextPart.Height; + int relX = centerPoint.X - rect.X; + int relY = centerPoint.Y - rect.Y; + + // find a different point + int diffX = relX, diffY = relY; + if (buffer.GetPixel(relX, relY + offs) == nextPart.GetPixel(relX, relY)) + { + bool found = false; + int maxDistance = Math.Min(Math.Min(relX, relY), Math.Min(nextPart.Width - relX, nextPart.Height - relY)); + for (int i = 1; !found && i < maxDistance; i++) + { + for (int j = 0; j < i * 2; j++) + { + int x = relX - i + j; + int y = relY - i; + if (buffer.GetPixel(x, y + offs) != nextPart.GetPixel(x, y)) + { + diffX = x; diffY = y; found = true; + break; + } + x = relX + i; + y = relY - i + j; + if (buffer.GetPixel(x, y + offs) != nextPart.GetPixel(x, y)) + { + diffX = x; diffY = y; found = true; + break; + } + x = relX + i - j; + y = relY + i; + if (buffer.GetPixel(x, y + offs) != nextPart.GetPixel(x, y)) + { + diffX = x; diffY = y; found = true; + break; + } + x = relX - i; + y = relY + i - j; + if (buffer.GetPixel(x, y + offs) != nextPart.GetPixel(x, y)) + { + diffX = x; diffY = y; found = true; + break; + } + } + } + if (!found) return; + } + + // score every possible scroll height + int[] scrollScores = new int[nextPart.Height / 2]; + for (int x = 0; x < rect.Width; x++) + { +#if !DEBUG + if (Cursor.Position != mousePoint) return; +#endif + for (int y = 0; y < rect.Height; y++) + { + // look at every pixel that does not match unmoved + Color pixel = nextPart.GetPixel(x, y); + if (buffer.GetPixel(x, y + offs) != pixel) + { + int score = 1000 / (Math.Abs(relX - x) + Math.Abs(relY - y)) + 1; + for (int scrollHeight = 1; scrollHeight < scrollScores.Length; scrollHeight++) + { + if (buffer.GetPixel(x, y + offs + scrollHeight) == pixel) + { + scrollScores[scrollHeight] += score; + } + } + } + } + } + + // remove scores that do not preserve relX/relY or diffX/diffY + for (int scrollHeight = 1; scrollHeight < scrollScores.Length; scrollHeight++) + { + if (buffer.GetPixel(relX, relY + offs + scrollHeight) != nextPart.GetPixel(relX, relY) + || buffer.GetPixel(diffX, diffY + offs + scrollHeight) != nextPart.GetPixel(diffX, diffY)) + { + scrollScores[scrollHeight] = 0; + } + } + + // take the first 5 scroll distances based on score + Rectangle newRect = rect; + int newRectSize = 0; + for (int i = 0; i < 5; i++) + { +#if !DEBUG + if (Cursor.Position != mousePoint) return; +#endif + int maxScore = 0; + for (int scrollHeight = 1; scrollHeight < scrollScores.Length; scrollHeight++) + { + if (scrollScores[scrollHeight] > maxScore) + maxScore = scrollScores[scrollHeight]; + } + if (maxScore == 0) + break; + for (int scrollHeight = 1; scrollHeight < scrollScores.Length; scrollHeight++) + { + if (scrollScores[scrollHeight] == maxScore) + { +#if !DEBUG + if (Cursor.Position != mousePoint) return; +#endif + scrollScores[scrollHeight] = 0; + + // check the maximum rectangle that scrolls and its size + int minY = 0, maxY = rect.Height - 1; + // first scan up and down with a width of 7 pixels + for (int y = relY - 1; y >= minY; y--) + { + bool same = true; + for (int x = relX - 3; x <= relX + 3; x++) + { + if (buffer.GetPixel(x, y + offs + scrollHeight) != nextPart.GetPixel(x, y)) + { + same = false; + break; + } + } + if (!same) + { + minY = y + 1; + } + } + for (int y = relY + 1; y <= maxY; y++) + { + bool same = true; + for (int x = relX - 3; x <= relX + 3; x++) + { + if (buffer.GetPixel(x, y + offs + scrollHeight) != nextPart.GetPixel(x, y)) + { + same = false; + break; + } + } + if (!same) + { + maxY = y - 1; + } + } + // now check left and right + int minX = 0, maxX = rect.Height - 1; + for (int x = relX - 1; x >= minX; x--) + { + bool same = true; + for (int y = minY; y <= maxY; y++) + { + + if (buffer.GetPixel(x, y + offs + scrollHeight) != nextPart.GetPixel(x, y)) + { + same = false; + break; + } + } + if (!same) + minX = x + 1; + } + for (int x = relX + 1; x <= maxX; x++) + { + bool same = true; + for (int y = minY; y <= maxY; y++) + { + if (buffer.GetPixel(x, y + offs + scrollHeight) != nextPart.GetPixel(x, y)) + { + same = false; + break; + } + } + if (!same) + maxX = x - 1; + } + Rectangle rr = new Rectangle(rect.X + minX, rect.Y + minY, maxX - minX + 1, maxY - minY + 1 + scrollHeight); + if (rr.Width > 16 && rr.Height > 16 && rr.Width * rr.Height > newRectSize) + { + newRect = rr; + newRectSize = rr.Width * rr.Height; + } + } + } + } + + // if we found a rectangle + if (newRectSize > 0) + { + // do the cropping + int cropTop = newRect.Top - rect.Top; + int cropLeft = newRect.Left - rect.Left; + int cropRight = rect.Right - newRect.Right; + int cropBottom = rect.Bottom - newRect.Bottom; + buffer = Crop(buffer, cropTop, cropLeft, cropRight, cropBottom); + nextPart = Crop(nextPart, cropTop, cropLeft, cropRight, cropBottom); + usedHeight -= cropTop + cropBottom; + + // update the rectangle + rect = newRect; + } + } + + private static Bitmap Crop(Bitmap original, int cropTop, int cropLeft, int cropRight, int cropBottom) + { + Bitmap result = new Bitmap(original.Width - cropLeft - cropRight, original.Height - cropTop - cropBottom); + using (Graphics g = Graphics.FromImage(result)) + { + g.DrawImage(original, -cropLeft, -cropTop); + } + return result; + } + + private static int AppendBelow(Bitmap buffer, int usedHeight, Bitmap nextPart) + { + int offs = usedHeight - nextPart.Height; + for (int scrollHeight = 0; scrollHeight < nextPart.Height / 2; scrollHeight++) + { + bool same = true; + for (int y = 0; same && y < nextPart.Height - scrollHeight; y++) + { + for (int x = 0; same && x < nextPart.Width; x++) + { + if (nextPart.GetPixel(x, y) != buffer.GetPixel(x, y + offs + scrollHeight)) + same = false; + } + } + if (same) + { + using (Graphics g = Graphics.FromImage(buffer)) + { + g.DrawImage(nextPart, 0, offs + scrollHeight); + } + return scrollHeight; + } + } + return -1; + } + + private static Bitmap ResizeBitmap(Bitmap original, int height) + { + Bitmap result = new Bitmap(original.Width, height); + using (Graphics g = Graphics.FromImage(result)) + { + g.DrawImage(original, 0, 0); + } + return result; + } + + private static Bitmap FlipRotate(Bitmap original) + { + Bitmap result = new Bitmap(original.Height, original.Width); + using (Graphics g = Graphics.FromImage(result)) + { + g.Transform = new Matrix(0, 1, 1, 0, 0, 0); + g.DrawImage(original, 0, 0); + } + return result; + } + + private static Rectangle FlipRotate(Rectangle original) + { + return new Rectangle(original.Y, original.X, original.Height, original.Width); + } + + #region PInvoke Declarations + + [StructLayout(LayoutKind.Sequential)] + struct CURSORINFO + { + public Int32 cbSize; + public Int32 flags; + public IntPtr hCursor; + public POINT ptScreenPos; + } + + [DllImport("user32.dll")] + static extern int GetCursorInfo(out CURSORINFO pci); + + private const Int32 CURSOR_SHOWING = 0x00000001; + + [DllImport("user32.dll")] + static extern int DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon); + + [DllImport("gdi32.dll", SetLastError = true)] + static extern IntPtr CreateCompatibleDC(IntPtr hdc); + + [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)] + static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); + + [DllImport("gdi32.dll")] + static extern bool DeleteObject(IntPtr hObject); + + [DllImport("user32.dll", SetLastError = true)] + static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags); + + #endregion + } +} Modified: trunk/ManagedWinapi/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/SystemWindow.cs 2011-01-02 20:33:36 UTC (rev 97) +++ trunk/ManagedWinapi/SystemWindow.cs 2011-01-12 22:19:42 UTC (rev 98) @@ -758,6 +758,25 @@ } /// <summary> + /// The position of the window's contents in absolute screen coordinates. Use + /// <see cref="Rectangle"/> if you want to include the title bar etc. + /// </summary> + public RECT ClientRectangle + { + get + { + RECT r = new RECT(); + ApiHelper.FailIfZero(GetClientRect(_hwnd, out r)); + Point p = new Point(); + p.X = p.Y = 0; + ApiHelper.FailIfZero(ClientToScreen(_hwnd, ref p)); + Rectangle result = r; + result.Location = p; + return result; + } + } + + /// <summary> /// Check whether this window is a descendant of <c>ancestor</c> /// </summary> /// <param name="ancestor">The suspected ancestor</param> @@ -1262,6 +1281,12 @@ static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] + static extern int GetClientRect(IntPtr hWnd, out RECT lpRect); + + [DllImport("user32.dll")] + static extern int ClientToScreen(IntPtr hWnd, ref Point lpPoint); + + [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("gdi32.dll")] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <po...@us...> - 2012-07-01 16:06:28
|
Revision: 113 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=113&view=rev Author: poovenb Date: 2012-07-01 16:06:19 +0000 (Sun, 01 Jul 2012) Log Message: ----------- (1) Created new folders to organise namespaces: moved files accordingly. (2) Added TextCursor and TextCursorProvider that allow a custom caret to be used. However, this only seems to work well for TextBox Control types. The aim was to ensure that the user selected color is used: by default the Windows API applies a bit mask so that the displayed color will not match the user elected color for non-white backgrounds. (3) Added BitmapDataHandler and PixelData that provide fast bitmap modification for large bitmap operations. (4) It seems that Screenshot was not added to the project; Visual Studio 2010 has included it. Modified Paths: -------------- trunk/ManagedWinapi/ManagedWinapi.csproj Added Paths: ----------- trunk/ManagedWinapi/Accessibility/ trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs trunk/ManagedWinapi/Audio/ trunk/ManagedWinapi/Audio/Mixer/ trunk/ManagedWinapi/Audio/Mixer/Mixer.cs trunk/ManagedWinapi/Audio/Mixer/MixerControl.cs trunk/ManagedWinapi/Audio/Mixer/MixerLine.cs trunk/ManagedWinapi/BitmapDataHandler.cs trunk/ManagedWinapi/Hooks/ trunk/ManagedWinapi/Hooks/Hook.cs trunk/ManagedWinapi/Hooks/JournalHook.cs trunk/ManagedWinapi/Hooks/LowLevelHook.cs trunk/ManagedWinapi/PixelData.cs trunk/ManagedWinapi/TextCursor.cs trunk/ManagedWinapi/TextCursorProvider.cs trunk/ManagedWinapi/Windows/ trunk/ManagedWinapi/Windows/Contents/ trunk/ManagedWinapi/Windows/EventDispatchingNativeWindow.cs trunk/ManagedWinapi/Windows/PInvokeTypes.cs trunk/ManagedWinapi/Windows/Screenshot.cs trunk/ManagedWinapi/Windows/SystemListBox.cs trunk/ManagedWinapi/Windows/SystemListView.cs trunk/ManagedWinapi/Windows/SystemTreeView.cs trunk/ManagedWinapi/Windows/SystemWindow.cs Removed Paths: ------------- trunk/ManagedWinapi/AccessibleObjectListener.cs trunk/ManagedWinapi/Contents/ trunk/ManagedWinapi/EventDispatchingNativeWindow.cs trunk/ManagedWinapi/Hook.cs trunk/ManagedWinapi/JournalHook.cs trunk/ManagedWinapi/LowLevelHook.cs trunk/ManagedWinapi/Mixer.cs trunk/ManagedWinapi/MixerControl.cs trunk/ManagedWinapi/MixerLine.cs trunk/ManagedWinapi/PInvokeTypes.cs trunk/ManagedWinapi/Screenshot.cs trunk/ManagedWinapi/SystemAccessibleObject.cs trunk/ManagedWinapi/SystemListBox.cs trunk/ManagedWinapi/SystemListView.cs trunk/ManagedWinapi/SystemTreeView.cs trunk/ManagedWinapi/SystemWindow.cs Copied: trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs (from rev 112, trunk/ManagedWinapi/AccessibleObjectListener.cs) =================================================================== --- trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs (rev 0) +++ trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs 2012-07-01 16:06:19 UTC (rev 113) @@ -0,0 +1,522 @@ +/* + * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to + * access native API by managed code. http://mwinapi.sourceforge.net/ + * Copyright (C) 2006, 2007 Michael Schierl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. if not, visit + * http://www.gnu.org/licenses/lgpl.html or write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using Accessibility; + +namespace ManagedWinapi.Accessibility +{ + /// <summary> + /// Listens to events from the Windows accessibility system. These events are useful + /// if you want to write a screenreader or similar program. + /// </summary> + public class AccessibleEventListener : Component + { + /// <summary> + /// Occurs when an accessible event is received. + /// </summary> + public event AccessibleEventHandler EventOccurred; + + private bool enabled; + private IntPtr handle = IntPtr.Zero; + private AccessibleEventType min = AccessibleEventType.EVENT_MIN; + private AccessibleEventType max = AccessibleEventType.EVENT_MAX; + private WinEventDelegate internalDelegate; + private GCHandle gch; + private UInt32 processId = 0; + private UInt32 threadId = 0; + + /// <summary> + /// Initializes a new instance of this class with the specified container. + /// </summary> + /// <param name="container">The container to add it to.</param> + public AccessibleEventListener(IContainer container) + : this() + { + container.Add(this); + } + + /// <summary> + /// Initializes a new instance of this class. + /// </summary> + public AccessibleEventListener() + { + internalDelegate = new WinEventDelegate(InternalCallback); + gch = GCHandle.Alloc(internalDelegate); + } + + /// <summary> + /// Enables this listener so that it reports accessible events. + /// </summary> + public bool Enabled + { + get + { + return enabled; + } + set + { + enabled = value; + updateListener(); + } + } + + /// <summary> + /// The minimal event type to listen to. + /// </summary> + public AccessibleEventType MinimalEventType + { + get { return min; } + set { min = value; updateListener(); } + } + + /// <summary> + /// The maximal event type to listen to. + /// </summary> + public AccessibleEventType MaximalEventType + { + get { return max; } + set { max = value; updateListener(); } + } + + /// <summary> + /// The Process ID to listen to. + /// Default 0 listens to all processes. + /// </summary> + public UInt32 ProcessId + { + get { return processId; } + set { processId = value; updateListener(); } + } + + /// <summary> + /// The Thread ID to listen to. + /// Default 0 listens to all threads. + /// </summary> + public UInt32 ThreadId + { + get { return threadId; } + set { threadId = value; updateListener(); } + } + + private void updateListener() + { + if (handle != IntPtr.Zero) + { + UnhookWinEvent(handle); + handle = IntPtr.Zero; + } + if (enabled) + { + handle = SetWinEventHook(min, max, IntPtr.Zero, internalDelegate, processId, threadId, 0); + } + } + + /// <summary> + /// Releases all resources used by the System.ComponentModel.Component. + /// </summary> + /// <param name="disposing">Whether to dispose managed resources.</param> + protected override void Dispose(bool disposing) + { + if (enabled) + { + enabled = false; + updateListener(); + } + gch.Free(); + base.Dispose(disposing); + } + + private void InternalCallback(IntPtr hWinEventHook, AccessibleEventType eventType, + IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime) + { + if (hWinEventHook != handle) return; + AccessibleEventArgs aea = new AccessibleEventArgs(eventType, hwnd, idObject, idChild, dwEventThread, dwmsEventTime); + if (EventOccurred != null) + EventOccurred(this, aea); + } + + internal static SystemAccessibleObject GetAccessibleObject(AccessibleEventArgs e) + { + IAccessible iacc; + object child; + uint result = AccessibleObjectFromEvent(e.HWnd, e.ObjectID, e.ChildID, out iacc, out child); + if (result != 0) throw new Exception("AccessibleObjectFromPoint returned " + result); + return new SystemAccessibleObject(iacc, (int)child); + } + + #region PInvoke Declarations + + [DllImport("user32.dll")] + private static extern IntPtr SetWinEventHook(AccessibleEventType eventMin, AccessibleEventType eventMax, IntPtr + hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, + uint idThread, uint dwFlags); + + [DllImport("user32.dll")] + static extern bool UnhookWinEvent(IntPtr hWinEventHook); + + private delegate void WinEventDelegate(IntPtr hWinEventHook, AccessibleEventType eventType, + IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime); + + [DllImport("oleacc.dll")] + private static extern uint AccessibleObjectFromEvent(IntPtr hwnd, uint dwObjectID, uint dwChildID, out IAccessible ppacc, [MarshalAs(UnmanagedType.Struct)] out object pvarChild); + + #endregion + } + + /// <summary> + /// Represents the method that will handle accessibility events. + /// </summary> + public delegate void AccessibleEventHandler(object sender, AccessibleEventArgs e); + + /// <summary> + /// Provides data for accessible events. + /// </summary> + public class AccessibleEventArgs : EventArgs + { + private AccessibleEventType eventType; + private IntPtr hWnd; + private uint idObject; + private uint idChild; + private uint dwEventThread; + private uint dwmsEventTime; + + /// <summary> + /// Initializes a new instance of the AccessibleEventArgs class. + /// </summary> + public AccessibleEventArgs(AccessibleEventType eventType, + IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime) + { + this.eventType = eventType; + this.hWnd = hwnd; + this.idObject = idObject; + this.idChild = idChild; + this.dwEventThread = dwEventThread; + this.dwmsEventTime = dwmsEventTime; + } + + /// <summary> + /// Type of this accessible event + /// </summary> + public AccessibleEventType EventType + { + get { return eventType; } + } + + /// <summary> + /// Handle of the affected window, if any. + /// </summary> + public IntPtr HWnd + { + get { return hWnd; } + } + + /// <summary> + /// Object ID. + /// </summary> + public uint ObjectID + { + get { return idObject; } + } + + /// <summary> + /// Child ID. + /// </summary> + public uint ChildID + { + get { return idChild; } + } + + /// <summary> + /// The thread that generated this event. + /// </summary> + public uint Thread + { + get { return dwEventThread; } + } + + /// <summary> + /// Time in milliseconds when the event was generated. + /// </summary> + public uint Time + { + get { return dwmsEventTime; } + } + + /// <summary> + /// The accessible object related to this event. + /// </summary> + public SystemAccessibleObject AccessibleObject + { + get + { + return AccessibleEventListener.GetAccessibleObject(this); + } + } + } + + /// <summary> + /// This enumeration lists known accessible event types. + /// </summary> + public enum AccessibleEventType + { + /// <summary> + /// Sent when a sound is played. Currently nothing is generating this, we + /// 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. + /// </summary> + EVENT_SYSTEM_SOUND = 0x0001, + + /// <summary> + /// Sent when an alert needs to be given to the user. MessageBoxes generate + /// alerts for example. + /// </summary> + EVENT_SYSTEM_ALERT = 0x0002, + + /// <summary> + /// Sent when the foreground (active) window changes, even if it is changing + /// to another window in the same thread as the previous one. + /// </summary> + EVENT_SYSTEM_FOREGROUND = 0x0003, + + /// <summary> + /// Sent when entering into and leaving from menu mode (system, app bar, and + /// track popups). + /// </summary> + EVENT_SYSTEM_MENUSTART = 0x0004, + + /// <summary> + /// Sent when entering into and leaving from menu mode (system, app bar, and + /// track popups). + /// </summary> + EVENT_SYSTEM_MENUEND = 0x0005, + + /// <summary> + /// 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. + /// </summary> + EVENT_SYSTEM_MENUPOPUPSTART = 0x0006, + + /// <summary> + /// 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. + /// </summary> + EVENT_SYSTEM_MENUPOPUPEND = 0x0007, + + + /// <summary> + /// Sent when a window takes the capture and releases the capture. + /// </summary> + EVENT_SYSTEM_CAPTURESTART = 0x0008, + + /// <summary> + /// Sent when a window takes the capture and releases the capture. + /// </summary> + EVENT_SYSTEM_CAPTUREEND = 0x0009, + + /// <summary> + /// Sent when a window enters and leaves move-size dragging mode. + /// </summary> + EVENT_SYSTEM_MOVESIZESTART = 0x000A, + + /// <summary> + /// Sent when a window enters and leaves move-size dragging mode. + /// </summary> + EVENT_SYSTEM_MOVESIZEEND = 0x000B, + + /// <summary> + /// Sent when a window enters and leaves context sensitive help mode. + /// </summary> + EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C, + + /// <summary> + /// Sent when a window enters and leaves context sensitive help mode. + /// </summary> + EVENT_SYSTEM_CONTEXTHELPEND = 0x000D, + + /// <summary> + /// Sent when a window enters and leaves drag drop mode. 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. + /// </summary> + EVENT_SYSTEM_DRAGDROPSTART = 0x000E, + + /// <summary> + /// Sent when a window enters and leaves drag drop mode. 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. + /// </summary> + EVENT_SYSTEM_DRAGDROPEND = 0x000F, + + /// <summary> + /// Sent when a dialog comes up and just before it goes away. + /// </summary> + EVENT_SYSTEM_DIALOGSTART = 0x0010, + + /// <summary> + /// Sent when a dialog comes up and just before it goes away. + /// </summary> + EVENT_SYSTEM_DIALOGEND = 0x0011, + + /// <summary> + /// Sent when beginning and ending the tracking of a scrollbar in a window, + /// and also for scrollbar controls. + /// </summary> + EVENT_SYSTEM_SCROLLINGSTART = 0x0012, + + /// <summary> + /// Sent when beginning and ending the tracking of a scrollbar in a window, + /// and also for scrollbar controls. + /// </summary> + EVENT_SYSTEM_SCROLLINGEND = 0x0013, + + /// <summary> + /// Sent when beginning and ending alt-tab mode with the switch window. + /// </summary> + EVENT_SYSTEM_SWITCHSTART = 0x0014, + + /// <summary> + /// Sent when beginning and ending alt-tab mode with the switch window. + /// </summary> + EVENT_SYSTEM_SWITCHEND = 0x0015, + + /// <summary> + /// Sent when a window minimizes. + /// </summary> + EVENT_SYSTEM_MINIMIZESTART = 0x0016, + + /// <summary> + /// Sent just before a window restores. + /// </summary> + EVENT_SYSTEM_MINIMIZEEND = 0x0017, + + /// <summary> + /// hwnd + ID + idChild is created item + /// </summary> + EVENT_OBJECT_CREATE = 0x8000, + + /// <summary> + /// hwnd + ID + idChild is destroyed item + /// </summary> + EVENT_OBJECT_DESTROY = 0x8001, + + /// <summary> + /// hwnd + ID + idChild is shown item + /// </summary> + EVENT_OBJECT_SHOW = 0x8002, + + /// <summary> + /// hwnd + ID + idChild is hidden item + /// </summary> + EVENT_OBJECT_HIDE = 0x8003, + + /// <summary> + /// hwnd + ID + idChild is parent of zordering children + /// </summary> + EVENT_OBJECT_REORDER = 0x8004, + + /// <summary> + /// hwnd + ID + idChild is focused item + /// </summary> + EVENT_OBJECT_FOCUS = 0x8005, + + /// <summary> + /// hwnd + ID + idChild is selected item (if only one), or idChild is OBJID_WINDOW if complex + /// </summary> + EVENT_OBJECT_SELECTION = 0x8006, + + /// <summary> + /// hwnd + ID + idChild is item added + /// </summary> + EVENT_OBJECT_SELECTIONADD = 0x8007, + + /// <summary> + /// hwnd + ID + idChild is item removed + /// </summary> + EVENT_OBJECT_SELECTIONREMOVE = 0x8008, + + /// <summary> + /// hwnd + ID + idChild is parent of changed selected items + /// </summary> + EVENT_OBJECT_SELECTIONWITHIN = 0x8009, + + /// <summary> + /// hwnd + ID + idChild is item w/ state change + /// </summary> + EVENT_OBJECT_STATECHANGE = 0x800A, + + /// <summary> + /// hwnd + ID + idChild is moved/sized item + /// </summary> + EVENT_OBJECT_LOCATIONCHANGE = 0x800B, + + /// <summary> + /// hwnd + ID + idChild is item w/ name change + /// </summary> + EVENT_OBJECT_NAMECHANGE = 0x800C, + + /// <summary> + /// hwnd + ID + idChild is item w/ desc change + /// </summary> + EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D, + + /// <summary> + /// hwnd + ID + idChild is item w/ value change + /// </summary> + EVENT_OBJECT_VALUECHANGE = 0x800E, + + /// <summary> + /// hwnd + ID + idChild is item w/ new parent + /// </summary> + EVENT_OBJECT_PARENTCHANGE = 0x800F, + + /// <summary> + /// hwnd + ID + idChild is item w/ help change + /// </summary> + EVENT_OBJECT_HELPCHANGE = 0x8010, + + /// <summary> + /// hwnd + ID + idChild is item w/ def action change + /// </summary> + EVENT_OBJECT_DEFACTIONCHANGE = 0x8011, + + /// <summary> + /// hwnd + ID + idChild is item w/ keybd accel change + /// </summary> + EVENT_OBJECT_ACCELERATORCHANGE = 0x8012, + + /// <summary> + /// The lowest possible event value + /// </summary> + EVENT_MIN = 0x00000001, + + /// <summary> + /// The highest possible event value + /// </summary> + EVENT_MAX = 0x7FFFFFFF, + } +} Copied: trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs (from rev 112, trunk/ManagedWinapi/SystemAccessibleObject.cs) =================================================================== --- trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs (rev 0) +++ trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs 2012-07-01 16:06:19 UTC (rev 113) @@ -0,0 +1,708 @@ +/* + * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to + * access native API by managed code. http://mwinapi.sourceforge.net/ + * Copyright (C) 2006 Michael Schierl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. if not, visit + * http://www.gnu.org/licenses/lgpl.html or write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +using System; +using System.Collections.Generic; +using System.Text; +using Accessibility; +using ManagedWinapi.Windows; +using System.Runtime.InteropServices; +using System.Drawing; +using System.Runtime.InteropServices.ComTypes; + +namespace ManagedWinapi.Accessibility +{ + /// <summary> + /// Provides access to the Active Accessibility API. Every <see cref="SystemWindow"/> + /// has one ore more AccessibleObjects attached that provide information about the + /// window to visually impaired people. This information is mainly used by screen + /// readers and other accessibility software.. + /// </summary> + public class SystemAccessibleObject + { + private IAccessible iacc; + private int childID; + + /// <summary> + /// The IAccessible instance of this object (if <see cref="ChildID"/> is zero) + /// or its parent. + /// </summary> + public IAccessible IAccessible { get { return iacc; } } + + /// <summary> + /// The underlying child ID + /// </summary> + public int ChildID { get { return childID; } } + + /// <summary> + /// Create an accessible object from an IAccessible instance and a child ID. + /// </summary> + public SystemAccessibleObject(IAccessible iacc, int childID) + { + if (iacc == null) throw new ArgumentNullException(); + //if (childID < 0) throw new ArgumentException(); + if (childID != 0) + { + try + { + object realChild = iacc.get_accChild(childID); + if (realChild != null) + { + iacc = (IAccessible)realChild; + childID = 0; + } + } + catch (ArgumentException) { } + catch (InvalidCastException) { } + } + this.iacc = iacc; + this.childID = childID; + } + + /// <summary> + /// Gets an accessibility object for given screen coordinates. + /// </summary> + public static SystemAccessibleObject FromPoint(int x, int y) + { + IAccessible iacc; + object ci; + IntPtr result = AccessibleObjectFromPoint(new ManagedWinapi.Windows.POINT(x, y), out iacc, out ci); + if (result != IntPtr.Zero) throw new Exception("AccessibleObjectFromPoint returned " + result.ToInt32()); + return new SystemAccessibleObject(iacc, (int)(ci ?? 0)); + } + + /// <summary> + /// Gets an accessibility object for a given window. + /// </summary> + /// <param name="window">The window</param> + /// <param name="objectID">Which accessibility object to get</param> + /// <returns></returns> + public static SystemAccessibleObject FromWindow(SystemWindow window, AccessibleObjectID objectID) + { + IAccessible iacc = (IAccessible)AccessibleObjectFromWindow(window == null ? IntPtr.Zero : window.HWnd, (uint)objectID, new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}")); + return new SystemAccessibleObject(iacc, 0); + } + + /// <summary> + /// Gets the automation object for a given window. + /// This is a COM object implementing the IDispatch interface, commonly + /// available from Microsoft Office windows. + /// </summary> + /// <param name="window">The window</param> + public static object COMObjectFromWindow(SystemWindow window) + { + return AccessibleObjectFromWindow(window == null ? IntPtr.Zero : window.HWnd, OBJID_NATIVEOM, new Guid("{00020400-0000-0000-C000-000000000046}")); + } + + /// <summary> + /// Gets an accessibility object for the mouse cursor. + /// </summary> + public static SystemAccessibleObject MouseCursor + { + get + { + return FromWindow(null, AccessibleObjectID.OBJID_CURSOR); + } + } + + /// <summary> + /// Gets an accessibility object for the input caret, or + /// <b>null</b> if there is none. + /// </summary> + public static SystemAccessibleObject Caret + { + get + { + try + { + return FromWindow(null, AccessibleObjectID.OBJID_CARET); + } + catch (COMException) + { + return null; + } + } + } + + /// <summary> + /// Convert a role number to a localized string. + /// </summary> + public static string RoleToString(int roleNumber) + { + StringBuilder sb = new StringBuilder(1024); + uint result = GetRoleText((uint)roleNumber, sb, 1024); + if (result == 0) throw new Exception("Invalid role number"); + return sb.ToString(); + } + + /// <summary> + /// Convert a state number (which may include more than one state bit) + /// to a localized string. + /// </summary> + public static String StateToString(int stateNumber) + { + if (stateNumber == 0) return "None"; + int lowBit = stateNumber & -stateNumber; + int restBits = stateNumber - lowBit; + String s1 = StateBitToString(lowBit); + if (restBits == 0) return s1; + return StateToString(restBits) + ", " + s1; + } + + /// <summary> + /// Convert a single state bit to a localized string. + /// </summary> + public static string StateBitToString(int stateBit) + { + StringBuilder sb = new StringBuilder(1024); + uint result = GetStateText((uint)stateBit, sb, 1024); + if (result == 0) throw new Exception("Invalid role number"); + return sb.ToString(); + } + + /// <summary> + /// The description of this accessible object. + /// </summary> + public string Description + { + get + { + try + { + return iacc.get_accDescription(childID); + } + catch (NotImplementedException) + { + return ""; + } + } + } + + /// <summary> + /// The name of this accessible object. + /// </summary> + public string Name + { + get + { + return iacc.get_accName(childID); + } + } + + /// <summary> + /// The role of this accessible object. This can either be an int + /// (for a predefined role) or a string. + /// </summary> + public object Role + { + get + { + return iacc.get_accRole(childID); + } + } + + /// <summary> + /// The role of this accessible object, as an integer. If this role + /// is not predefined, -1 is returned. + /// </summary> + public int RoleIndex + { + get + { + object role = Role; + if (role is int) + { + return (int)role; + } + else + { + return -1; + } + } + } + + /// <summary> + /// The role of this accessible object, as a localized string. + /// </summary> + public string RoleString + { + get + { + object role = Role; + if (role is int) + { + return RoleToString((int)role); + } + else if (role is string) + { + return (string)role; + } + else + { + return role.ToString(); + } + } + } + + /// <summary> + /// The location of this accessible object on screen. This rectangle + /// is the smallest rectangle that includes the whole object, but not + /// every point in the rectangle must be part of the object. + /// </summary> + public Rectangle Location + { + get + { + int x, y, w, h; + iacc.accLocation(out x, out y, out w, out h, childID); + return new Rectangle(x, y, w, h); + + } + } + + /// <summary> + /// The value of this accessible object. + /// </summary> + public string Value + { + get + { + try + { + return iacc.get_accValue(childID); + } + catch (COMException) + { + return null; + } + } + } + + /// <summary> + /// The state of this accessible object. + /// </summary> + public int State + { + get + { + try + { + return (int)iacc.get_accState(childID); + } + catch (COMException) + { + return 0; + } + } + } + + /// <summary> + /// A string representation of the state of this accessible object. + /// </summary> + public string StateString + { + get + { + return StateToString(State); + } + } + + /// <summary> + /// Whether this accessibile object is visible. + /// </summary> + public bool Visible + { + get + { + return (State & 0x8000) == 0; + } + } + + /// <summary> + /// The parent of this accessible object, or <b>null</b> if none exists. + /// </summary> + public SystemAccessibleObject Parent + { + get + { + if (childID != 0) return new SystemAccessibleObject(iacc, 0); + IAccessible p = (IAccessible)iacc.accParent; + if (p == null) return null; + return new SystemAccessibleObject(p, 0); + } + } + + /// <summary> + /// The keyboard shortcut of this accessible object. + /// </summary> + public string KeyboardShortcut + { + get + { + try + { + return iacc.get_accKeyboardShortcut(childID); + } + catch (ArgumentException) { return ""; } + catch (NotImplementedException) { return ""; } + catch (COMException) { return null; } + } + } + + /// <summary> + /// A string describing the default action of this accessible object. + /// For a button, this might be "Press". + /// </summary> + public string DefaultAction + { + get + { + try + { + return iacc.get_accDefaultAction(childID); + } + catch (COMException) { return null; } + } + } + + /// <summary> + /// Perform the default action of this accessible object. + /// </summary> + public void DoDefaultAction() + { + iacc.accDoDefaultAction(ChildID); + } + + /// <summary> + /// Get all objects of this accessible object that are selected. + /// </summary> + public SystemAccessibleObject[] SelectedObjects + { + get + { + if (childID != 0) return new SystemAccessibleObject[0]; + object sel; + try + { + sel = iacc.accSelection; + } + catch (NotImplementedException) + { + return new SystemAccessibleObject[0]; + } + catch (COMException) + { + return new SystemAccessibleObject[0]; + } + if (sel == null) return new SystemAccessibleObject[0]; + if (sel is IEnumVARIANT) + { + IEnumVARIANT e = (IEnumVARIANT)sel; + e.Reset(); + List<SystemAccessibleObject> retval = new List<SystemAccessibleObject>(); + object[] tmp = new object[1]; + while (e.Next(1, tmp, IntPtr.Zero) == 0) + { + if (tmp[0] is int && (int)tmp[0] < 0) break; + retval.Add(ObjectToSAO(tmp[0])); + } + return retval.ToArray(); + } + else + { + if (sel is int && (int)sel < 0) + { + return new SystemAccessibleObject[0]; + } + return new SystemAccessibleObject[] { ObjectToSAO(sel) }; + } + } + } + + private SystemAccessibleObject ObjectToSAO(object obj) + { + if (obj is int) + { + return new SystemAccessibleObject(iacc, (int)obj); + } + else + { + return new SystemAccessibleObject((IAccessible)obj, 0); + } + } + + /// <summary> + /// Get the SystemWindow that owns this accessible object. + /// </summary> + public SystemWindow Window + { + get + { + IntPtr hwnd; + WindowFromAccessibleObject(iacc, out hwnd); + return new SystemWindow(hwnd); + } + } + + /// <summary> + /// Get all child accessible objects. + /// </summary> + public SystemAccessibleObject[] Children + { + get + { + // ID-referenced objects cannot have children + if (childID != 0) return new SystemAccessibleObject[0]; + + int cs = iacc.accChildCount, csReal; + object[] children = new object[cs * 2]; + + uint result = AccessibleChildren(iacc, 0, cs * 2, children, out csReal); + if (result != 0 && result != 1) + return new SystemAccessibleObject[0]; + if (csReal == 1 && children[0] is int && (int)children[0] < 0) + return new SystemAccessibleObject[0]; + List<SystemAccessibleObject> values = new List<SystemAccessibleObject>(); + for (int i = 0; i < children.Length; i++) + { + if (children[i] != null) + { + try + { + values.Add(ObjectToSAO(children[i])); + } + catch (InvalidCastException) { } + } + } + return values.ToArray(); + } + } + + /// <summary> + /// Highlight the accessible object with a red border. + /// </summary> + public void Highlight() + { + Rectangle objectLocation = Location; + SystemWindow window = Window; + Rectangle windowLocation = window.Rectangle; + using (WindowDeviceContext windowDC = window.GetDeviceContext(false)) + { + using (Graphics g = windowDC.CreateGraphics()) + { + g.DrawRectangle(new Pen(Color.Red, 4), objectLocation.X - windowLocation.X, objectLocation.Y - windowLocation.Y, objectLocation.Width, objectLocation.Height); + } + } + } + + #region Equals and HashCode + + /// + public override bool Equals(System.Object obj) + { + if (obj == null) + { + return false; + } + SystemAccessibleObject sao = obj as SystemAccessibleObject; + return Equals(sao); + } + + /// + public bool Equals(SystemAccessibleObject sao) + { + if ((object)sao == null) + { + return false; + } + return childID == sao.childID && DeepEquals(iacc, sao.iacc); + } + + private static bool DeepEquals(IAccessible ia1, IAccessible ia2) + { + if (ia1.Equals(ia2)) return true; + if (Marshal.GetIUnknownForObject(ia1) == Marshal.GetIUnknownForObject(ia2)) return true; + try + { + if (ia1.accChildCount != ia2.accChildCount) return false; + SystemAccessibleObject sa1 = new SystemAccessibleObject(ia1, 0); + SystemAccessibleObject sa2 = new SystemAccessibleObject(ia2, 0); + if (sa1.Window.HWnd != sa2.Window.HWnd) return false; + if (sa1.Location != sa2.Location) return false; + if (sa1.DefaultAction != sa2.DefaultAction) return false; + if (sa1.Description != sa2.Description) return false; + if (sa1.KeyboardShortcut != sa2.KeyboardShortcut) return false; + if (sa1.Name != sa2.Name) return false; + if (!sa1.Role.Equals(sa2.Role)) return false; + if (sa1.State != sa2.State) return false; + if (sa1.Value != sa2.Value) return false; + if (sa1.Visible != sa2.Visible) return false; + if (ia1.accParent == null && ia2.accParent == null) return true; + if (ia1.accParent == null || ia2.accParent == null) return false; + } + catch (COMException) + { + return false; + } + bool de = DeepEquals((IAccessible)ia1.accParent, (IAccessible)ia2.accParent); + return de; + } + + /// + public override int GetHashCode() + { + return childID ^ iacc.GetHashCode(); + } + + /// <summary> + /// Compare two instances of this class for equality. + /// </summary> + public static bool operator ==(SystemAccessibleObject a, SystemAccessibleObject b) + { + if (System.Object.ReferenceEquals(a, b)) + { + return true; + } + if (((object)a == null) || ((object)b == null)) + { + return false; + } + return a.iacc == b.iacc && a.childID == b.childID; + } + + /// <summary> + /// Compare two instances of this class for inequality. + /// </summary> + public static bool operator !=(SystemAccessibleObject a, SystemAccessibleObject b) + { + return !(a == b); + } + + /// + public override string ToString() + { + try + { + return Name + " [" + RoleString + "]"; + } + catch + { + return "??"; + } + } + + #endregion + + #region PInvoke Declarations + + const uint OBJID_NATIVEOM = 0xFFFFFFF0; + + [DllImport("oleacc.dll")] + private static extern IntPtr AccessibleObjectFromPoint(POINT pt, [Out, MarshalAs(UnmanagedType.Interface)] out IAccessible accObj, [Out] out object ChildID); + [DllImport("oleacc.dll")] + private static extern uint GetRoleText(uint dwRole, [Out] StringBuilder lpszRole, uint cchRoleMax); + + [DllImport("oleacc.dll", ExactSpelling = true, PreserveSig = false)] + [return: MarshalAs(UnmanagedType.Interface)] + private static extern object AccessibleObjectFromWindow( + IntPtr hwnd, + uint dwObjectID, + [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid); + + [DllImport("oleacc.dll")] + private static extern uint GetStateText(uint dwStateBit, [Out] StringBuilder lpszStateBit, uint cchStateBitMax); + + [DllImport("oleacc.dll")] + private static extern uint WindowFromAccessibleObject(IAccessible pacc, out IntPtr phwnd); + + [DllImport("oleacc.dll")] + private static extern uint AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [Out] object[] rgvarChildren, out int pcObtained); + + #endregion + } + + /// <summary> + /// This enumeration lists all kinds of accessible objects that can + /// be directly assigned to a window. + /// </summary> + public enum AccessibleObjectID : uint + { + /// <summary> + /// The window itself. + /// </summary> + OBJID_WINDOW = 0x00000000, + + /// <summary> + /// The system menu. + /// </summary> + OBJID_SYSMENU = 0xFFFFFFFF, + + /// <summary> + /// The title bar. + /// </summary> + OBJID_TITLEBAR = 0xFFFFFFFE, + + /// <summary> + /// The menu. + /// </summary> + OBJID_MENU = 0xFFFFFFFD, + + /// <summary> + /// The client area. + /// </summary> + OBJID_CLIENT = 0xFFFFFFFC, + + /// <summary> + /// The vertical scroll bar. + /// </summary> + OBJID_VSCROLL = 0xFFFFFFFB, + + /// <summary> + /// The horizontal scroll bar. + /// </summary> + OBJID_HSCROLL = 0xFFFFFFFA, + + /// <summary> + /// The size grip (part in the lower right corner that + /// makes resizing the window easier). + /// </summary> + OBJID_SIZEGRIP = 0xFFFFFFF9, + + /// <summary> + /// The caret (text cursor). + /// </summary> + OBJID_CARET = 0xFFFFFFF8, + + /// <summary> + /// The mouse cursor. There is only one mouse + /// cursor and it is not assigned to any window. + /// </summary> + OBJID_CURSOR = 0xFFFFFFF7, + + /// <summary> + /// An alert window. + /// </summary> + OBJID_ALERT = 0xFFFFFFF6, + + /// <summary> + /// A sound this window is playing. + /// </summary> + OBJID_SOUND = 0xFFFFFFF5 + } +} Deleted: trunk/ManagedWinapi/AccessibleObjectListener.cs =================================================================== --- trunk/ManagedWinapi/AccessibleObjectListener.cs 2012-04-20 16:24:56 UTC (rev 112) +++ trunk/ManagedWinapi/AccessibleObjectListener.cs 2012-07-01 16:06:19 UTC (rev 113) @@ -1,522 +0,0 @@ -/* - * ManagedWinapi - A collection of .NET components that wrap PInvoke calls to - * access native API by managed code. http://mwinapi.sourceforge.net/ - * Copyright (C) 2006, 2007 Michael Schierl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; see the file COPYING. if not, visit - * http://www.gnu.org/licenses/lgpl.html or write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -using System; -using System.ComponentModel; -using System.Runtime.InteropServices; -using Accessibility; - -namespace ManagedWinapi.Accessibility -{ - /// <summary> - /// Listens to events from the Windows accessibility system. These events are useful - /// if you want to write a screenreader or similar program. - /// </summary> - public class AccessibleEventListener : Component - { - /// <summary> - /// Occurs when an accessible event is received. - /// </summary> - public event AccessibleEventHandler EventOccurred; - - private bool enabled; - private IntPtr handle = IntPtr.Zero; - private AccessibleEventType min = AccessibleEventType.EVENT_MIN; - private AccessibleEventType max = AccessibleEventType.EVENT_MAX; - private WinEventDelegate internalDelegate; - private GCHandle gch; - private UInt32 processId = 0; - private UInt32 threadId = 0; - - /// <summary> - /// Initializes a new instance of this class with the specified container. - /// </summary> - /// <param name="container">The container to add it to.</param> - public AccessibleEventListener(IContainer container) - : this() - { - container.Add(this); - } - - /// <summary> - /// Initializes a new instance of this class. - /// </summary> - public AccessibleEventListener() - { - internalDelegate = new WinEventDelegate(InternalCallback); - gch = GCHandle.Alloc(internalDelegate); - } - - /// <summary> - /// Enables this listener so that it reports accessible events. - /// </summary> - public bool Enabled - { - get - { - return enabled; - } - set - { - enabled = value; - updateListener(); - } - } - - /// <summary> - /// The minimal event type to listen to. - /// </summary> - public AccessibleEventType MinimalEventType - { - get { return min; } - set { min = value; updateListener(); } - } - - /// <summary> - /// The maximal event type to listen to. - /// </summary> - public AccessibleEventType MaximalEventType - { - get { return max; } - set { max = value; updateListener(); } - } - - /// <summary> - /// The Process ID to listen to. - /// Default 0 listens to all processes. - /// </summary> - public UInt32 ProcessId - { - get { return processId; } - set { processId = value; updateListener(); } - } - - /// <summary> - /// The Thread ID to listen to. - /// Default 0 listens to all threads. - /// </summary> - public UInt32 ThreadId - { - get { return threadId; } - set { threadId = value; updateListener(); } - } - - private void updateListener() - { - if (handle != IntPtr.Zero) - { - UnhookWinEvent(handle); - handle = IntPtr.Zero; - } - if (enabled) - { - handle = SetWinEventHook(min, max, IntPtr.Zero, internalDelegate, processId, threadId, 0); - } - } - - /// <summary> - /// Releases all resources used by the System.ComponentModel.Component. - /// </summary> - /// <param name="disposing">Whether to dispose managed resources.</param> - protected override void Dispose(bool disposing) - { - if (enabled) - { - enabled = false; - updateListener(); - } - gch.Free(); - base.Dispose(disposing); - } - - private void InternalCallback(IntPtr hWinEventHook, AccessibleEventType eventType, - IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime) - { - if (hWinEventHook != handle) return; - AccessibleEventArgs aea = new AccessibleEventArgs(eventType, hwnd, idObject, idChild, dwEventThread, dwmsEventTime); - if (EventOccurred != null) - EventOccurred(this, aea); - } - - internal static SystemAccessibleObject GetAccessibleObject(AccessibleEventArgs e) - { - IAccessible iacc; - object child; - uint result = AccessibleObjectFromEvent(e.HWnd, e.ObjectID, e.ChildID, out iacc, out child); - if (result != 0) throw new Exception("AccessibleObjectFromPoint returned " + result); - return new SystemAccessibleObject(iacc, (int)child); - } - - #region PInvoke Declarations - - [DllImport("user32.dll")] - private static extern IntPtr SetWinEventHook(AccessibleEventType eventMin, AccessibleEventType eventMax, IntPtr - hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, - uint idThread, uint dwFlags); - - [DllImport("user32.dll")] - static extern bool UnhookWinEvent(IntPtr hWinEventHook); - - private delegate void WinEventDelegate(IntPtr hWinEventHook, AccessibleEventType eventType, - IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime); - - [DllImport("oleacc.dll")] - private static extern uint AccessibleObjectFromEvent(IntPtr hwnd, uint dwObjectID, uint dwChildID, out IAccessible ppacc, [MarshalAs(UnmanagedType.Struct)] out object pvarChild); - - #endregion - } - - /// <summary> - /// Represents the method that will handle accessibility events. - /// </summary> - public delegate void AccessibleEventHandler(object sender, AccessibleEventArgs e); - - /// <summary> - /// Provides data for accessible events. - /// </summary> - public class AccessibleEventArgs : EventArgs - { - private AccessibleEventType eventType; - private IntPtr hWnd; - private uint idObject; - private uint idChild; - private uint dwEventThread; - private uint dwmsEventTime; - - /// <summary> - /// Initializes a new instance of the AccessibleEventArgs class. - /// </summary> - public AccessibleEventArgs(AccessibleEventType eventType, - IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime) - { - this.eventType = eventType; - this.hWnd = hwnd; - this.idObject = idObject; - this.idChild = idChild; - this.dwEventThread = dwEventThread; - this.dwmsEventTime = dwmsEventTime; - } - - /// <summary> - /// Type of this accessible event - /// </summary> - public AccessibleEventType EventType - { - get { return eventType; } - } - - /// <summary> - /// Handle of the affected window, if any. - /// </summary> - public IntPtr HWnd - { - get { return hWnd; } - } - - /// <summary> - /// Object ID. - /// </summary> - public uint ObjectID - { - get { return idObject; } - } - - /// <summary> - /// Child ID. - /// </summary> - public uint ChildID - { - get { return idChild; } - } - - /// <summary> - /// The thread that generated this event. - /// </summary> - public uint Thread - { - get { return dwEventThread; } - } - - /// <summary> - /// Time in milliseconds when the event was generated. - /// </summary> - public uint Time - { - get { return dwmsEventTime; } - } - - /// <summary> - /// The accessible object related to this event. - /// </summary> - public SystemAccessibleObject AccessibleObject - { - get - { - return AccessibleEventListener.GetAccessibleObject(this); - } - } - } - - /// <summary> - /// This enumeration lists known accessible event types. - /// </summary> - public enum AccessibleEventType - { - /// <summary> - /// Sent when a sound is played. Currently nothing is generating this, we - /// 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. - /// </summary> - EVENT_SYSTEM_SOUND = 0x0001, - - /// <summary> - /// Sent when an alert needs to be given to the user. MessageBoxes generate - /// alerts for example. - /// </summary> - EVENT_SYSTEM_ALERT = 0x0002, - - /// <summary> - /// Sent when the foreground (active) window changes, even if it is changing - /// to another window in the same thread as the previous one. - /// </summary> - EVENT_SYSTEM_FOREGROUND = 0x0003, - - /// <summary> - /// Sent when entering into and leaving from menu mode (system, app bar, and - /// track popups). - /// </summary> - EVENT_SYSTEM_MENUSTART = 0x0004, - - /// <summary> - /// Sent when entering into and leaving from menu mode (system, app bar, and - /// track popups). - /// </summary> - EVENT_SYSTEM_MENUEND = 0x0005, - - /// <summary> - /// 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. - /// </summary> - EVENT_SYSTEM_MENUPOPUPSTART = 0x0006, - - /// <summary> - /// 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. - /// </summary> - EVENT_SYSTEM_MENUPOPUPEND = 0x0007, - - - /// <summary> - /// Sent when a window takes the capture and releases the capture. - /// </summary> - EVENT_SYSTEM_CAPTURESTART = 0x0008, - - /// <summary> - /// Sent when a window takes the capture and releases the capture. - /// </summary> - EVENT_SYSTEM_CAPTUREEND = 0x0009, - - /// <summary> - /// Sent when a window enters and leaves move-size dragging mode. - /// </summary> - EVENT_SYSTEM_MOVESIZESTART = 0x000A, - - /// <summary> - /// Sent when a window enters and leaves move-size dragging mode. - /// </summary> - EVENT_SYSTEM_MOVESIZEEND = 0x000B, - - /// <summary> - /// Sent when a window enters and leaves context sensitive help mode. - /// </summary> - EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C, - - /// <summary> - /// Sent when a window enters and leaves context sensitive help mode. - /// </summary> - EVENT_SYSTEM_CONTEXTHELPEND = 0x000D, - - /// <summary> - /// Sent when a window enters and leaves drag drop mode. 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. - /// </summary> - EVENT_SYSTEM_DRAGDROPSTART = 0x000E, - - /// <summary> - /// Sent when a window enters and leaves drag drop mode. 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. - /// </summary> - EVENT_SYSTEM_DRAGDROPEND = 0x000F, - - /// <summary> - /// Sent when a dialog comes up and just before it goes away. - /// </summary> - EVENT_SYSTEM_DIALOGSTART = 0x0010, - - /// <summary> - /// Sent when a dialog comes up and just before it goes away. - /// </summary> - EVENT_SYSTEM_DIALOGEND = 0x0011, - - /// <summary> - /// Sent when beginning and ending the tracking of a scrollbar in a window, - /// and also for scrollbar controls. - /// </summary> - EVENT_SYSTEM_SCROLLINGSTART = 0x0012, - - /// <summary> - /// Sent when beginning and ending the tracking of a scrollbar in a window, - /// and also for scrollbar controls. - /// </summary> - EVENT_SYSTEM_SCROLLINGEND = 0x0013, - - /// <summary> - /// Sent when beginning and ending alt-tab mode with the switch window. - /// </summary> - EVENT_SYSTEM_SWITCHSTART = 0x0014, - - /// <summary> - /// Sent when beginning and ending alt-tab mode with the switch window. - /// </summary> - EVENT_SYSTEM_SWITCHEND = 0x0015, - - /// <summary> - /// Sent when a window minimizes. - /// </summary> - EVENT_SYSTEM_MINIMIZESTART = 0x0016, - - /// <summary> - /// Sent just before a window restores. - /// </summary> - EVENT_SYSTEM_MINIMIZEEND = 0x0017, - - /// <summary> - /// hwnd + ID + idChild is created item - /// </summary> - EVENT_OBJECT_CREATE = 0x8000, - - /// <summary> - /// hwnd + ID + idChild is destroyed item - /// </summary> - EVENT_OBJECT_DESTROY = 0x8001, - - /// <summary> - /// hwnd + ID + idChild is shown item - /// </summary> - EVENT_OBJECT_SHOW = 0x8002, - - /// <summary> - /// hwnd + ID + idChild is hidden item - /// </summary> - EVENT_OBJECT_HIDE = 0x8003, - - /// <summary> - /// hwnd + ID + idChild is parent of zordering children - /// </summary> - ... [truncated message content] |
From: <dan...@us...> - 2013-07-23 08:17:14
|
Revision: 116 http://sourceforge.net/p/mwinapi/code/116 Author: danielrose Date: 2013-07-23 08:17:11 +0000 (Tue, 23 Jul 2013) Log Message: ----------- Deleted app.config, since it is used for applications, but not for class libraries. Modified Paths: -------------- trunk/ManagedWinapi/ManagedWinapi-2010.csproj trunk/ManagedWinapi/ManagedWinapi.csproj Removed Paths: ------------- trunk/ManagedWinapi/app.config Modified: trunk/ManagedWinapi/ManagedWinapi-2010.csproj =================================================================== --- trunk/ManagedWinapi/ManagedWinapi-2010.csproj 2013-07-23 08:13:36 UTC (rev 115) +++ trunk/ManagedWinapi/ManagedWinapi-2010.csproj 2013-07-23 08:17:11 UTC (rev 116) @@ -131,9 +131,6 @@ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> - <ItemGroup> - <None Include="app.config" /> - </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. Modified: trunk/ManagedWinapi/ManagedWinapi.csproj =================================================================== --- trunk/ManagedWinapi/ManagedWinapi.csproj 2013-07-23 08:13:36 UTC (rev 115) +++ trunk/ManagedWinapi/ManagedWinapi.csproj 2013-07-23 08:17:11 UTC (rev 116) @@ -130,9 +130,6 @@ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> - <ItemGroup> - <None Include="app.config" /> - </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. Deleted: trunk/ManagedWinapi/app.config =================================================================== --- trunk/ManagedWinapi/app.config 2013-07-23 08:13:36 UTC (rev 115) +++ trunk/ManagedWinapi/app.config 2013-07-23 08:17:11 UTC (rev 116) @@ -1,3 +0,0 @@ -<?xml version="1.0"?> -<configuration> -<startup><supportedRuntime version="v2.0.50727"/></startup></configuration> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-01-14 21:43:34
|
Revision: 102 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=102&view=rev Author: schierlm Date: 2011-01-14 21:43:27 +0000 (Fri, 14 Jan 2011) Log Message: ----------- Make the EventDispatchingNativeWindow instance thread static, to make it work as expected in a multithreaded environment Modified Paths: -------------- trunk/ManagedWinapi/EventDispatchingNativeWindow.cs trunk/ManagedWinapi/Hotkey.cs trunk/ManagedWinapi/Mixer.cs Modified: trunk/ManagedWinapi/EventDispatchingNativeWindow.cs =================================================================== --- trunk/ManagedWinapi/EventDispatchingNativeWindow.cs 2011-01-13 21:44:46 UTC (rev 101) +++ trunk/ManagedWinapi/EventDispatchingNativeWindow.cs 2011-01-14 21:43:27 UTC (rev 102) @@ -44,6 +44,7 @@ { private static Object myLock = new Object(); + [ThreadStatic] private static EventDispatchingNativeWindow _instance; /// <summary> Modified: trunk/ManagedWinapi/Hotkey.cs =================================================================== --- trunk/ManagedWinapi/Hotkey.cs 2011-01-13 21:44:46 UTC (rev 101) +++ trunk/ManagedWinapi/Hotkey.cs 2011-01-14 21:43:27 UTC (rev 102) @@ -48,6 +48,7 @@ private Keys _keyCode; private bool _ctrl, _alt, _shift, _windows; private readonly IntPtr hWnd; + private readonly EventDispatchingNativeWindow nativeWindow; /// <summary> /// Initializes a new instance of this class with the specified container. @@ -63,12 +64,13 @@ /// </summary> public Hotkey() { - EventDispatchingNativeWindow.Instance.EventHandler += nw_EventHandler; + nativeWindow = EventDispatchingNativeWindow.Instance; + nativeWindow.EventHandler += nw_EventHandler; lock(myStaticLock) { hotkeyIndex = ++hotkeyCounter; } - hWnd = EventDispatchingNativeWindow.Instance.Handle; + hWnd = nativeWindow.Handle; } /// <summary> @@ -159,7 +161,7 @@ { isDisposed = true; updateHotkey(false); - EventDispatchingNativeWindow.Instance.EventHandler -= nw_EventHandler; + nativeWindow.EventHandler -= nw_EventHandler; base.Dispose(disposing); } Modified: trunk/ManagedWinapi/Mixer.cs =================================================================== --- trunk/ManagedWinapi/Mixer.cs 2011-01-13 21:44:46 UTC (rev 101) +++ trunk/ManagedWinapi/Mixer.cs 2011-01-14 21:43:27 UTC (rev 102) @@ -66,6 +66,7 @@ private MIXERCAPS mc; private IList<DestinationLine> destLines = null; private bool createEvents; + private readonly EventDispatchingNativeWindow nativeWindow; /// <summary> /// Occurs when a control of this mixer changes value. @@ -80,7 +81,8 @@ private Mixer(IntPtr hMixer) { this.hMixer = hMixer; - EventDispatchingNativeWindow.Instance.EventHandler += ednw_EventHandler; + nativeWindow = EventDispatchingNativeWindow.Instance; + nativeWindow.EventHandler += ednw_EventHandler; mixerGetDevCapsA(hMixer, ref mc, Marshal.SizeOf(mc)); } @@ -188,7 +190,7 @@ if (hMixer.ToInt32() != 0) { mixerClose(hMixer); - EventDispatchingNativeWindow.Instance.EventHandler -= ednw_EventHandler; + nativeWindow.EventHandler -= ednw_EventHandler; hMixer = IntPtr.Zero; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-01-22 20:07:54
|
Revision: 104 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=104&view=rev Author: schierlm Date: 2011-01-22 20:07:48 +0000 (Sat, 22 Jan 2011) Log Message: ----------- Fix OverflowException on x64 architecture Modified Paths: -------------- trunk/ManagedWinapi/Properties/AssemblyInfo.cs trunk/ManagedWinapi/SystemWindow.cs Modified: trunk/ManagedWinapi/Properties/AssemblyInfo.cs =================================================================== --- trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2011-01-14 21:55:15 UTC (rev 103) +++ trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2011-01-22 20:07:48 UTC (rev 104) @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.3.0.1")] -[assembly: AssemblyFileVersion("0.3.0.1")] +[assembly: AssemblyVersion("0.3.0.2")] +[assembly: AssemblyFileVersion("0.3.0.2")] Modified: trunk/ManagedWinapi/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/SystemWindow.cs 2011-01-14 21:55:15 UTC (rev 103) +++ trunk/ManagedWinapi/SystemWindow.cs 2011-01-22 20:07:48 UTC (rev 104) @@ -625,7 +625,7 @@ { get { - return (WindowStyleFlags)GetWindowLongPtr(_hwnd, (int)(GWL.GWL_STYLE)); + return unchecked((WindowStyleFlags)GetWindowLongPtr(_hwnd, (int)(GWL.GWL_STYLE)).ToInt64()); } set { @@ -641,7 +641,7 @@ { get { - return (WindowExStyleFlags)GetWindowLongPtr(_hwnd, (int)(GWL.GWL_EXSTYLE)); + return unchecked((WindowExStyleFlags)GetWindowLongPtr(_hwnd, (int)(GWL.GWL_EXSTYLE)).ToInt64()); } set { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-02-14 19:54:12
|
Revision: 107 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=107&view=rev Author: schierlm Date: 2011-02-14 19:54:06 +0000 (Mon, 14 Feb 2011) Log Message: ----------- - Highlight current rectangle while doing a scrolling screenshot Modified Paths: -------------- trunk/ManagedWinapi/Properties/AssemblyInfo.cs trunk/ManagedWinapi/Screenshot.cs Modified: trunk/ManagedWinapi/Properties/AssemblyInfo.cs =================================================================== --- trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2011-02-01 17:32:55 UTC (rev 106) +++ trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2011-02-14 19:54:06 UTC (rev 107) @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.3.0.2")] -[assembly: AssemblyFileVersion("0.3.0.2")] +[assembly: AssemblyVersion("0.3.0.3")] +[assembly: AssemblyFileVersion("0.3.0.3")] Modified: trunk/ManagedWinapi/Screenshot.cs =================================================================== --- trunk/ManagedWinapi/Screenshot.cs 2011-02-01 17:32:55 UTC (rev 106) +++ trunk/ManagedWinapi/Screenshot.cs 2011-02-14 19:54:06 UTC (rev 107) @@ -227,7 +227,7 @@ public static Bitmap TakeVerticalScrollingScreenshot(Point scrollPoint, Rectangle rect, Point? clickPoint) { int scrollCount; - return TakeScrollingScreenshot(scrollPoint, rect, clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => TakeScreenshot(r, false, null), out scrollCount); + return TakeScrollingScreenshot(scrollPoint, rect, clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => TakeScreenshot(r, false, null), r => HighlightRect(r), out scrollCount); } /// <summary> @@ -256,12 +256,13 @@ public static Bitmap TakeHorizontalScrollingScreenshot(Point scrollPoint, Rectangle rect, Point? clickPoint) { int scrollCount; - return FlipRotate(TakeScrollingScreenshot(new Point(scrollPoint.Y, scrollPoint.X), FlipRotate(rect), clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => FlipRotate(TakeScreenshot(FlipRotate(r), false, null)), out scrollCount)); + return FlipRotate(TakeScrollingScreenshot(new Point(scrollPoint.Y, scrollPoint.X), FlipRotate(rect), clickPoint.HasValue ? clickPoint.Value : scrollPoint, clickPoint.HasValue, r => FlipRotate(TakeScreenshot(FlipRotate(r), false, null)), r => HighlightRect(FlipRotate(r)), out scrollCount)); } private delegate Bitmap ScreenshotFunction(Rectangle rect); + private delegate void HighlightFunction(Rectangle rect); - private static Bitmap TakeScrollingScreenshot(Point centerPoint, Rectangle rect, Point mousePoint, bool click, ScreenshotFunction screenshot, out int scrollCount) + private static Bitmap TakeScrollingScreenshot(Point centerPoint, Rectangle rect, Point mousePoint, bool click, ScreenshotFunction screenshot, HighlightFunction highlight, out int scrollCount) { scrollCount = 0; Cursor.Position = mousePoint; @@ -282,6 +283,7 @@ KeyboardKey.InjectMouseEvent(0x0800, 0, 0, unchecked((uint)-120), UIntPtr.Zero); } Application.DoEvents(); + highlight(rect); Bitmap nextPart = screenshot(rect); int scrollHeight = AppendBelow(buffer, usedHeight, nextPart, false); foreach (int delay in new int[] { 0, 2, 10, 100, 200, 1000 }) @@ -290,6 +292,7 @@ break; Thread.Sleep(delay); Application.DoEvents(); + highlight(rect); nextPart = screenshot(rect); scrollHeight = AppendBelow(buffer, usedHeight, nextPart, false); } @@ -308,6 +311,7 @@ if (scrollHeight == -1) { CropToSimilarRange(centerPoint, ref rect, ref buffer, ref usedHeight, ref nextPart); + highlight(rect); scrollHeight = AppendBelow(buffer, usedHeight, nextPart, false); } if (scrollHeight <= 0) @@ -394,7 +398,7 @@ int pixel = nextPartPixels[x, y]; if (bufferPixels[x, y] != pixel) { - int score = 1000 / (Math.Abs(relX - x) + Math.Abs(relY - y)+1 ) + 1; + int score = 1000 / (Math.Abs(relX - x) + Math.Abs(relY - y) + 1) + 1; for (int scrollHeight = 1; scrollHeight < Math.Min(scrollScores.Length, rect.Height - y); scrollHeight++) { if (bufferPixels[x, y + scrollHeight] == pixel) @@ -594,6 +598,18 @@ return result; } + private static void HighlightRect(Rectangle rect) + { + SystemWindow window = SystemWindow.DesktopWindow; + using (WindowDeviceContext windowDC = window.GetDeviceContext(false)) + { + using (Graphics g = windowDC.CreateGraphics()) + { + g.DrawRectangle(Pens.Blue, rect.X - 1, rect.Y - 1, rect.Width + 2, rect.Height + 2); + } + } + } + private static Bitmap FlipRotate(Bitmap original) { Bitmap result = new Bitmap(original.Height, original.Width); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2011-07-14 18:26:52
|
Revision: 109 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=109&view=rev Author: schierlm Date: 2011-07-14 18:26:46 +0000 (Thu, 14 Jul 2011) Log Message: ----------- Replace System.Windows.Forms.Message structure by custom structure which correctly marshals the time and POINT fields. Keep the old delegate and methods as obsolete ones to not break compatibility (thanks to Daniel Rose). Modified Paths: -------------- trunk/ManagedWinapi/Hook.cs trunk/ManagedWinapi/JournalHook.cs trunk/ManagedWinapi/PInvokeTypes.cs Modified: trunk/ManagedWinapi/Hook.cs =================================================================== --- trunk/ManagedWinapi/Hook.cs 2011-07-13 17:24:53 UTC (rev 108) +++ trunk/ManagedWinapi/Hook.cs 2011-07-14 18:26:46 UTC (rev 109) @@ -26,6 +26,7 @@ using System.Diagnostics; using System.Reflection; using System.Threading; +using ManagedWinapi.Windows; namespace ManagedWinapi.Hooks { @@ -226,20 +227,40 @@ public class LocalMessageHook : Hook { /// <summary> - /// Called when a message has been intercepted. + /// Called when a message has been intercepted. Since this callback uses an incorrect + /// <see cref="System.Windows.Forms.Message"/> marshalling, it has been replaced by the + /// <see cref="MSGOccurred"/> event. /// </summary> + [Obsolete("Use MSGOccurred instead")] public event MessageCallback MessageOccurred; /// <summary> - /// Represents a method that handles a message from a message hook. + /// Represents a method that handles a message from a message hook. Since this callback + /// uses an incorrect <see cref="System.Windows.Forms.Message"/> marshalling, it has + /// been replaced by the <see cref="MSGCallback"/> event. /// </summary> /// <param name="msg"></param> + [Obsolete("Use MSGCallback instead")] public delegate void MessageCallback(Message msg); /// <summary> - /// Creates a local message hook and hooks it. + /// Called when a message has been intercepted. /// </summary> + public event MSGCallback MSGOccurred; + + /// <summary> + /// Represents a method that handles a message from a message hook. + /// </summary> + /// <param name="msg"></param> + public delegate void MSGCallback(MSG msg); + + /// <summary> + /// Creates a local message hook and hooks it. Since this constructor + /// uses an incorrect <see cref="System.Windows.Forms.Message"/> marshalling, it has + /// been replaced by constructor taking a <see cref="MSGCallback"/>. + /// </summary> /// <param name="callback"></param> + [Obsolete] public LocalMessageHook(MessageCallback callback) : this() { @@ -248,6 +269,17 @@ } /// <summary> + /// Creates a local message hook and hooks it. + /// </summary> + /// <param name="callback"></param> + public LocalMessageHook(MSGCallback callback) + : this() + { + this.MSGOccurred = callback; + StartHook(); + } + + /// <summary> /// Creates a local message hook. /// </summary> public LocalMessageHook() @@ -260,9 +292,14 @@ { if (code == HC_ACTION) { - Message msg = (Message)Marshal.PtrToStructure(lParam, typeof(Message)); + if (MSGOccurred != null) + { + MSG msg = (MSG)Marshal.PtrToStructure(lParam, typeof(MSG)); + MSGOccurred(msg); + } if (MessageOccurred != null) { + Message msg = (Message)Marshal.PtrToStructure(lParam, typeof(MSG)); MessageOccurred(msg); } } Modified: trunk/ManagedWinapi/JournalHook.cs =================================================================== --- trunk/ManagedWinapi/JournalHook.cs 2011-07-13 17:24:53 UTC (rev 108) +++ trunk/ManagedWinapi/JournalHook.cs 2011-07-14 18:26:46 UTC (rev 109) @@ -22,6 +22,7 @@ using System.Text; using System.ComponentModel; using System.Runtime.InteropServices; +using ManagedWinapi.Windows; namespace ManagedWinapi.Hooks { @@ -45,12 +46,12 @@ : base(type, true, false) { lmh = new LocalMessageHook(); - lmh.MessageOccurred += new LocalMessageHook.MessageCallback(lmh_Callback); + lmh.MSGOccurred += new LocalMessageHook.MSGCallback(lmh_Callback); } - private void lmh_Callback(System.Windows.Forms.Message msg) + private void lmh_Callback(MSG msg) { - if (msg.Msg == WM_CANCELJOURNAL) + if (msg.message == WM_CANCELJOURNAL) { hooked = false; lmh.Unhook(); Modified: trunk/ManagedWinapi/PInvokeTypes.cs =================================================================== --- trunk/ManagedWinapi/PInvokeTypes.cs 2011-07-13 17:24:53 UTC (rev 108) +++ trunk/ManagedWinapi/PInvokeTypes.cs 2011-07-14 18:26:46 UTC (rev 109) @@ -157,4 +157,40 @@ #endregion } + /// <summary> + /// The Win32 MSG structure. + /// </summary> + [StructLayout(LayoutKind.Sequential)] + public struct MSG + { + /// <summary> + /// The window handle of the message. + /// </summary> + public IntPtr hwnd; + + /// <summary> + /// The ID number for the message. + /// </summary> + public int message; + + /// <summary> + /// The WParam of the message. + /// </summary> + public IntPtr wParam; + + /// <summary> + /// The LParam of the message. + /// </summary> + public IntPtr lParam; + + /// <summary> + /// The time of the message. + /// </summary> + public int time; + + /// <summary> + /// The POINT of the message + /// </summary> + public POINT pt; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sch...@us...> - 2012-04-20 16:25:05
|
Revision: 112 http://mwinapi.svn.sourceforge.net/mwinapi/?rev=112&view=rev Author: schierlm Date: 2012-04-20 16:24:56 +0000 (Fri, 20 Apr 2012) Log Message: ----------- - Detect ListView/TreeView by ClassName if empty - Speed up ListView grabbing by caching the SystemWindow.Process object [thanks to Yusufi Bharmal for the suggestions] Modified Paths: -------------- trunk/ManagedWinapi/Contents/ListParser.cs trunk/ManagedWinapi/SystemListView.cs trunk/ManagedWinapi/SystemTreeView.cs trunk/ManagedWinapi/SystemWindow.cs Modified: trunk/ManagedWinapi/Contents/ListParser.cs =================================================================== --- trunk/ManagedWinapi/Contents/ListParser.cs 2012-01-03 21:56:22 UTC (rev 111) +++ trunk/ManagedWinapi/Contents/ListParser.cs 2012-04-20 16:24:56 UTC (rev 112) @@ -206,14 +206,14 @@ { uint LVM_GETITEMCOUNT = (0x1000 + 4); int cnt = sw.SendGetMessage(LVM_GETITEMCOUNT); - return cnt != 0; + return cnt != 0 || sw.ClassName == "SysListView32"; } internal override WindowContent ParsePreviewContent(SystemWindow sw) { uint LVM_GETITEMCOUNT = (0x1000 + 4); int cnt = sw.SendGetMessage(LVM_GETITEMCOUNT); - if (cnt == 0) throw new Exception(); + if (cnt == 0 && sw.ClassName != "SysListView32") throw new Exception(); SystemAccessibleObject o = SystemAccessibleObject.FromWindow(sw, AccessibleObjectID.OBJID_CLIENT); if (o.RoleIndex == 33) { @@ -229,7 +229,7 @@ { uint LVM_GETITEMCOUNT = (0x1000 + 4); int cnt = sw.SendGetMessage(LVM_GETITEMCOUNT); - if (cnt == 0) throw new Exception(); + if (cnt == 0 && sw.ClassName != "SysListView32") throw new Exception(); try { SystemListView slv = SystemListView.FromSystemWindow(sw); @@ -410,7 +410,7 @@ internal override bool CanParseContent(SystemWindow sw) { int cnt = sw.SendGetMessage(TVM_GETCOUNT, 0); - return cnt != 0; + return cnt != 0 || sw.ClassName == "SysTreeView32"; } internal override WindowContent ParsePreviewContent(SystemWindow sw) Modified: trunk/ManagedWinapi/SystemListView.cs =================================================================== --- trunk/ManagedWinapi/SystemListView.cs 2012-01-03 21:56:22 UTC (rev 111) +++ trunk/ManagedWinapi/SystemListView.cs 2012-04-20 16:24:56 UTC (rev 112) @@ -36,7 +36,7 @@ /// </summary> public static SystemListView FromSystemWindow(SystemWindow sw) { - if (sw.SendGetMessage(LVM_GETITEMCOUNT) == 0) return null; + if (sw.SendGetMessage(LVM_GETITEMCOUNT) == 0 && sw.ClassName != "SysListView32") return null; return new SystemListView(sw); } Modified: trunk/ManagedWinapi/SystemTreeView.cs =================================================================== --- trunk/ManagedWinapi/SystemTreeView.cs 2012-01-03 21:56:22 UTC (rev 111) +++ trunk/ManagedWinapi/SystemTreeView.cs 2012-04-20 16:24:56 UTC (rev 112) @@ -36,7 +36,7 @@ /// </summary> public static SystemTreeView FromSystemWindow(SystemWindow sw) { - if (sw.SendGetMessage(TVM_GETCOUNT) == 0) return null; + if (sw.SendGetMessage(TVM_GETCOUNT) == 0 && sw.ClassName != "SysTreeView32") return null; return new SystemTreeView(sw); } Modified: trunk/ManagedWinapi/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/SystemWindow.cs 2012-01-03 21:56:22 UTC (rev 111) +++ trunk/ManagedWinapi/SystemWindow.cs 2012-04-20 16:24:56 UTC (rev 112) @@ -786,6 +786,8 @@ return IsChild(ancestor._hwnd, _hwnd); } + private Process _cachedProcess = null; + /// <summary> /// The process which created this window. /// </summary> @@ -793,9 +795,13 @@ { get { - int pid; - GetWindowThreadProcessId(HWnd, out pid); - return Process.GetProcessById(pid); + if (_cachedProcess == null) + { + int pid; + GetWindowThreadProcessId(HWnd, out pid); + _cachedProcess = Process.GetProcessById(pid); + } + return _cachedProcess; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2013-07-23 08:31:58
|
Revision: 117 http://sourceforge.net/p/mwinapi/code/117 Author: danielrose Date: 2013-07-23 08:31:55 +0000 (Tue, 23 Jul 2013) Log Message: ----------- Marked the assembly as CLS-compliant. Marked all places where this is not the case (such as by using uint) explicitly as not CLS-compliant. Modified Paths: -------------- trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs trunk/ManagedWinapi/Audio/Mixer/Mixer.cs trunk/ManagedWinapi/ExtendedFileInfo.cs trunk/ManagedWinapi/Hooks/JournalHook.cs trunk/ManagedWinapi/Hooks/LowLevelHook.cs trunk/ManagedWinapi/KeyboardKey.cs trunk/ManagedWinapi/PrivilegedActions.cs trunk/ManagedWinapi/Properties/AssemblyInfo.cs trunk/ManagedWinapi/Windows/SystemListView.cs trunk/ManagedWinapi/Windows/SystemWindow.cs Modified: trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs =================================================================== --- trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Accessibility/AccessibleObjectListener.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -101,6 +101,7 @@ /// The Process ID to listen to. /// Default 0 listens to all processes. /// </summary> + [CLSCompliant(false)] public UInt32 ProcessId { get { return processId; } @@ -111,6 +112,7 @@ /// The Thread ID to listen to. /// Default 0 listens to all threads. /// </summary> + [CLSCompliant(false)] public UInt32 ThreadId { get { return threadId; } @@ -202,6 +204,7 @@ /// <summary> /// Initializes a new instance of the AccessibleEventArgs class. /// </summary> + [CLSCompliant(false)] public AccessibleEventArgs(AccessibleEventType eventType, IntPtr hwnd, uint idObject, uint idChild, uint dwEventThread, uint dwmsEventTime) { @@ -232,6 +235,7 @@ /// <summary> /// Object ID. /// </summary> + [CLSCompliant(false)] public uint ObjectID { get { return idObject; } @@ -240,6 +244,7 @@ /// <summary> /// Child ID. /// </summary> + [CLSCompliant(false)] public uint ChildID { get { return idChild; } @@ -248,6 +253,7 @@ /// <summary> /// The thread that generated this event. /// </summary> + [CLSCompliant(false)] public uint Thread { get { return dwEventThread; } @@ -256,6 +262,7 @@ /// <summary> /// Time in milliseconds when the event was generated. /// </summary> + [CLSCompliant(false)] public uint Time { get { return dwmsEventTime; } Modified: trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs =================================================================== --- trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Accessibility/SystemAccessibleObject.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -93,6 +93,7 @@ /// <param name="window">The window</param> /// <param name="objectID">Which accessibility object to get</param> /// <returns></returns> + [CLSCompliant(false)] public static SystemAccessibleObject FromWindow(SystemWindow window, AccessibleObjectID objectID) { IAccessible iacc = (IAccessible)AccessibleObjectFromWindow(window == null ? IntPtr.Zero : window.HWnd, (uint)objectID, new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}")); @@ -641,6 +642,7 @@ /// This enumeration lists all kinds of accessible objects that can /// be directly assigned to a window. /// </summary> + [CLSCompliant(false)] public enum AccessibleObjectID : uint { /// <summary> Modified: trunk/ManagedWinapi/Audio/Mixer/Mixer.cs =================================================================== --- trunk/ManagedWinapi/Audio/Mixer/Mixer.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Audio/Mixer/Mixer.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -35,6 +35,7 @@ /// <summary> /// Gets the number of available mixers in this system. /// </summary> + [CLSCompliant(false)] public static uint MixerCount { get @@ -48,6 +49,7 @@ /// </summary> /// <param name="index">The zero-based index of this mixer.</param> /// <returns>A reference to this mixer.</returns> + [CLSCompliant(false)] public static Mixer OpenMixer(uint index) { if (index < 0 || index > MixerCount) Modified: trunk/ManagedWinapi/ExtendedFileInfo.cs =================================================================== --- trunk/ManagedWinapi/ExtendedFileInfo.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/ExtendedFileInfo.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -106,6 +106,7 @@ /// Get the size a file requires on disk. This takes NTFS /// compression into account. /// </summary> + [CLSCompliant(false)] public static ulong GetPhysicalFileSize(string filename) { uint high; @@ -125,6 +126,7 @@ /// <summary> /// Get the cluster size for the filesystem that contains the given file. /// </summary> + [CLSCompliant(false)] public static uint GetClusterSize(string filename) { uint sectors, bytes, dummy; Modified: trunk/ManagedWinapi/Hooks/JournalHook.cs =================================================================== --- trunk/ManagedWinapi/Hooks/JournalHook.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Hooks/JournalHook.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -117,6 +117,7 @@ /// <summary> /// Creates a new journal message. /// </summary> + [CLSCompliant(false)] public JournalMessage(IntPtr hWnd, uint message, uint paramL, uint paramH, uint time) { msg = new JournalHook.EVENTMSG(); @@ -135,16 +136,19 @@ /// <summary> /// The message. /// </summary> + [CLSCompliant(false)] public uint Message { get { return msg.message; } } /// <summary> /// The first parameter of the message. /// </summary> + [CLSCompliant(false)] public uint ParamL { get { return msg.paramL; } } /// <summary> /// The second parameter of the message. /// </summary> + [CLSCompliant(false)] public uint ParamH { get { return msg.paramH; } } /// <summary> Modified: trunk/ManagedWinapi/Hooks/LowLevelHook.cs =================================================================== --- trunk/ManagedWinapi/Hooks/LowLevelHook.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Hooks/LowLevelHook.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -423,6 +423,7 @@ /// <summary> /// Mouse event flags needed to replay this message. /// </summary> + [CLSCompliant(false)] public uint MouseEventFlags { get @@ -534,6 +535,7 @@ /// <summary> /// Flags needed to replay this event. /// </summary> + [CLSCompliant(false)] public uint KeyboardEventFlags { get Modified: trunk/ManagedWinapi/KeyboardKey.cs =================================================================== --- trunk/ManagedWinapi/KeyboardKey.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/KeyboardKey.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -123,6 +123,7 @@ /// Inject a keyboard event into the event loop, as if the user performed /// it with his keyboard. /// </summary> + [CLSCompliant(false)] public static void InjectKeyboardEvent(Keys key, byte scanCode, uint flags, UIntPtr extraInfo) { keybd_event((byte)key, scanCode, flags, extraInfo); @@ -132,6 +133,7 @@ /// Inject a mouse event into the event loop, as if the user performed /// it with his mouse. /// </summary> + [CLSCompliant(false)] public static void InjectMouseEvent(uint flags, uint dx, uint dy, uint data, UIntPtr extraInfo) { mouse_event(flags, dx, dy, data, extraInfo); Modified: trunk/ManagedWinapi/PrivilegedActions.cs =================================================================== --- trunk/ManagedWinapi/PrivilegedActions.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/PrivilegedActions.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -14,6 +14,7 @@ /// <summary> /// Shutdown the system. /// </summary> + [CLSCompliant(false)] public static void ShutDown(ShutdownAction action) { ShutDown(action, ShutdownForceMode.NoForce); @@ -22,6 +23,7 @@ /// <summary> /// Shutdown the system. /// </summary> + [CLSCompliant(false)] public static void ShutDown(ShutdownAction action, ShutdownForceMode forceMode) { ApiHelper.FailIfZero(ExitWindowsEx((uint)action | (uint)forceMode, SHTDN_REASON_FLAG_PLANNED)); @@ -70,6 +72,7 @@ /// <summary> /// Actions that can be performed at shutdown. /// </summary> + [CLSCompliant(false)] public enum ShutdownAction : uint { /// <summary> @@ -103,6 +106,7 @@ /// Whether shutdown should be forced if an application cancels it /// or is hung. /// </summary> + [CLSCompliant(false)] public enum ShutdownForceMode : uint { /// <summary> Modified: trunk/ManagedWinapi/Properties/AssemblyInfo.cs =================================================================== --- trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Properties/AssemblyInfo.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -33,3 +34,5 @@ // by using the '*' as shown below: [assembly: AssemblyVersion("0.3.0.3")] [assembly: AssemblyFileVersion("0.3.0.3")] + +[assembly: CLSCompliant(true)] Modified: trunk/ManagedWinapi/Windows/SystemListView.cs =================================================================== --- trunk/ManagedWinapi/Windows/SystemListView.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Windows/SystemListView.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -209,6 +209,7 @@ /// <summary> /// State bits of this item. /// </summary> + [CLSCompliant(false)] public uint State { get { return state; } } /// <summary> Modified: trunk/ManagedWinapi/Windows/SystemWindow.cs =================================================================== --- trunk/ManagedWinapi/Windows/SystemWindow.cs 2013-07-23 08:17:11 UTC (rev 116) +++ trunk/ManagedWinapi/Windows/SystemWindow.cs 2013-07-23 08:31:55 UTC (rev 117) @@ -176,6 +176,7 @@ /// Extended Window Style Flags. The original constants started with WS_EX_. /// </summary> /// <seealso cref="SystemWindow.ExtendedStyle"/> + [CLSCompliant(false)] [Flags] public enum WindowExStyleFlags : uint { @@ -637,6 +638,7 @@ /// <summary> /// This window's extended style flags. /// </summary> + [CLSCompliant(false)] public WindowExStyleFlags ExtendedStyle { get This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |