Question

Keystroke Problem in WebBrowser control

Asked by: sgovinda

Hi all,

I have created a modeless dialog derived from ATL's CAxDialogImpl.  The dialog has a WebBrowser control (Internet Explorer).

If a webpage is loaded in the control, keystrokes do not work. Tabbing between HTML elements does not work and I am unabled to type text in HTML input fields. I can see the carat but cannot type any characters.

I know that in MFC, I have to override PreTranslateMessage.  But I don't know how to do this in ATL's CAxDialogImpl.

Thanks in advance.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2001-07-01 at 18:47:26ID20144215
Tags

webbrowser

Topics

Windows MFC Programming

,

Microsoft Programming

Participating Experts
1
Points
100
Comments
3

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. ATL vs MFC ???
    Hello, I am a beginner in MFC or ATL programming. I wish to do the following. 1) Build a database "server" for a visual basic realtime application. From the VB app, I want the interface to similar to the follwing: ---------------------------------------- db...
  2. MFC with ATL service
    I am trying to write a Win NT 4.0 service. And to cut down the initial work, I am using the Wizard in Visual Studio 6.0 to create a ATL based service. In this service when I use MFC classes such as CString, I need to include "afx.h" header. Once I include the heade...
  3. CWnd derived class in ATL object
    I have a control that I've written with MFC, and I would like to make it accessible to VB (and anything else) as an ActiveX control. I knocked out a demo ATL object (never used it before now), but I can't work out how to host my CWnd derived control within the ActiveX contro...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: GloriousRainPosted on 2001-07-01 at 19:26:53ID: 6243487

<MSDN>
This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
--------------------------------------------------------------------------------
 


Download the code (3KB) Scott Roberts  


'' WebBrowser Keystroke Problems
 
lot of people have noticed that when they're hosting the WebBrowser control in MFC, ATL, or standard C++ applications, they sometimes run into trouble with certain keys. These keystroke problems usually occur when typing into intrinsic controls such as text boxes that reside on Web pages loaded by the WebBrowser control. Usually these keys are accelerator keys such as Backspace, Delete, and Tab. The problem is that the intrinsic controls on a Web page do not automatically receive these accelerator keys. When the WebBrowser control receives an accelerator key message, it does not automatically pass it to child controls on a Web page. Therefore, you must somehow let the WebBrowser control know that it should pass these messages to controls on your Web page.     The solution is always the same whether you are hosting the control in MFC, ATL, or standard C++: call the TranslateAcclerator method of the IOleInPlaceActiveObject interface that is implemented by the WebBrowser control. But where and how you should do this is often unclear. Let's see how to work around keystroke problems in MFC, ATL, and standard C++ applications that are hosting the WebBrowser control.
MFC Dialogs

    You can create three types of applications in MFC: dialog-based, single-document interface (SDI), and multiple-document interface (MDI). Each type requires a different solution to the keystroke problems.

    When hosting the WebBrowser control in an MFC dialog-based application, the TranslateAccelerator method is automatically called for you, so you don't run into these problems with keystrokes. But understanding how MFC works when you are hosting the WebBrowser control in a dialog-based application will help you diagnose and solve problems with keystrokes in other situations.

    In an MFC application, the Windows? message pump is managed for you. In a dialog-based application, a method called IsDialogMessage is invoked each time a message enters the loop. Among other things, this function will call TranslateAccelerator for any controls in the dialog. IsDialogMessage will pass the MSG structure that was received from a call to the GetMessage function in the message pump to the TranslateAccelerator method. MFC does this by creating an instance of a class called COccManager that manages all the OLE controls on your dialog. The IsDialogMessage method is a member of the COccManager class.

    The IsDialogMessage method first gets a handle to the window that has the focus. If this window is a control, the TranslateAccelerator method is called on that control to give it a chance to process the message. If the window that has the focus is not a control, IsDialogMessage keeps calling the GetParent method until it finds an ActiveX? control. If it finds a control, it calls TranslateAccelerator on it.

MFC SDI/MDI Applications

    MFC SDI/MDI applications typically run into problems with keystrokes. Unlike dialog-based applications, IsDialogMessage is not automatically called for you in SDI/MDI applications. Therefore, the way to fix these keystroke problems is to call IsDialogMessage yourself. But where do you call it? Each time through the message pump, MFC gives your application a chance to process a message before the message is processed by the default window procedure. To give you a chance to process a message, MFC calls the PreTranslateMessage method, which is a virtual method of the CWnd class. If you implement this method in any of your CWnd-derived classes, it will be called automatically by MFC.

    CWinApp also has a PreTranslateMessage, which means that you can override this in the CWinApp-derived class for your application as well.

    An MFC SDI/MDI application typically has a view class that derives from CView. CView in turn derives from CWnd. Therefore, if you implement PreTranslateMessage in your view class, through the wonders of polymorphism your implementation of PreTranslateMessage will be called by MFC. So to solve the keystroke problems in an MFC SDI/MDI application, all you have to do is call IsDialogMessage from within PreTranslateMessage like this:
 


