I am developing an add in for excel. At some point, I can receive async events. I need to be able to show the Excel window if hidden on these events.
I am able to store the Hwnd property, which I believe must be an immutable int/reference to identify my Excel window.
Can someone elaborate on this Hwnd ? and explain how I can show a hidden window from C# using it ?
Thanks in advance folks ;)
UPDATE : shortly, that was the piece of code that sorted my problems :
/// <summary>Enumeration of the different ways of showing a window using
/// ShowWindow</summary>
private enum WindowShowStyle : uint
{
/// <summary>Hides the window and activates another window.</summary>
/// <remarks>See SW_HIDE</remarks>
Hide = 0,
/// <summary>Activates and displays a window. If the window is minimized
/// or maximized, the system restores it to its original size and
/// position. An application should specify this flag when displaying
/// the window for the first time.</summary>
/// <remarks>See SW_SHOWNORMAL</remarks>
ShowNormal = 1,
/// <summary>Activates the window and displays it as a minimized window.</summary>
/// <remarks>See SW_SHOWMINIMIZED</remarks>
ShowMinimized = 2,
/// <summary>Activates the window and displays it as a maximized window.</summary>
/// <remarks>See SW_SHOWMAXIMIZED</remarks>
ShowMaximized = 3,
/// <summary>Maximizes the specified window.</summary>
/// <remarks>See SW_MAXIMIZE</remarks>
Maximize = 3,
/// <summary>Displays a window in its most recent size and position.
/// This value is similar to "ShowNormal", except the window is not
/// actived.</summary>
/// <remarks>See SW_SHOWNOACTIVATE</remarks>
ShowNormalNoActivate = 4,
/// <summary>Activates the window and displays it in its current size
/// and position.</summary>
/// <remarks>See SW_SHOW</remarks>
Show = 5,
/// <summary>Minimizes the specified window and activates the next
/// top-level window in the Z order.</summary>
/// <remarks>See SW_MINIMIZE</remarks>
Minimize = 6,
/// <summary>Displays the window as a minimized window. This value is
/// similar to "ShowMinimized", except the window is not activated.</summary>
/// <remarks>See SW_SHOWMINNOACTIVE</remarks>
ShowMinNoActivate = 7,
/// <summary>Displays the window in its current size and position. This
/// value is similar to "Show", except the window is not activated.</summary>
/// <remarks>See SW_SHOWNA</remarks>
ShowNoActivate = 8,
/// <summary>Activates and displays the window. If the window is
/// minimized or maximized, the system restores it to its original size
/// and position. An application should specify this flag when restoring
/// a minimized window.</summary>
/// <remarks>See SW_RESTORE</remarks>
Restore = 9,
/// <summary>Sets the show state based on the SW_ value specified in the
/// STARTUPINFO structure passed to the CreateProcess function by the
/// program that started the application.</summary>
/// <remarks>See SW_SHOWDEFAULT</remarks>
ShowDefault = 10,
/// <summary>Windows 2000/XP: Minimizes a window, even if the thread
/// that owns the window is hung. This flag should only be used when
/// minimizing windows from a different thread.</summary>
/// <remarks>See SW_FORCEMINIMIZE</remarks>
ForceMinimized = 11
}
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);
static void ContentClick(object obj, EventArgs ea)
{
Microsoft.Office.Interop.Excel.Application oExcelApp = (Microsoft.Office.Interop.Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
oExcelApp.Visible = true;
ShowWindow( (System.IntPtr) Globals.ThisWorkbook.Application.Hwnd, WindowShowStyle.ShowMaximized);
}
hWnd means Window Handle. It's an identifying handle for the window instance.
As for showing it, you could use the user32.ShowWindow API. Here's the P/Invoke signature, courtesy of pinvoke.net:
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
And here's the ShowWindowCommands enum:
/// <summary>Enumeration of the different ways of showing a window using
/// ShowWindow</summary>
private enum WindowShowStyle : uint
{
/// <summary>Hides the window and activates another window.</summary>
/// <remarks>See SW_HIDE</remarks>
Hide = 0,
/// <summary>Activates and displays a window. If the window is minimized
/// or maximized, the system restores it to its original size and
/// position. An application should specify this flag when displaying
/// the window for the first time.</summary>
/// <remarks>See SW_SHOWNORMAL</remarks>
ShowNormal = 1,
/// <summary>Activates the window and displays it as a minimized window.</summary>
/// <remarks>See SW_SHOWMINIMIZED</remarks>
ShowMinimized = 2,
/// <summary>Activates the window and displays it as a maximized window.</summary>
/// <remarks>See SW_SHOWMAXIMIZED</remarks>
ShowMaximized = 3,
/// <summary>Maximizes the specified window.</summary>
/// <remarks>See SW_MAXIMIZE</remarks>
Maximize = 3,
/// <summary>Displays a window in its most recent size and position.
/// This value is similar to "ShowNormal", except the window is not
/// actived.</summary>
/// <remarks>See SW_SHOWNOACTIVATE</remarks>
ShowNormalNoActivate = 4,
/// <summary>Activates the window and displays it in its current size
/// and position.</summary>
/// <remarks>See SW_SHOW</remarks>
Show = 5,
/// <summary>Minimizes the specified window and activates the next
/// top-level window in the Z order.</summary>
/// <remarks>See SW_MINIMIZE</remarks>
Minimize = 6,
/// <summary>Displays the window as a minimized window. This value is
/// similar to "ShowMinimized", except the window is not activated.</summary>
/// <remarks>See SW_SHOWMINNOACTIVE</remarks>
ShowMinNoActivate = 7,
/// <summary>Displays the window in its current size and position. This
/// value is similar to "Show", except the window is not activated.</summary>
/// <remarks>See SW_SHOWNA</remarks>
ShowNoActivate = 8,
/// <summary>Activates and displays the window. If the window is
/// minimized or maximized, the system restores it to its original size
/// and position. An application should specify this flag when restoring
/// a minimized window.</summary>
/// <remarks>See SW_RESTORE</remarks>
Restore = 9,
/// <summary>Sets the show state based on the SW_ value specified in the
/// STARTUPINFO structure passed to the CreateProcess function by the
/// program that started the application.</summary>
/// <remarks>See SW_SHOWDEFAULT</remarks>
ShowDefault = 10,
/// <summary>Windows 2000/XP: Minimizes a window, even if the thread
/// that owns the window is hung. This flag should only be used when
/// minimizing windows from a different thread.</summary>
/// <remarks>See SW_FORCEMINIMIZE</remarks>
ForceMinimized = 11
}
HWnd is a windows handle, in C# it is really an IntPtr type.
Try creating a wrapper class based on IWin32Window and use that when calling Show() e.g.
public class WndWrapper : IWin32Window
{
IntPtr m_Handle;
public WndWrapper(long pHandle)
{
m_Handle = (IntPtr)pHandle;
}
#region IWin32Window Members
public IntPtr Handle
{
get { return m_Handle; }
}
#endregion
}
Then call it like this:
WndWrapper oWnd = new WndWrapper(pHandle);
MyForm oDlg = new MyForm();
oDlg.Show(oWnd);
Just be careful, as HWND elements are unmanaged you will be responsible for ensuring that they are disposed of when required.
Related
I am currently using Microsoft.Office.Core; and using Excel = Microsoft.Office.Interop.Excel; to export my data from windows form to excel to export data from windows form c# to excel
Is there any chance to add a border on selected cells like
How i need it to be
Sure, heres a function I made for the same thing
/// <summary>
/// Puts a border around range
/// </summary>
/// <param name="ws">Excel worksheet</param>
/// <param name="r1">First Row</param>
/// <param name="c1">First Column</param>
/// <param name="r2">Last Row</param>
/// <param name="c2">Last Column</param>
/// <param name="weight">Border Brush Weight</param>
public void BorderRange(Worksheet ws, int r1, int c1, int r2, int c2, XlBorderWeight weight = XlBorderWeight.xlThin)
{
Range r = ws.Range[ws.Cells[r1, c1], ws.Cells[r2, c2]];
r.BorderAround2(Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous, weight);
}
You'll need to call it a few times to put the borders round the ranges you need.
I have an application (that always runs in minimized mode) that constantly listens to keys typed on the keyboard.
When certain key is pressed, I want the C# application to post a command on the message queue of the active window to minimize, close, maximize, etc.
I know it is possible to get the handle to the active window, but, how can I post a message on its message queue (as we can do in win32).
Thanks.
You can use interop to call the native WINAPI functions. Using the p/invoke website I have created the following solution:
var proc = Process.GetProcesses().First(p => p.ProcessName.Contains("firefox"));
PostMessageSafe(
new HandleRef(proc, proc.MainWindowHandle),
(uint) WM.WM_SYSCOMMAND,
new IntPtr((int) SysCommands.SC_MAXIMIZE),
IntPtr.Zero);
What I basically do here is find a WindowHandle I'm interested in and then invoke PostMessage with the WM_SYSCOMMAND in Msg and the appropriate syscommand in the wParam, in this case Maximize, with the value 0xF030. The lParam is set to 0.
Please be aware that if your only goal is to change the window state you better use the specialized API endpoint for that, it's called ShowWindow
Its signature looks like this:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
and it is invoked like this:
ShowWindow(proc.MainWindowHandle, ShowWindowCommands.Maximize);
When either of these methods are called, a window from a process named firefox will be maximized.
Here are the helper methods and enums you need as a wrapper around PostMessage
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
// http://www.pinvoke.net/default.aspx/Enums/WindowsMessages.html
public enum WM : uint
{
WM_SYSCOMMAND = 0x0112
}
// http://www.pinvoke.net/default.aspx/Enums/SysCommands.html
enum SysCommands : int
{
SC_SIZE = 0xF000,
SC_MOVE = 0xF010,
SC_MINIMIZE = 0xF020,
SC_MAXIMIZE = 0xF030,
SC_NEXTWINDOW = 0xF040,
SC_PREVWINDOW = 0xF050,
SC_CLOSE = 0xF060,
SC_VSCROLL = 0xF070,
SC_HSCROLL = 0xF080,
SC_MOUSEMENU = 0xF090,
SC_KEYMENU = 0xF100,
SC_ARRANGE = 0xF110,
SC_RESTORE = 0xF120,
SC_TASKLIST = 0xF130,
SC_SCREENSAVE = 0xF140,
SC_HOTKEY = 0xF150,
//#if(WINVER >= 0x0400) //Win95
SC_DEFAULT = 0xF160,
SC_MONITORPOWER = 0xF170,
SC_CONTEXTHELP = 0xF180,
SC_SEPARATOR = 0xF00F,
//#endif /* WINVER >= 0x0400 */
//#if(WINVER >= 0x0600) //Vista
SCF_ISSECURE = 0x00000001,
//#endif /* WINVER >= 0x0600 */
/*
* Obsolete names
*/
SC_ICON = SC_MINIMIZE,
SC_ZOOM = SC_MAXIMIZE,
}
// http://www.pinvoke.net/default.aspx/Enums/ShowWindowCommand.html
enum ShowWindowCommands
{
/// <summary>
/// Hides the window and activates another window.
/// </summary>
Hide = 0,
/// <summary>
/// Activates and displays a window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when displaying the window
/// for the first time.
/// </summary>
Normal = 1,
/// <summary>
/// Activates the window and displays it as a minimized window.
/// </summary>
ShowMinimized = 2,
/// <summary>
/// Maximizes the specified window.
/// </summary>
Maximize = 3, // is this the right value?
/// <summary>
/// Activates the window and displays it as a maximized window.
/// </summary>
ShowMaximized = 3,
/// <summary>
/// Displays a window in its most recent size and position. This value
/// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except
/// the window is not activated.
/// </summary>
ShowNoActivate = 4,
/// <summary>
/// Activates the window and displays it in its current size and position.
/// </summary>
Show = 5,
/// <summary>
/// Minimizes the specified window and activates the next top-level
/// window in the Z order.
/// </summary>
Minimize = 6,
/// <summary>
/// Displays the window as a minimized window. This value is similar to
/// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the
/// window is not activated.
/// </summary>
ShowMinNoActive = 7,
/// <summary>
/// Displays the window in its current size and position. This value is
/// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the
/// window is not activated.
/// </summary>
ShowNA = 8,
/// <summary>
/// Activates and displays the window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when restoring a minimized window.
/// </summary>
Restore = 9,
/// <summary>
/// Sets the show state based on the SW_* value specified in the
/// STARTUPINFO structure passed to the CreateProcess function by the
/// program that started the application.
/// </summary>
ShowDefault = 10,
/// <summary>
/// <b>Windows 2000/XP:</b> Minimizes a window, even if the thread
/// that owns the window is not responding. This flag should only be
/// used when minimizing windows from a different thread.
/// </summary>
ForceMinimize = 11
}
Currently I need to process Arabic string (اسمي مصير الطفل. من أي بلد أنت) in my project. If the string is displayed in a single line, it is displayed correctly.
However, when the font size is much bigger, the display (I am using label) is wrong.
The string is printed starting from the second line. I found that on the .Net framework we could use drawstring with StringFormatFlags.DirectionRightToLeft. However, that is not available in compact framework. So, how could i print Arabic string in multiple lines? Any advice is appreciated, thanks.
I am sorry, the following is incorrect:
Since WinCE 5 and CompactFramework v 2.0 controls like the Textbox support a RicghtToLeft property (see also http://www.danielmoth.com/Blog/rtl-problem.aspx). So you should ensure you are using CF>=2.0 and WinCE 5 base sdk (ie Windows Mobile 6.x).
Looking at the help for Textbox class, the RightToLeft is marked as NOT AVAILABLE for Compact Framework.
So, you need to write your own DrawText class that splits the words and positions them from right to left.
The native DrawText API supports the uFormat flag DT_RTLREADING (according to the online help for Windows CE 5 Platform Builder):
DT_RTLREADING
Layout in right-to-left reading order for bi-directional text when the font selected into the hdc is a Hebrew or Arabic font. The default reading order for all text is left-to-right.
There is also an option DT_WORDBREAK which I would choose for multiline text and a large enough drawing rectangle.
BUT, that gives the following result using two rectangles and two font sizes to force a wordbreak:
As I can not read that I am not sure, but I assume the wordbreak flag does not work correctly. I assume the second line in the upper part has to start from right too.
Native Code for the above:
...
#define ARABIC_TEXT L"اسمي مصير الطفل. من أي بلد أنت"
#define MulDiv(a,b,c) (((a)*(b))/(c))
...
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
LOGFONT lf;
HFONT hFontNew, hFontOld;
...
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
// Clear out the lf structure to use when creating the font.
memset(&lf, 0, sizeof(LOGFONT));
wsprintf(lf.lfFaceName,L"Arial Unicode MS");
GetClientRect(hWnd, &rect);
hFontNew = CreateFontIndirect(&lf);
hFontOld = (HFONT) SelectObject(hdc, hFontNew);
rect.bottom=rect.bottom/2;
lf.lfHeight=-MulDiv(16, GetDeviceCaps(hdc, LOGPIXELSY), 72);
if(DrawText(hdc, ARABIC_TEXT, -1, &rect, DT_RTLREADING | DT_WORDBREAK)==0){
DEBUGMSG(1, (L"DrawText failed with %i\n", GetLastError()));
}
GetClientRect(hWnd, &rect);
lf.lfHeight=-MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
hFontNew = CreateFontIndirect(&lf);
hFontOld = (HFONT) SelectObject(hdc, hFontNew);
rect.top=rect.bottom/2;
if(DrawText(hdc, ARABIC_TEXT, -1, &rect, DT_RTLREADING | DT_WORDBREAK)==0){
DEBUGMSG(1, (L"DrawText failed with %i\n", GetLastError()));
}
EndPaint(hWnd, &ps);
SelectObject(hdc, hFontOld);
DeleteObject(hFontNew);
break;
The following form is an example of calling DrawText (see josef's answer) from C#:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Menu = null;
DrawText(e.Graphics, "اسمي مصير الطفل. من أي بلد أنت", Font, ClientRectangle);
}
private void DrawText(Graphics g, string text, Font font, Rectangle rectangle)
{
IntPtr dc = g.GetHdc();
RECT rect = (RECT)rectangle;
IntPtr hFont = IntPtr.Zero;
IntPtr previousFont = IntPtr.Zero;
try
{
hFont = font.ToHfont();
previousFont = SelectObject(dc, hFont);
DrawText(dc, text, text.Length, ref rect, DrawTextFlags.RightToLeft | DrawTextFlags.Right | DrawTextFlags.WordBreak);
}
finally
{
if (previousFont != IntPtr.Zero)
{
SelectObject(dc, previousFont);
}
if (hFont != IntPtr.Zero)
{
DeleteObject(hFont);
}
g.ReleaseHdc(dc);
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
internal int Left;
internal int Top;
internal int Right;
internal int Bottom;
public static explicit operator RECT(Rectangle rect)
{
return new RECT()
{
Left = rect.Left,
Top = rect.Top,
Right = rect.Right,
Bottom = rect.Bottom
};
}
}
[DllImport("coredll.dll", CharSet = CharSet.Unicode)]
internal static extern int DrawText(IntPtr hdc, string lpStr, int nCount, ref RECT lpRect, DrawTextFlags flags);
[DllImport("coredll.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject([In] IntPtr hObject);
[DllImport("coredll.dll")]
internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[Flags]
public enum DrawTextFlags : uint
{
/// <summary>
/// Use default values.
/// </summary>
None = 0x00000000,
/// <summary>
/// Justifies the text to the top of the rectangle.
/// </summary>
Top = 0x00000000,
/// <summary>
/// Aligns text to the left.
/// </summary>
Left = 0x00000000,
/// <summary>
/// Centers text horizontally in the rectangle.
/// </summary>
Center = 0x00000001,
/// <summary>
/// Aligns text to the right.
/// </summary>
Right = 0x00000002,
/// <summary>
/// Centers text vertically. This value is used only with the SingleLine value.
/// </summary>
VerticalCenter = 0x00000004,
/// <summary>
/// Justifies the text to the bottom of the rectangle. This value is used only with the
/// SingleLine value.
/// </summary>
Bottom = 0x00000008,
/// <summary>
/// Breaks words. Lines are automatically broken between words if a word would extend past the
/// edge of the rectangle specified by the lpRect parameter. A carriage return-line feed sequence
/// also breaks the line. If this is not specified, output is on one line.
/// </summary>
WordBreak = 0x00000010,
/// <summary>
/// Displays text on a single line only. Carriage returns and line feeds do not break the line.
/// </summary>
SingleLine = 0x00000020,
/// <summary>
/// Expands tab characters. The default number of characters per tab is eight.
/// </summary>
ExpandTabs = 0x00000040,
/// <summary>
/// Sets tab stops. Bits 15-8 (high-order byte of the low-order word) of the uFormat parameter
/// specify the number of characters for each tab. The default number of characters per tab is
/// eight.
/// </summary>
Tabstop = 0x00000080,
/// <summary>
/// Draws without clipping.
/// </summary>
NoClip = 0x00000100,
/// <summary>
/// Includes the font external leading in line height. Normally, external leading is not included
/// in the height of a line of text.
/// </summary>
ExternalLeading = 0x00000200,
/// <summary>
/// Determines the width and height of the rectangle. If there are multiple lines of text, DrawText
/// uses the width of the rectangle pointed to by the lpRect parameter and extends the base of the
/// rectangle to bound the last line of text. If the largest word is wider than the rectangle, the
/// width is expanded. If the text is less than the width of the rectangle, the width is reduced.
/// If there is only one line of text, DrawText modifies the right side of the rectangle so that it
/// bounds the last character in the line. In either case, DrawText returns the height of the
/// formatted text but does not draw the text.
/// </summary>
CalcRect = 0x00000400,
/// <summary>
/// Turns off processing of prefix characters. Normally, DrawText interprets the mnemonic-prefix
/// character & as a directive to underscore the character that follows, and the mnemonic-prefix
/// characters && as a directive to print a single &. By specifying DT_NOPREFIX, this processing
/// is turned off.
/// </summary>
NoPrefix = 0x00000800,
/// <summary>
/// Uses the system font to calculate text metrics.
/// </summary>
Internal = 0x00001000,
/// <summary>
/// Duplicates the text-displaying characteristics of a multiline edit control. Specifically,
/// the average character width is calculated in the same manner as for an edit control, and
/// the function does not display a partially visible last line.
/// </summary>
EditControl = 0x00002000,
/// <summary>
/// For displayed text, if the end of a string does not fit in the rectangle, it is truncated
/// and ellipses are added. If a word that is not at the end of the string goes beyond the
/// limits of the rectangle, it is truncated without ellipses.
/// </summary>
EndEllipsis = 0x00008000,
/// <summary>
/// Layout in right-to-left reading order for bidirectional text when the font selected into the
/// hdc is a Hebrew or Arabic font. The default reading order for all text is left-to-right.
/// </summary>
RightToLeft = 0x00020000,
/// <summary>
/// Truncates any word that does not fit in the rectangle and adds ellipses.
/// </summary>
WordEllipsis = 0x00040000
}
}
(As you can see I've ignored the return values of each native method)
It seems that there is no solid solution to this issue, so I created a temporary workaround. I am assuming that my Label size is fixed, and if my string size is larger than the width of my Label, I will split it into two. The method I use to split the string is to find a splitting point (currently I am doing it at 0.2 of the total string length).
private void processArabic(string arabicString)
{
string[] stringArray = new string[2];
double index = 0.8 * arabicString.Length;
index = Math.Ceiling(index);
int Index = (int)index;
for (int i = Index; i != 0; i--)
{
if (Char.IsWhiteSpace(arabicString, i))
{
stringArray[1] = arabicString.Substring(0, Index + 1);
stringArray[0] = arabicString.Substring(Index + 1, arabicString.Length - (Index + 1));
break;
}
}
label1.Text = stringArray[0];
label1.Text += "\n";
label1.Text += stringArray[1];
}
Although Arabic string is printed from right to left, index is still counted from left to right. The above snippet is rather rigid, and only apply if you want to split the string into two. I am sure there are lot of ways to improve the above code, any comment/suggestion is welcome.
I am using UIAutomation and trying to get the window Id of any control in 3rd party applications. I want to know how to find out the ID of the control at a specific coordinate on the screen.
Example: I have Calculator, Notepad, and Word running on the desktop. All of them are running and sharing the screen partially. I want to be able to run my program and then click at any location on the screen and get the window ID of the underlying control (if there is any under the mouse).
What do I need to use to achieve this functionality. I understand that I need to have some sort of mouse hook, but the real problem is how to get the window ID (not the window handle) of the control on the screen where the mouse was clicked.
AutomationElement.FromPoint() will return the automation element at a given point. Once you have that, you can trivially get the automation ID:
private string ElementFromCursor()
{
// Convert mouse position from System.Drawing.Point to System.Windows.Point.
System.Windows.Point point = new System.Windows.Point(Cursor.Position.X, Cursor.Position.Y);
AutomationElement element = AutomationElement.FromPoint(point);
string autoIdString;
object autoIdNoDefault = element.GetCurrentPropertyValue(AutomationElement.AutomationIdProperty, true);
if (autoIdNoDefault == AutomationElement.NotSupported)
{
// TODO Handle the case where you do not wish to proceed using the default value.
}
else
{
autoIdString = autoIdNoDefault as string;
}
return autoIdString;
}
If i understand it Correctly, what your are trying to achieve is->
Click at any point of screen, get the window id of the underlying element ,if any, from the running elements:
If that's the case,the following should help/give an idea(NOTE: This would extend for not only cursor position but will continue search along X-axis for 100 pixels with a interval of 10):
/// <summary>
/// Gets the automation identifier of underlying element.
/// </summary>
/// <returns></returns>
public static string GetTheAutomationIDOfUnderlyingElement()
{
string requiredAutomationID = string.Empty;
System.Drawing.Point currentLocation = Cursor.Position;//add you current location here
AutomationElement aeOfRequiredPaneAtTop = GetElementFromPoint(currentLocation, 10, 100);
if (aeOfRequiredPaneAtTop != null)
{
return aeOfRequiredPaneAtTop.Current.AutomationId;
}
return string.Empty;
}
/// <summary>
/// Gets the element from point.
/// </summary>
/// <param name="startingPoint">The starting point.</param>
/// <param name="interval">The interval.</param>
/// <param name="maxLengthToTraverse">The maximum length to traverse.</param>
/// <returns></returns>
public static AutomationElement GetElementFromPoint(Point startingPoint, int interval, int maxLengthToTraverse)
{
AutomationElement requiredElement = null;
for (Point p = startingPoint; ; )
{
requiredElement = AutomationElement.FromPoint(new System.Windows.Point(p.X, p.Y));
Console.WriteLine(requiredElement.Current.Name);
if (requiredElement.Current.ControlType.Equals(ControlType.Window))
{
return requiredElement;
}
if (p.X > (startingPoint.X + maxLengthToTraverse))
break;
p.X = p.X + interval;
}
return null;
}
I am developing an application that controls an Machine.
When I receive an error from the Machine the users should be able to directly notice it, one way that is done is Flashing the tray on the taskbar. When the machine clears the error the tray should stop flashing.
There's one little annoyance using the FlashWindowEx function, when I clear the flashing of the window, it stays (in my case WinXP) orange (not flashing).
[Flags]
public enum FlashMode {
/// <summary>
/// Stop flashing. The system restores the window to its original state.
/// </summary>
FLASHW_STOP = 0,
/// <summary>
/// Flash the window caption.
/// </summary>
FLASHW_CAPTION = 1,
/// <summary>
/// Flash the taskbar button.
/// </summary>
FLASHW_TRAY = 2,
/// <summary>
/// Flash both the window caption and taskbar button.
/// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
/// </summary>
FLASHW_ALL = 3,
/// <summary>
/// Flash continuously, until the FLASHW_STOP flag is set.
/// </summary>
FLASHW_TIMER = 4,
/// <summary>
/// Flash continuously until the window comes to the foreground.
/// </summary>
FLASHW_TIMERNOFG = 12
}
public static bool FlashWindowEx(IntPtr hWnd, FlashMode fm) {
FLASHWINFO fInfo = new FLASHWINFO();
fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
fInfo.hwnd = hWnd;
fInfo.dwFlags = (UInt32)fm;
fInfo.uCount = UInt32.MaxValue;
fInfo.dwTimeout = 0;
return FlashWindowEx(ref fInfo);
}
[StructLayout(LayoutKind.Sequential)]
public struct FLASHWINFO {
public UInt32 cbSize;
public IntPtr hwnd;
public UInt32 dwFlags;
public UInt32 uCount;
public UInt32 dwTimeout;
}
In my case I use FLASHW_TRAY to start flashing and FLASHW_STOP to stop the flashing.
Am I doing something wrong or is this a known bug of WinXP and is there a fix for it?
Behaviour is the same when a window finishes flashing for as long as it's supposed to: the taskbar button stays coloured. I don't think this is a bug. If you think about it, when you use FLASHW_STOP, the flashing does in fact stop, but the point of the flashing is to get the user's attention. The button stays coloured because the user still may not have looked down and discovered which window was trying to get her attention. Keeping the button coloured keeps that information available.
Here's an error:
fInfo.uCount = UInt32.MaxValue;
You should set fInfo.uCount to zero when calling with FLASHW_STOP parameter.
Otherwise when you try to call stop when taskbar button is active it will stay active.
You can check a note about undefined behavior here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms679348(v=vs.85).aspx
I know that's an old post but it can help other people to solve this problem fast.
If that's the expected functionality I think it's not so useful, at least there should be a reset.
I fixed it now just using the FLASHW_ALL | FLASHW_TIMERNOFG combination.
Just set uCount to 0 to stop the flashing.
fixed with uCount=0
if (flags = FLASHW_STOP) { .uCount = 0 } else { .uCount = 800 }
The misbehaviour is that if you are calling flashw_stop from a click/kb event from inside the Window itself, the taskbar button stay colored if a that moment was colored.
With that new logic line, done.