ListView onScroll event - c#

I’m programming one easy C# application, and i need onScroll event on Listview. So i created class ListviewEx witch inherits original ListView. I found how to detect scroll message from WinAPI and i modified WndProc method.
Now i have this WndProc:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_VSCROLL)
{
onScroll(this, new EventArgs());
}
}
But problem is, that I dont know how to detect information about scrolling. This data should be in WParam, but in C# is no LOWORD macro like in C++ and i need switch to detect parameters like SB_ BOTTOM, SB_ ENDSCROLL, SB_PAGEUP etc.
Is there any way how to replace LOWORD macro in C# ?
Or other way how to detect necessary parameters about scrolling?

Thanks for your answers. It really helped me :) Now I have what I wanted...
Here is code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
namespace ControlsEx
{
public class ListViewEx : ListView
{
// Windows messages
private const int WM_PAINT = 0x000F;
private const int WM_HSCROLL = 0x0114;
private const int WM_VSCROLL = 0x0115;
private const int WM_MOUSEWHEEL = 0x020A;
private const int WM_KEYDOWN = 0x0100;
private const int WM_LBUTTONUP = 0x0202;
// ScrollBar types
private const int SB_HORZ = 0;
private const int SB_VERT = 1;
// ScrollBar interfaces
private const int SIF_TRACKPOS = 0x10;
private const int SIF_RANGE = 0x01;
private const int SIF_POS = 0x04;
private const int SIF_PAGE = 0x02;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
// ListView messages
private const uint LVM_SCROLL = 0x1014;
private const int LVM_FIRST = 0x1000;
private const int LVM_SETGROUPINFO = (LVM_FIRST + 147);
public enum ScrollBarCommands : int
{
SB_LINEUP = 0,
SB_LINELEFT = 0,
SB_LINEDOWN = 1,
SB_LINERIGHT = 1,
SB_PAGEUP = 2,
SB_PAGELEFT = 2,
SB_PAGEDOWN = 3,
SB_PAGERIGHT = 3,
SB_THUMBPOSITION = 4,
SB_THUMBTRACK = 5,
SB_TOP = 6,
SB_LEFT = 6,
SB_BOTTOM = 7,
SB_RIGHT = 7,
SB_ENDSCROLL = 8
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch(m.Msg)
{
case WM_VSCROLL:
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(this.Handle, SB_VERT));
onScroll(this, sargs);
break;
case WM_MOUSEWHEEL:
ScrollEventArgs sarg = new ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(this.Handle, SB_VERT));
onScroll(this, sarg);
break;
case WM_KEYDOWN:
switch (m.WParam.ToInt32())
{
case (int)Keys.Down:
onScroll(this, new ScrollEventArgs(ScrollEventType.SmallDecrement, GetScrollPos(this.Handle, SB_VERT)));
break;
case (int)Keys.Up:
onScroll(this, new ScrollEventArgs(ScrollEventType.SmallIncrement, GetScrollPos(this.Handle, SB_VERT)));
break;
case (int)Keys.PageDown:
onScroll(this, new ScrollEventArgs(ScrollEventType.LargeDecrement, GetScrollPos(this.Handle, SB_VERT)));
break;
case (int)Keys.PageUp:
onScroll(this, new ScrollEventArgs(ScrollEventType.LargeIncrement, GetScrollPos(this.Handle, SB_VERT)));
break;
case (int)Keys.Home:
onScroll(this, new ScrollEventArgs(ScrollEventType.First, GetScrollPos(this.Handle, SB_VERT)));
break;
case (int)Keys.End:
onScroll(this, new ScrollEventArgs(ScrollEventType.Last, GetScrollPos(this.Handle, SB_VERT)));
break;
}
break;
}
}
public int ScrollPosition
{
get
{
return GetScrollPos(this.Handle, SB_VERT);
}
set
{
int prevPos;
int scrollVal;
if (ShowGroups == true)
{
prevPos = GetScrollPos(this.Handle, SB_VERT);
scrollVal = -(prevPos - value);
}
else
{
// TODO: Add setScrollPosition if ShowGroups == false
}
SendMessage(this.Handle, LVM_SCROLL, (IntPtr)0, (IntPtr)scrollVal);
}
}
public event ScrollEventHandler onScroll;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
[DllImport("user32.dll")]
public static extern int SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
long wParam, // first message parameter
long lParam // second message parameter
);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int wMsg,
int wParam, int lParam);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, uint wMsg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetScrollPos(IntPtr hWnd, int nBar);
[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
}
}

