Tom Tom
Tom Tom

Reputation: 1209

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);

Upvotes: 2

Views: 152

Answers (1)

Adrian Mole
Adrian Mole

Reputation: 51815

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;
}

Upvotes: 2

Related Questions