Drawing a circle outside the Winform - c#

I am creating a Screen Recording app using Windows media encoder, i Can record the video and save it to a disk,now i need to draw a filled circle around the mouse click area when ever the mouse click event Fire( to high light the area that mouse press event occur), is there a way to do that? any code sample? thank you!!! sorry for not inserting the code here is my code
public void CaptureMoni()
{
string dateTime = DateTime.Now.ToString("yyyy.MM.dd _ HH.mm");
var dir = #"C:\VIDEOS\" + dateTime;
try
{
System.Drawing.Rectangle _screenRectangle = Screen.PrimaryScreen.Bounds;
_screenCaptureJob = new ScreenCaptureJob();
_screenCaptureJob.CaptureRectangle = _screenRectangle;
_screenCaptureJob.ShowFlashingBoundary = true;
_screenCaptureJob.ScreenCaptureVideoProfile.FrameRate = 10;
_screenCaptureJob.CaptureMouseCursor = true;
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
_screenCaptureJob.OutputScreenCaptureFileName = string.Format(Path.Combine(dir, dateTime + ".wmv"));
}
}
catch (Exception)
{
MessageBox.Show("Screnn Capturing Failed!" );
}
string temPath = (_screenCaptureJob.OutputScreenCaptureFileName.ToString());
// MessageBox.Show(temPath);
}
public ScreenCaptureJob _screenCaptureJob { get; set; }
finally i did what i need Special thanks to PacMani he direct me the right way,
NOTE : this is not a full code which include red circle in the video, this is only for having a red circle and making the transparent form on top of the all the other forms (sorry for the language mistakes)) thank you for the Help # PacMAni
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
WindowState = FormWindowState.Maximized;
this.TopMost = true;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)RMouseListener.WM.WM_NCHITTEST)
m.Result = (IntPtr)RMouseListener.WM.HTTRANSPARENT;
else
base.WndProc(ref m);
}
public void draw_circle()
{
int x = MousePosition.X;
int y = MousePosition.Y;
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Salmon);
System.Drawing.Graphics formGraphics = this.CreateGraphics();
formGraphics.FillEllipse(myBrush, new Rectangle(x - 60, y - 60, 60, 60));
myBrush.Dispose();
formGraphics.Dispose();
Thread.Sleep(200);
this.Invalidate();
}
RMouseListener _native;
private void button1_Click(object sender, EventArgs e)
{
//_native = new RMouseListener();
//_native.RButtonClicked += new EventHandler<SysMouseEventInfo>(_native_RButtonClicked);
//_native.LButtonClicked += new EventHandler<SysMouseEventInfo>(_native_LButtonClicked);
}
private void button2_Click(object sender, EventArgs e)
{
_native.Close();
this.Dispose();
}
void _native_RButtonClicked(object sender, SysMouseEventInfo e)
{
// listBox1.Items.Add(e.WindowTitle);
draw_circle();
}
void _native_LButtonClicked(object sender, SysMouseEventInfo e)
{
// listBox2.Items.Add(e.WindowTitle);
draw_circle();
}
// }
public class SysMouseEventInfo : EventArgs
{
public string WindowTitle { get; set; }
}
public class RMouseListener
{
Form1 frm = new Form1();
public RMouseListener()
{
this.CallBack += new HookProc(MouseEvents);
//Module mod = Assembly.GetExecutingAssembly().GetModules()[0];
//IntPtr hMod = Marshal.GetHINSTANCE(mod);
using (Process process = Process.GetCurrentProcess())
using (ProcessModule module = process.MainModule)
{
IntPtr hModule = GetModuleHandle(module.ModuleName);
_hook = SetWindowsHookEx(WH_MOUSE_LL, this.CallBack, hModule, 0);
}
}
int WH_MOUSE_LL = 14;
int HC_ACTION = 0;
HookProc CallBack = null;
IntPtr _hook = IntPtr.Zero;
public event EventHandler<SysMouseEventInfo> RButtonClicked;
public event EventHandler<SysMouseEventInfo> LButtonClicked;
int MouseEvents(int code, IntPtr wParam, IntPtr lParam)
{
//Console.WriteLine("Called");
//MessageBox.Show("Called!");
if (code < 0)
return CallNextHookEx(_hook, code, wParam, lParam);
if (code == this.HC_ACTION)
{
// Left button pressed somewhere
if (wParam.ToInt32() == (uint)WM.WM_RBUTTONDOWN || wParam.ToInt32() == (uint)WM.WM_LBUTTONDOWN)
{
MSLLHOOKSTRUCT ms = new MSLLHOOKSTRUCT();
ms = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
IntPtr win = WindowFromPoint(ms.pt);
string title = GetWindowTextRaw(win);
if (RButtonClicked != null || LButtonClicked != null)
{
RButtonClicked(this, new SysMouseEventInfo { WindowTitle = title });
LButtonClicked(this, new SysMouseEventInfo { WindowTitle = title });
}
}
}
return CallNextHookEx(_hook, code, wParam, lParam);
}
public void Close()
{
if (_hook != IntPtr.Zero)
{
UnhookWindowsHookEx(_hook);
}
}
public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(POINT Point);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);
public static string GetWindowTextRaw(IntPtr hwnd)
{
// Allocate correct string length first
//int length = (int)SendMessage(hwnd, (int)WM.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
StringBuilder sb = new StringBuilder(65535);//THIS COULD BE BAD. Maybe you shoudl get the length
SendMessage(hwnd, (int)WM.WM_GETTEXT, (IntPtr)sb.Capacity, sb);
return sb.ToString();
}
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public UIntPtr dwExtraInfo;
}
public enum WM : uint
{//all windows messages here
WM_LBUTTONDOWN = 0x0201,
WM_RBUTTONDOWN = 0x0204,
WM_GETTEXT = 0x000D,
WM_GETTEXTLENGTH = 0x000E,
WM_MOUSE = 0x0200,
WM_NCHITTEST = 0x84,
HTTRANSPARENT
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
_native = new RMouseListener();
_native.RButtonClicked += new EventHandler<SysMouseEventInfo>(_native_RButtonClicked);
_native.LButtonClicked += new EventHandler<SysMouseEventInfo>(_native_LButtonClicked);
}

Screen recording applications add this circle in their video file, not on the desktop.
If you still want to create a circle window, you need a form with the two things you have to implement:
Click-through window (otherwise the cursor could not click on things behind it anymore). See here for the solution: Click through transparency for Visual C# Window Forms?
Transparent window (transparency key might be enough here already, if you want alpha-blended transparency, things get more exciting, there are many examples for that on CodeProject, for example http://www.codeproject.com/Articles/20758/Alpha-Blended-Windows-Forms). Without this, you would have a rectangular window and not just a circle.
Also you need to register a global mouse hook to detect global mouse clicks. I think you already did this, but your question does not show what you've done and what not.
If you received a mouse click, create a borderless window around the mouse coordinates and (with the background color being the same as the transparency key to make it invisible where the circle isn't drawn) draw an ellipse on it (hook the Paint-event and use the Graphics objects DrawEllipse method).
Start a timer after which this window disappears again (or the circle would be visible forever). If you want this circle to animate as in other screen recording apps, use the timer to animate the drawing.

Related

Could detect windows touch keyboard has popped up or not?

Currently, I can open & close the windows touch keyboard,
I don't know how to detect the touch keyboard is popped up or not,
so I try to get windows style value,
when I click the button at the top-right corner, to hiding the touch keyboard, please reference this image
the windows style value is the same as I did not hide the touch keyboard,
Is there any way to detect this situation?
---Test code as below -------------------------------------------------------
namespace WindowsFormsApp7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CloseWindowsTouchKeyboard();
}
private void btnOpen_Click(object sender, EventArgs e)
{
OpenWindowsTouchKeyboard();
}
private void btnClose_Click(object sender, EventArgs e)
{
CloseWindowsTouchKeyboard();
}
private void btnGetWindowLong_Click(object sender, EventArgs e)
{
GetWindowLong();
}
private const string IPTIP_MAIN_WINDOW_CLASS_NAME = "IPTip_Main_Window";
private const int GWL_STYLE = -16;
private const int WM_SYSCOMMAND = 274;
private const uint SC_CLOSE = 61536;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool PostMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
public static void OpenWindowsTouchKeyboard()
{
string strFilePath = #"C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe";
if (!File.Exists(strFilePath))
{
return;
}
Process.Start(strFilePath);
}
public static void CloseWindowsTouchKeyboard()
{
IntPtr TouchhWnd;
TouchhWnd = FindWindow(IPTIP_MAIN_WINDOW_CLASS_NAME, null);
if (TouchhWnd == IntPtr.Zero)
{
return;
}
PostMessage(TouchhWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
}
public static void GetWindowLong()
{
IntPtr tKeyboardHandle = FindWindow(IPTIP_MAIN_WINDOW_CLASS_NAME, null);
if (tKeyboardHandle != IntPtr.Zero)
{
uint iStyle = GetWindowLong(tKeyboardHandle, GWL_STYLE);
Console.WriteLine($"iStyle: {iStyle}");
}
}
}
}
You'll need to utilize ComImport to define interfaces manually:
[ComImport, Guid("228826af-02e1-4226-a9e0-99a855e455a6")]
class ImmersiveShellBroker { }
[ComImport, Guid("9767060c-9476-42e2-8f7b-2f10fd13765c")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IImmersiveShellBroker
{
void M();
IInputHostManagerBroker GetInputHostManagerBroker();
}
[ComImport, Guid("2166ee67-71df-4476-8394-0ced2ed05274")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IInputHostManagerBroker { void GetIhmLocation(out Bounds rect, out DisplayMode mode); }
[StructLayout(LayoutKind.Sequential)]
struct Bounds { public int Left, Top, Right, Bottom; }
enum DisplayMode { None = 0, Floating = 2, Docked = 3 }
Then you can use them to check the touch keyboard display mode like so,
IImmersiveShellBroker broker = (IImmersiveShellBroker)(new ImmersiveShellBroker());
IInputHostManagerBroker inputHost = broker.GetInputHostManagerBroker();
Marshal.ReleaseComObject(broker);
// if mode != DisplayMode.None then the keyboard is open
DisplayMode mode;
inputHost.GetIhmLocation(out _, out mode);
you can also cache the inputHost somewhere, but it's not necessary.

Attach WPF Window to the Window of Another Process

I want to write a WPF application that docks to an application running in another process (this is a 3rd party app I have no control of). Ideally I would like to be able to define if the app docks on the left or right.
Here's an example of what I want to do:
I have tried to implement the following 2 examples with no success.
Attach window to window of another process - Button_Click gives the following error:
Attach form window to another window in C# - Button_Click_1 docks it the title bar but I cannot see the entire app:
The following is the code:
namespace WpfApplicationTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
public static int GWL_STYLE = -16;
public static int WS_CHILD = 0x40000000;
[DllImport("user32")]
private static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int x,
int y,
int cx,
int cy,
uint uFlags);
private IntPtr _handle;
private void SetBounds(int left, int top, int width, int height)
{
if (_handle == IntPtr.Zero)
_handle = new WindowInteropHelper(this).Handle;
SetWindowPos(_handle, IntPtr.Zero, left, top, width, height, 0);
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault();
IntPtr hostHandle = hostProcess.MainWindowHandle;
//MyWindow window = new MyWindow();
this.ShowActivated = true;
HwndSourceParameters parameters = new HwndSourceParameters();
parameters.WindowStyle = 0x10000000 | 0x40000000;
parameters.SetPosition(0, 0);
parameters.SetSize((int)this.Width, (int)this.Height);
parameters.ParentWindow = hostHandle;
parameters.UsesPerPixelOpacity = true;
HwndSource src = new HwndSource(parameters);
src.CompositionTarget.BackgroundColor = Colors.Transparent;
src.RootVisual = (Visual)this.Content;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault();
if (hostProcess != null)
{
Hide();
//this.WindowStyle;
//new WindowInteropHelper(this).SetBounds(0, 0, 0, 0, BoundsSpecified.Location);
//SetWindowPos(new WindowInteropHelper(this).Handle, IntPtr.Zero, 0, 0, 0, 0, 0);
SetBounds(0, 0, 0, 0);
IntPtr hostHandle = hostProcess.MainWindowHandle;
IntPtr guestHandle = new WindowInteropHelper(this).Handle;
SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
SetParent(guestHandle, hostHandle);
Show();
}
}
}
You implementation is totally wrong, you are trying to make your window as a child window of the window you want to snap to.
I wrote a small helper class for snapping to another window by it's title, I hope this helps.
WindowSnapper.cs
public class WindowSnapper
{
private struct Rect
{
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
public int Height
{
get { return Bottom - Top; }
}
public static bool operator !=(Rect r1, Rect r2)
{
return !(r1 == r2);
}
public static bool operator ==(Rect r1, Rect r2)
{
return r1.Left == r2.Left && r1.Right == r2.Right && r1.Top == r2.Top && r1.Bottom == r2.Bottom;
}
}
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);
private DispatcherTimer _timer;
private IntPtr _windowHandle;
private Rect _lastBounds;
private Window _window;
private string _windowTitle;
public WindowSnapper(Window window, String windowTitle)
{
_window = window;
_window.Topmost = true;
_windowTitle = windowTitle;
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(10);
_timer.Tick += (x, y) => SnapToWindow();
_timer.IsEnabled = false;
}
public void Attach()
{
_windowHandle = GetWindowHandle(_windowTitle);
_timer.Start();
}
public void Detach()
{
_timer.Stop();
}
private void SnapToWindow()
{
var bounds = GetWindowBounds(_windowHandle);
if (bounds != _lastBounds)
{
_window.Top = bounds.Top;
_window.Left = bounds.Left - _window.Width;
_window.Height = bounds.Height;
_lastBounds = bounds;
}
}
private Rect GetWindowBounds(IntPtr handle)
{
Rect bounds = new Rect();
GetWindowRect(handle, ref bounds);
return bounds;
}
private IntPtr GetWindowHandle(string windowTitle)
{
foreach (Process pList in Process.GetProcesses())
{
if (pList.MainWindowTitle.Contains(windowTitle))
{
return pList.MainWindowHandle;
}
}
return IntPtr.Zero;
}
}
Usage example:
public partial class MainWindow : Window
{
private WindowSnapper _snapper;
public MainWindow()
{
InitializeComponent();
_snapper = new WindowSnapper(this, "Notepad");
_snapper.Attach();
}
}

