Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "StdAfx.h"
     27 #include "BrowserWindow.h"
     28 #include "MiniBrowser.h"
     29 #include "Resource.h"
     30 
     31 #include <assert.h>
     32 #include <commctrl.h>
     33 #include <shlwapi.h>
     34 #include <vector>
     35 #include <wininet.h>
     36 
     37 using namespace std;
     38 
     39 BrowserWindow::BrowserWindow()
     40     : m_window(0)
     41     , m_rebarWindow(0)
     42     , m_comboBoxWindow(0)
     43 {
     44 }
     45 
     46 LRESULT CALLBACK BrowserWindow::BrowserWindowWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
     47 {
     48     LONG_PTR longPtr = ::GetWindowLongPtr(window, 0);
     49 
     50     if (BrowserWindow* browserView = reinterpret_cast<BrowserWindow*>(longPtr))
     51         return browserView->wndProc(window, message, wParam, lParam);
     52 
     53     if (message == WM_CREATE) {
     54         LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
     55         BrowserWindow* browserWindow = static_cast<BrowserWindow*>(createStruct->lpCreateParams);
     56         browserWindow->m_window = window;
     57 
     58         ::SetWindowLongPtr(window, 0, (LONG_PTR)browserWindow);
     59 
     60         browserWindow->onCreate(createStruct);
     61         return 0;
     62     }
     63 
     64     return ::DefWindowProc(window, message, wParam, lParam);
     65 }
     66 
     67 LRESULT BrowserWindow::wndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
     68 {
     69     LRESULT lResult = 0;
     70     bool handled = true;
     71 
     72     switch (message) {
     73     case WM_ERASEBKGND:
     74         lResult = 1;
     75         break;
     76 
     77     case WM_COMMAND:
     78         lResult = onCommand(LOWORD(wParam), handled);
     79         break;
     80 
     81     case WM_SIZE:
     82         onSize(LOWORD(lParam), HIWORD(lParam));
     83         break;
     84 
     85     case WM_DESTROY:
     86         onDestroy();
     87         break;
     88 
     89     case WM_NCDESTROY:
     90         onNCDestroy();
     91         break;
     92 
     93     default:
     94         handled = false;
     95     }
     96 
     97     if (!handled)
     98         lResult = ::DefWindowProc(window, message, wParam, lParam);
     99 
    100     return lResult;
    101 }
    102 
    103 void BrowserWindow::createWindow(int x, int y, int width, int height)
    104 {
    105     assert(!m_window);
    106 
    107     // Register the class.
    108     WNDCLASSEX windowClass = { 0 };
    109     windowClass.cbSize = sizeof(windowClass);
    110     windowClass.style = 0;
    111     windowClass.lpfnWndProc = BrowserWindowWndProc;
    112     windowClass.cbClsExtra = 0;
    113     windowClass.cbWndExtra = sizeof(this);
    114     windowClass.hInstance = MiniBrowser::shared().instance();
    115     windowClass.hIcon = 0;
    116     windowClass.hCursor = ::LoadCursor(0, IDC_ARROW);
    117     windowClass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
    118     windowClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME);
    119     windowClass.lpszClassName = L"MiniBrowser";
    120     windowClass.hIconSm = 0;
    121 
    122     ::RegisterClassEx(&windowClass);
    123 
    124     ::CreateWindowW(L"MiniBrowser", L"MiniBrowser", WS_OVERLAPPEDWINDOW, x, y, width, height, 0, 0, MiniBrowser::shared().instance(), this);
    125 }
    126 
    127 void BrowserWindow::showWindow()
    128 {
    129     assert(m_window);
    130 
    131     ::ShowWindow(m_window, SW_SHOWNORMAL);
    132 }
    133 
    134 void BrowserWindow::goToURL(const std::wstring& url)
    135 {
    136     m_browserView.goToURL(url);
    137 }
    138 
    139 void BrowserWindow::onCreate(LPCREATESTRUCT createStruct)
    140 {
    141     // Register our window.
    142     MiniBrowser::shared().registerWindow(this);
    143 
    144     // Create the rebar control.
    145     m_rebarWindow = ::CreateWindowEx(0, REBARCLASSNAME, 0, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN | RBS_VARHEIGHT | RBS_BANDBORDERS,
    146                                      0, 0, 0, 0, m_window, 0, createStruct->hInstance, 0);
    147     REBARINFO rebarInfo = { 0 };
    148     rebarInfo.cbSize = sizeof(rebarInfo);
    149     rebarInfo.fMask = 0;
    150     ::SendMessage(m_rebarWindow, RB_SETBARINFO, 0, (LPARAM)&rebarInfo);
    151 
    152     // Create the combo box control.
    153     m_comboBoxWindow = ::CreateWindowEx(0, L"combobox", 0, WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBS_AUTOHSCROLL | CBS_DROPDOWN,
    154                                         0, 0, 0, 0, m_rebarWindow, 0, createStruct->hInstance, 0);
    155     SendMessage(m_comboBoxWindow, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
    156 
    157     REBARBANDINFO bandInfo;
    158     bandInfo.cbSize = sizeof(bandInfo);
    159     bandInfo.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
    160     bandInfo.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;
    161     bandInfo.lpText = L"Address";
    162     bandInfo.hwndChild = m_comboBoxWindow;
    163 
    164     RECT comboBoxRect;
    165     ::GetWindowRect(m_comboBoxWindow, &comboBoxRect);
    166     bandInfo.cx = 100;
    167     bandInfo.cxMinChild = comboBoxRect.right - comboBoxRect.left;
    168     bandInfo.cyMinChild = comboBoxRect.bottom - comboBoxRect.top;
    169 
    170     // Add the band to the rebar.
    171     int result = ::SendMessage(m_rebarWindow, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&bandInfo);
    172 
    173     // Create the browser view.
    174     RECT webViewRect = { 0, 0, 0, 0};
    175     m_browserView.create(webViewRect, this);
    176 }
    177 
    178 void BrowserWindow::onDestroy()
    179 {
    180     MiniBrowser::shared().unregisterWindow(this);
    181 
    182     // FIXME: Should we close the browser view here?
    183 }
    184 
    185 void BrowserWindow::onNCDestroy()
    186 {
    187     delete this;
    188 }
    189 
    190 void BrowserWindow::onSize(int width, int height)
    191 {
    192     RECT rebarRect;
    193     ::GetClientRect(m_rebarWindow, &rebarRect);
    194 
    195     // Resize the rebar.
    196     ::MoveWindow(m_rebarWindow, 0, 0, width, rebarRect.bottom - rebarRect.top, true);
    197 
    198     RECT webViewRect;
    199     webViewRect.top = rebarRect.bottom;
    200     webViewRect.left = 0;
    201     webViewRect.right = width;
    202     webViewRect.bottom = height;
    203     m_browserView.setFrame(webViewRect);
    204 }
    205 
    206 LRESULT BrowserWindow::onCommand(int commandID, bool& handled)
    207 {
    208     switch (commandID) {
    209     case ID_FILE_NEW_WINDOW:
    210         MiniBrowser::shared().createNewWindow();
    211         break;
    212     case ID_FILE_CLOSE:
    213         ::PostMessage(m_window, WM_CLOSE, 0, 0);
    214         break;
    215     case ID_DEBUG_SHOW_WEB_VIEW: {
    216         HMENU menu = ::GetMenu(m_window);
    217         bool shouldHide = ::GetMenuState(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND) & MF_CHECKED;
    218 
    219         ::CheckMenuItem(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND | (shouldHide ? MF_UNCHECKED : MF_CHECKED));
    220 
    221         // Show or hide the web view.
    222         HWND webViewWindow = WKViewGetWindow(m_browserView.webView());
    223         ::ShowWindow(webViewWindow, shouldHide ? SW_HIDE : SW_SHOW);
    224         break;
    225     }
    226     default:
    227         handled = false;
    228     }
    229 
    230     return 0;
    231 }
    232 
    233 bool BrowserWindow::handleMessage(const MSG* message)
    234 {
    235     if (message->hwnd != m_comboBoxWindow && !::IsChild(m_comboBoxWindow, message->hwnd))
    236         return false;
    237 
    238     // Look for a WM_KEYDOWN message.
    239     if (message->message != WM_KEYDOWN)
    240         return false;
    241 
    242     // Look for the VK_RETURN key.
    243     if (message->wParam != VK_RETURN)
    244         return false;
    245 
    246     std::vector<WCHAR> buffer;
    247     int textLength = ::GetWindowTextLength(m_comboBoxWindow);
    248 
    249     buffer.resize(textLength + 1);
    250     ::GetWindowText(m_comboBoxWindow, &buffer[0], buffer.size());
    251 
    252     std::wstring url(&buffer[0], buffer.size() - 1);
    253 
    254     if (url.find(L"http://"))
    255         url = L"http://" + url;
    256 
    257     m_browserView.goToURL(url);
    258 
    259     // We handled this message.
    260     return true;
    261 }
    262