Элемент управления MFC WebBrowser: Сколько (нормальных) строк кода требуется для имитации Ctrl + N?

Обновить: Ответ: Требуются две нормальные строки кода. Спасибо Noseratio!

Я стучал головой по клавиатуре больше часа, чем пытался симулировать поведение Ctrl + N в IE в моем размещенном приложении для управления браузером. К сожалению, из-за сложностей, которые я абстрагировал из приведенных ниже примеров кода, я не могу просто позволить IE самому выполнить Ctlr + N. Поэтому я должен сделать это вручную.

Имейте в виду, что у меня запущен браузер. Поэтому, как правило, открытие ссылок в новых окнах приводит к открытию их в новой «вкладке» в моем приложении (на самом деле это не вкладка, а другое окно … но с точки зрения внешнего вида это вкладка). Однако Ctrl + N отличается — здесь, как ожидается, при нажатии откроется полноценное окно IE.

Я думаю, что моя проблема состоит в том, чтобы сформулировать вопросы — по общему признанию, я новичок в управлении WebBrowser, и я нахожу это очень отвратительным. Независимо от того, что я искал в Интернете в течение последнего дня и не мог найти элегантное решение.

По сути, идеальным решением было бы вызвать функцию «NewWindow» в элементе управления WebBrowser или его дочерних библиотеках; Тем не менее, все, что я смог найти, где *На* Методы NewWindow, которые были обработчиками событий, а не сигнализаторами событий. Что я понимаю, что большую часть времени пользователь будет создавать события … но как насчет программного моделирования?

Я попытался изучить подход SENDMESSAGE, в котором я мог бы использовать идентификаторы, которые используют события OnNewWindow …, которые закончились ничем, кроме аварий. Возможно, я мог бы вернуться, чтобы заставить это работать, но я хотел бы подтверждения, что этот подход даже стоит моего времени.

Следующий подход, который должен иметь был самым элегантным, но, к сожалению, не получилось, было похоже на следующее:

Navigate2(GetLocationURL().GetBuffer(), BrowserNavConstants::navOpenInNewWindow);

Это работало бы чудесно, если бы не факт, что новое окно откроется на заднем плане, мигая на панели задач. нуждающийся в щелчке, чтобы вывести его на фронт.

Я попытался обойти это ограничение множеством способов, включая получение диспетчера текущего контекста, затем вызов OnNewWindow2 с этим объектом IDispatch. Затем я вызову QueryInterface для объекта отправки для элемента управления IWebBrowser. Элемент управления webBrowser (предположительно под управлением нового окна) может затем перейти к странице исходного контекста. Однако … это тоже было довольно грязное решение, которое в итоге могло привести к сбоям.

Наконец, я прибегнул к ручному вызову JavaScript, чтобы получить желаемое поведение. В самом деле?? Неужели не было более элегантного решения моей проблемы, чем приведенный ниже код?

        if ((pMsg->wParam == 'N') && (GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
{
LPDISPATCH pDisp = CHtmlView::GetHtmlDocument();
IHTMLDocument2 *pDoc;
if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLDocument2, (void **)&pDoc)))
{
IHTMLWindow2* pWnd;
pDoc->get_parentWindow(&pWnd);
BSTR bStrLang = ::SysAllocString(L"JavaScript");
CString sCode(L"window.open(\"");
sCode.Append(GetLocationURL().GetBuffer());
sCode.Append(L"\");");
BSTR bStrCode = sCode.AllocSysString();
COleVariant retVal;
pWnd->execScript(bStrCode, bStrLang, retVal);
::SysFreeString(bStrLang);
::SysFreeString(bStrCode);
pDoc->Release();
}
pDisp->Release();

Мне трудно поверить, что я должен прибегнуть к такой хакерской атаке, чтобы получить что-то столь же простое, как открытие нового окна, когда пользователь нажимает Ctrl + N.

Пожалуйста, stackoverflow, пожалуйста, укажите на очевидную вещь, которую я упустил.

3

Решение

Ctrl-N в IE запускает новое окно в том же сеансе. В твоем случае, window.open или же webBrowser.Navigate2 создаст окно для нового сеанса, потому что он будет запущен iexplore.exe процесс, который является отдельным от вашего приложения. Сессия является общей для каждого процесса, это то, как основной UrlMon библиотека работает. Таким образом, вы потеряете все куки и кеш аутентификации для нового окна. С другой стороны, когда вы создаете новое окно, в котором размещаются WebBrowser контролировать в своем собственном процессе приложения, вы будете держать сеанс.

Если такое поведение подходит для ваших нужд, попробуйте сначала Navigate2 подход, предшествуя ему с AllowSetForegroundWindow (ASFW_ANY) вызов. Если новое окно все еще не получает фокус правильно, вы можете попробовать создать экземпляр InternetExplorer.Application COM-объект вне процесса и использовать тот же IWebBrowser2 интерфейс для автоматизации этого. Ниже приведено простое приложение на C #, которое работает хорошо для меня, новое окно правильно выведено на передний план, никаких проблем с фокусировкой. Это не должно быть проблемой, чтобы сделать то же самое с MFC.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace IeApp
{
public partial class MainForm : Form
{
// get the underlying WebBrowser ActiveX object;
// this code depends on SHDocVw.dll COM interop assembly,
// generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
// and add as a reference to the project

public MainForm()
{
InitializeComponent();
}

private void NewWindow_Click(object sender, EventArgs e)
{
AllowSetForegroundWindow(ASFW_ANY);
// could do: var ie =  new SHDocVw.InternetExplorer()
var ie = (SHDocVw.InternetExplorer)Activator.CreateInstance(Type.GetTypeFromProgID("InternetExplorer.Application"));
ie.Visible = true;
ie.Navigate("http://www.example.com");
}

const int ASFW_ANY = -1;
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int dwProcessId);
}
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]