How to modify the default size of System.Windows.Forms.FolderBrowserDialog? It's too small if you don't modify it by hand

I want the FolderBrowserDialog to be larger when first shown so that it can show more than three-level directory. Is that anyway to do it or is there anyway to override a similiar dialog?
I shamelessly copied Hans's code and modified it to achieve what you want.
private void button1_Click(object sender, EventArgs e)
{
using (new SizeWinDialog(this)//This refers to wpf Window
{
PreferredSize = new Size(150, 150)//Change this size to whatever you want
})
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.ShowDialog();
}
}
class SizeWinDialog : IDisposable
{
private int mTries = 0;
private Window mOwner;
public SizeWinDialog(Window owner)
{
mOwner = owner;
owner.Dispatcher.BeginInvoke(new Action(findDialog));
}
public Size PreferredSize { get; set; }
private void findDialog()
{
// Enumerate windows to find the message box
if (mTries < 0) return;
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero))
{
if (++mTries < 10) mOwner.Dispatcher.BeginInvoke(new MethodInvoker(findDialog));
}
}
private bool checkWindow(IntPtr hWnd, IntPtr lp)
{
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got it
RECT dlgRect;
GetWindowRect(hWnd, out dlgRect);
SetWindowPos(new HandleRef(this, hWnd), new HandleRef(), dlgRect.Left, dlgRect.Top, PreferredSize.Width, PreferredSize.Height, 20 | 2);
return false;
}
public void Dispose()
{
mTries = -1;
}
// P/Invoke declarations
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy,
int flags);
private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}
I converted the code sample above back to WinForms from the WPF version that is shown. I also created two companion classes that will size a system dialog and will place it at a specific offset from the parent form. They are used like this:
using (new OffsetWinDialog(this) { PreferredOffset = new Point(75, 75 )})
using (new SizeWinDialog(this) { PreferredSize = new Size(400, 600)})
{
DialogResult result = dlgFolderBrowser.ShowDialog();
if (result == DialogResult.Cancel)
return;
}
The original post (below) shows how to place the system dialog at the center of the parent. Together, these three classes will let you control the initial size and position of the system dialogs. Rather than repeat the code here, please refer to the following thread.
Winforms-How can I make MessageBox appear centered on MainForm?

