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: 43HINSTANCE hInst; // current instance 44HWND hMainWnd; 45HWND hURLBarWnd; 46long DefEditProc; 47IWebView* gWebView = 0; 48HWND gViewWindow = 0; 49WinLauncherWebHost* gWebHost = 0; 50PrintWebUIDelegate* gPrintDelegate = 0; 51TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 52TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name 53 54// Forward declarations of functions included in this code module: 55ATOM MyRegisterClass(HINSTANCE hInstance); 56BOOL InitInstance(HINSTANCE, int); 57LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 58INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 59LRESULT CALLBACK MyEditProc(HWND, UINT, WPARAM, LPARAM); 60 61static void loadURL(BSTR urlBStr); 62 63HRESULT 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 92exit: 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 103HRESULT 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 117ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void) 118{ 119 return ++m_refCount; 120} 121 122ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void) 123{ 124 ULONG newRef = --m_refCount; 125 if (!newRef) 126 delete(this); 127 128 return newRef; 129} 130 131static 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 139int 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 = {0}; 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 245exit: 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 259ATOM 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 280BOOL 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 296static 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 307static 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 319static void initDocStruct(DOCINFO* di, TCHAR* docname) 320{ 321 memset(di, 0, sizeof(DOCINFO)); 322 di->cbSize = sizeof(DOCINFO); 323 di->lpszDocName = docname; 324} 325 326void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 327{ 328 HDC printDC = getPrinterDC(); 329 if (!printDC) { 330 ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK); 331 return; 332 } 333 334 if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) { 335 ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK); 336 return; 337 } 338 339 IWebFrame* frame = 0; 340 IWebFramePrivate* framePrivate = 0; 341 if (FAILED(gWebView->mainFrame(&frame))) 342 goto exit; 343 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, L"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 369exit: 370 if (frame) 371 frame->Release(); 372 if (framePrivate) 373 framePrivate->Release(); 374} 375 376LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 377{ 378 int wmId, wmEvent; 379 380 switch (message) { 381 case WM_COMMAND: 382 wmId = LOWORD(wParam); 383 wmEvent = HIWORD(wParam); 384 // Parse the menu selections: 385 switch (wmId) { 386 case IDM_ABOUT: 387 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 388 break; 389 case IDM_EXIT: 390 DestroyWindow(hWnd); 391 break; 392 case IDM_PRINT: 393 PrintView(hWnd, message, wParam, lParam); 394 break; 395 default: 396 return DefWindowProc(hWnd, message, wParam, lParam); 397 } 398 break; 399 case WM_DESTROY: 400 PostQuitMessage(0); 401 break; 402 case WM_SIZE: 403 if (!gWebView) 404 break; 405 resizeSubViews(); 406 break; 407 default: 408 return DefWindowProc(hWnd, message, wParam, lParam); 409 } 410 return 0; 411} 412 413 414#define MAX_URL_LENGTH 1024 415 416LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 417{ 418 switch (message) { 419 case WM_CHAR: 420 if (wParam == 13) { // Enter Key 421 wchar_t strPtr[MAX_URL_LENGTH]; 422 *((LPWORD)strPtr) = MAX_URL_LENGTH; 423 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr); 424 425 BSTR bstr = SysAllocStringLen(strPtr, strLen); 426 loadURL(bstr); 427 SysFreeString(bstr); 428 429 return 0; 430 } else 431 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); 432 break; 433 default: 434 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); 435 break; 436 } 437} 438 439 440// Message handler for about box. 441INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 442{ 443 UNREFERENCED_PARAMETER(lParam); 444 switch (message) { 445 case WM_INITDIALOG: 446 return (INT_PTR)TRUE; 447 448 case WM_COMMAND: 449 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { 450 EndDialog(hDlg, LOWORD(wParam)); 451 return (INT_PTR)TRUE; 452 } 453 break; 454 } 455 return (INT_PTR)FALSE; 456} 457 458static void loadURL(BSTR urlBStr) 459{ 460 IWebFrame* frame = 0; 461 IWebMutableURLRequest* request = 0; 462 463 static BSTR methodBStr = SysAllocString(TEXT("GET")); 464 465 if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) { 466 TCHAR fileURL[INTERNET_MAX_URL_LENGTH]; 467 DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]); 468 469 if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0))) 470 SysReAllocString(&urlBStr, fileURL); 471 } 472 473 HRESULT hr = gWebView->mainFrame(&frame); 474 if (FAILED(hr)) 475 goto exit; 476 477 hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request); 478 if (FAILED(hr)) 479 goto exit; 480 481 hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60); 482 if (FAILED(hr)) 483 goto exit; 484 485 hr = request->setHTTPMethod(methodBStr); 486 if (FAILED(hr)) 487 goto exit; 488 489 hr = frame->loadRequest(request); 490 if (FAILED(hr)) 491 goto exit; 492 493 SetFocus(gViewWindow); 494 495exit: 496 if (frame) 497 frame->Release(); 498 if (request) 499 request->Release(); 500} 501