You can define WParam constants as followed:
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
private const int SB_HORZ = 0;
private const int SB_VERT = 1;
private const int SB_LINELEFT = 0;
private const int SB_LINERIGHT = 1;
private const int SB_PAGELEFT = 2;
private const int SB_PAGERIGHT = 3;
private const int SB_THUMBPOSITION = 4;
private const int SB_THUMBTRACK = 5;
private const int SB_LEFT = 6;
private const int SB_RIGHT = 7;
private const int SB_ENDSCROLL = 8;
private const int SIF_TRACKPOS = 0x10;
private const int SIF_RANGE = 0x1;
private const int SIF_POS = 0x4;
private const int SIF_PAGE = 0x2;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
The actual code to inspect the WParam would be something like this:
if (m.Msg == WM_VSCROLL)
{
ScrollInfoStruct si = new ScrollInfoStruct();
si.fMask = SIF_ALL;
si.cbSize = (uint)Marshal.SizeOf(si);
GetScrollInfo(msg.HWnd, SB_VERT, ref si);
if (msg.WParam.ToInt32() == SB_ENDSCROLL)
{
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.EndScroll, si.nPos);
onScroll(this, sargs);
}
}
pinvoke.net is a great site to get the constant values used in windows32 API without having to inspect header files yourself.
See this example

Martijn answer will work but will not catch all scrolling. The WM_VSCROLL message is only sent when the user manipulates the scroll bar directly. If the user scrolls using a mouse wheel, or uses the UpArrow/DownArrow/PageUp/PageDown keys, then the WM_VSCROLL will not be sent.
You can catch scrolling that is caused by the scroll bar and by the mouse wheel by listening for the LVN_BEGINSCROLL notification message.
Catching scrolling that occurs when using keys is harder. No message that is sent to the control when it scrolls in response to a PageUp key, for example. The best that can be done in that case is to listen for KeyPress events, and then check for changes to the scroll bar positions before and after the event.
This could, of course, be complete overkill for your purposes. The WM_VSCROLL message may be completely sufficient for what you want. But if you want to catch all possible scrolling, have a look at the code in ObjectListView which already has a Scroll event that catches all these possibilities.

#Klinki
Thank you for you cool contribution
I think you forgot to handle horizontal scroll
Case WM_HSCROLL
Dim sargs As New ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(Me.Handle, SB_HORZ))
RaiseEvent OnScroll(Me, sargs)
Exit Select

Related

how to connect mobile camera or other camera to the picture box in c#,winforms?

