I have a small popup window , and I'd like to trigger event when I click the mouse outside of the window bound.
I've tried initiating it on OnMouseClick, and check if the mouse cursor is out of the pop up bounds, but it doesn't seem to trigger out of the popup bounds.
For discussion:
public partial class FrmPopup : Form {
public FrmPopup() {
InitializeComponent();
}
const uint WM_NCACTIVATE = 0x0086;
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == WM_NCACTIVATE && m.WParam == IntPtr.Zero) {
if(!ClientRectangle.Contains(PointToClient(Control.MousePosition)) && MouseButtons == MouseButtons.Left)
label1.Text = "Clicked outside of window";
}
}
}
Have you considered the Deactivate event? This will fire when the form loses focus. This could be from a mouse click OR a context switch, but may deliver what you want.
Related
I am trying to detect a click and preform calling a function only after the click actually happened.
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m) {
//Detect a Click
if (m.Msg == 0x210 && m.WParam.ToInt32() == 513){
lastClick = DateTime.Now;
clickedHappened();
Debug.Print("Click Detected!");
}
base.WndProc(ref m);
}
private void clickedHappened(){
MessageBox.Show("Click Already Happened");
}
I think that WndProc happens way before the actual click takes place.
I was wondering if there was a way to solve this with out using a timer? or sleep(400);
The only solution I can come up with is using a timer, but I want to get rid of some of my existing timers. It seems that the click actually happens 200 - 350 ms after it was detected in WndProc.
WndProc is short for Window Procedure, its the procedure that handles everything for the window, drawing, mouse capture, keyboard capture, resizing...
There are also several ways you can capture the mouse for varying results
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case 0x201:
//left button down
break;
case 0x202:
clickedHappened(); //left button up, ie. a click
break;
case 0x203:
//left button double click
break;
}
base.WndProc(ref m);
}
The thing is, windows forms in C# already handles all of these for you and from the WndProc, fires events there is no real need to handle WndProc yourself for this type of thing.
For a full list of mouse notification messages, see MSDN: Mouse Input Notifications and for a list of all wndproc messages, see MSDN System Defined Messages
Probably, you can handle WM_LBUTTONUP message that occured after click.
You can do it like this:
const int WM_LBUTTONUP = 0x202;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_LBUTTONUP)
{
clickedHappened();
}
base.WndProc(ref m);
}
I have a class based on the NativeWindow class and I want to be able to perform some action when the user clicks inside of it. Here is what I tried:
Code removed
However it doesn't work. Debugging suggests for some reason the message is never 0x0201 which is supposedly a left mouse button click. What's wrong with it?
I'm not sure tooltips can receive a WM_LBUTTONDOWN. You could try using the TTM_RELAYEVENT message that's meant for passing a mouse message to a tooltip control for processing, something like this:
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int TTM_RELAYEVENT = 0x407;
if (m.Msg == TTM_RELAYEVENT)
{
Message relayed = (Message)Marshal.PtrToStructure(m.LParam, typeof(Message));
if (related.Msg == WM_LBUTTONDOWN)
{
// Do something
}
}
base.WndProc(ref m);
}
Is it possible to create a MouseEnter-Event also for the border of the window? I mean also for the minimize and maximize-buttons. Because if I set the Event for my Form1, it works only when i'm inside the Form, but not on the border and the Buttons.
You can override WndProc in you form and you can detect mousemove
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// mouse in window or in Border and max, close & min buttons
if (m.Msg == 0xa0 || m.Msg == 0x200)
{
//Do some thing
}
}
I want to play a sound when the left mouse button is clicked anywhere in my form without having to place Mouse click events on every single control in the form. Is there a way to accomplish this?
You can detect the Windows notification before it is dispatched to the control with the focus with the IMessageFilter interface. Make it look similar to this:
public partial class Form1 : Form, IMessageFilter {
public Form1() {
InitializeComponent();
Application.AddMessageFilter(this);
this.FormClosed += delegate { Application.RemoveMessageFilter(this); };
}
public bool PreFilterMessage(ref Message m) {
// Trap WM_LBUTTONDOWN
if (m.Msg == 0x201) {
System.Diagnostics.Debug.WriteLine("BEEP!");
}
return false;
}
}
This works for any form in your project, not just the main one.
This should do the trick
const int WM_PARENTNOTIFY = 0x210;
const int WM_LBUTTONDOWN = 0x201;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN || (m.Msg == WM_PARENTNOTIFY && (int)m.WParam == WM_LBUTTONDOWN))
DoIt();
base.WndProc(ref m);
}
This project may be overkill for your needs (since it hooks global mouse events, not just ones on your form), but I think it shows the basics of what you need.
Case WM_PARENTNOTIFY
Select Case Wparam
Case 513 ' WM_LBUTTODOWN
PlaySoundA
End Select
Using For Vb Or Vba
I'd like a context menu on the caption bar right click
any tips/samples pref in c# ?
UPDATE - for various reasons, right click on the form won't work because the form is not empty and the form is composited dynamically so....
You can do this by trapping the WM_NCRBUTTONDOWN notification that Windows sends when the user right-clicks the title bar. The control class does not have an event for it, you'll need to override WndProc(). Here's an example form, you'll need to add a ContextMenuStrip:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected void OnTitlebarClick(Point pos) {
contextMenuStrip1.Show(pos);
}
protected override void WndProc(ref Message m) {
const int WM_NCRBUTTONDOWN = 0xa4;
if (m.Msg == WM_NCRBUTTONDOWN) {
var pos = new Point(m.LParam.ToInt32());
OnTitlebarClick(pos);
return;
}
base.WndProc(ref m);
}
}
MSDN explains how to handle right-clicks on Windows Forms controls. Controls, including Forms, inherit the MouseClick event.
MouseEventArgs will tell you what button was clicked through the Button property. Have a look at the MouseButtons Enumeration.
if you handle the form mouse-click, you can then use the following code:
private void Dialog_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
this.Text = "new caption text";
}
}
But you'll have to make sure that you generate this event for the top-level control on a form. For instance if you have a group box on the form, it will receive the mouse-click events rather than the form itself, for the areas of the form that are under the group box.
There is already a menu managed by Windows when you right-click the titlebar.
Do you want to replace it completely?
If you want to add to it you will have to use the Win32 API and interop and you will have to subclass the form.
See the AppendMenu() function.
Basically you need to use p-invoke to do this. There is a really great example at Here
You can see from the example you will need to manually mimic the event handlers, but this is pretty straight forward.
You can override WndProc of the form and capture the WM_NCRBUTTONDOWN message:
protected override void WndProc(ref Message m)
{
const int WM_NCRBUTTONDOWN = 0xA4;
if (m.Msg == WM_NCRBUTTONDOWN)
{
MessageBox.Show("Caption right clicked!");
}
else
{
base.WndProc(ref m);
}
}
This code will suppress the window's context menu, however. You may not wish this. The WM_NCRBUTTONDOWN message will also be sent if you right click the window borders as well. You may not desire this either.