I'm looking for .NET code which performs the same as Snipping Tool - capturing a screen area.
I believe it uses hooks. Would be interesting to know how does it highlight the selected fragment.
Update:
Found http://www.codeproject.com/KB/vb/Screen_Shot.aspx . Though people say it's missing some important files for proper compilation.
The snipping tool effect isn't difficult to implement in Windows Forms. Add a new form to your project and name it "SnippingTool". Make the code look like this:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1 {
public partial class SnippingTool : Form {
public static Image Snip() {
var rc = Screen.PrimaryScreen.Bounds;
using (Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)) {
using (Graphics gr = Graphics.FromImage(bmp))
gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);
using (var snipper = new SnippingTool(bmp)) {
if (snipper.ShowDialog() == DialogResult.OK) {
return snipper.Image;
}
}
return null;
}
}
public SnippingTool(Image screenShot) {
InitializeComponent();
this.BackgroundImage = screenShot;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.DoubleBuffered = true;
}
public Image Image { get; set; }
private Rectangle rcSelect = new Rectangle();
private Point pntStart;
protected override void OnMouseDown(MouseEventArgs e) {
// Start the snip on mouse down
if (e.Button != MouseButtons.Left) return;
pntStart = e.Location;
rcSelect = new Rectangle(e.Location, new Size(0, 0));
this.Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e) {
// Modify the selection on mouse move
if (e.Button != MouseButtons.Left) return;
int x1 = Math.Min(e.X, pntStart.X);
int y1 = Math.Min(e.Y, pntStart.Y);
int x2 = Math.Max(e.X, pntStart.X);
int y2 = Math.Max(e.Y, pntStart.Y);
rcSelect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
this.Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e) {
// Complete the snip on mouse-up
if (rcSelect.Width <= 0 || rcSelect.Height <= 0) return;
Image = new Bitmap(rcSelect.Width, rcSelect.Height);
using (Graphics gr = Graphics.FromImage(Image)) {
gr.DrawImage(this.BackgroundImage, new Rectangle(0, 0, Image.Width, Image.Height),
rcSelect, GraphicsUnit.Pixel);
}
DialogResult = DialogResult.OK;
}
protected override void OnPaint(PaintEventArgs e) {
// Draw the current selection
using (Brush br = new SolidBrush(Color.FromArgb(120, Color.White))) {
int x1 = rcSelect.X; int x2 = rcSelect.X + rcSelect.Width;
int y1 = rcSelect.Y; int y2 = rcSelect.Y + rcSelect.Height;
e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x2, 0, this.Width - x2, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, this.Height - y2));
}
using (Pen pen = new Pen(Color.Red, 3)) {
e.Graphics.DrawRectangle(pen, rcSelect);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
// Allow canceling the snip with the Escape key
if (keyData == Keys.Escape) this.DialogResult = DialogResult.Cancel;
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
Usage:
var bmp = SnippingTool.Snip();
if (bmp != null) {
// Do something with the bitmap
//...
}
This is a modified #Hans's version that is compatible with multiple monitors and works well with DPI scaling (tested on Windows 7 and Windows 10).
public sealed partial class SnippingTool : Form
{
public static event EventHandler Cancel;
public static event EventHandler AreaSelected;
public static Image Image { get; set; }
private static SnippingTool[] _forms;
private Rectangle _rectSelection;
private Point _pointStart;
public SnippingTool(Image screenShot, int x, int y, int width, int height)
{
InitializeComponent();
BackgroundImage = screenShot;
BackgroundImageLayout = ImageLayout.Stretch;
ShowInTaskbar = false;
FormBorderStyle = FormBorderStyle.None;
StartPosition = FormStartPosition.Manual;
SetBounds(x, y, width, height);
WindowState = FormWindowState.Maximized;
DoubleBuffered = true;
Cursor = Cursors.Cross;
TopMost = true;
}
private void OnCancel(EventArgs e)
{
Cancel?.Invoke(this, e);
}
private void OnAreaSelected(EventArgs e)
{
AreaSelected?.Invoke(this, e);
}
private void CloseForms()
{
for (int i = 0; i < _forms.Length; i++)
{
_forms[i].Dispose();
}
}
public static void Snip()
{
var screens = ScreenHelper.GetMonitorsInfo();
_forms = new SnippingTool[screens.Count];
for (int i = 0; i < screens.Count; i++)
{
int hRes = screens[i].HorizontalResolution;
int vRes = screens[i].VerticalResolution;
int top = screens[i].MonitorArea.Top;
int left = screens[i].MonitorArea.Left;
var bmp = new Bitmap(hRes, vRes, PixelFormat.Format32bppPArgb);
using (var g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(left, top, 0, 0, bmp.Size);
}
_forms[i] = new SnippingTool(bmp, left, top, hRes, vRes);
_forms[i].Show();
}
}
#region Overrides
protected override void OnMouseDown(MouseEventArgs e)
{
// Start the snip on mouse down
if (e.Button != MouseButtons.Left)
{
return;
}
_pointStart = e.Location;
_rectSelection = new Rectangle(e.Location, new Size(0, 0));
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
// Modify the selection on mouse move
if (e.Button != MouseButtons.Left)
{
return;
}
int x1 = Math.Min(e.X, _pointStart.X);
int y1 = Math.Min(e.Y, _pointStart.Y);
int x2 = Math.Max(e.X, _pointStart.X);
int y2 = Math.Max(e.Y, _pointStart.Y);
_rectSelection = new Rectangle(x1, y1, x2 - x1, y2 - y1);
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
// Complete the snip on mouse-up
if (_rectSelection.Width <= 0 || _rectSelection.Height <= 0)
{
CloseForms();
OnCancel(new EventArgs());
return;
}
Image = new Bitmap(_rectSelection.Width, _rectSelection.Height);
var hScale = BackgroundImage.Width / (double)Width;
var vScale = BackgroundImage.Height / (double)Height;
using (Graphics gr = Graphics.FromImage(Image))
{
gr.DrawImage(BackgroundImage,
new Rectangle(0, 0, Image.Width, Image.Height),
new Rectangle((int)(_rectSelection.X * hScale), (int)(_rectSelection.Y * vScale), (int)(_rectSelection.Width * hScale), (int)(_rectSelection.Height * vScale)),
GraphicsUnit.Pixel);
}
CloseForms();
OnAreaSelected(new EventArgs());
}
protected override void OnPaint(PaintEventArgs e)
{
// Draw the current selection
using (Brush br = new SolidBrush(Color.FromArgb(120, Color.White)))
{
int x1 = _rectSelection.X;
int x2 = _rectSelection.X + _rectSelection.Width;
int y1 = _rectSelection.Y;
int y2 = _rectSelection.Y + _rectSelection.Height;
e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, Height));
e.Graphics.FillRectangle(br, new Rectangle(x2, 0, Width - x2, Height));
e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, Height - y2));
}
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, _rectSelection);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Allow canceling the snip with the Escape key
if (keyData == Keys.Escape)
{
Image = null;
CloseForms();
OnCancel(new EventArgs());
}
return base.ProcessCmdKey(ref msg, keyData);
}
#endregion
}
Usage:
SnippingTool.AreaSelected += OnAreaSelected;
SnippingTool.Snip();
private static void OnAreaSelected(object sender, EventArgs e)
{
var bmp = SnippingTool.Image;
// Do something with the bitmap
//...
}
Note you need a helper class to get the actual monitor resolution and avoid problems with DPI scaling.
This is the code:
public class DeviceInfo
{
public string DeviceName { get; set; }
public int VerticalResolution { get; set; }
public int HorizontalResolution { get; set; }
public Rectangle MonitorArea { get; set; }
}
public static class ScreenHelper
{
private const int DektopVertRes = 117;
private const int DesktopHorzRes = 118;
[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct MONITORINFOEX
{
public int Size;
public Rect Monitor;
public Rect WorkArea;
public uint Flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
}
private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData);
[DllImport("user32.dll")]
private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
[DllImport("User32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);
[DllImport("gdi32.dll")]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
private static List<DeviceInfo> _result;
public static List<DeviceInfo> GetMonitorsInfo()
{
_result = new List<DeviceInfo>();
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnum, IntPtr.Zero);
return _result;
}
private static bool MonitorEnum(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData)
{
var mi = new MONITORINFOEX();
mi.Size = Marshal.SizeOf(typeof(MONITORINFOEX));
bool success = GetMonitorInfo(hMonitor, ref mi);
if (success)
{
var dc = CreateDC(mi.DeviceName, mi.DeviceName, null, IntPtr.Zero);
var di = new DeviceInfo
{
DeviceName = mi.DeviceName,
MonitorArea = new Rectangle(mi.Monitor.left, mi.Monitor.top, mi.Monitor.right-mi.Monitor.right, mi.Monitor.bottom-mi.Monitor.top),
VerticalResolution = GetDeviceCaps(dc, DektopVertRes),
HorizontalResolution = GetDeviceCaps(dc, DesktopHorzRes)
};
ReleaseDC(IntPtr.Zero, dc);
_result.Add(di);
}
return true;
}
}
Here is the complete source code
It takes a full-screen screenshot, then (probably) copies it, applies the translucent effect & displays it. When you click-drag it can then overlay the corresponding region from the original capture.
You can get a screenshot using CopyFromScreen() or using the GDI API.
I have a Arduino communicating the state of a button through serial port. On the PC I have a Windows Service application that is polling the serial port to get the state of the button. Whenever I receive a message in the serial port about the button state, I write the received message to a file, and also want to log the current mouse position. Following this I would like to raise a left click event at the current mouse position.
For some reason, when I read the current mouse position using GetCursorPos, I always get 0, 0 as the mouse position. I am using user32.dll to do this.
The following is my C# code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Threading;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
namespace MouseInterface
{
public class MyMouseClass
{
[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
}
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(ref Point pt);
public static void LeftDown(int x, int y)
{
SetCursorPos(x, y);
mouse_event((int)(MouseEventFlags.LEFTDOWN), x, y, 0, 0);
}
public static void LeftUp(int x, int y)
{
SetCursorPos(x, y);
mouse_event((int)(MouseEventFlags.LEFTUP), x, y, 0, 0);
}
}
public partial class Service1 : ServiceBase
{
private HCIDevice hcidev;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
hcidev = new HCIDevice();
hcidev.init();
}
protected override void OnStop()
{
hcidev.terminate();
}
private void onElapsedTimer(object source, ElapsedEventArgs e)
{
}
}
public class HCIDevice
{
private SerialPort _sPort;
private Thread _reader;
private bool _connected;
private bool _stop;
private System.Timers.Timer _contimer = new System.Timers.Timer();
public HCIDevice()
{
// create a new serial port
_sPort = new SerialPort();
// update settings
updateSerialPortSettings();
// set reader and writer threads.
_reader = new Thread(this._readerthread);
// reset flags.
_connected = false;
_stop = false;
// start the thread.
//init();
}
public void connect()
{
if (this._sPort.IsOpen == false)
{
try
{
this._sPort.Open();
_connected = true;
AddToFile("Device connected!\n");
}
catch
{
}
}
}
public void disconnect()
{
if (this._sPort.IsOpen)
{
this._sPort.Close();
}
_connected = false;
AddToFile("Device disconnected!\n");
}
public void init()
{
try
{
this._stop = false;
// start thread.
this._reader.Start();
}
catch
{
//AddToFile("Service could not be started!\n");
}
}
public void terminate()
{
// first stop.
this._stop = true;
this._reader.Join();
//AddToFile("Device stopped!");
}
public bool isRunning()
{
return (this._stop == false);
}
public bool isConnected()
{
return this._sPort.IsOpen;
}
private void updateSerialPortSettings()
{
// Allow the user to set the appropriate properties.
this._sPort.PortName = System.Configuration.ConfigurationManager.AppSettings["devCOM"];
this._sPort.BaudRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["devbaudrate"]);
this._sPort.Parity = Parity.None;
this._sPort.DataBits = 8;
this._sPort.StopBits = StopBits.One;
this._sPort.Handshake = Handshake.None;
// Set the read/write timeouts
this._sPort.ReadTimeout = 500;
this._sPort.WriteTimeout = 500;
}
private void _readerthread()
{
byte[] _rxdata = new byte[1024];
//int n;
double nanosecPerTick = 1.0 / Stopwatch.Frequency;
Stopwatch stp_watch = new Stopwatch();
stp_watch.Start();
AddToFile("Service started!\n");
while (_stop == false)
{
// make sure the device is still connected.
if (isConnected())
{
// Do nothing if in pause
// Not paused read data and parse
try
{
handle_message();
}
catch (System.TimeoutException) { }
}
else
{
// Just got disconnected?
if (_connected)
{
disconnect();
// Reset timer.
stp_watch.Reset();
stp_watch.Start();
}
else
{
// try to connect every one second.
if (stp_watch.ElapsedMilliseconds >= 1000)
{
connect();
// Reset timer.
stp_watch.Reset();
if (_connected == false)
{
stp_watch.Start();
}
}
}
}
}
disconnect();
AddToFile("Service stopped!\n");
}
private void AddToFile(string line)
{
using (FileStream fs = File.Open(System.Configuration.ConfigurationManager.AppSettings["logloc"], FileMode.Append, FileAccess.Write, FileShare.None))
{
Byte[] info = new UTF8Encoding(true).GetBytes(string.Format("{0} {1}", DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss"), line));
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
}
private void handle_message()
{
// read line.
string msg = _sPort.ReadLine();
AddToFile(msg);
Point pt = new Point();
MyMouseClass.GetCursorPos(ref pt);
AddToFile(string.Format("{0}, {1}", pt.X, pt.Y));
}
}
}
What am I doing wrong? I googled for a couple of hours to find the solution, but could not find anything about this.
I've written a simple auto clicker using MouseKeyHook.
The reason I use MouseKeyHook is to detect global left clicks throughout Windows OS.
Although, when I run the .exe, the software lags on the click and after a while I can't seem to hit the 'X' button anymore and the application crashed my windows or slows down everything.
I am making this software to test our game, but this is not really helping :P
The code for the software can be found below:
using Gma.System.MouseKeyHook;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Rapid_Fire
{
public partial class Form1 : Form
{
#region structs
/// <summary>
/// Structure for SendInput function holding relevant mouse coordinates and information
/// </summary>
public struct INPUT
{
public uint type;
public MOUSEINPUT mi;
};
/// <summary>
/// Structure for SendInput function holding coordinates of the click and other information
/// </summary>
public struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
};
#endregion
// Constants for use in SendInput and mouse_event
public const int INPUT_MOUSE = 0x0000;
public const int MOUSEEVENTF_LEFTDOWN = 0x0002;
public const int MOUSEEVENTF_LEFTUP = 0x0004;
private const int INTERVAL = 10;
private bool m_fire = false;
private bool m_close = false;
private int m_counter = INTERVAL;
private INPUT m_input = new INPUT();
private IKeyboardMouseEvents m_GlobalHook;
public Form1()
{
InitializeComponent();
Subscribe();
InitAutoClick();
this.FormClosed += new FormClosedEventHandler(formClosed);
}
private void Subscribe()
{
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.KeyPress += GlobalHookKeyPress;
m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
}
private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 'q') m_fire = false;
}
private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
{
m_fire = true;
RapidFire();
}
private void InitAutoClick()
{
m_input.type = INPUT_MOUSE;
m_input.mi.dx = 0;
m_input.mi.dy = 0;
m_input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
m_input.mi.dwExtraInfo = IntPtr.Zero;
m_input.mi.mouseData = 0;
m_input.mi.time = 0;
}
private void RapidFire()
{
while (m_fire && !m_close)
{
if (m_counter <= 0)
{
// ClickLeftMouseButtonSendInput();
m_counter = INTERVAL;
}
m_counter--;
}
}
private void ClickLeftMouseButtonSendInput()
{
// Send a left click down followed by a left click up to simulate a full left click
SendInput(1, ref m_input, Marshal.SizeOf(m_input));
m_input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, ref m_input, Marshal.SizeOf(m_input));
}
private void formClosed(object sender, FormClosedEventArgs e)
{
m_fire = false;
m_close = true;
Unsubscribe();
}
public void Unsubscribe()
{
m_GlobalHook.MouseDownExt -= GlobalHookMouseDownExt;
m_GlobalHook.KeyPress -= GlobalHookKeyPress;
m_GlobalHook.Dispose();
}
}
}
Fixed the script by doing it another way. Turns out I had to attach it to a left mouse button down event :D
Here the script is:
using Gma.System.MouseKeyHook;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Rapid_Fire
{
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendInput(int nInputs, ref INPUT pInputs, int cbSize);
#region structs
/// <summary>
/// Structure for SendInput function holding relevant mouse coordinates and information
/// </summary>
public struct INPUT
{
public uint type;
public MOUSEINPUT mi;
};
/// <summary>
/// Structure for SendInput function holding coordinates of the click and other information
/// </summary>
public struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
};
#endregion
public const int INPUT_MOUSE = 0x0000;
public const int MOUSEEVENTF_LEFTDOWN = 0x0002;
public const int MOUSEEVENTF_LEFTUP = 0x0004;
private const int TIMES_CLICK_FIRE = 25;
private bool m_fire = false;
private INPUT m_input = new INPUT();
private IKeyboardMouseEvents m_Events;
public Form1()
{
InitializeComponent();
SubscribeGlobal();
InitAutoClick();
this.FormClosed += new FormClosedEventHandler(formClosed);
}
private void SubscribeGlobal()
{
Unsubscribe();
Subscribe(Hook.GlobalEvents());
}
private void Subscribe(IKeyboardMouseEvents events)
{
m_Events = events;
m_Events.MouseUp += OnMouseUp;
m_Events.MouseDown += OnMouseDown;
}
private void InitAutoClick()
{
m_input.type = INPUT_MOUSE;
m_input.mi.dx = 0;
m_input.mi.dy = 0;
m_input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
m_input.mi.dwExtraInfo = IntPtr.Zero;
m_input.mi.mouseData = 0;
m_input.mi.time = 0;
}
private void Log(string text)
{
if (IsDisposed) return;
Console.WriteLine(text);
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
m_fire = true;
Thread thread = new Thread(RapidFire);
thread.Start();
}
private void RapidFire()
{
while (m_fire)
{
for (; ; )
{
ClickLeftMouseButtonSendInput();
}
}
}
private void OnMouseUp(object sender, MouseEventArgs e)
{
m_fire = false;
}
private void ClickLeftMouseButtonSendInput()
{
SendInput(1, ref m_input, Marshal.SizeOf(m_input));
m_input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, ref m_input, Marshal.SizeOf(m_input));
}
private void formClosed(object sender, FormClosedEventArgs e)
{
Unsubscribe();
}
private void Unsubscribe()
{
if (m_Events == null) return;
m_Events.MouseUp -= OnMouseUp;
m_Events.MouseDown -= OnMouseDown;
m_Events.Dispose();
m_Events = null;
}
}
}
i am currently learning on QR code webcam decoder. i have taken an example from https://zxingnet.svn.codeplex.com/svn/trunk/Clients/AForgeDemo/ and have succesfully build it without error. however when i run it with my webcam connected, no input or it wont switch on the webcam. based on my understanding, the webcam would be switch on when user select it at combobox. well, since there is no error at build, i cant pinpoint what went wrong. i have also taken a look at a project which switch on the webcam when user press a button and i plan to implement it to the current project. i have already insert the button but i do not know what should i program at the button to switch on the webcam instead on having to choose at combobox
would someone kindly advise or guide me through it.
below is the main program, and 2 class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video;
using ZXing;
using System.Threading;
namespace AForgeDemo
{
public partial class AForgeDemoForm : Form
{
private struct Device
{
public int Index;
public string Name;
public override string ToString()
{
return Name;
}
}
private readonly CameraDevices camDevices;
private Bitmap currentBitmapForDecoding;
private readonly Thread decodingThread;
private Result currentResult;
private readonly Pen resultRectPen;
public AForgeDemoForm()
{
InitializeComponent();
camDevices = new CameraDevices();
decodingThread = new Thread(DecodeBarcode);
decodingThread.Start();
pictureBox1.Paint += pictureBox1_Paint;
resultRectPen = new Pen(Color.Green, 10);
}
void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (currentResult == null)
return;
if (currentResult.ResultPoints != null && currentResult.ResultPoints.Length > 0)
{
var resultPoints = currentResult.ResultPoints;
var rect = new Rectangle((int)resultPoints[0].X, (int)resultPoints[0].Y, 1, 1);
foreach (var point in resultPoints)
{
if (point.X < rect.Left)
rect = new Rectangle((int)point.X, rect.Y, rect.Width + rect.X - (int)point.X, rect.Height);
if (point.X > rect.Right)
rect = new Rectangle(rect.X, rect.Y, rect.Width + (int)point.X - rect.X, rect.Height);
if (point.Y < rect.Top)
rect = new Rectangle(rect.X, (int)point.Y, rect.Width, rect.Height + rect.Y - (int)point.Y);
if (point.Y > rect.Bottom)
rect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + (int)point.Y - rect.Y);
}
using (var g = pictureBox1.CreateGraphics())
{
g.DrawRectangle(resultRectPen, rect);
}
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadDevicesToCombobox();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (!e.Cancel)
{
decodingThread.Abort();
if (camDevices.Current != null)
{
camDevices.Current.NewFrame -= Current_NewFrame;
if (camDevices.Current.IsRunning)
{
camDevices.Current.SignalToStop();
}
}
}
}
private void LoadDevicesToCombobox()
{
cmbDevice.Items.Clear();
for (var index = 0; index < camDevices.Devices.Count; index++)
{
cmbDevice.Items.Add(new Device { Index = index, Name = camDevices.Devices[index].Name });
}
}
private void cmbDevice_SelectedIndexChanged(object sender, EventArgs e)
{
if (camDevices.Current != null)
{
camDevices.Current.NewFrame -= Current_NewFrame;
if (camDevices.Current.IsRunning)
{
camDevices.Current.SignalToStop();
}
}
camDevices.SelectCamera(((Device)(cmbDevice.SelectedItem)).Index);
camDevices.Current.NewFrame += Current_NewFrame;
camDevices.Current.Start();
}
private void Current_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (IsDisposed)
{
return;
}
try
{
if (currentBitmapForDecoding == null)
{
currentBitmapForDecoding = (Bitmap)eventArgs.Frame.Clone();
}
Invoke(new Action<Bitmap>(ShowFrame), eventArgs.Frame.Clone());
}
catch (ObjectDisposedException)
{
// not sure, why....
}
}
private void ShowFrame(Bitmap frame)
{
if (pictureBox1.Width < frame.Width)
{
pictureBox1.Width = frame.Width;
}
if (pictureBox1.Height < frame.Height)
{
pictureBox1.Height = frame.Height;
}
pictureBox1.Image = frame;
}
private void DecodeBarcode()
{
var reader = new BarcodeReader();
while (true)
{
if (currentBitmapForDecoding != null)
{
var result = reader.Decode(currentBitmapForDecoding);
if (result != null)
{
Invoke(new Action<Result>(ShowResult), result);
}
currentBitmapForDecoding.Dispose();
currentBitmapForDecoding = null;
}
Thread.Sleep(200);
}
}
private void ShowResult(Result result)
{
currentResult = result;
txtBarcodeFormat.Text = result.BarcodeFormat.ToString();
txtContent.Text = result.Text;
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
the class for cameradevice
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge.Video.DirectShow;
namespace AForgeDemo
{
internal class CameraDevices
{
public FilterInfoCollection Devices { get; private set; }
public VideoCaptureDevice Current { get; private set; }
public CameraDevices()
{
Devices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
}
public void SelectCamera(int index)
{
if (index >= Devices.Count)
{
throw new ArgumentOutOfRangeException("index");
}
Current = new VideoCaptureDevice(Devices[index].MonikerString);
}
}
}
again, i kindly ask for anybody help on what i shall put at the button command to activate the webcam directly instead of choosing from combobox
thanks a million
The code which you need for your event handler behind the button is similar to the code within the method cmbDevice_SelectedIndexChanged.
I think it should look like the following
// select the first available camera and start capturing
camDevices.SelectCamera(0);
camDevices.Current.NewFrame += Current_NewFrame;
camDevices.Current.Start();
But I think the main challenge is to find out why the original example doesn't work as expected. It makes no difference if the same code is called in the handler of the combobox or in the handler of the button.
I my program I need to capture when the Print Screen key is pressed down but it is not working (however it works with other keys).
I guess this has something to do with windows hijacking my authority and since im still new at this I'd love to know how I can get around this issue.
Here's my current code:
namespace Boom_Screenshot_
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
//SETTINGS
Key TRIGGER_KEY = Key.PrintScreen;
public Window1()
{
InitializeComponent();
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == TRIGGER_KEY)
{
MessageBox.Show("'PrintScreen' was pressed.");
}
}
}
}
I have an answer for you that I found here (I don't speak Chinese so don't ask me what it says :). You have to set a hook. He provides a wrapper class. I repeat some code here without the Chinese characters. RegisterHotKey.cs ...
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TestKeydown
{
public class RegisterHotKeyClass
{
private IntPtr m_WindowHandle = IntPtr.Zero;
private MODKEY m_ModKey = MODKEY.MOD_CONTROL;
private Keys m_Keys = Keys.A;
private int m_WParam = 10000;
private bool Star = false;
private HotKeyWndProc m_HotKeyWnd = new HotKeyWndProc();
public IntPtr WindowHandle
{
get { return m_WindowHandle; }
set { if (Star)return; m_WindowHandle = value; }
}
public MODKEY ModKey
{
get { return m_ModKey; }
set { if (Star)return; m_ModKey = value; }
}
public Keys Keys
{
get { return m_Keys; }
set { if (Star)return; m_Keys = value; }
}
public int WParam
{
get { return m_WParam; }
set { if (Star)return; m_WParam = value; }
}
public void StarHotKey()
{
if (m_WindowHandle != IntPtr.Zero)
{
if (!RegisterHotKey(m_WindowHandle, m_WParam, m_ModKey, m_Keys))
{
throw new Exception("");
}
try
{
m_HotKeyWnd.m_HotKeyPass = new HotKeyPass(KeyPass);
m_HotKeyWnd.m_WParam = m_WParam;
m_HotKeyWnd.AssignHandle(m_WindowHandle);
Star = true;
}
catch
{
StopHotKey();
}
}
}
private void KeyPass()
{
if (HotKey != null) HotKey();
}
public void StopHotKey()
{
if (Star)
{
if (!UnregisterHotKey(m_WindowHandle, m_WParam))
{
throw new Exception("");
}
Star = false;
m_HotKeyWnd.ReleaseHandle();
}
}
public delegate void HotKeyPass();
public event HotKeyPass HotKey;
private class HotKeyWndProc : NativeWindow
{
public int m_WParam = 10000;
public HotKeyPass m_HotKeyPass;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312 && m.WParam.ToInt32() == m_WParam)
{
if (m_HotKeyPass != null) m_HotKeyPass.Invoke();
}
base.WndProc(ref m);
}
}
public enum MODKEY
{
MOD_ALT = 0x0001,
MOD_CONTROL = 0x0002,
MOD_SHIFT = 0x0004,
MOD_WIN = 0x0008,
}
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr wnd, int id, MODKEY mode, Keys vk);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr wnd, int id);
}
}
Calling code in a Form ...
private RegisterHotKeyClass _RegisKey = new RegisterHotKeyClass();
void _Regis_HotKey()
{
MessageBox.Show("ok");
}
private void Form1_Load(object sender, EventArgs e)
{
_RegisKey.Keys = Keys.PrintScreen;
_RegisKey.ModKey = 0;
_RegisKey.WindowHandle = this.Handle;
_RegisKey.HotKey += new RegisterHotKeyClass.HotKeyPass(_Regis_HotKey);
_RegisKey.StarHotKey();
}
Below is my pure WPF solution.
We can achieve this in xaml by using NavigationCommands (Namespace: System.Window.Input) class which provides a standard set of navigation commands (e.g. NextPage, PreviousPage, Refresh, Search etc.)
Implementation Approach:
So we can call any custom code to execute on application refresh using NavigationCommands.Refresh as
<UserControl.CommandBindings>
<CommandBinding Command='NavigationCommands.Refresh'
Executed="ApplicationRefresh_Executed">
</CommandBinding>
</UserControl.CommandBindings>
Now in code behind class of UserControl we can define method as
private void ApplicationRefresh_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Implementation goes here.
}