Started learning c# from past 1 month,I have a question that whether is it possibility to connect and display mobile camera or other web camera in the picture box.,in c# .net framework in windows forms. thanks in advance
You question is a bit too broad for this site. The answer is "Yes it is possible" but it is not as simple as writing a few lines of code in C#. You will need some kind of toolkit/library/framework that allows you to connect to the camera and display the video. There are tons of them out there, each having pros and cons, some simple, some complicated.
If you are using Visual Studio, in the Solution Explorer right-click on your Project name and select "Manage Nuget Packages". In the Window that opens select "Browse" and then type "camera" into the search box. You will see a number of packages that provide support for using cameras.
There are several ways to communicate with the camera.
I use this code to communicate with the camera.
public class CameraAPI
{
public bool IsAvailable { get; set; }
[DllImport("avicap32.dll")]
public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
[DllImport("avicap32.dll")]
public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, long lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, long lParam);
[System.Runtime.InteropServices.DllImport("user32")]
public static extern bool DestroyWindow(IntPtr hWnd);
public const int WM_USER = 0x400;
public const int WS_CHILD = 0x40000000;
public const int WS_VISIBLE = 0x10000000;
public const int SWP_NOMOVE = 0x2;
public const int SWP_NOZORDER = 0x4;
public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;
public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;
public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;
public const int WM_CAP_SET_PREVIEW = WM_USER + 50;
public const int WM_CAP_SET_PREVIEWFORMAT = WM_USER + 45;
public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;
public const int WM_CAP_START = WM_USER;
public const int WM_CAP_SAVEDIB = WM_CAP_START + 25;
public const int WM_CAP_EDIT_COPY = (WM_CAP_START + 30);
private IntPtr hWnd;
private IntPtr mControlPtr;
private int mWidth;
private int mHeight;
public CameraAPI(IntPtr handel, int width, int height)
{
mControlPtr = handel; //handle of video dom
mWidth = width; //video width
mHeight = height; //video height
}
public void StartPreviewWebcam()
{
if (hWnd != null)
DestroyWindow(hWnd);
byte[] lpszName = new byte[100];
byte[] lpszVer = new byte[100];
capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 0);
hWnd = capCreateCaptureWindowA(lpszName, WS_CHILD | WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);
if (SendMessage(hWnd, WM_CAP_DRIVER_CONNECT, 0, 0))
{
SendMessage(hWnd, WM_CAP_SET_PREVIEWRATE, 100, 0);
SendMessage(hWnd, WM_CAP_SET_PREVIEW, true, 0);
IsAvailable = true;
}
else
{
IsAvailable = false;
}
}
public void CloseWebcam()
{
SendMessage(hWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
IsAvailable = false;
}
public void SavePictureByPath(string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWnd, WM_CAP_SAVEDIB, 0, hBmp.ToInt64());
}
public byte[] TakePicture()
{
byte[] imgByteArray = null;
var path = Application.StartupPath + #"\Image.png";
try
{
DeleteExist(path);
SavePictureByPath(path);
if (File.Exists(path))
{
using (Image img = Image.FromFile(path))
{
imgByteArray = ImageToByteArray(img);
}
}
}
catch (Exception exp)
{
var a = 1;
}
finally
{
DeleteExist(path);
}
return imgByteArray;
}
public void DeleteExist(string path)
{
if (File.Exists(path))
{
File.Delete(path);
}
}
public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
using (var ms = new MemoryStream())
{
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
}

MouseKeyHook in C# can't detect left mouse click out of the form

