2 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: SecondPage.cpp,v $
26 Revision 1.18 2005/07/20 17:44:54 shersche
27 <rdar://problem/4124524> UI fixes for CUPS workaround
29 Revision 1.17 2005/07/11 20:17:15 shersche
30 <rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
32 Revision 1.16 2005/07/07 17:53:20 shersche
33 Fix problems associated with the CUPS printer workaround fix.
35 Revision 1.15 2005/04/13 17:46:22 shersche
36 <rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
38 Revision 1.14 2005/03/20 20:08:37 shersche
39 <rdar://problem/4055670> Second screen should not select a printer by default
41 Revision 1.13 2005/02/15 07:50:10 shersche
42 <rdar://problem/4007151> Update name
44 Revision 1.12 2005/02/10 22:35:11 cheshire
45 <rdar://problem/3727944> Update name
47 Revision 1.11 2005/01/31 23:54:30 shersche
48 <rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
50 Revision 1.10 2005/01/20 19:54:38 shersche
51 Fix parse error when text record is NULL
53 Revision 1.9 2005/01/06 08:13:50 shersche
54 Don't use moreComing flag to determine number of text record, disregard queue name if qtotal isn't defined, don't disregard queue name if "rp" is the only key specified
56 Revision 1.8 2005/01/04 21:09:14 shersche
57 Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
59 Revision 1.7 2004/12/31 07:25:27 shersche
60 Tidy up printer management, and fix memory leaks when hitting 'Cancel'
62 Revision 1.6 2004/12/30 01:24:02 shersche
63 <rdar://problem/3906182> Remove references to description key
66 Revision 1.5 2004/12/30 01:02:47 shersche
67 <rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
70 Revision 1.4 2004/12/29 18:53:38 shersche
71 <rdar://problem/3725106>
72 <rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
73 Bug #: 3725106, 3737413
75 Revision 1.3 2004/09/13 21:26:15 shersche
76 <rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
79 Revision 1.2 2004/06/26 03:19:57 shersche
80 clean up warning messages
82 Submitted by: herscher
84 Revision 1.1 2004/06/18 04:36:57 rpantos
91 #include "PrinterSetupWizardApp.h"
92 #include "PrinterSetupWizardSheet.h"
93 #include "SecondPage.h"
94 #include "DebugServices.h"
95 #include "WinServices.h"
98 // local variable is initialize but not referenced
99 #pragma warning(disable:4189)
101 // CSecondPage dialog
103 IMPLEMENT_DYNAMIC(CSecondPage
, CPropertyPage
)
104 CSecondPage::CSecondPage()
105 : CPropertyPage(CSecondPage::IDD
)
107 m_psp
.dwFlags
&= ~(PSP_HASHELP
);
108 m_psp
.dwFlags
|= PSP_DEFAULT
|PSP_USEHEADERTITLE
|PSP_USEHEADERSUBTITLE
;
110 m_psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_BROWSE_TITLE
);
111 m_psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE
);
113 m_emptyListItem
= NULL
;
114 m_initialized
= false;
119 CSecondPage::~CSecondPage()
125 CSecondPage::InitBrowseList()
127 CPrinterSetupWizardSheet
* psheet
;
130 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
131 require_quiet( psheet
, exit
);
133 // Initialize so that nothing is selected when we add to the list
135 psheet
->SetSelectedPrinter( NULL
);
137 m_browseList
.Select( NULL
, TVGN_FIRSTVISIBLE
);
140 // load the no printers message until something shows up in the browse list
142 text
.LoadString(IDS_NO_PRINTERS
);
144 LoadTextAndDisableWindow( text
);
147 // disable the next button until there's a printer to select
149 psheet
->SetWizardButtons(PSWIZB_BACK
);
152 // disable the printer information box
154 SetPrinterInformationState( FALSE
);
155 m_descriptionField
.SetWindowText( L
"" );
156 m_locationField
.SetWindowText( L
"" );
164 void CSecondPage::DoDataExchange(CDataExchange
* pDX
)
166 CPropertyPage::DoDataExchange(pDX
);
167 DDX_Control(pDX
, IDC_BROWSE_LIST
, m_browseList
);
168 DDX_Control(pDX
, IDC_PRINTER_INFORMATION
, m_printerInformation
);
170 DDX_Control(pDX
, IDC_DESCRIPTION_LABEL
, m_descriptionLabel
);
172 DDX_Control(pDX
, IDC_DESCRIPTION_FIELD
, m_descriptionField
);
174 DDX_Control(pDX
, IDC_LOCATION_LABEL
, m_locationLabel
);
176 DDX_Control(pDX
, IDC_LOCATION_FIELD
, m_locationField
);
182 CSecondPage::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
185 DEBUG_UNUSED(nHitTest
);
186 DEBUG_UNUSED(message
);
188 CPrinterSetupWizardSheet
* psheet
;
190 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
191 require_quiet( psheet
, exit
);
193 SetCursor(psheet
->GetCursor());
202 CSecondPage::OnSetActive()
204 CPrinterSetupWizardSheet
* psheet
;
206 Printers::iterator it
;
207 OSStatus err
= kNoErr
;
210 b
= CPropertyPage::OnSetActive();
212 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
213 require_action( psheet
, exit
, err
= kUnknownErr
);
215 // Stash the selected printer if any
217 printer
= psheet
->GetSelectedPrinter();
219 // initialize the browse list...this will remove everything currently
220 // in it, and add the no printers item
224 // Populate the list with any printers that we currently know about
226 for ( it
= psheet
->m_printers
.begin(); it
!= psheet
->m_printers
.end(); it
++ )
228 OnAddPrinter( *it
, false );
231 // And if we hit 'Back' from page 3, then re-select printer
233 if ( ( psheet
->GetLastPage() == psheet
->GetPage( 2 ) ) && printer
)
235 psheet
->SetSelectedPrinter( printer
);
236 m_browseList
.Select( printer
->item
, TVGN_FIRSTVISIBLE
);
246 CSecondPage::OnKillActive()
248 CPrinterSetupWizardSheet
* psheet
;
250 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
251 require_quiet( psheet
, exit
);
253 psheet
->SetLastPage(this);
257 return CPropertyPage::OnKillActive();
261 BEGIN_MESSAGE_MAP(CSecondPage
, CPropertyPage
)
262 ON_NOTIFY(TVN_SELCHANGED
, IDC_BROWSE_LIST
, OnTvnSelchangedBrowseList
)
263 ON_NOTIFY(NM_CLICK
, IDC_BROWSE_LIST
, OnNmClickBrowseList
)
264 ON_NOTIFY(TVN_KEYDOWN
, IDC_BROWSE_LIST
, OnTvnKeyDownBrowseList
)
269 // Printer::EventHandler implementation
271 CSecondPage::OnAddPrinter(
275 CPrinterSetupWizardSheet
* psheet
;
276 OSStatus err
= kNoErr
;
278 check( IsWindow( m_hWnd
) );
280 m_browseList
.SetRedraw(FALSE
);
282 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
283 require_quiet( psheet
, exit
);
285 printer
->item
= m_browseList
.InsertItem(printer
->displayName
);
287 m_browseList
.SetItemData( printer
->item
, (DWORD_PTR
) printer
);
289 m_browseList
.SortChildren(TVI_ROOT
);
292 // if the searching item is still in the list
295 // note that order is important here. Insert the printer
296 // item before removing the placeholder so we always have
297 // an item in the list to avoid experiencing the bug
298 // in Microsoft's implementation of CTreeCtrl
300 if (m_emptyListItem
!= NULL
)
302 m_browseList
.DeleteItem(m_emptyListItem
);
303 m_emptyListItem
= NULL
;
304 m_browseList
.EnableWindow(TRUE
);
311 m_browseList
.SetRedraw(TRUE
);
312 m_browseList
.Invalidate();
320 CSecondPage::OnRemovePrinter(
324 CPrinterSetupWizardSheet
* psheet
;
325 OSStatus err
= kNoErr
;
327 check( IsWindow( m_hWnd
) );
330 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
331 require_quiet( psheet
, exit
);
333 m_browseList
.SetRedraw(FALSE
);
336 // check to make sure if we're the only item in the control...i.e.
337 // the list size is 1.
339 if (m_browseList
.GetCount() > 1)
342 // if we're not the only thing in the list, then
343 // simply remove it from the list
345 m_browseList
.DeleteItem( printer
->item
);
350 // if we're the only thing in the list, then redisplay
351 // it with the no printers message
360 m_browseList
.SetRedraw(TRUE
);
361 m_browseList
.Invalidate();
369 CSecondPage::OnResolveService( Service
* service
)
371 CPrinterSetupWizardSheet
* psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
372 require_quiet( psheet
, exit
);
376 Queue
* q
= service
->SelectedQueue();
382 // and set it to selected
385 m_selectedName
= service
->printer
->name
;
388 // and update the printer information box
390 SetPrinterInformationState( TRUE
);
392 m_descriptionField
.SetWindowText( q
->description
);
393 m_locationField
.SetWindowText( q
->location
);
399 SetCursor(psheet
->m_active
);
407 void CSecondPage::OnTvnSelchangedBrowseList(NMHDR
*pNMHDR
, LRESULT
*pResult
)
409 LPNMTREEVIEW pNMTreeView
= reinterpret_cast<LPNMTREEVIEW
>(pNMHDR
);
410 CPrinterSetupWizardSheet
* psheet
;
414 psheet
= reinterpret_cast<CPrinterSetupWizardSheet
*>(GetParent());
415 require_action( psheet
, exit
, err
= kUnknownErr
);
417 // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
418 // we selected isn't passed through correctly to this callback routine.
422 printer
= psheet
->GetSelectedPrinter();
424 // If we really haven't selected a printer, then re-select NULL and exit
428 m_browseList
.SelectItem( NULL
);
433 // If we already have selected a printer, fake like we've clicked on it, but only
434 // if the CTreeCtrl hasn't already selected it
436 else if ( printer
->item
!= m_browseList
.GetSelectedItem() )
440 m_browseList
.SelectItem( printer
->item
);
446 HTREEITEM item
= m_browseList
.GetSelectedItem();
447 require_quiet( item
, exit
);
449 printer
= reinterpret_cast<Printer
*>(m_browseList
.GetItemData( item
) );
450 require_quiet( printer
, exit
);
453 // this call will trigger a resolve. When the resolve is complete,
454 // our OnResolve will be called.
456 err
= psheet
->StartResolve( printer
);
457 require_noerr( err
, exit
);
460 // And clear out the printer information box
462 SetPrinterInformationState( FALSE
);
463 m_descriptionField
.SetWindowText(L
"");
464 m_locationField
.SetWindowText(L
"");
473 text
.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT
);
474 caption
.LoadString(IDS_ERROR_SELECTING_PRINTER_CAPTION
);
476 MessageBox(text
, caption
, MB_OK
|MB_ICONEXCLAMATION
);
483 void CSecondPage::OnNmClickBrowseList(NMHDR
*pNMHDR
, LRESULT
*pResult
)
485 DEBUG_UNUSED( pNMHDR
);
493 void CSecondPage::OnTvnKeyDownBrowseList( NMHDR
* pNMHDR
, LRESULT
* pResult
)
495 DEBUG_UNUSED( pNMHDR
);
504 CSecondPage::LoadTextAndDisableWindow( CString
& text
)
506 m_emptyListItem
= m_browseList
.InsertItem( text
, 0, 0, NULL
, TVI_FIRST
);
507 m_browseList
.SelectItem( NULL
);
510 // this will remove everything else in the list...we might be navigating
511 // back to this window, and the browse list might have changed since
512 // we last displayed it.
514 if ( m_emptyListItem
)
516 HTREEITEM item
= m_browseList
.GetNextVisibleItem( m_emptyListItem
);
520 m_browseList
.DeleteItem( item
);
521 item
= m_browseList
.GetNextVisibleItem( m_emptyListItem
);
525 m_browseList
.EnableWindow( FALSE
);
530 CSecondPage::SetPrinterInformationState( BOOL state
)
532 m_printerInformation
.EnableWindow( state
);
534 m_descriptionLabel
.EnableWindow( state
);
536 m_descriptionField
.EnableWindow( state
);
538 m_locationLabel
.EnableWindow( state
);
540 m_locationField
.EnableWindow( state
);