Handling wm_mousewheel message in WTL - c++

I am trying to handle wm_mousewheel for my application.
Code:
BEGIN_MSG_MAP(DxWindow)
MESSAGE_HANDLER(WM_MOUSEWHEEL, KeyHandler)
END_MSG_MAP()
.
.
.
LRESULT DxWindow::KeyHandler( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled )
{
if(uMsg==wm_mousewheel)
{
//Perform task.
}
return 0;
}
But this code doesn't work.KeyHandler doesn't receive wm_mousewheel message.
I am testing this application on vista.
If my approach is wrong how to handle wm_mousewheel properly?
Do vista is responsible for failure in handling wm_mousewheel message?

From the doc:
The WM_MOUSEWHEEL message is sent to the focus window when the mouse wheel is rotated. The DefWindowProc function propagates the message to the window's parent. There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.
Change your test to if(uMsg == WM_MOUSEWHEEL).
Check that your window or one of it's children has focus.
If this is related to your previous wtl-child-window-event-handling question, I edited my answer to not forward WM_MOUSEWHEEL.

Well, first, you don't have to somehow check uMsg in message handler, because in this situation every message handler is bound to one concrete message.
Second, these atl macroses usually mean to write something like CHAIN_MSG_MAP(CMyBaseClass)
at the end of your map.
Anyway, what you've posted here looks ok, except this part:
if(uMsg==wm_mousewheel)
{
//Perform task.
}
Try erasing it, adding a breakpoint to the handler and debugging. Also you could try adding another neutral message handler (such as WM_CLICK) and tracing it's behavior.
This is the example from MSDN, and the code block that you've posted actually follows it.
class CMyWindow : ...
{
public:
...
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
CHAIN_MSG_MAP(CMyBaseWindow)
END_MSG_MAP()
LRESULT OnPaint(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{ ... }
LRESULT OnSetFocus(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{ ... }
};

Related

How to handle mouse clicks in CMainFrame

How can I detect in an "empty" CMainFrame mouse clicks? With empty I mean a MDI which has not yet any document/view.
I have tried to detect mouse clicks with:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg);
MDI main frame windows have an 'invisible' client window that occupies the client area of the main frame. This window is inaccessible using 'normal' class override techniques but, if that main frame window is derived from either CMDIFrameWnd or CMDIFrameWndEx, you can use its m_hWndMDIClient member (the HWND of that invisible window) to subclass it, by overriding its WindowProc.
I do this (actually, to draw in that client area) in an override of the main frame's UpdateWindow procedure, using a bool member variable (set to false on construction) to keep track of whether or not the subclassing has already been done.
Here's a possible solution (adapted from my own code) that will likely work for intercepting mouse clicks. (I tested it and did actually get the Beep() diagnostic on mouse clicks!)
// Local function pointer to store the 'original' (default) window procedure...
LRESULT (CALLBACK *DefCliPrc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = nullptr;
// Static definition of our override procedure...
static LRESULT CALLBACK ClientProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT answer = DefCliPrc(hWnd, uMsg, wParam, lParam); // First, call default proc.
if (uMsg == WM_LBUTTONDOWN) {
Beep(1000,1000); // Make a sound to show that it's working!
// <Insert your handling code here>
}
//...
// Intercept/handle other messages, as required ...
//...
return answer;
}
// Override of the UpdateWindow function, to enact the subclassing...
void MyMainFrame::UpdateWindow(void)
{
if (!funchange) { // Only do the sub-classing ONCE ...
DefCliPrc = (WNDPROC)(intptr_t)(::GetWindowLongPtr(m_hWndMDIClient, GWLP_WNDPROC));
::SetWindowLongPtr(m_hWndMDIClient, GWLP_WNDPROC, (intptr_t)(ClientProc));
funchange = true; // Set this 'flag' to prevent repetition!
}
CMDIFrameWnd::UpdateWindow(); // Should always call base class
return;
}

Button and ON_MESSAGE

In gui app there is ON_MESSAGE(id, handler) with hanler's LRESULT CMainFrame::handler(WPARAM wParam, LPARAM lParam) declaration.
Well, visial studio doesn't want to get such handler in ON_COMMAND(). What can I do to use the same hanler in ON_MESSAGE and in ON_COMMAND?
Thanks in advance.
as you noticed the handlers need different declarations to work for the ON_MESSAGE and the ON_COMMAND so you can't have the same function for both ON_COMMAND and ON_MESSAGE.
you will have to create one function for each handler and then you can encapsulate your code into another function that is called from the first handlers.
like:
BEGIN_MESSAGE_MAP(CMyClass, CMyParentClass)
//{{AFX_MSG_MAP(CMyClass)
ON_MESSAGE(ID_MY_MESSAGE_ID,OnMyMessage)
ON_COMMAND(ID_MY_COMMAND_ID,OnMyCommand)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
LRESULT CMyClass::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
MyEncapsulatedCode();
return 0;
}
void CMyClass::OnMyCommand()
{
MyEncapsulatedCode();
}
void CMyClass::MyEncapsulatedCode()
{
//do stuff
}