first of all sorry if my english is not that good, this is my first post here, i am developing a C# windows form application, and i want to detect a click from outside the form ( on desktop or somethign else ). I am trying to use MouseKeyHook, because i think it is the solution for my problem, but i can't make it work.. here is my code ( i took it from https://github.com/gmamaladze/globalmousekeyhook, i also tried to replace globalevents to Hook.AppEvents. Anyone can help me to get this working?:
private IKeyboardMouseEvents m_GlobalHook;
public void Subscribe()
{
// Note: for the application hook, use the Hook.AppEvents() instead
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
m_GlobalHook.KeyPress += GlobalHookKeyPress;
}
private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
Console.WriteLine("KeyPress: \t{0}", e.KeyChar);
}
private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
{
Console.WriteLine("MouseDown: \t{0}; \t System Timestamp: \t{1}", e.Button, e.Timestamp);
// uncommenting the following line will suppress the middle mouse button click
// if (e.Buttons == MouseButtons.Middle) { e.Handled = true; }
}
public void Unsubscribe()
{
m_GlobalHook.MouseDownExt -= GlobalHookMouseDownExt;
m_GlobalHook.KeyPress -= GlobalHookKeyPress;
//It is recommened to dispose it
m_GlobalHook.Dispose();
}
I am using a class independant of type of program (winform, WPF and so on)
its an example:
using System;
using System.Runtime.InteropServices;
using HookInput.API;
namespace HookInput.Mouse
{
public class MouseInput
{
private const Int32 WM_MOUSEMOVE = 0x0200;
private const Int32 WM_LBUTTONDOWN = 0x0201;
private const Int32 WM_LBUTTONUP = 0x0202;
private const Int32 WM_LBUTTONDBLCLK = 0x0203;
private const Int32 WM_RBUTTONDOWN = 0x0204;
private const Int32 WM_RBUTTONUP = 0x0205;
private const Int32 WM_RBUTTONDBLCLK = 0x0206;
private const Int32 WM_MBUTTONDOWN = 0x0207;
private const Int32 WM_MBUTTONUP = 0x0208;
private const Int32 WM_MBUTTONDBLCLK = 0x0209;
private const Int32 WM_MOUSEWHEEL = 0x020A;
private const Int32 WM_XBUTTONDOWN = 0x020B;
private const Int32 WM_XBUTTONUP = 0x020C;
private const Int32 WM_XBUTTONDBLCLK = 0x020D;
private bool hooked = false;
private WindowsHookAPI.HookDelegate mouseDelegate;
private IntPtr mouseHandle;
private const Int32 WH_MOUSE_LL = 14;
public MouseInput()
{
mouseDelegate = MouseHookDelegate;
}
public void setHook(bool on)
{
if (hooked == on) return;
if (on)
{
mouseHandle = WindowsHookAPI.SetWindowsHookEx(WH_MOUSE_LL, mouseDelegate, IntPtr.Zero, 0);
if (mouseHandle != IntPtr.Zero) hooked = true;
}
else
{
WindowsHookAPI.UnhookWindowsHookEx(mouseHandle);
hooked = false;
}
}
private IntPtr MouseHookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam)
{
//VK_LBUTTON 0x01 Left mouse button
//VK_RBUTTON 0x02 Right mouse button
//VK_MBUTTON 0x04 Middle mouse button
//VK_XBUTTON1 0x05 X1 mouse button
//VK_XBUTTON2 0x06 X2 mouse button
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms644970(v=vs.85).aspx
//mouseData:
//If the message is WM_MOUSEWHEEL, the high-order word of this member is the wheel delta.The low-order word is reserved.
// A positive value indicates that the wheel was rotated forward, away from the user;
// a negative value indicates that the wheel was rotated backward, toward the user.
// One wheel click is defined as WHEEL_DELTA, which is 120.(0x78 or 0xFF88)
//If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, or WM_NCXBUTTONDBLCLK,
// the high - order word specifies which X button was pressed or released,
// and the low - order word is reserved.This value can be one or more of the following values.Otherwise, mouseData is not used.
//XBUTTON1 = 0x0001 The first X button was pressed or released.
//XBUTTON2 = 0x0002 The second X button was pressed or released.
MSLLHOOKSTRUCT lparam = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
int command = (int)wParam;
if (Code < 0 || command == WM_LBUTTONDBLCLK || command == WM_RBUTTONDBLCLK)
return WindowsHookAPI.CallNextHookEx(mouseHandle, Code, wParam, lParam);
if (command == WM_MOUSEMOVE)
{
Console.WriteLine($"x:{lparam.pt.x} y:{lparam.pt.y}");
}
else if (command == WM_LBUTTONDOWN || command == WM_LBUTTONUP)
{
if (command == WM_LBUTTONDOWN)
{
//do something
}
else
{
//do something
}
}
else if (command == WM_RBUTTONDOWN || command == WM_RBUTTONUP)
{
if (command == WM_RBUTTONDOWN)
{
//do something
}
else
{
//do something
}
}
else if (command == WM_MBUTTONDOWN || command == WM_MBUTTONUP)
{
if (command == WM_MBUTTONDOWN)
{
//do something
}
else
{
//do something
}
}
else if (command == WM_MOUSEWHEEL)
{
int wheelvalue = (Int16)(lparam.mouseData >> 16) < 0 ? -120 : 120; // Forward = 120, Backward = -120
}
return WindowsHookAPI.CallNextHookEx(mouseHandle, Code, wParam, lParam);
}
~MouseInput()
{
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
}
}
the file API:
using System;
using System.Runtime.InteropServices;
namespace HookInput.API
{
public class WindowsHookAPI
{
//public delegate IntPtr HookDelegate(
// Int32 Code, IntPtr wParam, IntPtr lParam);
public delegate IntPtr HookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hHook, Int32 nCode, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook);
[DllImport("User32.dll")]
public static extern IntPtr SetWindowsHookEx(Int32 idHook, HookDelegate lpfn, IntPtr hmod, Int32 dwThreadId);
}
}
you can instance the class
private MouseInput mouseInputHook = null;
mouseInputHook = new MouseInput();
mouseInputHook.setHook(true); // to activate the mousehook
:
:
mouseInputHook.setHook(false); // to desactivate the mousehook

Every other window freezes after replacing mouse action - c#

I'm writing an application that binds custom actions to my mouse buttons. For example, I connected the volume up to one of the thumb buttons. Everything works fine as long as I stay in one window because every other windows and the taskbar seems to freeze and it will take some time before the windows are activated again or if I kill my application or the window I am working in.
In the code below I capture the mouse events and check with the settings in the application if the button action is still default or if it has changed. If the action has changed, then the application should for example turn the volume up with two.
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public static bool usingKeyboard = false;
public static bool leftButtonDown = false;
static int hMHook;
public const int WH_MOUSE_LL = 14;
//Declare MouseHookProcedure as a HookProc type.
static HookProc MouseHookProcedure;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_XBUTTONDOWN = 0x020B,
WM_XBUTTONUP = 0x020C,
WM_MBUTTONUP = 0x0208,
WM_MBUTTONDOWN = 0x0207
}
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);
private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
MouseUsageMessage message = new MouseUsageMessage(1);
MouseUsageManager.mouseUsageMessageQueue.Add(message);
if (nCode >= 0)
{
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
leftButtonDown = true;
} else if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
leftButtonDown = false;
} else if (MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
{
} else if (MouseMessages.WM_RBUTTONUP == (MouseMessages) wParam) {
} else if (MouseMessages.WM_XBUTTONUP == (MouseMessages)wParam)
{
switch (MyMouseHookStruct.hwnd)
{
case 65536:
if (Settings.Default.thumbClick1User != Settings.Default.thumbClick1Default)
{
ExecuteAction(Settings.Default.thumbClick1User);
return 1;
}
break;
case 131072:
if (Settings.Default.thumbClick2User != Settings.Default.thumbClick2Default)
{
ExecuteAction(Settings.Default.thumbClick2User);
return 1;
}
break;
}
} else if (MouseMessages.WM_MBUTTONDOWN == (MouseMessages)wParam)
{
}
}
return CallNextHookEx(hMHook, nCode, wParam, lParam);
}
Why are the other windows freezing or why can't I use my mouse on the other windows after I've clicked the thumb buttons?
EDIT: Additional code
private void ExecuteAction(string setting)
{
VolumeControl vc = new VolumeControl();
Keybindings kb = new Keybindings();
switch (setting)
{
case "volUp":
vc.VolUp();
break;
case "volDown":
vc.VolDown();
break;
case "cut":
kb.Cut();
break;
case "selectAll":
kb.SelectAll();
break;
case "copy":
kb.Copy();
break;
default:
break;
}
}
The setting string that is sended to the ExecuteAction function is just a string with the action to be performed, i.e. copy, volume up, volume down etc.
VolumeControl class:
public class VolumeControl
{
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
public void VolDown()
{
SendMessageW(handle, WM_APPCOMMAND, handle,
(IntPtr)APPCOMMAND_VOLUME_DOWN);
}
public void VolUp()
{
SendMessageW(handle, WM_APPCOMMAND, handle,
(IntPtr)APPCOMMAND_VOLUME_UP);
}
}
Create Hook function, the function that is called when the class is initialized:
private void createHook()
{
while (hMHook == 0) //|| hKHook == 0)
{
//if (hMHook == 0)
//{
//hMHook = SetWindowsHookEx(WH_MOUSE_LL,
//MouseHookProcedure,
//GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
//(IntPtr)0,
//0);
//}
if (hMHook == 0)
{
hMHook = SetWindowsHookEx(WH_MOUSE_LL,
MouseHookProcedure,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
0);
}
if (hMHook == 0) //|| hKHook == 0)
{
Console.WriteLine("SetWindowsHookEx Failed");
return;
}
Console.WriteLine("Hooked");
}
}
My solution, i have built a simple console project
when you launch program, the hook is activated, and you can toggle with middle mouse button. the right button up and letf button up play with system volume..
the main program:
using HookInput.API;
using HookInput.Mouse;
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace ConsoleApp3
{
public class Program
{
private static MouseInput mouseInputHook = null;
static void Main(string[] args)
{
var vc = new VolumeControl();
mouseInputHook = new MouseInput(vc);
mouseInputHook.setHook(true);
Console.WriteLine("hook activated");
Application.Run(new ApplicationContext());
}
}
public class VolumeControl
{
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
public IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
public void VolDown()
{
WindowsHookAPI.SendMessageW(handle, WM_APPCOMMAND, handle, (IntPtr)APPCOMMAND_VOLUME_DOWN);
}
public void VolUp()
{
WindowsHookAPI.SendMessageW(handle, WM_APPCOMMAND, handle, (IntPtr)APPCOMMAND_VOLUME_UP);
}
}
}
the APIs:
using System;
using System.Runtime.InteropServices;
namespace HookInput.API
{
public class WindowsHookAPI
{
//public delegate IntPtr HookDelegate(
// Int32 Code, IntPtr wParam, IntPtr lParam);
public delegate IntPtr HookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hHook, Int32 nCode, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr UnhookWindowsHookEx(IntPtr hHook);
[DllImport("User32.dll")]
public static extern IntPtr SetWindowsHookEx(Int32 idHook, HookDelegate lpfn, IntPtr hmod, Int32 dwThreadId);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}
}
the hook and structures:
using HookInput.API;
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using ConsoleApp3;
namespace HookInput.Mouse
{
public class MouseInput
{
private const Int32 WM_MOUSEMOVE = 0x0200;
private const Int32 WM_LBUTTONDOWN = 0x0201;
private const Int32 WM_LBUTTONUP = 0x0202;
private const Int32 WM_LBUTTONDBLCLK = 0x0203;
private const Int32 WM_RBUTTONDOWN = 0x0204;
private const Int32 WM_RBUTTONUP = 0x0205;
private const Int32 WM_RBUTTONDBLCLK = 0x0206;
private const Int32 WM_MBUTTONDOWN = 0x0207;
private const Int32 WM_MBUTTONUP = 0x0208;
private const Int32 WM_MBUTTONDBLCLK = 0x0209;
private const Int32 WM_MOUSEWHEEL = 0x020A;
private const Int32 WM_XBUTTONDOWN = 0x020B;
private const Int32 WM_XBUTTONUP = 0x020C;
private const Int32 WM_XBUTTONDBLCLK = 0x020D;
private MemoryMappedViewAccessor accessor;
private bool hooked = false;
private WindowsHookAPI.HookDelegate mouseDelegate;
private IntPtr mouseHandle;
private const Int32 WH_MOUSE_LL = 14;
private readonly VolumeControl vc;
public MouseInput(VolumeControl vc)
{
this.vc = vc;
}
public void setHook(bool on)
{
if (hooked == on) return;
if (on)
{
mouseDelegate = MouseHookDelegate;
mouseHandle = WindowsHookAPI.SetWindowsHookEx(WH_MOUSE_LL, mouseDelegate, IntPtr.Zero, 0);
if (mouseHandle != IntPtr.Zero) hooked = true;
}
else
{
WindowsHookAPI.UnhookWindowsHookEx(mouseHandle);
hooked = false;
}
}
private IntPtr MouseHookDelegate(Int32 Code, IntPtr wParam, IntPtr lParam)
{
//mouseData:
//If the message is WM_MOUSEWHEEL, the high-order word of this member is the wheel delta.The low-order word is reserved.
// A positive value indicates that the wheel was rotated forward, away from the user;
// a negative value indicates that the wheel was rotated backward, toward the user.
// One wheel click is defined as WHEEL_DELTA, which is 120.(0x78 or 0xFF88)
//If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, or WM_NCXBUTTONDBLCLK,
// the high - order word specifies which X button was pressed or released,
// and the low - order word is reserved.This value can be one or more of the following values.Otherwise, mouseData is not used.
//XBUTTON1 = 0x0001 The first X button was pressed or released.
//XBUTTON2 = 0x0002 The second X button was pressed or released.
MSLLHOOKSTRUCT lparam = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
int command = (int)wParam;
if (Code < 0 || command == WM_LBUTTONDBLCLK || command == WM_RBUTTONDBLCLK)
return WindowsHookAPI.CallNextHookEx(mouseHandle, Code, wParam, lParam);
else if (command == WM_XBUTTONDOWN || command == WM_XBUTTONUP)
{
int numbutton = ((int)lparam.mouseData >> 16) - 1;
//return (IntPtr)1;
}
else if (command == WM_LBUTTONDOWN || command == WM_LBUTTONUP)
{
if (command == WM_LBUTTONUP)
{
vc.VolDown();
Console.WriteLine("L down");
}
}
else if (command == WM_RBUTTONDOWN || command == WM_RBUTTONUP)
{
if (command == WM_RBUTTONUP)
{
vc.VolUp();
Console.WriteLine("L Up");
}
}
else if (command == WM_MBUTTONDOWN || command == WM_MBUTTONUP)
{
if (hooked)
{
setHook(false);
Console.WriteLine("hook deactivated");
}
else
{
setHook(true);
Console.WriteLine("hook activated");
}
}
else if (command == WM_MOUSEWHEEL)
{
}
return WindowsHookAPI.CallNextHookEx(mouseHandle, Code, wParam, lParam);
}
~MouseInput()
{
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
}
}

Create a full screen application

We want our application to run in full screen mode with no title bar on a Win CE 5.0 powered device. The application is being developed using .NET Compact Framework 3.5 (C#).
I have followed this tutorial, but I encountered an error. Here is my code:
namespace DatalogicDeviceControl
{
public partial class Form1 : Form
{
public const int SWP_ASYNCWINDOWPOS = 0x4000;
public const int SWP_DEFERERASE = 0x2000;
public const int SWP_DRAWFRAME = 0x0020;
public const int SWP_FRAMECHANGED = 0x0020;
public const int SWP_HIDEWINDOW = 0x0080;
public const int SWP_NOACTIVATE = 0x0010;
public const int SWP_NOCOPYBITS = 0x0100;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOOWNERZORDER = 0x0200;
public const int SWP_NOREDRAW = 0x0008;
public const int SWP_NOREPOSITION = 0x0200;
public const int SWP_NOSENDCHANGING = 0x0400;
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_SHOWWINDOW = 0x0040;
public const int HWND_TOP = 0;
public const int HWND_BOTTOM = 1;
public const int HWND_TOPMOST = -1;
public const int HWND_NOTOPMOST = -2;
public Form1()
{
InitializeComponent();
HideStartBar();
}
[DllImport("coredll.dll", EntryPoint = "FindWindowW", SetLastError = true)]
private static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
public void HideStartBar()
{
IntPtr handle;
try
{
// Find the handle to the Start Bar
handle = FindWindowCE("HHTaskBar", null);
// If the handle is found then hide the start bar
if (handle != IntPtr.Zero)
{
// Hide the start bar
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW);
}
}
catch
{
MessageBox.Show("Could not hide Start Bar.");
}
}
}
}
I have encountered the following error:
The best overloaded method match for 'DatalogicDeviceControl.Form1.SetWindowPos(System.IntPtr, int, int, int, int, uint)' has some invalid arguments
#dzerow: Your answer is correct: Windows Mobile does not support the user32.dll library.
Use the coredll.dll library instead.
private const int SRCCOPY = 0x00CC0020;
private const string CORE_DLL = "coredll.dll";
private static IntPtr _taskBar;
private static IntPtr _sipButton;
private static string _deviceId, _deviceIp;
private static DateTime _lastUpdateCheck, _startTime;
[DllImport(CORE_DLL)]
public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
[DllImport(CORE_DLL)]
public static extern bool CeRunAppAtEvent(string appName, int Event);
[DllImport(CORE_DLL, EntryPoint = "FindWindowW", SetLastError = true)]
public static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
[DllImport(CORE_DLL)]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport(CORE_DLL)]
public static extern bool MessageBeep(int uType);
[DllImport(CORE_DLL, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
Below is a lot of the code from an application I used to manage. Parts of it may be incomplete and there could be too much info. If something is missing, just comment and I will fill that in.
Basically, the routine I have written enables you to call ShowWindowsMenu(bool enable) to either enable or disable the HHTaskBar (task bar) and the MS_SIPBUTTON (soft input button).
public static void ShowWindowsMenu(bool enable) {
try {
if (enable) {
if (_taskBar != IntPtr.Zero) {
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_taskBar = FindWindowCE("HHTaskBar", null); // Find the handle to the Start Bar
if (_taskBar != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show Start" : "Hide Start", err);
}
try {
if (enable) {
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_sipButton = FindWindowCE("MS_SIPBUTTON", "MS_SIPBUTTON");
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show SIP" : "Hide SIP", err);
}
}
Be sure to turn these features back on when your program exits, or the user will have to reboot the device to get those re-enabled.
EDIT: I forgot the WindowPosition enumerated value I created:
public enum WindowPosition {
SWP_HIDEWINDOW = 0x0080,
SWP_SHOWWINDOW = 0x0040
}
Sorry about that.
Anything else?
Unfortunately Windows Mobile doesn't contain user32.dll, as well as many other normal Windows API DLLs. I had to P/Invoke into coredll.dll instead. For signatures, see PInvoke.net's section (at the bottom left) for "Smart Device Functions".

How to simulate a mouse click on a started process

I am trying to open an application through C# using Process.Start() and then simulate a mouse click on the application.
When I run the application, the mouse click occurs in the left top corner, which is not what I want.
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, int dx, int dy,
int dwData, int dwExtraInfo);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private const int MOUSEEVENTF_ABSOLUTE = 0x8000;
private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
private const int MOUSEEVENTF_LEFTUP = 0x0004;
private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
private const int MOUSEEVENTF_MOVE = 0x0001;
private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const int MOUSEEVENTF_RIGHTUP = 0x0010;
private const int MOUSEEVENTF_WHEEL = 0x0800;
private const int MOUSEEVENTF_XDOWN = 0x0080;
private const int MOUSEEVENTF_XUP = 0x0100;
private void button1_Click(object sender, EventArgs e)
{
new Thread(() =>
{
AddTextToListBox1(label1);
}).Start();
new Thread(() =>
{
// AddTextToListBox2(label2);
}).Start();
}
private void AddTextToListBox1(Label label)
{
if (label1.InvokeRequired)
{
stringDelegate sd = new stringDelegate(AddTextToListBox1);
this.Invoke(sd, new object[] { label1 });
}
else
{
label1.Text = this.ToString()+"Hi";
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "C://xyz//xyz.exe";
p.Start();
IntPtr hwnd = p.MainWindowHandle;
}
}
private void AddTextToListBox2(Label label)
{
if (label1.InvokeRequired)
{
stringDelegate sd = new stringDelegate(AddTextToListBox2);
this.Invoke(sd, new object[] { label1 });
}
else
{
label2.Text = "done";
Thread.Sleep(6000);
int X = 579;
int Y = 637;
mouse_event(MOUSEEVENTF_ABSOLUTE| MOUSEEVENTF_MOVE, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
}
I think mouse_event will only raise event in current app because it doesn't take hwnd on params. My experience in this area is really low, but I've done some research. Look at SendMessage function.
MSDN article:
Sends the specified message to a window or windows.
The SendMessage function calls the window procedure for the specified window
and does not return until the window procedure has processed the message.
You can send many messages with it, including mouse events

Categories