1

A browser helper object I'm writing at the moment needs to alert the user of certain situations. I don't want to use the WinAPI function MessageBox, because it forces the user to click it away. Is there a possibillity to ask the user a question without blocking his workflow? He should be able to just ignore the question, if he isn't interested in it at the moment. Something like gBrowser.getNotificationBox() for firefox extensions would be ideal (example image appended). Firefox gBrowser.getNotificationBox()

Heinzi
  • 5,793
  • 4
  • 40
  • 69
  • I know for a fact that IE has something similar (that bar you get every time it says "Internet Explorer has prevented an ActiveX [blah]" or whatever), but I don't remember what it's called or how you'd use it programmatically. – JAB Aug 08 '11 at 17:08

2 Answers2

0

You can create your own window and use SetWindowPos to move it into the IE window.

If you want to play safe, I suggest you to write a browser band

There is not yet an API to customize the content of information bar aka security band.

Sheng Jiang 蒋晟
  • 15,125
  • 2
  • 28
  • 46
  • A browser band would be showable via the IE menu and therefore isn't suitable for the needs of a message box. So I think SetWindowPos is the way. Is there a possibillity to say "please automatically resize with your parent window" or do I have to resize the child window in the OnResize event of IE? I found an interesting tutorial (http://msdn.microsoft.com/en-us/library/bb250436%28v=VS.85%29.aspx#bho_lifecycle). The child window there seems to be what I want (except for the positioning at the bottom of the window and not at the top), but the author doesn't mention, how he did it. – Heinzi Aug 10 '11 at 09:26
  • That window is actually outside the browser, the BHO resized the browser to leave some room for the editing window. I don't think you should do that in a BHO in the age of tabbed browsing. Now one window may host many BHOs and you don't want to resize the browser every time the user open a tab. – Sheng Jiang 蒋晟 Aug 10 '11 at 15:01
0

I finally could solve it. The answer below and the answers in this question did help me. There you can also find some more information about this problem. If someone has the same problem, here is my code. I don't think it will compile without the rest of my projects code, but it should give an idea, how to implement such a dialog box in a browser helper object:

Header:

#include "atlbase.h"
#include "atlwin.h"
#include "resources/resource.h"
#include <string>

class NotificationBar : public CDialogImpl<NotificationBar>
{
public:
    NotificationBar();

    enum { IDD = IDD_NOTIFICATIONBAR };

    BEGIN_MSG_MAP(CMyDialog)
        COMMAND_HANDLER(IDC_CANCEL, BN_CLICKED, OnBnClickedCancel)
    END_MSG_MAP()

    void show(const std::string &message);

    void show();

    void fitSize();

    void hide();

    void setText(const std::string &text);

private:

    LRESULT OnBnClickedCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);

    bool isShown;
};

Source:

#include "NotificationBar.hpp"

NotificationBar::NotificationBar()
    :isShown(false)
{
}

void NotificationBar::show(const std::string &message)
{
    show();
    setText(message);
}

void NotificationBar::show()
{
    if(isShown)
    {
        fitSize();
        return;
    }
    isShown=true;

    WebBrowser webbrowser(BrowserHelperObject::getInstance().getBrowser());
    //Create dialog
    Create(webbrowser.getCurrentTabHwnd());
    //Set dialog size
    fitSize();
    ShowWindow(SW_SHOWNORMAL);
}

void NotificationBar::hide()
{
    if(!isShown) return;
    ShowWindow(SW_HIDE);
    DestroyWindow();
    isShown=false;
    fitSize();
}

void NotificationBar::fitSize()
{
    //This method is highly non portable. I is possible that it will not work in future versions of
    //Internet explorer. It is dependend on the layout of the IE window and on the class names
    //of its child windows (status bar, document view, ...).
    //If the plugin gets some strange layout on future versions of IE or doesn't show a message at all,
    //check and change this function.

    WebBrowser webbrowser(BrowserHelperObject::getInstance().getBrowser());
    CWindow tab(webbrowser.getCurrentTabHwnd());
    CWindow child(FindWindowEx(tab,NULL,_T("Shell DocObject View"),_T("")));
    CWindow statusbar(FindWindowEx(tab,NULL,_T("msctls_statusbar32"),_T("")));

    RECT statusbarrect;
    statusbar.GetWindowRect(&statusbarrect);
    RECT documentrect;
    tab.GetClientRect(&documentrect);
    documentrect.bottom-=(statusbarrect.bottom-statusbarrect.top);

    if(isShown)
    {
        //Request document window rect
        static const unsigned int DLGHEIGHT=50;
        RECT dialogrect=documentrect;
        documentrect.top+=DLGHEIGHT;
        dialogrect.bottom=dialogrect.top+DLGHEIGHT;
        //Shrink document window
        MoveWindow(&dialogrect);
    }

    child.MoveWindow(&documentrect);
}

LRESULT NotificationBar::OnBnClickedCancel(WORD, WORD, HWND , BOOL&)
{
    hide();
    return 0;
}

void NotificationBar::setText(const std::string &text)
{
    if(0==SetDlgItemText(IDC_TEXT, CA2W(text.c_str())))
        ieaddon::util::bho::BrowserHelperObject::getInstance().ErrorMessageBox("Error",ieaddon::util::cast::IntToStr(GetLastError()));
}

The function webbrowser.getCurrentTabHwnd() returns the current tab window:

HWND WebBrowser::getCurrentTabHwnd()
{
    CComPtr<IServiceProvider> pServiceProvider;
    if (!SUCCEEDED(_browser->QueryInterface(IID_PPV_ARGS(&pServiceProvider))))
        throw std::exception("QueryInterface for IID_IServiceProvider failed in WebBrowser::getCurrentTabHwnd()");

    CComPtr<IOleWindow> pWindow;
    if (!SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARGS(&pWindow))))
        throw std::exception("QueryService for SID_SShellBrowser, IID_IOleWindow failed in WebBrowser::getCurrentTabHwnd()");

    HWND hwndBrowser = NULL;
    if (!SUCCEEDED(pWindow->GetWindow(&hwndBrowser)))
        throw std::exception("GetWindow failed in WebBrowser::getCurrentTabHwnd()");

    return hwndBrowser;
}

You also have to call NotificationBar::fitSize() on each resize of the browser window. For this you can use IHTMLWindow3::attachEvent(_T("onresize"),...) in the DocumentComplete event of IE.

Here the way to get an instance of IHTMLWindow3 in the DocumentComplete handler:

  1. IWebBrowser2::getDocument() returns IHTMLDocument2
  2. IHTMLDocument2::get_parentWindow() returns IHTMLWindow2
  3. IHTMLWindow2::QueryInterface(IID_IHTMLWindow3,...) is successful
Community
  • 1
  • 1
Heinzi
  • 5,793
  • 4
  • 40
  • 69