Please guide me how to use this WndProc in Windows Forms application:
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == NativeCalls.APIAttach && (uint)lParam == NativeCalls.SKYPECONTROLAPI_ATTACH_SUCCESS)
{
// Get the current handle to the Skype window
NativeCalls.HWND_BROADCAST = wParam;
handled = true;
return new IntPtr(1);
}
// Skype sends our program messages using WM_COPYDATA. the data is in lParam
if (msg == NativeCalls.WM_COPYDATA && wParam == NativeCalls.HWND_BROADCAST)
{
COPYDATASTRUCT data = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
StatusTextBox.AppendText(data.lpData + Environment.NewLine);
// Check for connection
if (data.lpData.IndexOf("CONNSTATUS ONLINE") > -1)
ConnectButton.IsEnabled = false;
// Check for calls
IsCallInProgress(data.lpData);
handled = true;
return new IntPtr(1);
}
return IntPtr.Zero;
}
I have seen people use the above code in this way in WPF like
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Attach WndProc
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
You can use Application.AddMessageFilter Method.
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public class TestMessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
// Blocks all the messages relating to the left mouse button.
if (m.Msg >= 513 && m.Msg <= 515)
{
Console.WriteLine("Processing the messages : " + m.Msg);
return true;
}
return false;
}
}
The prototype for WndProc in C# is:
protected virtual void WndProc(ref Message m)
So, you need to override this procedure in your class, assumed that it's derived from Control.
protected override void WndProc(ref Message m)
{
Boolean handled = false; m.Result = IntPtr.Zero;
if (m.Msg == NativeCalls.APIAttach && (uint)m.Param == NativeCalls.SKYPECONTROLAPI_ATTACH_SUCCESS)
{
// Get the current handle to the Skype window
NativeCalls.HWND_BROADCAST = m.WParam;
handled = true;
m.Result = new IntPtr(1);
}
// Skype sends our program messages using WM_COPYDATA. the data is in lParam
if (m.Msg == NativeCalls.WM_COPYDATA && m.WParam == NativeCalls.HWND_BROADCAST)
{
COPYDATASTRUCT data = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
StatusTextBox.AppendText(data.lpData + Environment.NewLine);
// Check for connection
if (data.lpData.IndexOf("CONNSTATUS ONLINE") > -1)
ConnectButton.IsEnabled = false;
// Check for calls
IsCallInProgress(data.lpData);
handled = true;
m.Result = new IntPtr(1);
}
if (handled) DefWndProc(ref m); else base.WndProc(ref m);
}
Related
I want to design a textbox which has index of each line on a separate list-box beside itself.everything is almost done but scrolling is still a problem for me.when I use WndProc to control scrolling, WM_VSCROLL works very well and makes both control scroll in same time,but when I want to send WM_MOUSEWHEEL via List-box,it doesn't work.I thought I can use a trick and iterate WM_VSCROLL when user moves mouse wheel but It doesn't work too.
private const int WM_VSCROLL = 0x115;
private const int WM_MOUSEWHEEL = 0x20A;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_VSCROLL )
{
Message newMessage = Message.Create(Sequence.Handle, m.Msg, m.WParam, m.LParam);
Sequence.DirectMessage(newMessage);//turn to thread
}
else if(m.Msg == WM_MOUSEWHEEL)
{
if((int)m.WParam<0)
{
Message newMessage = Message.Create(Sequence.Handle, WM_VSCROLL,(IntPtr)1,(IntPtr) 0);
Message newMessage2 = Message.Create(this.Handle, WM_VSCROLL, (IntPtr)1, (IntPtr)0);
Sequence.DirectMessage(newMessage);
base.WndProc(ref newMessage2);
}
else
{
Message newMessage = Message.Create(Sequence.Handle, WM_VSCROLL, (IntPtr)0, (IntPtr)0);
Message newMessage2 = Message.Create(this.Handle, WM_VSCROLL, (IntPtr)0, (IntPtr)0);
Sequence.DirectMessage(newMessage);
base.WndProc(ref newMessage2);
}
}
}
Sequence is the name of my list-box and this infers to my textbox.I would appreciate any kind of help... .
Do the same as WM_SCROLL:
[DllImport("user32.dll", EntryPoint = "SendMessage")]
internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
private const int WM_VSCROLL = 0x115;
private const int WM_MOUSEWHEEL = 0x20A;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_VSCROLL || m.Msg == WM_MOUSEWHEEL)
{
SendMessage(Sequence.Handle, (UInt32)m.Msg, m.WParam, m.LParam);
}
base.WndProc(ref m);
}
i was trying to override this WndProc in my win form application but got error IntPtr WndProc no suitable method found to override. my code as follows
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == NativeCalls.APIAttach && (uint)lParam == NativeCalls.SKYPECONTROLAPI_ATTACH_SUCCESS)
{
// Get the current handle to the Skype window
NativeCalls.HWND_BROADCAST = wParam;
handled = true;
return new IntPtr(1);
}
// Skype sends our program messages using WM_COPYDATA. the data is in lParam
if (msg == NativeCalls.WM_COPYDATA && wParam == NativeCalls.HWND_BROADCAST)
{
COPYDATASTRUCT data = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
StatusTextBox.Items.Add(data.lpData + Environment.NewLine);
// Check for connection
//if (data.lpData.IndexOf("CONNSTATUS ONLINE") > -1)
// ConnectButton.IsEnabled = false;
// Check for calls
IsCallInProgress(data.lpData);
handled = true;
return new IntPtr(1);
}
return IntPtr.Zero;
}
anyone can guide me what i am missing. thanks
Your method signature is incorrect, Form.WndProc you are overriding returns void.
protected virtual void WndProc(ref Message m)
I don't know where you got that code, port from C++ maybe? but it won't work with a WinForms form.
My main goal is to implement a proper message loop purely with P/Invoke calls that is able to handle USB HID events. Definitely its functionality should be identical with the following code that works well in Windows Forms. This NativeWindow descendant receives the events:
public class Win32EventHandler : NativeWindow
{
public const int WM_DEVICECHANGE = 0x0219;
public Win32EventHandler()
{
this.CreateHandle(new CreateParams());
}
protected override void OnHandleChange()
{
base.OnHandleChange();
IntPtr handle = UsbHelper.RegisterForUsbEvents(this.Handle);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE)
{
// Handle event
}
base.WndProc(ref m);
}
}
... powered by this event loop:
Win32EventHandler handler = new Win32EventHandler();
var context = new ApplicationContext();
Application.Run(context);
// Other thread calls:
// context.ExitThread()
I found out that implementing the event loop is rather easy:
while (true)
{
res = Win32.GetMessage(out msg, IntPtr.Zero, 0, 0);
if (res == 0)
{
break;
}
Win32.TranslateMessage(ref msg);
Win32.DispatchMessage(ref msg);
if (msg.message == WM_DEVICECHANGE)
{
// Handle event
}
}
But I have no idea how the underlying Window object should be created. The implementation of the NativeWindow class seems too complex for me.
This is my solution at the moment:
public void CustomLoop()
{
string clsName = "Class";
string wndName = "Window";
Win32.WNDCLASSEX wndClassEx = new Win32.WNDCLASSEX();
wndClassEx.cbSize = (uint)Marshal.SizeOf(wndClassEx);
wndClassEx.lpszClassName = clsName;
wndClassEx.lpfnWndProc = WndProc;
Win32.RegisterClassEx(ref wndClassEx);
IntPtr windowHandle = Win32.CreateWindowEx(0, clsName, wndName, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
IntPtr usbEventHandle = UsbHelper.RegisterForUsbEvents(windowHandle);
Win32.MSG msg;
sbyte res = 0;
while (true)
{
res = Win32.GetMessage(out msg, IntPtr.Zero, 0, 0);
if (res == 0)
{
break;
}
if (msg.message == WM.DEVICECHANGE)
{
// Handle event (does not fire)
}
else
{
Win32.TranslateMessage(ref msg);
Win32.DispatchMessage(ref msg);
}
}
Win32.DestroyWindow(windowHandle);
Win32.UnregisterClass(clsName, IntPtr.Zero);
}
[AllowReversePInvokeCalls]
private IntPtr WndProc(IntPtr hWnd, WM msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case WM.DEVICECHANGE:
// Handle event (fires)
break;
default:
return Win32.DefWindowProc(hWnd, msg, wParam, lParam);
}
return IntPtr.Zero;
}
That's an very under-powered event loop. Consider using something like MsgWaitForMultipleObjectsEx instead of GetMessage.
Anyway, creating a window requires you to first register a window class (RegisterClassEx) and then create the window (CreateWindow). Neither one is particularly difficult. And instead of using base.WndProc(), you'll need to call DefWindowProc.
Trying to handle all messages directly inside the message loop is going to be overly difficult, that's why window procedures were created. And don't call TranslateMessage or DispatchMessage for any message you choose to process directly.
You may want to check out how this guy detect USB devices: A USB Library to Detect USB Devices
I want to override the minimize control to instead of sending the window to the taskbar it would do what ever I write it to do.
Basicly this is what I wanted my new minimized and restored effects to be:
private void ChangeForm(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Height = 80;
iDebug.Visible = false;
mainMenu.Visible = false;
}
else
{
this.Height = 359;
iDebug.Visible = true;
mainMenu.Visible = true;
}
}
I have tried to fire an Event on the Resize to do this but without success
this.Resize += new EventHandler(ChangeForm);
Cancel A WinForm Minimize?
Just tested this and it will make the form 100 pixels shorter when minimize is clicked without flicker.
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_MINIMIZE = 0xf020;
protected override void WndProc(ref Message m) {
if (m.Msg == WM_SYSCOMMAND) {
if (m.WParam.ToInt32() == SC_MINIMIZE) {
m.Result = IntPtr.Zero;
Height -= 100;
return;
}
}
base.WndProc(ref m);
}
The Minimize command has a very well defined meaning to a user, it shouldn't be messed with. Winforms accordingly doesn't have an event for it. But not a real problem, you can detect any Windows message by overriding WndProc(). Like tihs:
private void OnMinimize() {
this.Close(); // Do your stuff
}
protected override void WndProc(ref Message m) {
// Trap WM_SYSCOMMAND, SC_MINIMIZE
if (m.Msg == 0x112 && m.WParam.ToInt32() == 0xf020) {
OnMinimize();
return; // NOTE: delete if you still want the default behavior
}
base.WndProc(ref m);
}
In WinForms I used the following block of code to stop the application gaining focus by being clicked on:
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATEANDEAT = 0x0004;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATEANDEAT;
return;
}
base.WndProc(ref m);
}
Is there any alternative to this in a WPF application? Can I use a HwndSource? Here is what I have so far (WM_MOUSEACTIVATE alone does not work as required and the application still gets focus):
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
int WM_MOUSEACTIVATE = 0x0021;
int WM_LBUTTONDOWN = 0x0201; //513
int WM_LBUTTONUP = 0x0202; //514
int WM_LBUTTONDBLCLK = 0x0203; //515
if (msg == WM_MOUSEACTIVATE || msg == MA_NOACTIVATEANDEAT || msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP || msg == WM_LBUTTONDBLCLK)
{
handled = true;
}
return IntPtr.Zero;
}
How can I get the Message Result?
Resolved by using:
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
int WM_MOUSEACTIVATE = 0x0021;
if (msg == WM_MOUSEACTIVATE )
{
handled = true;
return new IntPtr(MA_NOACTIVATEANDEAT);
}
return IntPtr.Zero;
}