Get tooltips text from C# with PInvoke

I'm using PInvoke in C#, trying to read tooltips visible in a window with a known handler, but the apps who's windows I try to inspect in this manner crash with memory access violation errors, or simply don't reveal the tooltip text in the lpszText TOOLINFO member.
I'm calling EnumWindows with a callback and then sending a message to the tooltip window in that function:
public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);
static void Main(string[] args)
{
callBackPtr = new CallBackPtr(Report);
IntPtr hWnd = WindowFromPoint(<mouse coordinates point>);
if (hWnd != IntPtr.Zero)
{
Console.Out.WriteLine("Window with handle " + hWnd +
" and class name " +
getWindowClassName(hWnd));
EnumWindows(callBackPtr, hWnd);
Console.Out.WriteLine();
}
public static bool Report(IntPtr hWnd, IntPtr lParam)
{
String windowClassName = getWindowClassName(hWnd);
if (windowClassName.Contains("tool") &&
GetParent(hWnd) == lParam)
{
string szToolText = new string(' ', 250);
TOOLINFO ti = new TOOLINFO();
ti.cbSize = Marshal.SizeOf(typeof(TOOLINFO));
ti.hwnd = GetParent(hWnd);
ti.uId = hWnd;
ti.lpszText = szToolText;
SendMessage(hWnd, TTM_GETTEXT, (IntPtr)250, ref ti);
Console.WriteLine("Child window handle is " + hWnd + " and class name " + getWindowClassName(hWnd) + " and value " + ti.lpszText);
}
return true;
}
Here's how I defined the TOOLINFO structure:
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
private int _Left;
private int _Top;
private int _Right;
private int _Bottom;
}
struct TOOLINFO
{
public int cbSize;
public int uFlags;
public IntPtr hwnd;
public IntPtr uId;
public RECT rect;
public IntPtr hinst;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpszText;
public IntPtr lParam;
}
the TTM_GETTEXT value
private static UInt32 WM_USER = 0x0400;
private static UInt32 TTM_GETTEXT = (WM_USER + 56);
and the SendMessage overload
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref TOOLINFO lParam);
So, is there any obvious error that I'm missing in my code, what should I change so that this situation is resolved?
Edit: Here is the whole code, so you could test.
You are sending a private message across processes, which requires manual marshaling. Here's another stackoverflow question on the same topic. Better would be to change direction entirely and use Active Accessibility and/or UI Automation, which are designed for this sort of thing.
I ended up using UI Automation, as Raymond suggested. AutomationElement, who's Name property value contains the text in case of tooltips, proved to be exactly what the code required. I'm cycling through all the Desktop's child windows, where all the tooltips reside and I only display those that belong to the process that owns the window under the mouse:
public static bool Report(IntPtr hWnd, IntPtr lParam)
{
if (getWindowClassName(hWnd).Contains("tool"))
{
AutomationElement element = AutomationElement.FromHandle(hWnd);
string value = element.Current.Name;
if (value.Length > 0)
{
uint currentWindowProcessId = 0;
GetWindowThreadProcessId(currentWindowHWnd, out currentWindowProcessId);
if (element.Current.ProcessId == currentWindowProcessId)
Console.WriteLine(value);
}
}
return true;
}
static void Main(string[] args)
{
callBackPtr = new CallBackPtr(Report);
do
{
System.Drawing.Point mouse = System.Windows.Forms.Cursor.Position; // use Windows forms mouse code instead of WPF
currentWindowHWnd = WindowFromPoint(mouse);
if (currentWindowHWnd != IntPtr.Zero)
EnumChildWindows((IntPtr)0, callBackPtr, (IntPtr)0);
Thread.Sleep(1000);
}
while (true);
}

