I have a dialog window (with CDialogEx based class) containing a single list control (report view, with CListCtrl attached as a control variable). I want to check which line of the displayed list was double clicked.
I thought it will be just a matter of adding OnNotify and converting the double click coordinates to the line number:
BOOL MyDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
if (((NMMOUSE *)lParam)->hdr.idFrom == IDC_MYLIST &&
((NMMOUSE *)lParam)->hdr.code == NM_DBLCLK)
{
CPoint cp(((LPNMMOUSE)lParam)->pt);
int iLine = myListCtrl.HitText(cp);
It partially works: I am correctly catching doubleclick notifications coming from the control. What doesn't work though is I don't get correct double click coordinates. cp contains some numbers as coordinates, but they are wrong. x is always 0, and y is what x should be.
Any ideas where I am going wrong and what should I do? With some digging it looks like lParam points to some structure containing the coordinates, but it is not NMMOUSE as I expected, and I can't find any information about what other structure it could be.
This is deep into undefined behavior from the get-go: The only guarantee you get from the system when receiving a
WM_NOTIFYmessage is thatlParampoints to anNMHDRstructure. That's a piece of generic information provided to direct subsequent processing.Consequently, the only safe unconditional cast in an
OnNotifyoverride is fromLPARAMintoNMHDR const*, so let's just do that to keep our sanity:Once the preconditions have been established, it's safe to move on. At this point we know that the origin passed our filter (
IDC_MYLIST), and that the notification is anNM_DBLCLK, which passes additional information by way of a pointer to anNMITEMACTIVATEstructure.The following takes advantage of that additional knowledge, and produces a
CPointholding the double-click position: