| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "printing/printing_context_win.h" | 5 #include "printing/printing_context_win.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 } // anonymous namespace | 43 } // anonymous namespace |
| 44 | 44 |
| 45 namespace printing { | 45 namespace printing { |
| 46 | 46 |
| 47 // static | 47 // static |
| 48 scoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { | 48 scoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
| 49 return make_scoped_ptr<PrintingContext>(new PrintingContextWin(delegate)); | 49 return make_scoped_ptr<PrintingContext>(new PrintingContextWin(delegate)); |
| 50 } | 50 } |
| 51 | 51 |
| 52 PrintingContextWin::PrintingContextWin(Delegate* delegate) | 52 PrintingContextWin::PrintingContextWin(Delegate* delegate) |
| 53 : PrintingContext(delegate), context_(NULL) { | 53 : PrintingContext(delegate), context_(NULL), dialog_box_(NULL) { |
| 54 } | 54 } |
| 55 | 55 |
| 56 PrintingContextWin::~PrintingContextWin() { | 56 PrintingContextWin::~PrintingContextWin() { |
| 57 ReleaseContext(); | 57 ReleaseContext(); |
| 58 } | 58 } |
| 59 | 59 |
| 60 void PrintingContextWin::AskUserForSettings( | 60 void PrintingContextWin::AskUserForSettings( |
| 61 int max_pages, | 61 int max_pages, |
| 62 bool has_selection, | 62 bool has_selection, |
| 63 const PrintSettingsCallback& callback) { | 63 const PrintSettingsCallback& callback) { |
| 64 NOTIMPLEMENTED(); | 64 DCHECK(!in_print_job_); |
| 65 dialog_box_dismissed_ = false; |
| 66 |
| 67 HWND window = GetRootWindow(delegate_->GetParentView()); |
| 68 DCHECK(window); |
| 69 |
| 70 // Show the OS-dependent dialog box. |
| 71 // If the user press |
| 72 // - OK, the settings are reset and reinitialized with the new settings. OK is |
| 73 // returned. |
| 74 // - Apply then Cancel, the settings are reset and reinitialized with the new |
| 75 // settings. CANCEL is returned. |
| 76 // - Cancel, the settings are not changed, the previous setting, if it was |
| 77 // initialized before, are kept. CANCEL is returned. |
| 78 // On failure, the settings are reset and FAILED is returned. |
| 79 PRINTDLGEX dialog_options = { sizeof(PRINTDLGEX) }; |
| 80 dialog_options.hwndOwner = window; |
| 81 // Disable options we don't support currently. |
| 82 // TODO(maruel): Reuse the previously loaded settings! |
| 83 dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | |
| 84 PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE; |
| 85 if (!has_selection) |
| 86 dialog_options.Flags |= PD_NOSELECTION; |
| 87 |
| 88 PRINTPAGERANGE ranges[32]; |
| 89 dialog_options.nStartPage = START_PAGE_GENERAL; |
| 90 if (max_pages) { |
| 91 // Default initialize to print all the pages. |
| 92 memset(ranges, 0, sizeof(ranges)); |
| 93 ranges[0].nFromPage = 1; |
| 94 ranges[0].nToPage = max_pages; |
| 95 dialog_options.nPageRanges = 1; |
| 96 dialog_options.nMaxPageRanges = arraysize(ranges); |
| 97 dialog_options.nMinPage = 1; |
| 98 dialog_options.nMaxPage = max_pages; |
| 99 dialog_options.lpPageRanges = ranges; |
| 100 } else { |
| 101 // No need to bother, we don't know how many pages are available. |
| 102 dialog_options.Flags |= PD_NOPAGENUMS; |
| 103 } |
| 104 |
| 105 if (ShowPrintDialog(&dialog_options) != S_OK) { |
| 106 ResetSettings(); |
| 107 callback.Run(FAILED); |
| 108 } |
| 109 |
| 110 // TODO(maruel): Support PD_PRINTTOFILE. |
| 111 callback.Run(ParseDialogResultEx(dialog_options)); |
| 65 } | 112 } |
| 66 | 113 |
| 67 PrintingContext::Result PrintingContextWin::UseDefaultSettings() { | 114 PrintingContext::Result PrintingContextWin::UseDefaultSettings() { |
| 68 DCHECK(!in_print_job_); | 115 DCHECK(!in_print_job_); |
| 69 | 116 |
| 70 scoped_refptr<PrintBackend> backend = PrintBackend::CreateInstance(NULL); | 117 PRINTDLG dialog_options = { sizeof(PRINTDLG) }; |
| 71 base::string16 default_printer = | 118 dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT; |
| 72 base::UTF8ToWide(backend->GetDefaultPrinterName()); | 119 if (PrintDlg(&dialog_options)) |
| 73 if (!default_printer.empty()) { | 120 return ParseDialogResult(dialog_options); |
| 74 ScopedPrinterHandle printer; | |
| 75 if (printer.OpenPrinter(default_printer.c_str())) { | |
| 76 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = | |
| 77 CreateDevMode(printer, NULL); | |
| 78 if (InitializeSettings(default_printer, dev_mode.get()) == OK) | |
| 79 return OK; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 ReleaseContext(); | |
| 84 | 121 |
| 85 // No default printer configured, do we have any printers at all? | 122 // No default printer configured, do we have any printers at all? |
| 86 DWORD bytes_needed = 0; | 123 DWORD bytes_needed = 0; |
| 87 DWORD count_returned = 0; | 124 DWORD count_returned = 0; |
| 88 (void)::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, | 125 (void)::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, |
| 89 NULL, 2, NULL, 0, &bytes_needed, &count_returned); | 126 NULL, 2, NULL, 0, &bytes_needed, &count_returned); |
| 90 if (bytes_needed) { | 127 if (bytes_needed) { |
| 91 DCHECK_GE(bytes_needed, count_returned * sizeof(PRINTER_INFO_2)); | 128 DCHECK_GE(bytes_needed, count_returned * sizeof(PRINTER_INFO_2)); |
| 92 scoped_ptr<BYTE[]> printer_info_buffer(new BYTE[bytes_needed]); | 129 scoped_ptr<BYTE[]> printer_info_buffer(new BYTE[bytes_needed]); |
| 93 BOOL ret = ::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, | 130 BOOL ret = ::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, |
| 94 NULL, 2, printer_info_buffer.get(), | 131 NULL, 2, printer_info_buffer.get(), |
| 95 bytes_needed, &bytes_needed, | 132 bytes_needed, &bytes_needed, |
| 96 &count_returned); | 133 &count_returned); |
| 97 if (ret && count_returned) { // have printers | 134 if (ret && count_returned) { // have printers |
| 98 // Open the first successfully found printer. | 135 // Open the first successfully found printer. |
| 99 const PRINTER_INFO_2* info_2 = | 136 const PRINTER_INFO_2* info_2 = |
| 100 reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get()); | 137 reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get()); |
| 101 const PRINTER_INFO_2* info_2_end = info_2 + count_returned; | 138 const PRINTER_INFO_2* info_2_end = info_2 + count_returned; |
| 102 for (; info_2 < info_2_end; ++info_2) { | 139 for (; info_2 < info_2_end; ++info_2) { |
| 103 ScopedPrinterHandle printer; | 140 ScopedPrinterHandle printer; |
| 104 if (!printer.OpenPrinter(info_2->pPrinterName)) | 141 if (!printer.OpenPrinter(info_2->pPrinterName)) |
| 105 continue; | 142 continue; |
| 106 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = | 143 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = |
| 107 CreateDevMode(printer, NULL); | 144 CreateDevMode(printer, NULL); |
| 108 if (InitializeSettings(info_2->pPrinterName, dev_mode.get()) == OK) | 145 if (!dev_mode || !AllocateContext(info_2->pPrinterName, dev_mode.get(), |
| 146 &context_)) { |
| 147 continue; |
| 148 } |
| 149 if (InitializeSettings(*dev_mode.get(), info_2->pPrinterName, NULL, 0, |
| 150 false)) { |
| 109 return OK; | 151 return OK; |
| 152 } |
| 153 ReleaseContext(); |
| 110 } | 154 } |
| 111 if (context_) | 155 if (context_) |
| 112 return OK; | 156 return OK; |
| 113 } | 157 } |
| 114 } | 158 } |
| 115 | 159 |
| 116 return OnError(); | 160 ResetSettings(); |
| 161 return FAILED; |
| 117 } | 162 } |
| 118 | 163 |
| 119 gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() { | 164 gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() { |
| 120 // Default fallback to Letter size. | 165 // Default fallback to Letter size. |
| 121 gfx::SizeF paper_size(kLetterWidthInch, kLetterHeightInch); | 166 gfx::SizeF paper_size(kLetterWidthInch, kLetterHeightInch); |
| 122 | 167 |
| 123 // Get settings from locale. Paper type buffer length is at most 4. | 168 // Get settings from locale. Paper type buffer length is at most 4. |
| 124 const int paper_type_buffer_len = 4; | 169 const int paper_type_buffer_len = 4; |
| 125 wchar_t paper_type_buffer[paper_type_buffer_len] = {0}; | 170 wchar_t paper_type_buffer[paper_type_buffer_len] = {0}; |
| 126 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE, paper_type_buffer, | 171 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE, paper_type_buffer, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 dev_mode->dmPaperSize = static_cast<short>(id); | 250 dev_mode->dmPaperSize = static_cast<short>(id); |
| 206 } else if (width > 0 && height > 0) { | 251 } else if (width > 0 && height > 0) { |
| 207 dev_mode->dmFields |= DM_PAPERWIDTH; | 252 dev_mode->dmFields |= DM_PAPERWIDTH; |
| 208 dev_mode->dmPaperWidth = width; | 253 dev_mode->dmPaperWidth = width; |
| 209 dev_mode->dmFields |= DM_PAPERLENGTH; | 254 dev_mode->dmFields |= DM_PAPERLENGTH; |
| 210 dev_mode->dmPaperLength = height; | 255 dev_mode->dmPaperLength = height; |
| 211 } | 256 } |
| 212 } | 257 } |
| 213 | 258 |
| 214 // Update data using DocumentProperties. | 259 // Update data using DocumentProperties. |
| 215 if (show_system_dialog) { | 260 scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get()); |
| 216 scoped_dev_mode = ShowPrintDialog( | 261 if (!scoped_dev_mode) |
| 217 printer, delegate_->GetParentView(), scoped_dev_mode.get()); | 262 return OnError(); |
| 218 } else { | 263 |
| 219 scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get()); | 264 // Set printer then refresh printer settings. |
| 265 if (!AllocateContext(settings_.device_name(), scoped_dev_mode.get(), |
| 266 &context_)) { |
| 267 return OnError(); |
| 220 } | 268 } |
| 221 // Set printer then refresh printer settings. | 269 PrintSettingsInitializerWin::InitPrintSettings(context_, |
| 222 return InitializeSettings(settings_.device_name(), scoped_dev_mode.get()); | 270 *scoped_dev_mode.get(), |
| 271 &settings_); |
| 272 return OK; |
| 223 } | 273 } |
| 224 | 274 |
| 225 PrintingContext::Result PrintingContextWin::InitWithSettings( | 275 PrintingContext::Result PrintingContextWin::InitWithSettings( |
| 226 const PrintSettings& settings) { | 276 const PrintSettings& settings) { |
| 227 DCHECK(!in_print_job_); | 277 DCHECK(!in_print_job_); |
| 228 | 278 |
| 229 settings_ = settings; | 279 settings_ = settings; |
| 230 | 280 |
| 231 // TODO(maruel): settings_.ToDEVMODE() | 281 // TODO(maruel): settings_.ToDEVMODE() |
| 232 ScopedPrinterHandle printer; | 282 ScopedPrinterHandle printer; |
| 233 if (!printer.OpenPrinter(settings_.device_name().c_str())) | 283 if (!printer.OpenPrinter(settings_.device_name().c_str())) { |
| 234 return FAILED; | 284 return FAILED; |
| 285 } |
| 235 | 286 |
| 236 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = | 287 Result status = OK; |
| 237 CreateDevMode(printer, NULL); | |
| 238 | 288 |
| 239 return InitializeSettings(settings_.device_name(), dev_mode.get()); | 289 if (!GetPrinterSettings(printer, settings_.device_name())) |
| 290 status = FAILED; |
| 291 |
| 292 if (status != OK) |
| 293 ResetSettings(); |
| 294 return status; |
| 240 } | 295 } |
| 241 | 296 |
| 242 PrintingContext::Result PrintingContextWin::NewDocument( | 297 PrintingContext::Result PrintingContextWin::NewDocument( |
| 243 const base::string16& document_name) { | 298 const base::string16& document_name) { |
| 244 DCHECK(!in_print_job_); | 299 DCHECK(!in_print_job_); |
| 245 if (!context_) | 300 if (!context_) |
| 246 return OnError(); | 301 return OnError(); |
| 247 | 302 |
| 248 // Set the flag used by the AbortPrintJob dialog procedure. | 303 // Set the flag used by the AbortPrintJob dialog procedure. |
| 249 abort_printing_ = false; | 304 abort_printing_ = false; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 368 |
| 314 ResetSettings(); | 369 ResetSettings(); |
| 315 return OK; | 370 return OK; |
| 316 } | 371 } |
| 317 | 372 |
| 318 void PrintingContextWin::Cancel() { | 373 void PrintingContextWin::Cancel() { |
| 319 abort_printing_ = true; | 374 abort_printing_ = true; |
| 320 in_print_job_ = false; | 375 in_print_job_ = false; |
| 321 if (context_) | 376 if (context_) |
| 322 CancelDC(context_); | 377 CancelDC(context_); |
| 378 if (dialog_box_) { |
| 379 DestroyWindow(dialog_box_); |
| 380 dialog_box_dismissed_ = true; |
| 381 } |
| 323 } | 382 } |
| 324 | 383 |
| 325 void PrintingContextWin::ReleaseContext() { | 384 void PrintingContextWin::ReleaseContext() { |
| 326 if (context_) { | 385 if (context_) { |
| 327 DeleteDC(context_); | 386 DeleteDC(context_); |
| 328 context_ = NULL; | 387 context_ = NULL; |
| 329 } | 388 } |
| 330 } | 389 } |
| 331 | 390 |
| 332 gfx::NativeDrawingContext PrintingContextWin::context() const { | 391 gfx::NativeDrawingContext PrintingContextWin::context() const { |
| 333 return context_; | 392 return context_; |
| 334 } | 393 } |
| 335 | 394 |
| 336 // static | 395 // static |
| 337 BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { | 396 BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { |
| 338 if (nCode) { | 397 if (nCode) { |
| 339 // TODO(maruel): Need a way to find the right instance to set. Should | 398 // TODO(maruel): Need a way to find the right instance to set. Should |
| 340 // leverage PrintJobManager here? | 399 // leverage PrintJobManager here? |
| 341 // abort_printing_ = true; | 400 // abort_printing_ = true; |
| 342 } | 401 } |
| 343 return true; | 402 return true; |
| 344 } | 403 } |
| 345 | 404 |
| 346 PrintingContext::Result PrintingContextWin::InitializeSettings( | 405 bool PrintingContextWin::InitializeSettings(const DEVMODE& dev_mode, |
| 347 const std::wstring& device_name, | 406 const std::wstring& new_device_name, |
| 348 DEVMODE* dev_mode) { | 407 const PRINTPAGERANGE* ranges, |
| 349 if (!dev_mode) | 408 int number_ranges, |
| 350 return OnError(); | 409 bool selection_only) { |
| 410 skia::InitializeDC(context_); |
| 411 DCHECK(GetDeviceCaps(context_, CLIPCAPS)); |
| 412 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB); |
| 413 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64); |
| 414 // Some printers don't advertise these. |
| 415 // DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING); |
| 416 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA); |
| 417 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA); |
| 351 | 418 |
| 352 ReleaseContext(); | 419 // StretchDIBits() support is needed for printing. |
| 353 context_ = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode); | 420 if (!(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB) || |
| 354 if (!context_) | 421 !(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64)) { |
| 355 return OnError(); | 422 NOTREACHED(); |
| 356 | 423 ResetSettings(); |
| 357 skia::InitializeDC(context_); | 424 return false; |
| 425 } |
| 358 | 426 |
| 359 DCHECK(!in_print_job_); | 427 DCHECK(!in_print_job_); |
| 360 settings_.set_device_name(device_name); | 428 DCHECK(context_); |
| 361 PrintSettingsInitializerWin::InitPrintSettings( | 429 PageRanges ranges_vector; |
| 362 context_, *dev_mode, &settings_); | 430 if (!selection_only) { |
| 431 // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector. |
| 432 ranges_vector.reserve(number_ranges); |
| 433 for (int i = 0; i < number_ranges; ++i) { |
| 434 PageRange range; |
| 435 // Transfer from 1-based to 0-based. |
| 436 range.from = ranges[i].nFromPage - 1; |
| 437 range.to = ranges[i].nToPage - 1; |
| 438 ranges_vector.push_back(range); |
| 439 } |
| 440 } |
| 363 | 441 |
| 364 return OK; | 442 settings_.set_ranges(ranges_vector); |
| 443 settings_.set_device_name(new_device_name); |
| 444 settings_.set_selection_only(selection_only); |
| 445 PrintSettingsInitializerWin::InitPrintSettings(context_, dev_mode, |
| 446 &settings_); |
| 447 |
| 448 return true; |
| 365 } | 449 } |
| 366 | 450 |
| 367 scoped_ptr<DEVMODE, base::FreeDeleter> PrintingContextWin::ShowPrintDialog( | 451 bool PrintingContextWin::GetPrinterSettings(HANDLE printer, |
| 368 HANDLE printer, | 452 const std::wstring& device_name) { |
| 369 gfx::NativeView parent_view, | 453 DCHECK(!in_print_job_); |
| 370 DEVMODE* dev_mode) { | 454 |
| 455 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = |
| 456 CreateDevMode(printer, NULL); |
| 457 |
| 458 if (!dev_mode || !AllocateContext(device_name, dev_mode.get(), &context_)) { |
| 459 ResetSettings(); |
| 460 return false; |
| 461 } |
| 462 |
| 463 return InitializeSettings(*dev_mode.get(), device_name, NULL, 0, false); |
| 464 } |
| 465 |
| 466 // static |
| 467 bool PrintingContextWin::AllocateContext(const std::wstring& device_name, |
| 468 const DEVMODE* dev_mode, |
| 469 gfx::NativeDrawingContext* context) { |
| 470 *context = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode); |
| 471 DCHECK(*context); |
| 472 return *context != NULL; |
| 473 } |
| 474 |
| 475 PrintingContext::Result PrintingContextWin::ParseDialogResultEx( |
| 476 const PRINTDLGEX& dialog_options) { |
| 477 // If the user clicked OK or Apply then Cancel, but not only Cancel. |
| 478 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) { |
| 479 // Start fresh. |
| 480 ResetSettings(); |
| 481 |
| 482 DEVMODE* dev_mode = NULL; |
| 483 if (dialog_options.hDevMode) { |
| 484 dev_mode = |
| 485 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); |
| 486 DCHECK(dev_mode); |
| 487 } |
| 488 |
| 489 std::wstring device_name; |
| 490 if (dialog_options.hDevNames) { |
| 491 DEVNAMES* dev_names = |
| 492 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames)); |
| 493 DCHECK(dev_names); |
| 494 if (dev_names) { |
| 495 device_name = reinterpret_cast<const wchar_t*>(dev_names) + |
| 496 dev_names->wDeviceOffset; |
| 497 GlobalUnlock(dialog_options.hDevNames); |
| 498 } |
| 499 } |
| 500 |
| 501 bool success = false; |
| 502 if (dev_mode && !device_name.empty()) { |
| 503 context_ = dialog_options.hDC; |
| 504 PRINTPAGERANGE* page_ranges = NULL; |
| 505 DWORD num_page_ranges = 0; |
| 506 bool print_selection_only = false; |
| 507 if (dialog_options.Flags & PD_PAGENUMS) { |
| 508 page_ranges = dialog_options.lpPageRanges; |
| 509 num_page_ranges = dialog_options.nPageRanges; |
| 510 } |
| 511 if (dialog_options.Flags & PD_SELECTION) { |
| 512 print_selection_only = true; |
| 513 } |
| 514 success = InitializeSettings(*dev_mode, |
| 515 device_name, |
| 516 page_ranges, |
| 517 num_page_ranges, |
| 518 print_selection_only); |
| 519 } |
| 520 |
| 521 if (!success && dialog_options.hDC) { |
| 522 DeleteDC(dialog_options.hDC); |
| 523 context_ = NULL; |
| 524 } |
| 525 |
| 526 if (dev_mode) { |
| 527 GlobalUnlock(dialog_options.hDevMode); |
| 528 } |
| 529 } else { |
| 530 if (dialog_options.hDC) { |
| 531 DeleteDC(dialog_options.hDC); |
| 532 } |
| 533 } |
| 534 |
| 535 if (dialog_options.hDevMode != NULL) |
| 536 GlobalFree(dialog_options.hDevMode); |
| 537 if (dialog_options.hDevNames != NULL) |
| 538 GlobalFree(dialog_options.hDevNames); |
| 539 |
| 540 switch (dialog_options.dwResultAction) { |
| 541 case PD_RESULT_PRINT: |
| 542 return context_ ? OK : FAILED; |
| 543 case PD_RESULT_APPLY: |
| 544 return context_ ? CANCEL : FAILED; |
| 545 case PD_RESULT_CANCEL: |
| 546 return CANCEL; |
| 547 default: |
| 548 return FAILED; |
| 549 } |
| 550 } |
| 551 |
| 552 HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) { |
| 371 // Note that this cannot use ui::BaseShellDialog as the print dialog is | 553 // Note that this cannot use ui::BaseShellDialog as the print dialog is |
| 372 // system modal: opening it from a background thread can cause Windows to | 554 // system modal: opening it from a background thread can cause Windows to |
| 373 // get the wrong Z-order which will make the print dialog appear behind the | 555 // get the wrong Z-order which will make the print dialog appear behind the |
| 374 // browser frame (but still being modal) so neither the browser frame nor | 556 // browser frame (but still being modal) so neither the browser frame nor |
| 375 // the print dialog will get any input. See http://crbug.com/342697 | 557 // the print dialog will get any input. See http://crbug.com/342697 |
| 376 // http://crbug.com/180997 for details. | 558 // http://crbug.com/180997 for details. |
| 377 base::MessageLoop::ScopedNestableTaskAllower allow( | 559 base::MessageLoop::ScopedNestableTaskAllower allow( |
| 378 base::MessageLoop::current()); | 560 base::MessageLoop::current()); |
| 379 | 561 |
| 380 bool canceled = false; | 562 return PrintDlgEx(options); |
| 381 scoped_ptr<DEVMODE, base::FreeDeleter> result = | 563 } |
| 382 PromptDevMode(printer, | |
| 383 settings_.device_name(), | |
| 384 dev_mode, | |
| 385 GetRootWindow(parent_view), | |
| 386 &canceled); | |
| 387 | 564 |
| 388 if (canceled) { | 565 PrintingContext::Result PrintingContextWin::ParseDialogResult( |
| 389 result.reset(); | 566 const PRINTDLG& dialog_options) { |
| 390 abort_printing_ = true; | 567 // If the user clicked OK or Apply then Cancel, but not only Cancel. |
| 568 // Start fresh. |
| 569 ResetSettings(); |
| 570 |
| 571 DEVMODE* dev_mode = NULL; |
| 572 if (dialog_options.hDevMode) { |
| 573 dev_mode = |
| 574 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode)); |
| 575 DCHECK(dev_mode); |
| 391 } | 576 } |
| 392 | 577 |
| 393 return result.Pass(); | 578 std::wstring device_name; |
| 579 if (dialog_options.hDevNames) { |
| 580 DEVNAMES* dev_names = |
| 581 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames)); |
| 582 DCHECK(dev_names); |
| 583 if (dev_names) { |
| 584 device_name = |
| 585 reinterpret_cast<const wchar_t*>( |
| 586 reinterpret_cast<const wchar_t*>(dev_names) + |
| 587 dev_names->wDeviceOffset); |
| 588 GlobalUnlock(dialog_options.hDevNames); |
| 589 } |
| 590 } |
| 591 |
| 592 bool success = false; |
| 593 if (dev_mode && !device_name.empty()) { |
| 594 context_ = dialog_options.hDC; |
| 595 success = InitializeSettings(*dev_mode, device_name, NULL, 0, false); |
| 596 } |
| 597 |
| 598 if (!success && dialog_options.hDC) { |
| 599 DeleteDC(dialog_options.hDC); |
| 600 context_ = NULL; |
| 601 } |
| 602 |
| 603 if (dev_mode) { |
| 604 GlobalUnlock(dialog_options.hDevMode); |
| 605 } |
| 606 |
| 607 if (dialog_options.hDevMode != NULL) |
| 608 GlobalFree(dialog_options.hDevMode); |
| 609 if (dialog_options.hDevNames != NULL) |
| 610 GlobalFree(dialog_options.hDevNames); |
| 611 |
| 612 return context_ ? OK : FAILED; |
| 394 } | 613 } |
| 395 | 614 |
| 396 } // namespace printing | 615 } // namespace printing |
| OLD | NEW |