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