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 |