/* * Copyright (C) 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "StdAfx.h" #include "BrowserWindow.h" #include "MiniBrowser.h" #include "Resource.h" #include #include #include #include #include using namespace std; BrowserWindow::BrowserWindow() : m_window(0) , m_rebarWindow(0) , m_comboBoxWindow(0) { } LRESULT CALLBACK BrowserWindow::BrowserWindowWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { LONG_PTR longPtr = ::GetWindowLongPtr(window, 0); if (BrowserWindow* browserView = reinterpret_cast(longPtr)) return browserView->wndProc(window, message, wParam, lParam); if (message == WM_CREATE) { LPCREATESTRUCT createStruct = reinterpret_cast(lParam); BrowserWindow* browserWindow = static_cast(createStruct->lpCreateParams); browserWindow->m_window = window; ::SetWindowLongPtr(window, 0, (LONG_PTR)browserWindow); browserWindow->onCreate(createStruct); return 0; } return ::DefWindowProc(window, message, wParam, lParam); } LRESULT BrowserWindow::wndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT lResult = 0; bool handled = true; switch (message) { case WM_ERASEBKGND: lResult = 1; break; case WM_COMMAND: lResult = onCommand(LOWORD(wParam), handled); break; case WM_SIZE: onSize(LOWORD(lParam), HIWORD(lParam)); break; case WM_DESTROY: onDestroy(); break; case WM_NCDESTROY: onNCDestroy(); break; default: handled = false; } if (!handled) lResult = ::DefWindowProc(window, message, wParam, lParam); return lResult; } void BrowserWindow::createWindow(int x, int y, int width, int height) { assert(!m_window); // Register the class. WNDCLASSEX windowClass = { 0 }; windowClass.cbSize = sizeof(windowClass); windowClass.style = 0; windowClass.lpfnWndProc = BrowserWindowWndProc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = sizeof(this); windowClass.hInstance = MiniBrowser::shared().instance(); windowClass.hIcon = 0; windowClass.hCursor = ::LoadCursor(0, IDC_ARROW); windowClass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); windowClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME); windowClass.lpszClassName = L"MiniBrowser"; windowClass.hIconSm = 0; ::RegisterClassEx(&windowClass); ::CreateWindowW(L"MiniBrowser", L"MiniBrowser", WS_OVERLAPPEDWINDOW, x, y, width, height, 0, 0, MiniBrowser::shared().instance(), this); } void BrowserWindow::showWindow() { assert(m_window); ::ShowWindow(m_window, SW_SHOWNORMAL); } void BrowserWindow::goToURL(const std::wstring& url) { m_browserView.goToURL(url); } void BrowserWindow::onCreate(LPCREATESTRUCT createStruct) { // Register our window. MiniBrowser::shared().registerWindow(this); // Create the rebar control. m_rebarWindow = ::CreateWindowEx(0, REBARCLASSNAME, 0, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN | RBS_VARHEIGHT | RBS_BANDBORDERS, 0, 0, 0, 0, m_window, 0, createStruct->hInstance, 0); REBARINFO rebarInfo = { 0 }; rebarInfo.cbSize = sizeof(rebarInfo); rebarInfo.fMask = 0; ::SendMessage(m_rebarWindow, RB_SETBARINFO, 0, (LPARAM)&rebarInfo); // Create the combo box control. m_comboBoxWindow = ::CreateWindowEx(0, L"combobox", 0, WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBS_AUTOHSCROLL | CBS_DROPDOWN, 0, 0, 0, 0, m_rebarWindow, 0, createStruct->hInstance, 0); SendMessage(m_comboBoxWindow, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0)); REBARBANDINFO bandInfo; bandInfo.cbSize = sizeof(bandInfo); bandInfo.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE; bandInfo.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS; bandInfo.lpText = L"Address"; bandInfo.hwndChild = m_comboBoxWindow; RECT comboBoxRect; ::GetWindowRect(m_comboBoxWindow, &comboBoxRect); bandInfo.cx = 100; bandInfo.cxMinChild = comboBoxRect.right - comboBoxRect.left; bandInfo.cyMinChild = comboBoxRect.bottom - comboBoxRect.top; // Add the band to the rebar. int result = ::SendMessage(m_rebarWindow, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&bandInfo); // Create the browser view. RECT webViewRect = { 0, 0, 0, 0}; m_browserView.create(webViewRect, this); } void BrowserWindow::onDestroy() { MiniBrowser::shared().unregisterWindow(this); // FIXME: Should we close the browser view here? } void BrowserWindow::onNCDestroy() { delete this; } void BrowserWindow::onSize(int width, int height) { RECT rebarRect; ::GetClientRect(m_rebarWindow, &rebarRect); // Resize the rebar. ::MoveWindow(m_rebarWindow, 0, 0, width, rebarRect.bottom - rebarRect.top, true); RECT webViewRect; webViewRect.top = rebarRect.bottom; webViewRect.left = 0; webViewRect.right = width; webViewRect.bottom = height; m_browserView.setFrame(webViewRect); } LRESULT BrowserWindow::onCommand(int commandID, bool& handled) { switch (commandID) { case ID_FILE_NEW_WINDOW: MiniBrowser::shared().createNewWindow(); break; case ID_FILE_CLOSE: ::PostMessage(m_window, WM_CLOSE, 0, 0); break; case ID_DEBUG_SHOW_WEB_VIEW: { HMENU menu = ::GetMenu(m_window); bool shouldHide = ::GetMenuState(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND) & MF_CHECKED; ::CheckMenuItem(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND | (shouldHide ? MF_UNCHECKED : MF_CHECKED)); // Show or hide the web view. HWND webViewWindow = WKViewGetWindow(m_browserView.webView()); ::ShowWindow(webViewWindow, shouldHide ? SW_HIDE : SW_SHOW); break; } default: handled = false; } return 0; } bool BrowserWindow::handleMessage(const MSG* message) { if (message->hwnd != m_comboBoxWindow && !::IsChild(m_comboBoxWindow, message->hwnd)) return false; // Look for a WM_KEYDOWN message. if (message->message != WM_KEYDOWN) return false; // Look for the VK_RETURN key. if (message->wParam != VK_RETURN) return false; std::vector buffer; int textLength = ::GetWindowTextLength(m_comboBoxWindow); buffer.resize(textLength + 1); ::GetWindowText(m_comboBoxWindow, &buffer[0], buffer.size()); std::wstring url(&buffer[0], buffer.size() - 1); if (url.find(L"http://")) url = L"http://" + url; m_browserView.goToURL(url); // We handled this message. return true; }