BOOL CMyView::PreTranslateMessage(MSG* pMsg)
 {
     if (IsDialogMessage(pMsg))
         return TRUE;
     else
         return CWnd::PreTranslateMessage(pMsg);
 }

Knowledge Base article Q165074 (http://support.microsoft.com/support/kb/articles/q165/0/74.asp) explains this in detail.
    But sometimes it does not work. For instance, if the user presses Tab, you would expect the focus to be shifted between all controls in your application as well as controls in the WebBrowser window. Say that you have an application with an edit box in which you can enter a URL. If focus is set to that edit box, each time you press Tab the focus will be shifted around in your application window, but focus will never move to controls on the Web page inside of the WebBrowser control window.

    To make this work, it may be necessary to pass the Tab key directly to the WebBrowser control. Call TranslateAccelerator in the PreTranslateMessage method for your CMainFrame class (see Figure 1). ID_URL_NAME is the resource ID of an edit control in the application that is used to enter a URL.

    If you are hosting the WebBrowser control in a DLL, calling TranslateAccelerator is a bit more involved. Please see Knowledge Base article (Q175502) for more information.

ATL and Standard C++

    When hosting the WebBrowser control in either an ATL application or one written in standard C++, the solution is sometimes rather simple. All you have to do is query the WebBrowser control for the IOleInPlaceActiveObject interface and call its TranslateAccelerator method. Typically, you call this method in your handler function for the WM_KEYDOWN message. Figure 2 contains ATL and standard C++ code that shows how to call the TranslateAccelerator method to fix the keystroke problem.

    Sometimes your application will not automatically be sent WM_KEYDOWN messages for accelerator keys. In this case, you must manually send this message to your window. Here is a sample message pump that sends all keyboard messages to the window of your application:

while (GetMessage(&msg, NULL, 0, 0))
 {
    TranslateMessage(&msg);
 
    // Send all keyboard messages to the window of your
    // application.  hwndApp is the window handle of
    // your application.
    //
    if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
       ::SendMessage(hwndApp, msg.message, msg.wParam, msg.lParam);
         
    DispatchMessage(&msg);
 }

Win32 SDK Modal Dialogs

    The Win32? dialog box functions (DialogBox, DialogBoxIndirect, DialogBoxIndirectParam, and DialogBoxParam) are very helpful when creating modal dialog boxes. They take care of handling the message pump for your application. However, this creates a problem when you are trying to fix these keystroke problems. Where do you put the call to TranslateAccelerator?

    Unfortunately, if you need to host the WebBrowser control in a dialog, it is not a good idea to use these functions to create the modal dialog. The reason for this is simple. When focus is set to a control on a dialog, the control is sent the WB_GETDLGCODE message. Controls typically respond to this message by returning DLGC_WANTALLKEYS. Then the control is given a chance to handle all keys entered by the user.

    The WebBrowser control returns DLGC_WANTARROWS| DLGC_WANTCHARS in response to the WM_GETDLGCODE message. This means that it will not handle certain keys such as Tab and Delete. Therefore, to work around these keystroke problems, you need to have control of the message pump so that you can call TranslateAccelerator.

For these reasons, I recommend that you do not use the Win32 dialog box functions to create your modal dialog box. Create the dialog window yourself so you have control of the message pump. You can use MFC or ATL to create this dialog. In addition, if you just need a modal dialog that displays a Web page, you can use the DHTML showModalDialog function provided by Microsoft Internet Explorer.

    There is one other option you can use to fix these problems, instead of creating the dialog window manually. You can use a Windows hook. This will enable you to retrieve all keyboard messages for the current thread and then call TranslateAccelerator so that accelerator keys will be processed. There is one problem with this approach, however. When the focus is on the WebBrowser control and you attempt to change focus between controls on the Web page by pressing tab, the focus will never leave the WebBrowser window. This means that you can Tab between controls on the Web page or between controls in your application, but not both.

There are four steps required to set up a Windows hook to work around the keystroke problems in a Win32 SDK dialog. First, declare your hook procedure in your header file.

static LRESULT CALLBACK GetMsgHookProc(int nCode, WPARAM wParam, LPARAM lParam);

Next, set your hook procedure during initialization by calling SetWindowsHookEx. Also, make sure to save the returned hook handle so that you can unhook the procedure when you are shutting down or when it is no longer needed.
// Declare this global handle in one of your project files.
 HHOOK g_hook;
 
 // Place this code inside an initialization
 // method in your implementation file (.cpp)
 g_hook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgHookProc,
                           NULL, GetCurrentThreadId());