Why LRESULT CALLBACK is used in this function?

Recently, I've started to learn DX11 and I was trying to create message loops in WinAPI. I saw a LRESULT CALLBACK function from the tutorial that I haven't seen before. It is called in Window Procedure function. Here is the WndProc function and the MessageHandler function(the function that I'm talking about).
WndProc:
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch(umessage)
{
// Check if the window is being destroyed.
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
// Check if the window is being closed.
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
// All other messages pass to the message handler in the system class.
default:
{
return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
MessageHandler:
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch(umsg)
{
// Check if a key has been pressed on the keyboard.
case WM_KEYDOWN:
{
// If a key is pressed send it to the input object so it can record that state.
m_Input->KeyDown((unsigned int)wparam);
return 0;
}
// Check if a key has been released on the keyboard.
case WM_KEYUP:
{
// If a key is released then send it to the input object so it can unset the state for that key.
m_Input->KeyUp((unsigned int)wparam);
return 0;
}
// Any other messages send to the default message handler as our application won't make use of them.
default:
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
}
}
What I don't understand is, why we added the "LRESULT CALLBACK" part to the MessageHandler function? I know, we must add it to WndProc function, but I don't get the point of creating a new function and adding it a calling convention. What if we don't add any calling convention to the MessageHandler function? What if we didn't create the MessageHandler funciton and write the KEY_DOWN listeners to WndProc's switch-case statement?
These codes are in one class and ApplicationHandler pointer points to "this".
There is no obvious reason for SystemClass::MessageHandler to be declared as CALLBACK because it cannot be used as a message handler for Windows since it is not static. There is no reason for SystemClass::MessageHandler to be declared as CALLBACK in the code you showed.
About the CALLBACK (__stdcall):
Functions called from "within Windows" just have to be stdcall because Windows developers decided to write/compile Windows that it calls stdcall functions. In theory, any CC could be used, but Windows and your code must have the same.
Your own function won´t need it if you´re using it only in your own code in your program.
LRESULT (some int/pointer-like thing) is just the return type.
The reason for not just writing int (or something like that) is that LRESULT is a int with a certain length etc., and if MS decides to change it for some reason, they only need to change the definition of LRESULT, but not every function which has a LRESULT return type.

Subclassing an edit control from a user defined class/pointer-to-member-function

I think I've fallen in the same trap as many before me where I try to impose a nice OO methodology on win32 API programming. No MFC, no AFX, I'm not even using VC++, I'm using C::B with gcc.
I think what I'm trying to do is impossible, but since MFC exists (although I'm not using it) there must be some way.
I've created a class to contain several window controls. It implements handlers for WM_CREATE and WM_COMMAND, and keeps track of all the associated data around my small group of controls (ID codes and HWNDs).
It works great for buttons, static controls, even light GDI methods, but it all breaks down when I try to subclass an edit control.
Really, I just want to capture the "enter" key, but as anybody who's been down that road before will attest, when an edit control has focus, the parent window doesn't receive WM_KEYDOWN or WM_COMMAND, we are left to implement our own proc. Super lame.
OK, so subclassing an edit control is fine, if the editProc is global or static. I know that is because SetWindowLongPtr needs a function address, and that concept is nebulous for a member function.
So the object of my class is declared as "static" inside the parent WndProc. But the function is not "static" because then I wouldn't have access to non-static data members (completely defeating the purpose of this exercise). I'm hoping that because the objest is itself static, I should be able to properly define the address of one of its member functions.
Readers that have tried this before will either have given up and used MFC or something else, or perhaps have found a clever work-around.
I'll let this sample code do the rest of the talking: (simplified - will not compile as such)
/**** myprogram.c ****/
#include "MyControlGroup.h"
int winMain(){ // etc... }
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// object is static becuse it only needs to be initialized once
static MyControlGroup myControl;
if (msg == WM_CREATE)
myControl.onWMCreate(hWnd);
else if (msg == WM_COMMAND)
myControl.onWMCommand( wParam, lParam );
else if (msg == WM_DESTROY)
PostQuitMessage(0);
return DefWindowProcW(l_hWnd, l_msg, l_wParam, l_lParam);
}
The header file for my class:
/**** MyControlGroup.h ****/
class MyControlGroup
{
private:
HWND m_hWndParent;
HWND m_hWndEditBox;
int m_editBoxID;
public:
MyControlGroup();
void onWMCreate(HWND);
void onWMCommand(WPARAM, LPARAM);
// want to find a way to pass the address of this function to SetWindowLongPtr
LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
...and the implementation:
/**** MyControlGroup.cpp ****/
static int staticID = 1;
MyControlGroup::MyControlGroup()
{
m_editBoxID = staticID++;
}
void MyControlGroup::onWMCreate(HWND hWnd)
{
// My control group has buttons, static controls, and other stuff which are created here with CreateWindowW. It also has an edit control:
m_hWndEditBox = CreateWindowW(L"EDIT", L"initial text", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 150, 20, hWnd, (HMENU)m_editBoxID, NULL, NULL);
/*
To subclass the edit control, I need a pointer to my customized proc. That means I
need a pointer-to-member-function, but SetWindowLongPtr needs a pointer to global or
static function (__stdcall or CALLBACK, but not __thiscall).
*/
// I'd like to do something like this, adapted from a great write-up at
// http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
LERSULT (MyControlGroup::*myEditProcPtr)(HWND, UINT, WPARAM, LPARAM);
myEditProcPtr = &MyControlGroup::myEditProc;
// Up to now it compiles ok, but then when I try to pass it to SetWindowLongPtr, I get
// an "invalid cast" error. Any ideas?
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProcPtr);
}
void MyControlGroup::onWMCommand(WPARAM wParam, LPARAM lParam){ /* process parent window messages. Editboxes don't generate WM_COMMAND or WM_KEYDOWN in the parent :''( */}
LRESULT MyControlGroup::myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// process messages like IDOK, WM_KEYDOWN and so on in the edit control
}
Even once I get this done, I'll still need to figure out a way to pass the address of the parent WndProc to myEditProc for the return value, but until I get past this there is no point in worrying about that.
Thanks in advance for reading!
myEditProc needs to be a static function.
Once you've done that you can pass the address of the function directly without going through the intermediate variable:
static LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
...
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProc);
To access your class data from the static function, you can save it in the userdata field of the edit control, e.g.:
// before sub-classing the control
SetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA, (LPARAM)this);
// in the sub-class procedure
MyControlGroup* pThis = (MyControlGroup*)GetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA);
But as #K-ballo suggested, SetWindowSubclass is definitely the way to do this unless you want compatibility with pre-XP. It handles the sub-classing procedure for you automatically, lets you associate a userdata pointer (e.g. this) that is automatically passed to the sub-class procedure, and safely handles removing the sub-class at the end.

Implement user activity logger in old application?

How to go about implementing a user activity logger in MFC application.To get to know what are all the features are used most in an existing application.
You can override the windows procedure of your application window:
class CMyMainWindow {
void LogUsageData(UINT message);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
LogData(message);
return CWnd::WindowProc(message, wParam, lParam); // route message to message map
}
}
Note that the task is not so trivial: LogUsageData should discard most messages, focusing only on the ones defined in the message map.
However, this should be a good place to start.