I have a small application I wrote that simply displays a preview of webcam or my capture card. At the moment it works exactly how I want it to, with the exception that the capture card displays at a much lower framerate than I'd like it to.
Here is my relevant code:
private const int WM_CAP_DRIVER_CONNECT = 1034;
private const int WM_CAP_SET_PREVIEW = 1074;
private const int WM_CAP_SET_PREVIEWRATE = 1076;
private const int WM_CAP_SET_SCALE = 1077;
private const int WS_CHILD = 1073741824;
private const int WS_VISIBLE = 268435456;
private const short SWP_NOMOVE = 2;
private const short SWP_NOZORDER = 4;
private const short HWND_BOTTOM = 1;
private const int iDevice = 0;
private int hHwnd;
private int previewRate = 34;
private int width = 640;
private int height = 480;
[DllImport("user32.dll", EntryPoint="SendMessageA")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll", EntryPoint="SetWindowPos")]
static extern int SetWindowPos(int hwnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
[DllImport("user32.dll")]
static extern bool DestroyWindow(int hndw);
[DllImport("avicap32.dll")]
public static extern int capCreateCaptureWindow(string lpszWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int hwndParent, int nID);
private void OpenPreviewWindow()
{
hHwnd = capCreateCaptureWindow(iDevice.ToString(), (WS_VISIBLE | WS_CHILD), 0, 0, width, height, Handle.ToInt32(), 0);
// Connect to device
if (SendMessage(hHwnd, WM_CAP_DRIVER_CONNECT, iDevice, 0) != -1)
{
SendMessage(hHwnd, WM_CAP_SET_SCALE, 1, 0);
SendMessage(hHwnd, WM_CAP_SET_PREVIEWRATE, previewRate, 0);
SendMessage(hHwnd, WM_CAP_SET_PREVIEW, 1, 0);
SetWindowPos(hHwnd, HWND_BOTTOM, 0, 0, width, height, (SWP_NOMOVE | SWP_NOZORDER));
}
else
{
DestroyWindow(hHwnd);
}
}
When I preview the capture card in an application like FMLE, it previews at 30 FPS, which is my target framerate (~34 milliseconds per frame,) however when I use my application to preview it's closer to 10-15 FPS. I should probably also note that my program will preview 30 FPS from my webcam. What could be causing the problem with the capture card, and how can I fix it?
Use DirectShow to view the webcam.
An example would be: http://www.codeproject.com/KB/audio-video/WebcamUsingDirectShowNET.aspx
or http://www.codeproject.com/KB/miscctrl/webcam_c_sharp.aspx
Related
I'm trying to learn a few things, but I'm kinda stuck and I don't know where to go from here. I'm either blind or just confused.
I've been looking at some scripts from here: Answers.Unity
Right now, I got the background transparency working on my main screen, but I'm wondering what I should do to make this happen on my second monitor too. Or third, if I had one. As of right now the other screens turn black. This is the code:
[SerializeField]
private Material m_Material;
[SerializeField]
private Camera mainCamera;
private bool clickThrough = true;
private bool prevClickThrough = true;
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const int HWND_TOPMOST = -1;
int fWidth;
int fHeight;
IntPtr hwnd;
MARGINS margins;
public bool OverUI()
{ //Use sparingly
//Set up the new Pointer Event
PointerEventData m_PointerEventData = new PointerEventData(EventSystem.current);
m_PointerEventData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(m_PointerEventData, results);
if (results.Count > 0) return true;
return false;
}
void Start()
{
fWidth = Screen.width;
fHeight = Screen.height;
margins = new MARGINS() { cxLeftWidth = -1 };
hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
DwmExtendFrameIntoClientArea(hwnd, ref margins);
Application.runInBackground = true;
}
void Update()
{
// If our mouse is overlapping an object
RaycastHit hit = new RaycastHit();
clickThrough = !Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition).origin,
mainCamera.ScreenPointToRay(Input.mousePosition).direction, out hit, 100,
Physics.DefaultRaycastLayers) && !OverUI();
if (clickThrough != prevClickThrough)
{
if (clickThrough)
{
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowLong (hwnd, -20, (uint)524288 | (uint)32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes (hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
}
else
{
SetWindowLong (hwnd, -20, ~(((uint)524288) | ((uint)32)));//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
}
prevClickThrough = clickThrough;
}
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
Could anyone guide me a little bit so that I can figure this out?
Edit: I've figured out a little bit.. I think.
When Unity opens, (with multiple displays), it creates two windows in the task bar. I'm guessing I need to find that other window, set it as active and then run something similar to this code again. But I'm guessing I would need to fix the pos and margins before doing so.
It's beyond my understanding of WinApi right now, but I hope someone knows a bit more about this than me.
I need to make some automatic clicks in certain positions, but when I put the method inside the FOR the click action is only executed in the last loop.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
//Mouse actions
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public void DoMouseClick()
{
// Call the imported function with the cursor's current position
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public static void MoveCursorToPoint(int x, int y)
{
SetCursorPos(x, y);
}
How I wish to use:
for (int i = 0; i <= 3; i++)
{
MoveCursorToPoint(100, 100);
DoMouseClick();
}
The click action works perfectly, however when I put in some loop the program only clicks when it is in the last loop.
How to do the click action whenever it is requested inside the looping?
It may be happening too fast. Try adding a small delay after the click event to allow the OS to have time to process it before firing more.
Please let me elaborate what I am doing.
I am creating a screen share application. Where there are 2 apps first is a windows application (whose screen is getting shared) and the other is a browser web app (On which the user is watching the screen). The browser web app is sending client x and y coordinates of the mouse to the windows app. The windows app is using the x and y coordinates to move the mouse using the given below code.
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public static void MoveCursorToPoint(int x, int y)
{
SetCursorPos(x, y);
}
The browser app is also sending mouse clicks and the windows app is performing the clicks using the given below code.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public static void DoMouseClick()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Problem/Challenge
The problem or a challenge here is to perform the drag operation. For an example how will I drag the window of any application from one place to the another place from C# code.
Many thanks for your attention.
Finally, here is the code that will do all the system mouse events. In order to perform the drag and drop operation, you will need to First Send MouseDown(Mouse Click) and keep it Clicked While Changing the Mouse Position than Send MouseUp(Release Click) something like this.
MouseHelper mh = new MouseHelper();
mh.sendMouseDown();
Cursor.Position = new Point(30, 30);
mh.sendMouseUp();
Here is the whole helper file
public class MouseHelper
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
//public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
private const uint MOUSEEVENTF_RIGHTUP = 0x10;
public void sendMouseRightclick(Point p)
{
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, (uint)0, (uint)0);
}
public void sendMouseDoubleClick(Point p)
{
mouse_event((uint)MOUSEEVENTF_LEFTDOWN | (uint)MOUSEEVENTF_LEFTUP, (uint)p.X, (uint)p.Y, (uint)0, (uint)0);
Thread.Sleep(150);
mouse_event((uint)MOUSEEVENTF_LEFTDOWN | (uint)MOUSEEVENTF_LEFTUP, (uint)p.X, (uint)p.Y, 0, 0);
}
public void sendMouseRightDoubleClick(Point p)
{
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, 0, 0);
Thread.Sleep(150);
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, 0, 0);
}
public void sendMouseDown()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0);
}
public void sendMouseUp()
{
mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0);
}
}
Source The given code at this source link will give an error
Additional Information: A call to PInvoke function 'KinectHandTrackmyApping!myApp.MainWindow::mouse_event' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
In order resolve the error I have changed
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
to this
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
The error was usage of long because long gives an exception because it's a 64-bit, uint works because it's 32-bit -- but it won't work for negative coordinates (which is a common monitor setup in Windows).
I'm using a c# code to click on other process window,It's work great but it doesn't work when i want to click in Bluestack(Android Emulator) window.
any idea ?
the code :
[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public void DoMouseClick()
{
//Call the imported function with the cursor's current position
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
Maybe you need to make a virtual mouse device to work correctly
It will be difficult to make maybe try to use external DLLs
I have a program that simulates mouse click.
Code is something like this:
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
public static void DoMouseClick(int x, int y)
{
Cursor.Position = new Point(x, y);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}
This code works perfectly. For example I call this function every 30 minutes. But if I press WINKEY+L (Windows is locked) only cursor is moved but not press occurs.
Any ideas?
The Login screen on windows is designed to NOT allow clicks and automation of UI, as a security feature, IIRC