Detect button presses by intercepting WM_COMMAND

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I want to insert a 'general' message filter into a .NET application that will
intercept button presses. IMessageFilter cannot be used because it only
intercepts posted messages. So I override WndProc and filter on WM_COMMAND
messages to detect button presses in the application. However the button
presses are not being detected in my app. I have modified the app to have
just one button on it and used spy++ to see what messages the button press
generates. But nothing ! Any ideas ?
 
Message filter will work only for messages that comes through the thread
message queue. When child window sends message to its parent because they
are created by the same thread the parents wndproc is called directly and
doesn't go through the message queue.

Buttons send WM_COMMAND to their parent. If you want to intersept them you
need to override their WndProc. If button is placed on a panel you need to
derive the panel and override its WndProc. There is no way you can intersept
WM_COMMAND from all the buttons unless you don't use panels or any other
containers and place all the buttons in the same parent.
 
Thanks. that is exactly what I am doing. My form has one control, which
is a Windoes.Forms.Button. In my form I override WndProc as follows :-
protected override void WndProc(ref Message m)

and in WndProc I check for a message of type WM_COMMAND. I expected that
when I clicked the button my form would get a WM_COMMAND message, but it
doesn't ?
 
Oh, you are right. The WindowsForms button doesn't send WM_COMMAND as native
buttons does because it is not a native button. This is not a window create
using BUTTON WNDCLASS. This is internal implementation and it simply doesn't
send this message. However using SPY++ you can see that it sends
WM_PARENTNOTIFY; try to use this.
 
Thanks Stoitcho - capturing WM_PARENTNOTIFY appears to work ok. But I don't
understand the explanation of why my button on the from which is of type
Windows.Forms.Button does not cause the BN_CLICKED notification code to go to
the parent through the WM_COMMAND message. Could you elaborate on your
explanation please.
 
leightonr,

WindowsForms control classes use native windows internally for visualizing
the UI. The Handle property that the control class exposes is the
connection between the native window and the .NET control.
Native windows controls' event system as well as the whole communication
with them is based on sending and receiving windows messages; most of them
starts WM_*. For each native control there is a stucture called WNDCLASS
which describes the common properties and functionality of all native
controls created using the class. One of the characteristics of the class is
the window procedure (winproc) that will handle the windows messages send to
all the windows in this class. The classes have name. There are predefined
classes for native windows for some of the control. One such class is the
BUTTON class. Its winproc is written in a way that it notifies its parent
with WM_COMMAND and BN_CLICKED when the button is considered to be clicked
on. In other words if one creates a native control (see CreateWindow and
CreateWindowEx API calls ) using BUTTON as the name of the class, then this
window will draw itself as a button and behaves as a button. (BTW push
buttons are only one kind of buttons that windows of this class can
represent)

This is all related to native windows and windows API. If WindowsForms
wasn't based on native windows any of this will be valid in the context of
..NET.

The best is to forget about all the native windows stuff when programming
for .NET. All this WndProc and WM_* and alike shouldn't be used. However
apparently this is not possible.

Why System.Windows.Forms.Button class doesn't send this message? Because it
doens't create native window of class BUTTON (this is the WNDCLASS, not the
..NET class) that on the other hand means it doesn't uses native BUTTON
winproc that actually sends this WM_COMMAND. Keep in mind that .NET doesn't
need this windows messages in order to work. It uses them only to make the
link between native windows and the .NET classes. When they provide new
winproc for the button for example they don't need to send this WM_COMMAND
and BN_CLICKED because all the event system used by WindowsForms framework
is implemented in different way (not usinng windows messages).


WM_PARENTNOTIFY is a common message for all windows regardless of their
class (it is send by one winproc called default windows procedure
(DefWindowProc) that's why it still works with .NET buttons.
 
Back
Top