I want to make mousescroll volume up and down event when the player is playing, but when the player starting the videofile, the focus is gone. How can i "force focus" to the volume trackbar?
What you could do is install a MessageFilter on your form. This will get you any mouse input before VLC's control.
Have your form implement IMessageFilter and the PreMessageFilter method which will get you your mousewheel. The paramater is a Win32 message. Here's some info on the WM_MOUSEWHEEL event.
public partial class Form1 : Form, IMessageFilter
public bool PreFilterMessage(ref Message m)
{
const int WM_MOUSEWHEEL = 0x020A;
if (m.Msg == WM_MOUSEWHEEL)
{
// The wheeldelta is stored in the highorder of WParam.
// The value of which will be 120 (positive for forward, negative for backward).
int hiWord = m.WParam.ToInt32() >> 16;
// So use the delta as a way to increment/decrement the volume
this.axVLCPlugin21.volume += 10 * (hiWord / 120);
Trace.WriteLine("vol: " + this.axVLCPlugin21.volume);
}
return false;
}
And also don't forget to register the message filter with the Application. You can do this in your form's constructor.
public Form1()
{
Application.AddMessageFilter(this);
InitializeComponent();
}
Related
I'm developing a custom form that provides more options to customize the appearance of the form. I have override the wndproc and calculated the size of the form in calcsize()method while getting message 131 in wndproc. I have done the calculation to customize the height of the titlebar in calcsize().Please refer the following code below.The problem is while opening the form with borderstyle sizeablewindowtool in windows 10 and 8,the form goes inside the taskbar(its a behavior of the msdn form).But the problem is while im opening the form in the windows 7, the form goes inside the taskbar.I have checked with the msdn form its not going inside the taskbar for windows 7. Please help me to find my mistake.
/// <summary>
/// Calculates the non client area of the form
/// </summary>
/// <param name="m">reference message</param>
/// <returns>retruns true if the method returns combiantion of values
/// returns false if the method return zero</returns>
private bool OnWmNcCalcSize(ref Message m)
{
NativeMethods.RECT rc = (NativeMethods.RECT)m.GetLParam(typeof(NativeMethods.RECT));
int iBorderWidth = fl.BorderWidth;
fl.PerformLayout(rc.Width, rc.Height);
rc.top += fl.CaptionHeight;
if (this.WindowState == FormWindowState.Maximized)
{
///<summary>
/// local variable to store x-coordinate of native rectangle,rc.left is -6 when we double click on title-bar and -8 when we click the maximize button.
///</summary>
int xcoordinate = rc.left;
rc.left -= xcoordinate;
rc.right += xcoordinate;
rc.bottom += xcoordinate;
}
else
{
rc.left += iBorderWidth - (iBorderWidth / 3);
rc.right -= iBorderWidth - (iBorderWidth / 3);
rc.bottom -= iBorderWidth - (iBorderWidth / 3);
}
Marshal.StructureToPtr(rc, m.LParam, true);
m.Result = IntPtr.Zero;
return true;
}
I am having the Problem, that if I alter the LParam of a WM_MOVING message to keep my Form at a certain position, which is legal according to this , the Windows Aero Shake feature gets triggered and all other Windows minimize. The behaviour can be reproduced by creating a Windows Forms Project in Visual Studio and pasting the following code into the Form:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace FormsTest
{
public partial class ShakeTest : Form
{
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public const int WM_MOVING = 0x0216;
public ShakeTest()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_MOVING:
{
RECT rec;
rec.bottom = 500;
rec.left = 100;
rec.top = 100;
rec.right = 500;
Marshal.StructureToPtr(rec, m.LParam, true);
m.Result = new IntPtr(1);
}
break;
}
base.WndProc(ref m);
}
}
}
If you now grab the Window's title bar and move the mouse around a bit, the Shake gesture should get triggered, even though the Window isn't moving at all.
I tested this on Windows 10 only so far.
So my question is, can i disable the Shake feature for a certain Window or Process? If not, can i prevent Windows from thinking that im shaking the Window any other Way?
Thanks!
Frankly, I don't know if that is possible to disable Aero Shake for a particular window. But I can suggest a workaround that will prevent the Aero Shake from triggering.
There's a possibility to direct all the mouse input to only one window (and this will also hide the mouse events from the Aero Shake handler). Check the SetCapture description at MSDN. Also we will need a GetCapture and ReleaseCapture functions.
There's one remark: once you have set the mouse capture to a window - you are responsible for handling all the mouse input. So to achieve the goal you'll need to implement your own handler that will move the window. Fortunately, it's not that difficult.
Here's a code sample with a dialog that changes its size when it gets moving and restores the size when the moving is finished. Aero Shake is also never triggered.
public partial class ShakeTest : Form
{
[DllImport("user32.dll")]
static extern IntPtr SetCapture(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetCapture();
[DllImport("user32.dll")]
static extern bool ReleaseCapture();
public const int WM_LBUTTONUP = 0x0202;
public const int WM_MOUSEMOVE = 0x0200;
public const int WM_NCLBUTTONDOWN = 0x00A1;
public const int HTCAPTION = 2;
private Point _lastCursorPos;
private Size _origianlSize;
public ShakeTest()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
// We need to get the moment when the user clicked on a non-client area
case WM_NCLBUTTONDOWN:
// We are interested only in a click on a title bar
if ((int) m.WParam == HTCAPTION)
{
// Set the capture so all the mouse input will be handled by this window
SetCapture(Handle);
// Keep the current cursor position to use it during the moving.
_lastCursorPos = Cursor.Position;
// Keep the original window size.
_origianlSize = Size;
// And change the dialog size to whatever you want
Size = new Size(300, 300);
}
break;
// Once we got the capture, we need to handle mouse moving by ourself
case WM_MOUSEMOVE:
// Check that our window has the capture
if (GetCapture() == Handle)
{
// Change the position of a window
Left += Cursor.Position.X - _lastCursorPos.X;
Top += Cursor.Position.Y - _lastCursorPos.Y;
_lastCursorPos = Cursor.Position;
}
break;
// When the left mouse button is released - it's time to release the mouse capture
case WM_LBUTTONUP:
// Check that our window has the capture
if (GetCapture() == Handle)
{
// Release the mouse capture
ReleaseCapture();
// Restore the size
Size = _origianlSize;
}
break;
}
base.WndProc(ref m);
}
}
There is a window display setting called 'Show window contents while dragging'.
http://www.thewindowsclub.com/disable-show-windows-contents-while-dragging
When this setting is turned on, if you drag a window the window will immediately repaint at the new position. If you resize a window, it will repaint the window for each new window size immediately, even if you are still holding down the mouse button.
When the setting is turned off, dragging or resizing the window simply shows an outline of the new window position or size until you release the mouse button and then it will paint the window at the new position or size.
I would like to display my forms in my C# WinForms application with 'Show window contents while dragging' setting turned off. However as this is an operating setting, I would only like this to be effective for when my forms are displayed regardless of what the setting is set to in the OS.
Is there a way to achieve this using some WinAPI calls to change the behavior specifically for my winforms?
If not, is there a way that I can change the setting programatically before my form is displayed and reset it after my form has closed? Would performing this change require admin rights (because I don't want that)?
The following code below will use the system setting of 'Show window content while dragging' for window re-positioning, while it will temporarily set it to off, while resizing the window and then set it back to the system setting.
This gives you flicker free form resizing in windows forms.
Since this property is a user setting that modifies the HKEY_CURRENT_USER\Control Panel\Desktop\DragFullWindows registry key, it should not require admin rights.
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", CharSet = CharSet.Auto)]
public static extern int GetSystemParametersInfo(int uAction, int uParam, out int lpvParam, int fuWinIni);
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", CharSet = CharSet.Auto)]
public static extern int SetSystemParametersInfo(int uAction, int uParam, int lpvParam, int fuWinIni);
private const int SPI_GETDRAGFULLWINDOWS = 38;
private const int SPI_SETDRAGFULLWINDOWS = 37;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_SIZE = 0xF000;
//change 'Show window content while dragging' to false while resizing
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND && (m.WParam.ToInt32() & 0xfff0) == SC_SIZE)
{
int isDragFullWindow;
GetSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, out isDragFullWindow, 0);
if (isDragFullWindow != 0)
SetSystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 0, 0, 0);
base.WndProc(ref m);
if (isDragFullWindow != 0)
SetSystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 1, 0, 0);
}
else
{
base.WndProc(ref m);
}
}
//reduce control flickering and black stripes when window is resized
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
The OS is Windows 8 on a Retina Macbook PRO.
i need to support both vertical scrolling using the trackpad and horizontal scrolling in my app.
I would like to move the WPF scrollviewer position based on the two finger swipes up-down (vertical scrolling) and left-right (horizontal scrolling).
As far as i see the vertical scrolling on the trackpad gets translated to a mouse wheel event in the framework. However, I found no way to recognize if a mouse wheel event is a horizontal scroll.
what events should i handle in WPF to be able to implement this?
I wrote an article especially for you to know how to handle horizontal scrolling of touchpad in a WPF application. That is Support Horizontal Scrolling of TouchPad in WPF Application - walterlv
We need to fetch WM_MOUSEHWHEEL message from our WPF window. Yes! That mouse wheel message. We fetch vertical data from it before, but we now fetch horizontal data from it.
At first, we should hook the window message.
protected override void OnSourceInitialized(EventArgs e)
{
var source = PresentationSource.FromVisual(_board);
((HwndSource) source)?.AddHook(Hook);
}
private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle window message here.
return IntPtr.Zero;
}
Next, handle WM_MOUSEHWHEEL:
const int WM_MOUSEHWHEEL = 0x020E;
private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_MOUSEHWHEEL:
int tilt = (short) HIWORD(wParam);
OnMouseTilt(tilt);
return (IntPtr) 1;
}
return IntPtr.Zero;
}
/// <summary>
/// Gets high bits values of the pointer.
/// </summary>
private static int HIWORD(IntPtr ptr)
{
var val32 = ptr.ToInt32();
return ((val32 >> 16) & 0xFFFF);
}
/// <summary>
/// Gets low bits values of the pointer.
/// </summary>
private static int LOWORD(IntPtr ptr)
{
var val32 = ptr.ToInt32();
return (val32 & 0xFFFF);
}
private void OnMouseTilt(int tilt)
{
// Write your horizontal handling codes here.
}
You can write horizontal scrolling code in OnMouseTilt method.
Better yet, you could pack all the codes above in a more common class and raise a MouseTilt event just like raising MouseWheel event.
Completing the answer walterlv
private void OnMouseTilt(int tilt)
{
UIElement element = Mouse.DirectlyOver as UIElement;
if (element == null) return;
ScrollViewer scrollViewer = element is ScrollViewer viewer ? viewer : FindParent<ScrollViewer>(element);
if (scrollViewer == null)
return;
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + tilt);
}
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
Improve walterlv's answer and fix arithmetic overflow on 64 bit system when scrolling left:
/// <summary>
/// Gets high bits values of the pointer.
/// </summary>
private static int HIWORD(IntPtr ptr)
{
unchecked
{
if (Environment.Is64BitOperatingSystem)
{
var val64 = ptr.ToInt64();
return (short) ((val64 >> 16) & 0xFFFF);
}
var val32 = ptr.ToInt32();
return (short) ((val32 >> 16) & 0xFFFF);
}
}
/// <summary>
/// Gets low bits values of the pointer.
/// </summary>
private static int LOWORD(IntPtr ptr)
{
unchecked
{
if (Environment.Is64BitOperatingSystem)
{
var val64 = ptr.ToInt64();
return (short)(val64 & 0xFFFF);
}
var val32 = ptr.ToInt32();
return (short)(val32 & 0xFFFF);
}
}
Simple, i want to move a windows pressing ALT+MOUSE, like linux os (ALT+drag).
It's possible to pass a win32 api (move api) to the windows interested clicking on it?
I have a windows services that hook key pressed (ALT button in specific).
When ALT key is pressed and a mouse down event is verified, i want to move window clicking anywhere, not only on the title bar!
Currently i move my form windows in this way:
using System.Runtime.InteropServices;
[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, int wParam, int lParam );
[DllImportAttribute( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
public static extern bool ReleaseCapture();
private void Form1_MouseDown( object sender, MouseEventArgs e )
{
ReleaseCapture();
SendMessage( this.Handle, 0xa1, 0x2, 0 );
}
How can I get windows handle of the specific windows by clicking and after call SendMessage() on it?
It's possible?
You can do this by trapping the WM_NCHITTEST message that Windows sends to see what area of the window got clicked. You can fool it by returning HTCAPTION and it will dutifully perform the mouse actions you'd normally get when clicking the caption of a window. Including moving the window. Paste this code into your form:
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
// Trap WM_NCHITTEST when the ALT key is down
if (m.Msg == 0x84 && (Control.ModifierKeys == Keys.Alt)) {
// Translate HTCLIENT to HTCAPTION
if (m.Result == (IntPtr)1) m.Result = (IntPtr)2;
}
}
I worked this out my self, came up with something interesting of my own calculations, worked perfectly for me, for any window (any active foreground window). Kinda long, but really easy to understand if you follow along the comments, hope it helps :)
The way it works, is that you press a certain registered key-combo, like Ctrl+Alt+M
and the mouse will stick in the center of an active window, you move the mouse, the windows follows it, press the SAME combo again, to release, no need for mouse clicks or anything.
public void MoveWindow_AfterMouse()
{
// 1- get a handle to the foreground window (or any window that you want to move).
// 2- set the mouse pos to the window's center.
// 3- let the window move with the mouse in a loop, such that:
// win(x) = mouse(x) - win(width)/2
// win(y) = mouse(y) - win(height)/2
// This is because the origin (point of rendering) of the window, is at its top-left corner and NOT its center!
// 1-
IntPtr hWnd = WinAPIs.GetForegroundWindow();
// 2- Then:
// first we need to get the x, y to the center of the window.
// to do this, we have to know the width/height of the window.
// to do this, we could use GetWindowRect which will give us the coords of the bottom right and upper left corners of the window,
// with some math, we could deduce the width/height of the window.
// after we do that, we simply set the x, y coords of the mouse to that center.
RECT wndRect = new RECT();
WinAPIs.GetWindowRect(hWnd, out wndRect);
int wndWidth = wndRect.right - wndRect.left;
int wndHeight = wndRect.bottom - wndRect.top; // cuz the more you go down, the more y value increases.
Point wndCenter = new Point(wndWidth / 2, wndHeight / 2); // this is the center of the window relative to itself.
WinAPIs.ClientToScreen(hWnd, out wndCenter); // this will make its center relative to the screen coords.
WinAPIs.SetCursorPos(wndCenter.X, wndCenter.Y);
// 3- Moving :)))
while (true)
{
Point cursorPos = new Point();
WinAPIs.GetCursorPos(out cursorPos);
int xOffset = cursorPos.X - wndWidth / 2;
int yOffset = cursorPos.Y - wndHeight / 2;
WinAPIs.MoveWindow(hWnd, xOffset, yOffset, wndWidth, wndHeight, true);
Thread.Sleep(25);
}
}
And now:
int moveCommandToggle = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312)
{
int keyID = m.WParam.ToInt32();
if(keyID == some_key_combo_you_registered_for_the_moving)
{
if (moveCommandToggle++ % 2 == 0)
{
mover = new Thread(() => MoveWindow_AfterMouse());
mover.Start();
}
else mover.Abort();
}
}
}
If you're wondering about RECT:
public struct RECT
{
public int left; // xCoor of upper left corner.
public int top; // yCoor of upper left corner.
public int right; // xCoor of lower right corner.
public int bottom; // yCoor of lower right corner.
};
WinAPIs was just a static class that I did my DllImports in.