| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/printing/win_printing_context.h" | |
| 6 | |
| 7 #include <winspool.h> | |
| 8 | |
| 9 #include "base/file_util.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "base/time.h" | |
| 12 #include "base/time_format.h" | |
| 13 #include "chrome/browser/browser_process.h" | |
| 14 #include "chrome/browser/printing/printed_document.h" | |
| 15 #include "skia/ext/platform_device_win.h" | |
| 16 | |
| 17 using base::Time; | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 // Retrieves the content of a GetPrinter call. | |
| 22 void GetPrinterHelper(HANDLE printer, int level, scoped_array<uint8>* buffer) { | |
| 23 DWORD buf_size = 0; | |
| 24 GetPrinter(printer, level, NULL, 0, &buf_size); | |
| 25 if (buf_size) { | |
| 26 buffer->reset(new uint8[buf_size]); | |
| 27 memset(buffer->get(), 0, buf_size); | |
| 28 if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) { | |
| 29 buffer->reset(); | |
| 30 } | |
| 31 } | |
| 32 } | |
| 33 | |
| 34 } // namespace | |
| 35 | |
| 36 namespace printing { | |
| 37 | |
| 38 class PrintingContext::CallbackHandler | |
| 39 : public IPrintDialogCallback, | |
| 40 public IObjectWithSite { | |
| 41 public: | |
| 42 CallbackHandler(PrintingContext& owner, HWND owner_hwnd) | |
| 43 : owner_(owner), | |
| 44 owner_hwnd_(owner_hwnd), | |
| 45 services_(NULL) { | |
| 46 } | |
| 47 | |
| 48 ~CallbackHandler() { | |
| 49 if (services_) | |
| 50 services_->Release(); | |
| 51 } | |
| 52 | |
| 53 IUnknown* ToIUnknown() { | |
| 54 return static_cast<IUnknown*>(static_cast<IPrintDialogCallback*>(this)); | |
| 55 } | |
| 56 | |
| 57 // IUnknown | |
| 58 virtual HRESULT WINAPI QueryInterface(REFIID riid, void**object) { | |
| 59 if (riid == IID_IUnknown) { | |
| 60 *object = ToIUnknown(); | |
| 61 } else if (riid == IID_IPrintDialogCallback) { | |
| 62 *object = static_cast<IPrintDialogCallback*>(this); | |
| 63 } else if (riid == IID_IObjectWithSite) { | |
| 64 *object = static_cast<IObjectWithSite*>(this); | |
| 65 } else { | |
| 66 return E_NOINTERFACE; | |
| 67 } | |
| 68 return S_OK; | |
| 69 } | |
| 70 | |
| 71 // No real ref counting. | |
| 72 virtual ULONG WINAPI AddRef() { | |
| 73 return 1; | |
| 74 } | |
| 75 virtual ULONG WINAPI Release() { | |
| 76 return 1; | |
| 77 } | |
| 78 | |
| 79 // IPrintDialogCallback methods | |
| 80 virtual HRESULT WINAPI InitDone() { | |
| 81 return S_OK; | |
| 82 } | |
| 83 | |
| 84 virtual HRESULT WINAPI SelectionChange() { | |
| 85 if (services_) { | |
| 86 // TODO(maruel): Get the devmode for the new printer with | |
| 87 // services_->GetCurrentDevMode(&devmode, &size), send that information | |
| 88 // back to our client and continue. The client needs to recalculate the | |
| 89 // number of rendered pages and send back this information here. | |
| 90 } | |
| 91 return S_OK; | |
| 92 } | |
| 93 | |
| 94 virtual HRESULT WINAPI HandleMessage(HWND dialog, | |
| 95 UINT message, | |
| 96 WPARAM wparam, | |
| 97 LPARAM lparam, | |
| 98 LRESULT* result) { | |
| 99 // Cheap way to retrieve the window handle. | |
| 100 if (!owner_.dialog_box_) { | |
| 101 // The handle we receive is the one of the groupbox in the General tab. We | |
| 102 // need to get the grand-father to get the dialog box handle. | |
| 103 owner_.dialog_box_ = GetAncestor(dialog, GA_ROOT); | |
| 104 // Trick to enable the owner window. This can cause issues with navigation | |
| 105 // events so it may have to be disabled if we don't fix the side-effects. | |
| 106 EnableWindow(owner_hwnd_, TRUE); | |
| 107 } | |
| 108 return S_FALSE; | |
| 109 } | |
| 110 | |
| 111 virtual HRESULT WINAPI SetSite(IUnknown* site) { | |
| 112 if (!site) { | |
| 113 DCHECK(services_); | |
| 114 services_->Release(); | |
| 115 services_ = NULL; | |
| 116 // The dialog box is destroying, PrintJob::Worker don't need the handle | |
| 117 // anymore. | |
| 118 owner_.dialog_box_ = NULL; | |
| 119 } else { | |
| 120 DCHECK(services_ == NULL); | |
| 121 HRESULT hr = site->QueryInterface(IID_IPrintDialogServices, | |
| 122 reinterpret_cast<void**>(&services_)); | |
| 123 DCHECK(SUCCEEDED(hr)); | |
| 124 } | |
| 125 return S_OK; | |
| 126 } | |
| 127 | |
| 128 virtual HRESULT WINAPI GetSite(REFIID riid, void** site) { | |
| 129 return E_NOTIMPL; | |
| 130 } | |
| 131 | |
| 132 private: | |
| 133 PrintingContext& owner_; | |
| 134 HWND owner_hwnd_; | |
| 135 IPrintDialogServices* services_; | |
| 136 | |
| 137 DISALLOW_EVIL_CONSTRUCTORS(CallbackHandler); | |
| 138 }; | |
| 139 | |
| 140 PrintingContext::PrintingContext() | |
| 141 : hdc_(NULL), | |
| 142 #ifndef NDEBUG | |
| 143 page_number_(-1), | |
| 144 #endif | |
| 145 dialog_box_(NULL), | |
| 146 dialog_box_dismissed_(false), | |
| 147 abort_printing_(false), | |
| 148 in_print_job_(false) { | |
| 149 } | |
| 150 | |
| 151 PrintingContext::~PrintingContext() { | |
| 152 ResetSettings(); | |
| 153 } | |
| 154 | |
| 155 PrintingContext::Result PrintingContext::AskUserForSettings( | |
| 156 HWND window, | |
| 157 int max_pages, | |
| 158 bool has_selection) { | |
| 159 DCHECK(window); | |
| 160 DCHECK(!in_print_job_); | |
| 161 dialog_box_dismissed_ = false; | |
| 162 // Show the OS-dependent dialog box. | |
| 163 // If the user press | |
| 164 // - OK, the settings are reset and reinitialized with the new settings. OK is | |
| 165 // returned. | |
| 166 // - Apply then Cancel, the settings are reset and reinitialized with the new | |
| 167 // settings. CANCEL is returned. | |
| 168 // - Cancel, the settings are not changed, the previous setting, if it was | |
| 169 // initialized before, are kept. CANCEL is returned. | |
| 170 // On failure, the settings are reset and FAILED is returned. | |
| 171 PRINTDLGEX dialog_options = { sizeof(PRINTDLGEX) }; | |
| 172 dialog_options.hwndOwner = window; | |
| 173 // Disable options we don't support currently. | |
| 174 // TODO(maruel): Reuse the previously loaded settings! | |
| 175 dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | | |
| 176 PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE; | |
| 177 if (!has_selection) | |
| 178 dialog_options.Flags |= PD_NOSELECTION; | |
| 179 | |
| 180 PRINTPAGERANGE ranges[32]; | |
| 181 dialog_options.nStartPage = START_PAGE_GENERAL; | |
| 182 if (max_pages) { | |
| 183 // Default initialize to print all the pages. | |
| 184 memset(ranges, 0, sizeof(ranges)); | |
| 185 ranges[0].nFromPage = 1; | |
| 186 ranges[0].nToPage = max_pages; | |
| 187 dialog_options.nPageRanges = 1; | |
| 188 dialog_options.nMaxPageRanges = arraysize(ranges); | |
| 189 dialog_options.nMinPage = 1; | |
| 190 dialog_options.nMaxPage = max_pages; | |
| 191 dialog_options.lpPageRanges = ranges; | |
| 192 } else { | |
| 193 // No need to bother, we don't know how many pages are available. | |
| 194 dialog_options.Flags |= PD_NOPAGENUMS; | |
| 195 } | |
| 196 | |
| 197 { | |
| 198 if (PrintDlgEx(&dialog_options) != S_OK) { | |
| 199 ResetSettings(); | |
| 200 return FAILED; | |
| 201 } | |
| 202 } | |
| 203 // TODO(maruel): Support PD_PRINTTOFILE. | |
| 204 return ParseDialogResultEx(dialog_options); | |
| 205 } | |
| 206 | |
| 207 PrintingContext::Result PrintingContext::UseDefaultSettings() { | |
| 208 DCHECK(!in_print_job_); | |
| 209 | |
| 210 PRINTDLG dialog_options = { sizeof(PRINTDLG) }; | |
| 211 dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT; | |
| 212 if (PrintDlg(&dialog_options) == 0) { | |
| 213 ResetSettings(); | |
| 214 return FAILED; | |
| 215 } | |
| 216 return ParseDialogResult(dialog_options); | |
| 217 } | |
| 218 | |
| 219 PrintingContext::Result PrintingContext::InitWithSettings( | |
| 220 const PrintSettings& settings) { | |
| 221 DCHECK(!in_print_job_); | |
| 222 settings_ = settings; | |
| 223 // TODO(maruel): settings_->ToDEVMODE() | |
| 224 HANDLE printer; | |
| 225 if (!OpenPrinter(const_cast<wchar_t*>(settings_.device_name().c_str()), | |
| 226 &printer, | |
| 227 NULL)) | |
| 228 return FAILED; | |
| 229 | |
| 230 Result status = OK; | |
| 231 | |
| 232 if (!GetPrinterSettings(printer, settings_.device_name())) | |
| 233 status = FAILED; | |
| 234 | |
| 235 // Close the printer after retrieving the context. | |
| 236 ClosePrinter(printer); | |
| 237 | |
| 238 if (status != OK) | |
| 239 ResetSettings(); | |
| 240 return status; | |
| 241 } | |
| 242 | |
| 243 void PrintingContext::ResetSettings() { | |
| 244 if (hdc_ != NULL) { | |
| 245 DeleteDC(hdc_); | |
| 246 hdc_ = NULL; | |
| 247 } | |
| 248 settings_.Clear(); | |
| 249 in_print_job_ = false; | |
| 250 | |
| 251 #ifndef NDEBUG | |
| 252 page_number_ = -1; | |
| 253 #endif | |
| 254 } | |
| 255 | |
| 256 PrintingContext::Result PrintingContext::NewDocument( | |
| 257 const std::wstring& document_name) { | |
| 258 DCHECK(!in_print_job_); | |
| 259 if (!hdc_) | |
| 260 return OnError(); | |
| 261 | |
| 262 // Set the flag used by the AbortPrintJob dialog procedure. | |
| 263 abort_printing_ = false; | |
| 264 | |
| 265 in_print_job_ = true; | |
| 266 | |
| 267 // Register the application's AbortProc function with GDI. | |
| 268 if (SP_ERROR == SetAbortProc(hdc_, &AbortProc)) | |
| 269 return OnError(); | |
| 270 | |
| 271 DOCINFO di = { sizeof(DOCINFO) }; | |
| 272 di.lpszDocName = document_name.c_str(); | |
| 273 | |
| 274 // Is there a debug dump directory specified? If so, force to print to a file. | |
| 275 std::wstring debug_dump_path = PrintedDocument::debug_dump_path(); | |
| 276 if (!debug_dump_path.empty()) { | |
| 277 // Create a filename. | |
| 278 std::wstring filename; | |
| 279 Time now(Time::Now()); | |
| 280 filename = base::TimeFormatShortDateNumeric(now); | |
| 281 filename += L"_"; | |
| 282 filename += base::TimeFormatTimeOfDay(now); | |
| 283 filename += L"_"; | |
| 284 filename += document_name; | |
| 285 filename += L"_"; | |
| 286 filename += L"buffer.prn"; | |
| 287 file_util::ReplaceIllegalCharacters(&filename, '_'); | |
| 288 file_util::AppendToPath(&debug_dump_path, filename); | |
| 289 di.lpszOutput = debug_dump_path.c_str(); | |
| 290 } | |
| 291 | |
| 292 DCHECK_EQ(MessageLoop::current()->NestableTasksAllowed(), false); | |
| 293 // Begin a print job by calling the StartDoc function. | |
| 294 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with | |
| 295 // IPC. Make sure recursive task processing is disabled. | |
| 296 if (StartDoc(hdc_, &di) <= 0) | |
| 297 return OnError(); | |
| 298 | |
| 299 #ifndef NDEBUG | |
| 300 page_number_ = 0; | |
| 301 #endif | |
| 302 return OK; | |
| 303 } | |
| 304 | |
| 305 PrintingContext::Result PrintingContext::NewPage() { | |
| 306 if (abort_printing_) | |
| 307 return CANCEL; | |
| 308 DCHECK(in_print_job_); | |
| 309 | |
| 310 // Inform the driver that the application is about to begin sending data. | |
| 311 if (StartPage(hdc_) <= 0) | |
| 312 return OnError(); | |
| 313 | |
| 314 #ifndef NDEBUG | |
| 315 ++page_number_; | |
| 316 #endif | |
| 317 | |
| 318 return OK; | |
| 319 } | |
| 320 | |
| 321 PrintingContext::Result PrintingContext::PageDone() { | |
| 322 if (abort_printing_) | |
| 323 return CANCEL; | |
| 324 DCHECK(in_print_job_); | |
| 325 | |
| 326 if (EndPage(hdc_) <= 0) | |
| 327 return OnError(); | |
| 328 return OK; | |
| 329 } | |
| 330 | |
| 331 PrintingContext::Result PrintingContext::DocumentDone() { | |
| 332 if (abort_printing_) | |
| 333 return CANCEL; | |
| 334 DCHECK(in_print_job_); | |
| 335 | |
| 336 // Inform the driver that document has ended. | |
| 337 if (EndDoc(hdc_) <= 0) | |
| 338 return OnError(); | |
| 339 | |
| 340 ResetSettings(); | |
| 341 return OK; | |
| 342 } | |
| 343 | |
| 344 void PrintingContext::Cancel() { | |
| 345 abort_printing_ = true; | |
| 346 in_print_job_ = false; | |
| 347 if (hdc_) | |
| 348 CancelDC(hdc_); | |
| 349 DismissDialog(); | |
| 350 } | |
| 351 | |
| 352 void PrintingContext::DismissDialog() { | |
| 353 if (dialog_box_) { | |
| 354 DestroyWindow(dialog_box_); | |
| 355 dialog_box_dismissed_ = true; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 PrintingContext::Result PrintingContext::OnError() { | |
| 360 // This will close hdc_ and clear settings_. | |
| 361 ResetSettings(); | |
| 362 return abort_printing_ ? CANCEL : FAILED; | |
| 363 } | |
| 364 | |
| 365 // static | |
| 366 BOOL PrintingContext::AbortProc(HDC hdc, int nCode) { | |
| 367 if (nCode) { | |
| 368 // TODO(maruel): Need a way to find the right instance to set. Should | |
| 369 // leverage PrintJobManager here? | |
| 370 // abort_printing_ = true; | |
| 371 } | |
| 372 return true; | |
| 373 } | |
| 374 | |
| 375 bool PrintingContext::InitializeSettings(const DEVMODE& dev_mode, | |
| 376 const std::wstring& new_device_name, | |
| 377 const PRINTPAGERANGE* ranges, | |
| 378 int number_ranges, | |
| 379 bool selection_only) { | |
| 380 skia::PlatformDevice::InitializeDC(hdc_); | |
| 381 DCHECK(GetDeviceCaps(hdc_, CLIPCAPS)); | |
| 382 DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_STRETCHDIB); | |
| 383 DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_BITMAP64); | |
| 384 // Some printers don't advertise these. | |
| 385 // DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_SCALING); | |
| 386 // DCHECK(GetDeviceCaps(hdc_, SHADEBLENDCAPS) & SB_CONST_ALPHA); | |
| 387 // DCHECK(GetDeviceCaps(hdc_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA); | |
| 388 | |
| 389 // StretchDIBits() support is needed for printing. | |
| 390 if (!(GetDeviceCaps(hdc_, RASTERCAPS) & RC_STRETCHDIB) || | |
| 391 !(GetDeviceCaps(hdc_, RASTERCAPS) & RC_BITMAP64)) { | |
| 392 NOTREACHED(); | |
| 393 ResetSettings(); | |
| 394 return false; | |
| 395 } | |
| 396 | |
| 397 DCHECK(!in_print_job_); | |
| 398 DCHECK(hdc_); | |
| 399 PageRanges ranges_vector; | |
| 400 if (!selection_only) { | |
| 401 // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector. | |
| 402 ranges_vector.reserve(number_ranges); | |
| 403 for (int i = 0; i < number_ranges; ++i) { | |
| 404 PageRange range; | |
| 405 // Transfer from 1-based to 0-based. | |
| 406 range.from = ranges[i].nFromPage - 1; | |
| 407 range.to = ranges[i].nToPage - 1; | |
| 408 ranges_vector.push_back(range); | |
| 409 } | |
| 410 } | |
| 411 settings_.Init(hdc_, | |
| 412 dev_mode, | |
| 413 ranges_vector, | |
| 414 new_device_name, | |
| 415 selection_only); | |
| 416 return true; | |
| 417 } | |
| 418 | |
| 419 bool PrintingContext::GetPrinterSettings(HANDLE printer, | |
| 420 const std::wstring& device_name) { | |
| 421 DCHECK(!in_print_job_); | |
| 422 scoped_array<uint8> buffer; | |
| 423 | |
| 424 // A PRINTER_INFO_9 structure specifying the per-user default printer | |
| 425 // settings. | |
| 426 GetPrinterHelper(printer, 9, &buffer); | |
| 427 if (buffer.get()) { | |
| 428 PRINTER_INFO_9* info_9 = reinterpret_cast<PRINTER_INFO_9*>(buffer.get()); | |
| 429 if (info_9->pDevMode != NULL) { | |
| 430 if (!AllocateContext(device_name, info_9->pDevMode)) { | |
| 431 ResetSettings(); | |
| 432 return false; | |
| 433 } | |
| 434 return InitializeSettings(*info_9->pDevMode, device_name, NULL, 0, false); | |
| 435 } | |
| 436 buffer.reset(); | |
| 437 } | |
| 438 | |
| 439 // A PRINTER_INFO_8 structure specifying the global default printer settings. | |
| 440 GetPrinterHelper(printer, 8, &buffer); | |
| 441 if (buffer.get()) { | |
| 442 PRINTER_INFO_8* info_8 = reinterpret_cast<PRINTER_INFO_8*>(buffer.get()); | |
| 443 if (info_8->pDevMode != NULL) { | |
| 444 if (!AllocateContext(device_name, info_8->pDevMode)) { | |
| 445 ResetSettings(); | |
| 446 return false; | |
| 447 } | |
| 448 return InitializeSettings(*info_8->pDevMode, device_name, NULL, 0, false); | |
| 449 } | |
| 450 buffer.reset(); | |
| 451 } | |
| 452 | |
| 453 // A PRINTER_INFO_2 structure specifying the driver's default printer | |
| 454 // settings. | |
| 455 GetPrinterHelper(printer, 2, &buffer); | |
| 456 if (buffer.get()) { | |
| 457 PRINTER_INFO_2* info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get()); | |
| 458 if (info_2->pDevMode != NULL) { | |
| 459 if (!AllocateContext(device_name, info_2->pDevMode)) { | |
| 460 ResetSettings(); | |
| 461 return false; | |
| 462 } | |
| 463 return InitializeSettings(*info_2->pDevMode, device_name, NULL, 0, false); | |
| 464 } | |
| 465 buffer.reset(); | |
| 466 } | |
| 467 // Failed to retrieve the printer settings. | |
| 468 ResetSettings(); | |
| 469 return false; | |
| 470 } | |
| 471 | |
| 472 bool PrintingContext::AllocateContext(const std::wstring& printer_name, | |
| 473 const DEVMODE* dev_mode) { | |
| 474 hdc_ = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); | |
| 475 DCHECK(hdc_); | |
| 476 return hdc_ != NULL; | |
| 477 } | |
| 478 | |
| 479 PrintingContext::Result PrintingContext::ParseDialogResultEx( | |
| 480 const PRINTDLGEX& dialog_options) { | |
| 481 // If the user clicked OK or Apply then Cancel, but not only Cancel. | |
| 482 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) { | |
| 483 // Start fresh. | |
| 484 ResetSettings(); | |
| 485 | |
| 486 DEVMODE* dev_mode = NULL; | |
| 487 if (dialog_options.hDevMode) { | |
| 488 dev_mode = | |
| 489 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); | |
| 490 DCHECK(dev_mode); | |
| 491 } | |
| 492 | |
| 493 std::wstring device_name; | |
| 494 if (dialog_options.hDevNames) { | |
| 495 DEVNAMES* dev_names = | |
| 496 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames)); | |
| 497 DCHECK(dev_names); | |
| 498 if (dev_names) { | |
| 499 device_name = | |
| 500 reinterpret_cast<const wchar_t*>( | |
| 501 reinterpret_cast<const wchar_t*>(dev_names) + | |
| 502 dev_names->wDeviceOffset); | |
| 503 GlobalUnlock(dialog_options.hDevNames); | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 bool success = false; | |
| 508 if (dev_mode && !device_name.empty()) { | |
| 509 hdc_ = dialog_options.hDC; | |
| 510 PRINTPAGERANGE* page_ranges = NULL; | |
| 511 DWORD num_page_ranges = 0; | |
| 512 bool print_selection_only = false; | |
| 513 if (dialog_options.Flags & PD_PAGENUMS) { | |
| 514 page_ranges = dialog_options.lpPageRanges; | |
| 515 num_page_ranges = dialog_options.nPageRanges; | |
| 516 } | |
| 517 if (dialog_options.Flags & PD_SELECTION) { | |
| 518 print_selection_only = true; | |
| 519 } | |
| 520 success = InitializeSettings(*dev_mode, | |
| 521 device_name, | |
| 522 dialog_options.lpPageRanges, | |
| 523 dialog_options.nPageRanges, | |
| 524 print_selection_only); | |
| 525 } | |
| 526 | |
| 527 if (!success && dialog_options.hDC) { | |
| 528 DeleteDC(dialog_options.hDC); | |
| 529 hdc_ = NULL; | |
| 530 } | |
| 531 | |
| 532 if (dev_mode) { | |
| 533 GlobalUnlock(dialog_options.hDevMode); | |
| 534 } | |
| 535 } else { | |
| 536 if (dialog_options.hDC) { | |
| 537 DeleteDC(dialog_options.hDC); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 if (dialog_options.hDevMode != NULL) | |
| 542 GlobalFree(dialog_options.hDevMode); | |
| 543 if (dialog_options.hDevNames != NULL) | |
| 544 GlobalFree(dialog_options.hDevNames); | |
| 545 | |
| 546 switch (dialog_options.dwResultAction) { | |
| 547 case PD_RESULT_PRINT: | |
| 548 return hdc_ ? OK : FAILED; | |
| 549 case PD_RESULT_APPLY: | |
| 550 return hdc_ ? CANCEL : FAILED; | |
| 551 case PD_RESULT_CANCEL: | |
| 552 return CANCEL; | |
| 553 default: | |
| 554 return FAILED; | |
| 555 } | |
| 556 } | |
| 557 | |
| 558 PrintingContext::Result PrintingContext::ParseDialogResult( | |
| 559 const PRINTDLG& dialog_options) { | |
| 560 // If the user clicked OK or Apply then Cancel, but not only Cancel. | |
| 561 // Start fresh. | |
| 562 ResetSettings(); | |
| 563 | |
| 564 DEVMODE* dev_mode = NULL; | |
| 565 if (dialog_options.hDevMode) { | |
| 566 dev_mode = | |
| 567 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); | |
| 568 DCHECK(dev_mode); | |
| 569 } | |
| 570 | |
| 571 std::wstring device_name; | |
| 572 if (dialog_options.hDevNames) { | |
| 573 DEVNAMES* dev_names = | |
| 574 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames)); | |
| 575 DCHECK(dev_names); | |
| 576 if (dev_names) { | |
| 577 device_name = | |
| 578 reinterpret_cast<const wchar_t*>( | |
| 579 reinterpret_cast<const wchar_t*>(dev_names) + | |
| 580 dev_names->wDeviceOffset); | |
| 581 GlobalUnlock(dialog_options.hDevNames); | |
| 582 } | |
| 583 } | |
| 584 | |
| 585 bool success = false; | |
| 586 if (dev_mode && !device_name.empty()) { | |
| 587 hdc_ = dialog_options.hDC; | |
| 588 success = InitializeSettings(*dev_mode, device_name, NULL, 0, false); | |
| 589 } | |
| 590 | |
| 591 if (!success && dialog_options.hDC) { | |
| 592 DeleteDC(dialog_options.hDC); | |
| 593 hdc_ = NULL; | |
| 594 } | |
| 595 | |
| 596 if (dev_mode) { | |
| 597 GlobalUnlock(dialog_options.hDevMode); | |
| 598 } | |
| 599 | |
| 600 if (dialog_options.hDevMode != NULL) | |
| 601 GlobalFree(dialog_options.hDevMode); | |
| 602 if (dialog_options.hDevNames != NULL) | |
| 603 GlobalFree(dialog_options.hDevNames); | |
| 604 | |
| 605 return hdc_ ? OK : FAILED; | |
| 606 } | |
| 607 | |
| 608 } // namespace printing | |
| OLD | NEW |