how to write an event for shockWave flash object

Is there any way to write click event for shockWave flash object?
AFAIK there is no way of doing this without modifing the flash application (swf) or at least wrapping it in a new one. Once you are able to capture the click event in Flash, you can use any of the communication schemes available for flash+a host application. You could use in this scenario:
-FS Command ("Sending Data from a Flash Movie to the Hosting C# Application" in CodeProject)
-External Interface ("Fun with C# and the Flash Player 8 External API" also in CodeProject)
How about this:
public abstract partial class SetWindowLongForm : Form
{
[DllImport("user32.dll")]
private static extern IntPtr RealChildWindowFromPoint(IntPtr hwndParent, POINT ptParentClientCoords);
[DllImport("user32.dll")]
private static extern IntPtr ChildWindowFromPoint(IntPtr hWndParent, POINT Point);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32")]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, WindowProcedure newProc);
[DllImport("user32.dll")]
private static extern IntPtr DefWindowProc(IntPtr hWnd, int uMsg, int wParam, int lParam);
[DllImport("user32")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool ReleaseCapture();
private delegate IntPtr WindowProcedure(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public POINT(System.Drawing.Point pt) : this(pt.X, pt.Y) { }
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
}
private WindowProcedure newWindowProcedure = null;
private IntPtr oldWindowProcedure = IntPtr.Zero;
private IntPtr HookedWindowHandle = IntPtr.Zero;
private const int GWL_WNDPROC = -4;
private Timer SetWindowLongTimer;
protected abstract void onShockWaveClick();
protected abstract void onShockWaveBorderLineMouseMove(int x, int y);
public SetWindowLongForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
SetWindowLongTimer = new Timer();
SetWindowLongTimer.Interval = 1000;
SetWindowLongTimer.Tick += new EventHandler(SetWindowLongTimer_Tick);
SetWindowLongTimer.Start();
}
private void SetWindowLongTimer_Tick(object sender, EventArgs e)
{
SetWindowLongTimer.Stop();
SetWindowLongTimer.Tick -= new EventHandler(SetWindowLongTimer_Tick);
try
{
Control shockerHandle = Controls.OfType<AxShockwaveFlashObjects.AxShockwaveFlash>().FirstOrDefault();
if (shockerHandle == null) return;
ChangeShockWaveWindowProcedure(shockerHandle.Handle);
}
catch { }
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
RevertShockWaveWindowProcedure();
}
private void ChangeShockWaveWindowProcedure(IntPtr theHandle)
{
if (theHandle != IntPtr.Zero)
{
HookedWindowHandle = theHandle;
newWindowProcedure = new WindowProcedure(newWindowProc);
oldWindowProcedure = SetWindowLong(HookedWindowHandle, GWL_WNDPROC, newWindowProcedure);
}
}
private void RevertShockWaveWindowProcedure()
{
if (HookedWindowHandle != IntPtr.Zero)
{
SetWindowLong(HookedWindowHandle, GWL_WNDPROC, oldWindowProcedure);
HookedWindowHandle = IntPtr.Zero;
}
}
private IntPtr newWindowProc(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam)
{
const int WM_MOUSEMOVE = 0x0200;
const int WM_LBUTTONDOWN = 0x0201;
switch (Msg)
{
case WM_MOUSEMOVE:
{
//Control ctrlTmp = Control.FromHandle(hWnd);
int x = lParam.ToInt32() & 0xffff;
int y = lParam.ToInt32() >> 16;
onShockWaveBorderLineMouseMove(x, y);
break;
}
case WM_LBUTTONDOWN:
ReleaseCapture();
Point pt = new Point(MousePosition.X, MousePosition.Y);
Control ctrl = Control.FromHandle(hWnd); // Controls.OfType<AxShockwaveFlashObjects.AxShockwaveFlash>().FirstOrDefault();
pt = ctrl.PointToClient(pt);
IntPtr ax = ctrl.Handle;
Rectangle r = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
IntPtr isTHis = ChildWindowFromPoint(Handle, new POINT(pt)); //where was the mouse pressed
if (r.Contains(pt))
{
onShockWaveClick();
}
ReleaseCapture();
break;
}
return CallWindowProc(oldWindowProcedure, hWnd, Msg, wParam, lParam);
}
protected override void WndProc(ref Message m)
{
//if (m.Msg == 528)
//{
// IntPtr lbutDown = new IntPtr(0x0201);
// if (m.WParam == lbutDown)
// {
// Point pt = new Point(MousePosition.X, MousePosition.Y);
// pt = axShockwaveFlash1.PointToClient(pt);
// IntPtr ax = axShockwaveFlash1.Handle;
// Rectangle r = new Rectangle(0, 0, axShockwaveFlash1.Width, axShockwaveFlash1.Height);
// IntPtr isTHis = ChildWindowFromPoint(Handle, new POINT(pt));
// if (r.Contains(pt))
// {
// int k = 90;
// k += 90;
// }
// }
//}
base.WndProc(ref m);
}
}
Derive your Form from this class, and insert this code in your derived class
protected override void onShockWaveClick()
{
MessageBox.Show("Is this it?\n In Main Form", "AxSHockWave Message");
}
protected override void onShockWaveBorderLineMouseMove(int x, int y)
{
if (y >= axShockwaveFlash1.Height - 20)
{
Text = "Borderline x=" + x.ToString() + " , y = " + y.ToString() + ", ht= " + axShockwaveFlash1.Height;
}
else
{
Text = "Moving x=" + x.ToString() + " , y = " + y.ToString() + ", ht= " + axShockwaveFlash1.Height;
}
}
everything else will be taken care by the base class

Categories