Preventing Mouse Back button from navigating back in history

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Preventing Mouse Back button from navigating back in history

Postby hyzerfool » Tue Feb 05, 2019 3:26 pm

I'm using Visual Studio 2017, C++ / MFC.

When clicking the, "Back", button on a mouse:

In CEF 3.2840.1518, is handled by CMainFrame::OnAppCommand in my MFC app. We handle it to change which view is active and the CEF browser does not receive the event. This is what we want to happen.

In CEF 3.3578.1863, CMainFrame::OnAppCommand does not receive the event, so the browser catches it and navigates back in history. We do not want this.

1) I used SetWindowSubclass on the browser's HWND and catch the event (WM_PARENTNOTIFY with WM_XBUTTONDOWN as LoWord), which works for letting me change the active view, but the CEF browser is still handling the message and navigating back in history, despite me returning 0 from our handler (which I think for WM_PARENTNOTIFY should say I handled things).

2) I tried to trap this in OnBeforeBrowse, using request->GetTransitionType () & TT_FORWARD_BACK_FLAG. This does work for catching the Forward button event from a mouse, but OnBeforeBrowse is not called when using the back button. This is usually navigating back to an about:blank, which DOES seem to make a difference. I ran a test where "Back" reverted the browser to a previously loaded html page, as opposed to about:blank, and then OnBeforeBrowse WAS called.

3) I found some old threads that suggest trapping it in OnBeforeNavigation, but that's no longer supported. My understanding is that the functionality is now handled by OnBeforeBrowse.

4) I tried stopping it in OnLoadStart (by calling browser->StopLoad ()), but it seems to be too late at that point.

Ideally, I'd like this to be handled by OnAppCommand, but I'm also ok hacking my way around it with SetWindowSubClass, as long as I can stop the CEF browser from navigating forward / back in response to the mouse click.

Help?

I guess I can try initially opening the browser on an empty html page, but that's getting pretty hack-y at that point. I will if I have to, but...
hyzerfool
Techie
 
Posts: 23
Joined: Wed May 13, 2015 2:37 pm

Re: Preventing Mouse Back button from navigating back in his

Postby ndesktop » Wed Feb 06, 2019 12:58 am

At low level, best best would be a msg filter hook.

Better yet is to implement CefContextMenuHandler in ClientHandler, return client handler from GetContextMenuHandler(), and trap OnContextMenuCommand (MENU_ID_BACK is the ID you are after).
Or use the model passed in OnBeforeContextMenu to disable the MENU_ID_BACK item when back navigation is to be disabled. I'm not sure if this is permanent or the menu regenerates every time document changes.
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: Preventing Mouse Back button from navigating back in his

Postby hyzerfool » Wed Feb 06, 2019 11:31 am

Love the suggestion for CefContextMenuHandler. Had not occurred to me. But...

... doesn't seem to fire unless the command comes specifically from a context menu, and my case isn't.

Regarding a message filter hook, do you have any suggestions? I thought using SetWindowSubclass and saying I handled the message would work, but maybe it's not because I'm getting a WM_PARENTNOTIFY, as opposed to a specific WM_XBUTTONDOWN message?

I'll keep looking, but eager for guidance from anyone who knows more about this than I do (which is most of you).

Thanks!
hyzerfool
Techie
 
Posts: 23
Joined: Wed May 13, 2015 2:37 pm

Re: Preventing Mouse Back button from navigating back in his

Postby hyzerfool » Wed Feb 06, 2019 12:13 pm

Aha! If I subclass the CefBrowser's CHILD window, then I get better events. I'm now getting XM_WBUTTONUP, and when I return true to say I handled it, the browser no longer processes it.

So this is working as I want, though I'm still curious why my old solution of OnAppCommand no longer works.

For any future long, lost souls, a slimmed down version of my code (that hopefully I didn't break while slimming down):

Code: Select all
CefRefPtr<CefBrowserHost> pBrowserHost = m_pBrowser->GetHost();
if (NULL == pBrowserHost)
   return NULL;

HWND hWndToSubclass = pBrowserHost->GetWindowHandle ();

if (NULL != hWndToSubclass)
{
   HWND hChild = GetWindow (hWndToSubclass, GW_CHILD);
   if (NULL != hChild)
      hWndToSubclass = hChild;

   SetWindowSubclass (hWndToSubclass, &mySubClassProcChromiumCtrl, 1, DWORD_PTR (this));
}


Code: Select all
LRESULT CALLBACK mySubClassProcChromiumCtrl (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
   UINT nLoWord = LOWORD (wParam);
   UINT nHiWord = HIWORD (wParam);

   switch (uMsg)
   {
      case WM_XBUTTONUP:
         if (MK_XBUTTON1 == nLoWord)
            return true;  // we processed it, nobody else should
         break;

      case WM_NCDESTROY:
         RemoveWindowSubclass (hWnd, &mySubClassProcChromiumCtrl, 1);
         break;
   }

   return DefSubclassProc (hWnd, uMsg, wParam, lParam);
}

hyzerfool
Techie
 
Posts: 23
Joined: Wed May 13, 2015 2:37 pm


Return to Support Forum

Who is online

Users browsing this forum: Majestic-12 [Bot] and 57 guests