After that, implement your hook procedure and call TranslateAccelerator.

 LRESULT CALLBACK CYourClass::GetMsgHookProc(int nCode, WPARAM wParam,
                                             LPARAM lParam)
 {
    LPCKFSEARCH pThis = (LPCKFSEARCH)GetWindowLong(hwndMain, DWL_USER);
 
    if (pThis && nCode >= 0)
    {
       MSG* pMsg = (MSG*)lParam;
 
       // m_pOleInPlaceActObj is an IOleInPlaceActiveObject
       // data member of the view class that is initialized
       // after the WebBrowser control is loaded.
 
       if (pThis->m_pOleInPlaceActObj)
          pThis->m_pOleInPlaceActObj->TranslateAccelerator(pMsg);
 
       // This causes the tab to work in the WebBrowser window. If you do not do
       // this, tabbing will happen in the dialog only.  You have the choice of
       // tabbing in the dialog or the WebBrowser window, not both.
 
       if (pMsg->wParam == VK_TAB)
          ZeroMemory(pMsg, sizeof(MSG));
    }
 
    return CallNextHookEx(g_hook, nCode, wParam, lParam);
 }

Finally, when your application is shutting down or when you no longer need the hook, unhook the procedure.
UnhookWindowsHookEx(g_hook);

Explorer Bars

    When hosting the WebBrowser control in Explorer bars (Explorer bands, comm bands, or desk bands), you need to do a little more to fix keystroke problems. You still have to call TranslateAccelerator, but there are also issues regarding focus. The WebBrowser control has to know that your browser band currently has the focus or the accelerator keys will not be processed.

    It is very common for people to forget that they have to implement IOleControlSite when hosting a control. This is true when hosting the WebBrowser control in a standard application or when hosting it in an Explorer bar. You must implement this interface because its OnFocus method is called when focus is set to the WebBrowser control. When this method is called, you must query the WebBrowser control for the IInputObjectSite interface and call its OnFocusChangeIS method. This tells the WebBrowser control that your Explorer bar now has the focus.

Here is some ATL-based code that demonstrates how to call the OnFocusChangeIS method:

STDMETHODIMP CWBExplorerBar::OnFocus(BOOL fGotFocus)
 {
    if (m_pSite)
       m_pSite->OnFocusChangeIS(static_cast<IInputObject*>(this), fGotFocus);
       return S_OK;
 }

    Note that m_pSite is a data member of type IInputObjectSite that was retrieved from the WebBrowser control in the Explorer bar's IObjectWithSite::SetSite method. Also, note that the Explorer bar has to implement the IInputObject interface.
    Now, whenever a key is pressed, three things occur. First, the Explorer bar's IInputObject::HasFocusIO method is called to see if the Explorer bar currently has the focus. The Explorer bar's implementation of this method should determine if the WebBrowser control that the Explorer bar is hosting has the focus or if any of the WebBrowser control's children have the focus. The HasFocusIO method should return S_OK if the WebBrowser control or one of its children has the focus; otherwise it should return S_FALSE. Here is the code for this method.

STDMETHODIMP CWBExplorerBar::HasFocusIO(void)
 {
    HWND hwnd = GetFocus();
    HWND hwndTmp = m_hwndWB;  // HWND of the WebBrowser control
 
    // See if the focus has been set to any of the children
    while (hwnd && hwndTmp)
    {
       if (hwnd == hwndTmp) return S_OK;
       hwndTmp = ::GetWindow(hwndTmp, GW_CHILD);
    }
 
    return S_FALSE;
 }

    The Explorer bar's IInputObject::UIActivateIO method is called next to tell the Explorer bar that it is being activated. The Explorer bar's implementation of this method either UI activates or in-place activates the WebBrowser control depending on one of the input values to this method. In Figure 3, m_pIOleObject is a pointer to an instance of IOleObject that was retrieved from the WebBrowser control in the SetSite method of this Explorer bar.
    Finally, the Explorer bar's IInputObject::TranslateAcceleratorIO method is called. Here the Explorer bar passes the keystroke to the hosted WebBrowser control by calling IOleInPlaceActiveObject::TranslateAccelerator. This causes accelerators such as the Backspace and the Delete keys to be processed by the WebBrowser control (see Figure 4).

    The steps and associated code that I just showed you may be a little confusing at first. To better understand how browser bands work and how to deal with keystroke problems of this sort, pick up a copy of my book, Programming Microsoft Internet Explorer 5.0 (Microsoft Press, 1999). This book should be in stores very soon.

Conclusion

    Keystroke problems that occur when hosting the WebBrowser control are one of the hardest problems to resolve. The solution is always to call the TranslateAccelerator method of IOleInPlaceActiveObject. But since every application is different and written with different development libraries, the method used to fix keystroke problems is going to differ. If you follow the steps in this article, you should be able to solve most keystroke problems when hosting the WebBrowser control.

This article is adapted from the upcoming book Programming Microsoft Internet Explorer 5.0 by Scott Roberts (Microsoft Press, Spring 1999).

From the April 1999 issue of Microsoft Internet Developer.


--------------------------------------------------------------------------------
Send feedback to MSDN.Look here for MSDN Online resources.
<MSDN>

 

by: GloriousRainPosted on 2001-07-01 at 19:40:56ID: 6243503

That's too large. Follow link http://microsoft.com/mind/0499/faq/faq0499.htm

 

by: sgovindaPosted on 2001-07-02 at 14:39:04ID: 6246442

thanks GloriousRain.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...