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