1 /* 2 * Copyright (C) 2006, 2008 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2009 Brent Fulgha. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "stdafx.h" 28 #include "WinLauncher.h" 29 #include <WebKit/WebKitCOMAPI.h> 30 31 #include <commctrl.h> 32 #include <commdlg.h> 33 #include <objbase.h> 34 #include <shlwapi.h> 35 #include <wininet.h> 36 37 #include "PrintWebUIDelegate.h" 38 39 #define MAX_LOADSTRING 100 40 #define URLBAR_HEIGHT 24 41 42 // Global Variables: 43 HINSTANCE hInst; // current instance 44 HWND hMainWnd; 45 HWND hURLBarWnd; 46 long DefEditProc; 47 IWebView* gWebView = 0; 48 HWND gViewWindow = 0; 49 WinLauncherWebHost* gWebHost = 0; 50 PrintWebUIDelegate* gPrintDelegate = 0; 51 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 52 TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name 53 54 // Forward declarations of functions included in this code module: 55 ATOM MyRegisterClass(HINSTANCE hInstance); 56 BOOL InitInstance(HINSTANCE, int); 57 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 58 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 59 LRESULT CALLBACK MyEditProc(HWND, UINT, WPARAM, LPARAM); 60 61 static void loadURL(BSTR urlBStr); 62 63 HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView) 64 { 65 IWebFrame* mainFrame = 0; 66 IWebDataSource* dataSource = 0; 67 IWebMutableURLRequest* request = 0; 68 BSTR frameURL = 0; 69 70 HRESULT hr = S_OK; 71 72 hr = webView->mainFrame(&mainFrame); 73 if (FAILED(hr)) 74 goto exit; 75 76 hr = mainFrame->dataSource(&dataSource); 77 if (FAILED(hr) || !dataSource) 78 hr = mainFrame->provisionalDataSource(&dataSource); 79 if (FAILED(hr) || !dataSource) 80 goto exit; 81 82 hr = dataSource->request(&request); 83 if (FAILED(hr) || !request) 84 goto exit; 85 86 hr = request->mainDocumentURL(&frameURL); 87 if (FAILED(hr)) 88 goto exit; 89 90 SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL); 91 92 exit: 93 if (mainFrame) 94 mainFrame->Release(); 95 if (dataSource) 96 dataSource->Release(); 97 if (request) 98 request->Release(); 99 SysFreeString(frameURL); 100 return 0; 101 } 102 103 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject) 104 { 105 *ppvObject = 0; 106 if (IsEqualGUID(riid, IID_IUnknown)) 107 *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); 108 else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate)) 109 *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); 110 else 111 return E_NOINTERFACE; 112 113 AddRef(); 114 return S_OK; 115 } 116 117 ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void) 118 { 119 return ++m_refCount; 120 } 121 122 ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void) 123 { 124 ULONG newRef = --m_refCount; 125 if (!newRef) 126 delete(this); 127 128 return newRef; 129 } 130 131 static void resizeSubViews() 132 { 133 RECT rcClient; 134 GetClientRect(hMainWnd, &rcClient); 135 MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE); 136 MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE); 137 } 138 139 int APIENTRY _tWinMain(HINSTANCE hInstance, 140 HINSTANCE hPrevInstance, 141 LPTSTR lpCmdLine, 142 int nCmdShow) 143 { 144 #ifdef _CRTDBG_MAP_ALLOC 145 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 146 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 147 #endif 148 149 UNREFERENCED_PARAMETER(hPrevInstance); 150 UNREFERENCED_PARAMETER(lpCmdLine); 151 152 // TODO: Place code here. 153 MSG msg; 154 HACCEL hAccelTable; 155 156 INITCOMMONCONTROLSEX InitCtrlEx; 157 158 InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); 159 InitCtrlEx.dwICC = 0x00004000; //ICC_STANDARD_CLASSES; 160 InitCommonControlsEx(&InitCtrlEx); 161 162 // Initialize global strings 163 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 164 LoadString(hInstance, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING); 165 MyRegisterClass(hInstance); 166 167 // Perform application initialization: 168 if (!InitInstance (hInstance, nCmdShow)) 169 return FALSE; 170 171 // Init COM 172 OleInitialize(NULL); 173 174 hURLBarWnd = CreateWindow(L"EDIT", 0, 175 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 176 0, 0, 0, 0, 177 hMainWnd, 178 0, 179 hInstance, 0); 180 181 DefEditProc = GetWindowLong(hURLBarWnd, GWL_WNDPROC); 182 SetWindowLong(hURLBarWnd, GWL_WNDPROC,(long)MyEditProc); 183 SetFocus(hURLBarWnd); 184 185 HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, (void**)&gWebView); 186 if (FAILED(hr)) 187 goto exit; 188 189 gWebHost = new WinLauncherWebHost(); 190 gWebHost->AddRef(); 191 hr = gWebView->setFrameLoadDelegate(gWebHost); 192 if (FAILED(hr)) 193 goto exit; 194 195 gPrintDelegate = new PrintWebUIDelegate; 196 gPrintDelegate->AddRef(); 197 hr = gWebView->setUIDelegate(gPrintDelegate); 198 if (FAILED (hr)) 199 goto exit; 200 201 hr = gWebView->setHostWindow((OLE_HANDLE) hMainWnd); 202 if (FAILED(hr)) 203 goto exit; 204 205 RECT clientRect; 206 GetClientRect(hMainWnd, &clientRect); 207 hr = gWebView->initWithFrame(clientRect, 0, 0); 208 if (FAILED(hr)) 209 goto exit; 210 211 IWebFrame* frame; 212 hr = gWebView->mainFrame(&frame); 213 if (FAILED(hr)) 214 goto exit; 215 216 static BSTR defaultHTML = SysAllocString(TEXT("<p style=\"background-color: #00FF00\">Testing</p><img src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>")); 217 frame->loadHTMLString(defaultHTML, 0); 218 frame->Release(); 219 220 IWebViewPrivate* viewExt; 221 hr = gWebView->QueryInterface(IID_IWebViewPrivate, (void**)&viewExt); 222 if (FAILED(hr)) 223 goto exit; 224 225 hr = viewExt->viewWindow((OLE_HANDLE*) &gViewWindow); 226 viewExt->Release(); 227 if (FAILED(hr) || !gViewWindow) 228 goto exit; 229 230 resizeSubViews(); 231 232 ShowWindow(gViewWindow, nCmdShow); 233 UpdateWindow(gViewWindow); 234 235 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINLAUNCHER)); 236 237 // Main message loop: 238 while (GetMessage(&msg, NULL, 0, 0)) { 239 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { 240 TranslateMessage(&msg); 241 DispatchMessage(&msg); 242 } 243 } 244 245 exit: 246 gPrintDelegate->Release(); 247 gWebView->Release(); 248 shutDownWebKit(); 249 #ifdef _CRTDBG_MAP_ALLOC 250 _CrtDumpMemoryLeaks(); 251 #endif 252 253 // Shut down COM. 254 OleUninitialize(); 255 256 return static_cast<int>(msg.wParam); 257 } 258 259 ATOM MyRegisterClass(HINSTANCE hInstance) 260 { 261 WNDCLASSEX wcex; 262 263 wcex.cbSize = sizeof(WNDCLASSEX); 264 265 wcex.style = CS_HREDRAW | CS_VREDRAW; 266 wcex.lpfnWndProc = WndProc; 267 wcex.cbClsExtra = 0; 268 wcex.cbWndExtra = 0; 269 wcex.hInstance = hInstance; 270 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER)); 271 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 272 wcex.hbrBackground = 0; 273 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINLAUNCHER); 274 wcex.lpszClassName = szWindowClass; 275 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 276 277 return RegisterClassEx(&wcex); 278 } 279 280 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 281 { 282 hInst = hInstance; // Store instance handle in our global variable 283 284 hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 285 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 286 287 if (!hMainWnd) 288 return FALSE; 289 290 ShowWindow(hMainWnd, nCmdShow); 291 UpdateWindow(hMainWnd); 292 293 return TRUE; 294 } 295 296 static BOOL CALLBACK AbortProc(HDC hDC, int Error) 297 { 298 MSG msg; 299 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { 300 ::TranslateMessage(&msg); 301 ::DispatchMessage(&msg); 302 } 303 304 return TRUE; 305 } 306 307 static HDC getPrinterDC() 308 { 309 PRINTDLG pdlg; 310 memset(&pdlg, 0, sizeof(PRINTDLG)); 311 pdlg.lStructSize = sizeof(PRINTDLG); 312 pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC; 313 314 ::PrintDlg(&pdlg); 315 316 return pdlg.hDC; 317 } 318 319 static void initDocStruct(DOCINFO* di, TCHAR* docname) 320 { 321 memset(di, 0, sizeof(DOCINFO)); 322 di->cbSize = sizeof(DOCINFO); 323 di->lpszDocName = docname; 324 } 325 326 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 327 { 328 HDC printDC = getPrinterDC(); 329 if (!printDC) { 330 ::MessageBox(0, _T("Error creating printing DC"), _T("Error"), MB_APPLMODAL | MB_OK); 331 return; 332 } 333 334 if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) { 335 ::MessageBox(0, _T("Error setting up AbortProc"), _T("Error"), MB_APPLMODAL | MB_OK); 336 return; 337 } 338 339 IWebFrame* frame = 0; 340 if (FAILED(gWebView->mainFrame(&frame))) 341 goto exit; 342 343 IWebFramePrivate* framePrivate = 0; 344 if (FAILED(frame->QueryInterface(&framePrivate))) 345 goto exit; 346 347 framePrivate->setInPrintingMode(TRUE, printDC); 348 349 UINT pageCount = 0; 350 framePrivate->getPrintedPageCount(printDC, &pageCount); 351 352 DOCINFO di; 353 initDocStruct(&di, _T("WebKit Doc")); 354 ::StartDoc(printDC, &di); 355 356 // FIXME: Need CoreGraphics implementation 357 void* graphicsContext = 0; 358 for (size_t page = 1; page <= pageCount; ++page) { 359 ::StartPage(printDC); 360 framePrivate->spoolPages(printDC, page, page, graphicsContext); 361 ::EndPage(printDC); 362 } 363 364 framePrivate->setInPrintingMode(FALSE, printDC); 365 366 ::EndDoc(printDC); 367 ::DeleteDC(printDC); 368 369 exit: 370 if (frame) 371 frame->Release(); 372 if (framePrivate) 373 framePrivate->Release(); 374 } 375 376 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 377 { 378 int wmId, wmEvent; 379 PAINTSTRUCT ps; 380 HDC hdc; 381 382 switch (message) { 383 case WM_COMMAND: 384 wmId = LOWORD(wParam); 385 wmEvent = HIWORD(wParam); 386 // Parse the menu selections: 387 switch (wmId) { 388 case IDM_ABOUT: 389 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 390 break; 391 case IDM_EXIT: 392 DestroyWindow(hWnd); 393 break; 394 case IDM_PRINT: 395 PrintView(hWnd, message, wParam, lParam); 396 break; 397 default: 398 return DefWindowProc(hWnd, message, wParam, lParam); 399 } 400 break; 401 case WM_DESTROY: 402 PostQuitMessage(0); 403 break; 404 case WM_SIZE: 405 if (!gWebView) 406 break; 407 resizeSubViews(); 408 break; 409 default: 410 return DefWindowProc(hWnd, message, wParam, lParam); 411 } 412 return 0; 413 } 414 415 416 #define MAX_URL_LENGTH 1024 417 418 LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 419 { 420 switch (message) { 421 case WM_CHAR: 422 if (wParam == 13) { // Enter Key 423 wchar_t strPtr[MAX_URL_LENGTH]; 424 *((LPWORD)strPtr) = MAX_URL_LENGTH; 425 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr); 426 427 BSTR bstr = SysAllocStringLen(strPtr, strLen); 428 loadURL(bstr); 429 SysFreeString(bstr); 430 431 return 0; 432 } else 433 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); 434 break; 435 default: 436 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); 437 break; 438 } 439 return 0; 440 } 441 442 443 // Message handler for about box. 444 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 445 { 446 UNREFERENCED_PARAMETER(lParam); 447 switch (message) { 448 case WM_INITDIALOG: 449 return (INT_PTR)TRUE; 450 451 case WM_COMMAND: 452 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { 453 EndDialog(hDlg, LOWORD(wParam)); 454 return (INT_PTR)TRUE; 455 } 456 break; 457 } 458 return (INT_PTR)FALSE; 459 } 460 461 static void loadURL(BSTR urlBStr) 462 { 463 IWebFrame* frame = 0; 464 IWebMutableURLRequest* request = 0; 465 466 static BSTR methodBStr = SysAllocString(TEXT("GET")); 467 468 if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) { 469 TCHAR fileURL[INTERNET_MAX_URL_LENGTH]; 470 DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]); 471 472 if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0))) 473 SysReAllocString(&urlBStr, fileURL); 474 } 475 476 HRESULT hr = gWebView->mainFrame(&frame); 477 if (FAILED(hr)) 478 goto exit; 479 480 hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request); 481 if (FAILED(hr)) 482 goto exit; 483 484 hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60); 485 if (FAILED(hr)) 486 goto exit; 487 488 hr = request->setHTTPMethod(methodBStr); 489 if (FAILED(hr)) 490 goto exit; 491 492 hr = frame->loadRequest(request); 493 if (FAILED(hr)) 494 goto exit; 495 496 SetFocus(gViewWindow); 497 498 exit: 499 if (frame) 500 frame->Release(); 501 if (request) 502 request->Release(); 503 } 504