Question Edited!! This is an example of compilabile files to help you find my problem!
I save some screenshots in a specific file.
When i use function DeleteFile() it should delete first the contents and then the folder but then i get "that icon.jpg is used by another process"!
(Either way to delete a folder it has to have no content!)
ImageExtensions.cs
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace name
{
static class ImageExtensions
{
public static void SaveToFile(Image image,string path,ImageFormat format)
{
using (var stream = File.OpenWrite(path))
{
image.Save(stream, format);
}
}
}
}
ScreenCapture.cs
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace name
{
public class ScreenCapture
{
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetDesktopWindow();
public static Image CaptureDesktop()
{
return CaptureWindow(GetDesktopWindow());
}
public static Bitmap CaptureActiveWindow()
{
return CaptureWindow(GetForegroundWindow());
}
public static Bitmap CaptureWindow(IntPtr handle)
{
var rect = new Rect();
GetWindowRect(handle, ref rect);
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
var result = new Bitmap(bounds.Width, bounds.Height);
using (var graphics = Graphics.FromImage(result))
{
graphics.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
}
return result;
}
}
}
AnotherFile.cs (Uses PrintScreen() )
public void PrintScreen()
{
using (var image = ScreenCapture.CaptureDesktop())
{
ImageExtensions.SaveToFile(image, (file_images + ".jpg"), ImageFormat.Jpeg);
}
}
Form1.cs (Main)
using ...
using ...
namespace name{
public partial class Form1 : Form
{
const int MaxRetries = 3;
const int DelayBetweenRetries = 1000;
const int ERROR_SHARING_VIOLATION = unchecked((int)0x80070020);
string file_images = my_path_of_images_file;
Public Form1()
{
InitializeComponent();
CreateFile();
}
private void Form1_Load(object sender, EventArgs e){}
public void CreateFile()
{
if (!Directory.Exists(file_images))
{
DirectoryInfo di = Directory.CreateDirectory(file_images);
}
}
public void DeleteFiles()
{
string[] filesToDelete = Directory.GetFiles(file_images);
if (filesToDelete != null)
{
var files = filesToDelete.Where(x => Path.GetExtension(x).Contains(".jpg"));
foreach (var file in files)
{
var temp = file;
DeleteFile(temp); // Delete JPEG
}
}
Directory.Delete(file_images); // Delete Folder
}
public static void DeleteFile(string path)
{
for (int i = 0; i < MaxRetries; ++i)
{
try
{
File.Delete(path);
}
catch (IOException e)
{
// You may also sleep whatever the error is...
if (Marshal.GetHRForException(e) == ERROR_SHARING_VIOLATION)
{
Thread.Sleep(DelayBetweenRetries);
continue;
}
throw;
}
}
}
} // End Of Main.cs
} // End Of Namespace
I have had this problem before and I solved it by copying the image data from the filestream into a memorystream, then loading the image from it. Similarly with the saving the image. This way, even if Image keeps a reference to the source or saved stream, it is not a physical file.
A more complete solution: https://siderite.dev/blog/imagefromstream-or-imagefromfile.html
try:
using (var ms=new MemoryStream()) {
image.Save(ms,format);
File.WriteAllBytes(path,ms.ToArray());
}
I wrote this inline, so tweak it if it doesn't work exactly.
Related
I have a program that has a small graphics portion to it, where you can look at and store the color of specific pixels of the screen.
The problem is that when I extract color, sometimes I get the color I want... sometimes I just get White, or some other random color (usually white, but I'm also using a white background to test with).
Can you spot any reason why that would be? I'm also totally open to possible improvements.
I have a picturebox called Canvas, and I can either click "Capture Image" which does a screenshot as follows:
private void CaptureImage_Click(object sender, EventArgs e)
{
this.Visible = false;
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
Canvas.SizeMode = PictureBoxSizeMode.AutoSize;
Canvas.Image = bitmap;
graphics.Dispose();
this.Visible = true;
}
Or I can load an image file, though for this test I'm just doing the capture.
When I right-click somewhere on the image, in my mousedown event I do:
if (e.Button == MouseButtons.Right)
{
pointPoint = e.Location;
Debug.WriteLine("right mouse: " + e.Location.ToString());
ContextMenuStrip cm = new ContextMenuStrip();
cm.Items.Add("Flag this as Point");
cm.Items.Add("Extract Color");
Canvas.ContextMenuStrip = cm;
cm.ItemClicked += new ToolStripItemClickedEventHandler(Cm2Click);
}
(pointPoint is a Point object)
As you can see, I verify the location where I clicked using the debug window. In my context menu, I also verify it again to make sure it didn't change before getting called. The context menu does:
private void Cm2Click(object sender, ToolStripItemClickedEventArgs e)
{
//var clickedMenuItem = sender as MenuItem;
ToolStripItem menuText = e.ClickedItem;
Debug.WriteLine(menuText);
if (menuText.ToString() == "Extract Color")
{
string input = "Default";
bool testBox = false;
do
{
if (InputBox.inputBox("ColorName", "You must provide a unique name for this color", ref input) == DialogResult.OK)
{
if (!String.IsNullOrWhiteSpace(input) && input != "Default")
{
Debug.WriteLine("location changed to: " + pointPoint);
colorExtractor = Functions.GetColorAt(pointPoint);
ColorData clr = new ColorData(input, colorExtractor);
string expression;
expression = $"Name = '{clr.Name}'";
DataRow[] foundRows;
DataTable dt = _allEventData.Tables["ColorData"];
foundRows = dt.Select(expression);
if (foundRows.Length > 0) {
testBox = false;
Debug.WriteLine("Color Found");
}
else {
dt.Rows.Add(clr.Name, clr.R, clr.G, clr.B);
dt.AcceptChanges();
testBox = true;
}
}
} else
{
return;
}
} while (testBox == false);
}
}
and ColorData is just a class I defined to help store data:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace EventClicker
{
public class ColorData : EventArgs
{
public string Name { get; set; }
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
public bool Found { get; set; }
public ColorData(String name, Color color)
{
this.Name = name;
this.R = color.R;
this.G = color.G;
this.B = color.B;
}
public ColorData(String name, String r, String g, String b)
{
this.Name = name;
this.R = Int32.Parse(r);
this.G = Int32.Parse(g);
this.B = Int32.Parse(b);
}
}
}
Last but not least, the method I call (Functions.GetColorAt) is defined here (and I definitely stole this from someone on the web) Edit: That somewhere is here, How to read the Color of a Screen Pixel
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace EventClicker
{
public static class Functions
{
private static Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
public static Color GetColorAt(Point location)
{
using (Graphics gdest = Graphics.FromImage(screenPixel))
{
using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hSrcDC = gsrc.GetHdc();
IntPtr hDC = gdest.GetHdc();
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
gdest.ReleaseHdc();
gsrc.ReleaseHdc();
}
}
return screenPixel.GetPixel(0, 0);
}
}
}
I'd like to change my desktop wallpaper. To do so I've written following code, but it doesn't work:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Background bg = new Background();
bg.DoSomething();
}
}
class Background
{
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam,
string pvParam, uint fWinIni);
private const uint SPI_SETDESKWALLPAPER = 0x0014;
private const uint SPIF_UPDATEINIFILE = 0x01;
private const uint SPIF_SENDWININICHANGE = 0x02;
private string pathtofiles;
private string[] filename;
private int count, o, ui;
private Object thisLock = new Object();
public Background()
{
pathtofiles = #"C:\Users\Mine\Desktop\Test\";
filename = new string[150];
count = 0;
o = 0;
ui = 0;
}
public void DoSomething()
{
System.IO.DirectoryInfo ParentDirectory = new System.IO.DirectoryInfo(#"C:\Users\Mine\Desktop\Test\");
foreach (System.IO.FileInfo f in ParentDirectory.GetFiles())
{
if (f.Name.EndsWith(".jpg"))
{
filename[count] = f.Name;
count++;
}
if (f.Name.EndsWith(".png"))
{
filename[count] = f.Name;
count++;
}
if (f.Name.EndsWith(".bmp"))
{
filename[count] = f.Name;
count++;
}
}
count = 0;
foreach (string s in filename)
{
if (System.IO.File.Exists(pathtofiles + s))
{
System.IO.Stream BitmapStream = System.IO.File.Open(pathtofiles + s, System.IO.FileMode.Open);
System.Drawing.Image img = System.Drawing.Image.FromStream(BitmapStream);
System.Drawing.Bitmap mBitmap = new System.Drawing.Bitmap(img);
mBitmap.Save(#"C:\Users\Mine\Desktop\BmpSpeichern\00" + o + ".bmp");
o++;
}
}
System.IO.DirectoryInfo ParentDirectory2 = new System.IO.DirectoryInfo(#"C:\Users\Mine\Desktop\BmpSpeichern\");
foreach (System.IO.FileInfo f in ParentDirectory2.GetFiles())
{
if (f.Name.EndsWith(".bmp"))
{
filename[count] = f.Name;
count++;
}
}
if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, #"C:\Users\Mine\Desktop\BmpSpeichern\" + filename[ui],
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE))
{
throw new Win32Exception();
}
}
}
}
First I copy the image files to another directory then convert them to .bmp data type. Works perfectly but the call to the WINAPI function SystemParametersInfo fails to change the wallpaper.
What am I doing wrong?
I am working on a small project (just for fun) that allows me to display the frequencies played back in my current audio buffer.
The plan is:
The thread that is executing the WaveOutPlayer.ThreadProc() method keeps playing and refilling two audio buffers. While the first buffer is playing, the second buffer gets refilled and vice versa. To be sure that one buffer does not start playing before the other one stopped playback, I use the WaitOne() method. After the buffer's audio data has beed played back by the WaveOut device, the buffer's OnCompleted() method is called. This method cancels the waiting.
The playback itself starts, but it is very choppy.
Could anyone tell me why this happens?
The Visual Studio project is located at http://www.pour-toujours.net/lowlevelaudio.zip
(currently, only 16-bit, Stereo, 44,1kHz uncompressed wav is supported.)
Here goes some of my code that seems to be relevant:
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
namespace LowLevelAudio
{
internal class WaveOutHelper
{
public static void Try(int err)
{
if (err != WaveNative.MMSYSERR_NOERROR)
throw new Exception(err.ToString());
}
}
public delegate void BufferFillEventHandler(IntPtr data, int size);
public class WaveOutBuffer : IDisposable
{
private AutoResetEvent m_PlayEvent = new AutoResetEvent(false);
private IntPtr m_WaveOut;
private int m_buffersize;
private static byte[] m_samples;
private static double[] m_fftsamples;
private WaveNative.WaveHdr m_Header;
private byte[] m_HeaderData;
private GCHandle m_HeaderHandle;
private GCHandle m_HeaderDataHandle;
private WaveFormat m_waveformat;
private double[] m_fftOccurances;
private double[] m_fftHertzlist;
private bool m_Playing;
public int ID
{
get; set;
}
internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
{
if (uMsg == WaveNative.MM_WOM_DONE)
{
try
{
GCHandle h = (GCHandle)wavhdr.dwUser;
WaveOutBuffer buf = (WaveOutBuffer)h.Target;
buf.OnPlayCompleted();
}
catch(Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
}
}
}
public WaveOutBuffer(IntPtr waveOutHandle, int size, WaveFormat format)
{
m_WaveOut = waveOutHandle;
m_waveformat = format;
m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned);
m_Header.dwUser = (IntPtr)GCHandle.Alloc(this);
m_HeaderData = new byte[size];
m_HeaderDataHandle = GCHandle.Alloc(m_HeaderData, GCHandleType.Pinned);
m_Header.lpData = m_HeaderDataHandle.AddrOfPinnedObject();
m_Header.dwBufferLength = size;
m_buffersize = size;
m_samples = new byte[m_buffersize];
WaveOutHelper.Try(WaveNative.waveOutPrepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)));
}
~WaveOutBuffer()
{
Dispose();
}
public int Size
{
get { return m_Header.dwBufferLength; }
}
public IntPtr Data
{
get { return m_Header.lpData; }
}
public void Dispose()
{
if (m_Header.lpData != IntPtr.Zero)
{
WaveNative.waveOutUnprepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header));
m_HeaderHandle.Free();
m_Header.lpData = IntPtr.Zero;
}
m_PlayEvent.Close();
if (m_HeaderDataHandle.IsAllocated)
m_HeaderDataHandle.Free();
}
public bool Play()
{
lock(this) // works, but has to be fine tuned... (to do)
{
m_PlayEvent.Reset();
m_Playing = WaveNative.waveOutWrite(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)) == WaveNative.MMSYSERR_NOERROR;
if (!m_Playing)
throw new Exception("test exception");
return m_Playing;
}
}
public void WaitForMe()
{
Console.WriteLine(this.ID + " WaitFor()");
if (m_Playing)
{
m_Playing = m_PlayEvent.WaitOne();
}
else
{
m_Playing = false;
}
}
public void OnPlayCompleted()
{
Console.WriteLine(this.ID + " OnCompleted()");
m_PlayEvent.Set();
m_Playing = false;
}
}
public class WaveOutPlayer : IDisposable
{
private IntPtr m_WaveOut;
private WaveOutBuffer[] m_bufferlist;
private Thread m_Thread;
private BufferFillEventHandler m_FillProc;
private bool m_Finished;
private byte m_zero;
private int m_buffercount = 0;
private int m_buffersize = 0;
private WaveFormat m_waveformat;
private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc);
public static int DeviceCount
{
get { return WaveNative.waveOutGetNumDevs(); }
}
public WaveOutPlayer(int device, WaveFormat format, int bufferSize, BufferFillEventHandler fillProc)
{
m_zero = format.wBitsPerSample == 8 ? (byte)128 : (byte)0;
m_FillProc = fillProc;
m_buffercount = 2;
m_buffersize = bufferSize;
m_waveformat = format;
WaveOutHelper.Try(WaveNative.waveOutOpen(out m_WaveOut, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
AllocateBuffers(bufferSize, m_buffercount, format);
m_Thread = new Thread(new ThreadStart(ThreadProc));
m_Thread.Start();
}
~WaveOutPlayer()
{
Dispose();
}
public void Dispose()
{
if (m_Thread != null)
{
try
{
m_Finished = true;
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutReset(m_WaveOut);
m_Thread.Join();
m_FillProc = null;
FreeBuffers();
if (m_WaveOut != IntPtr.Zero)
WaveNative.waveOutClose(m_WaveOut);
}
finally
{
m_Thread = null;
m_WaveOut = IntPtr.Zero;
}
}
}
private void ThreadProc()
{
WaveOutBuffer b0 = m_bufferlist[0];
WaveOutBuffer b1 = m_bufferlist[1];
MainForm form = Program.getUI();
bool s = true;
m_FillProc(b0.Data, b0.Size);
while (!m_Finished)
{
if (s)
{
Console.WriteLine("-------------------------");
Console.WriteLine("Playing b0, filling b1");
b0.Play();
m_FillProc(b1.Data, b1.Size);
form.paintEqualizer(b0);
Console.WriteLine("callng waitFor on b0");
b0.WaitForMe();
}
else
{
Console.WriteLine("-------------------------");
Console.WriteLine("Playing b1, filling b0");
b1.Play();
m_FillProc(b0.Data, b0.Size);
form.paintEqualizer(b1);
Console.WriteLine("callng waitFor on b1");
b1.WaitForMe();
}
s = !s;
}
}
private void AllocateBuffers(int bufferSize, int bufferCount, WaveFormat format)
{
FreeBuffers();
m_bufferlist = new WaveOutBuffer[m_buffercount];
if (bufferCount > 0)
{
for (int i = 0; i < m_buffercount; i++)
{
m_bufferlist[i] = new WaveOutBuffer(m_WaveOut, bufferSize, format);
m_bufferlist[i].ID = i;
}
}
}
private void FreeBuffers()
{
if (m_bufferlist != null)
{
foreach (WaveOutBuffer currentBuffer in m_bufferlist)
{
if (currentBuffer != null)
{
currentBuffer.Dispose();
}
}
}
}
}
}
This is a class i'm using to capture my screen and mouse cursour as screenshot.
But i want to make somehow that if the Form is in the middle of the screen don't capture it captrue the screen and the area behind the Form but not the Form it self.
Even if the form is in the front and i click on buttons or change something in the Form while the application is running do not capture it just keep capture the screen the area behind the Form like the Form is not there.
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace ScreenShotDemo
{
public class ScreenCapture
{
[StructLayout(LayoutKind.Sequential)]
struct CURSORINFO
{
public Int32 cbSize;
public Int32 flags;
public IntPtr hCursor;
public POINTAPI ptScreenPos;
}
[StructLayout(LayoutKind.Sequential)]
struct POINTAPI
{
public int x;
public int y;
}
[DllImport("user32.dll")]
static extern bool GetCursorInfo(out CURSORINFO pci);
[DllImport("user32.dll")]
static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
const Int32 CURSOR_SHOWING = 0x00000001;
public static Bitmap CaptureScreen(bool CaptureMouse)
{
Bitmap result = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
try
{
using (Graphics g = Graphics.FromImage(result))
{
g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
if (CaptureMouse)
{
CURSORINFO pci;
pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CURSORINFO));
if (GetCursorInfo(out pci))
{
if (pci.flags == CURSOR_SHOWING)
{
DrawIcon(g.GetHdc(), pci.ptScreenPos.x, pci.ptScreenPos.y, pci.hCursor);
g.ReleaseHdc();
}
}
}
}
}
catch
{
result = null;
}
return result;
}
}
What i mean is that i will see the Form when it's running and i will be able to change things click buttons but the captured screenshot if i will edit it with Paint i will not see the Form .
This is in Form1 how i make the capture:
private void StartRecording_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
And timer1 tick event:
private void timer1_Tick(object sender, EventArgs e)
{
using (bitmap = (Bitmap)ScreenCapture.CaptureScreen(true))
{
ffmp.PushFrame(bitmap);
}
}
This line make the actual capture: using (bitmap = (Bitmap)ScreenCapture.CaptureScreen(true))
Um.. Hide the form?
this.Visible = false; and THEN run the screenshot method.
Like this:
protected Bitmap TakeScreenshot(bool cursor)
{
Bitmap bitmap;
this.Visible = false;
bitmap = CaptureScreen(cursor);
this.Visible = true;
return bitmap;
}
and use it in your code the way you wanted:
private void timer1_Tick(object sender, EventArgs e)
{
using (bitmap = (Bitmap)ScreenCapture.TakeScreenshot(true))
{
ffmp.PushFrame(bitmap);
}
}
I want to do something when my cursor is on an open window with C# WPF. How shoould I do this? I have some ideas, but I'm not sure.
Should I detect open windows first? and how?
How should I detect when my cursor is on open windows?
This will be idea:
if ( cursor is on any open window( How to do this? ) ) {
I will do something here
}
else {
I will do something here
}
You'll need some WinAPI:
static class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(POINT point);
[DllImport("user32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(ref POINT lpPoint);
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
You can get list of WPF app windows from Application.Current.Windows property and get their handles using WindowInteropHelper class:
public static Window GetWindowFromPoint(Point point)
{
var hwnd = NativeMethods.WindowFromPoint(new POINT((int)point.X, (int)point.Y));
if(hwnd == IntPtr.Zero) return null;
var p = NativeMethods.GetParent(hwnd);
while(p != IntPtr.Zero)
{
hwnd = p;
p = NativeMethods.GetParent(hwnd);
}
foreach(Window w in Application.Current.Windows)
{
if(w.IsVisible)
{
var helper = new WindowInteropHelper(w);
if(helper.Handle == hwnd) return w;
}
}
return null;
}
public static Window GetWindowFromMousePosition()
{
POINT p = new POINT();
NativeMethods.GetCursorPos(ref p);
return GetWindowFromPoint(new Point(p.x, p.y));
}
Usage:
if(GetWindowFromMousePosition() != null)
{
// mouse cursor is over window
}
else
{
// mouse cursor is somewhere else
}
Update:
Since you want to check windows outside your app, it's even easier:
public static bool IsCursorOverWindow()
{
POINT p = new POINT();
NativeMethods.GetCursorPos(ref p);
var hwnd = NativeMethods.WindowFromPoint(p);
if(hwnd == IntPtr.Zero) return false;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.IO;
using System.Windows.Forms;
namespace WpfApplication6
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
public static void LeftClick(int X, int Y)
{
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
}
public static void LeftClickRelease(int X, int Y)
{
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
}
static class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(POINT point);
[DllImport("user32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(ref POINT lpPoint);
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
public static Window GetWindowFromPoint(Point point)
{
var hwnd = NativeMethods.WindowFromPoint(new POINT((int)point.X, (int)point.Y));
if (hwnd == IntPtr.Zero) return null;
var p = NativeMethods.GetParent(hwnd);
while (p != IntPtr.Zero)
{
hwnd = p;
p = NativeMethods.GetParent(hwnd);
}
foreach (Window w in System.Windows.Application.Current.Windows)
{
if (w.IsVisible)
{
var helper = new WindowInteropHelper(w);
if (helper.Handle == hwnd) return w;
}
}
return null;
}
public static Window GetWindowFromMousePosition()
{
POINT p = new POINT();
NativeMethods.GetCursorPos(ref p);
return GetWindowFromPoint(new Point(p.x, p.y));
}
public MainWindow()
{
InitializeComponent();
if (GetWindowFromMousePosition() != null)
{
LeftClick(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
// mouse cursor is over window
}
else
{
LeftClickRelease(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
// mouse cursor is somewhere else
}
}
}
}