Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

devprop.cpp

Go to the documentation of this file.
00001 /****************************************************************************** 00002 00003 Source File: Device Profile Management .CPP 00004 00005 Change History: 00006 00007 00008 Implements the class which provides the various device profile management UI 00009 00010 Copyright (c) 1996 by Microsoft Corporation 00011 00012 A Pretty Penny Enterprises, Inc. Production 00013 11-27-96 a-RobKj@microsoft.com coded it 00014 00015 ******************************************************************************/ 00016 00017 #include "ICMUI.H" 00018 00019 // 00020 // This function is obtained from the April 1998 Knowledge Base 00021 // Its purpose is to determine if the current user is an 00022 // Administrator and therefore priveledged to change profile 00023 // settings. 00024 // 00025 // BOOL IsAdmin(void) 00026 // 00027 // returns TRUE if user is an admin 00028 // FALSE if user is not an admin 00029 // 00030 00031 #if defined(_WIN95_) 00032 00033 // 00034 // Always administrator on Windows 9x platform. 00035 // 00036 00037 BOOL IsAdmin(void) { 00038 00039 return (TRUE); 00040 } 00041 00042 #else 00043 00044 BOOL IsAdmin(void) 00045 { 00046 BOOL fReturn = FALSE; 00047 PSID psidAdmin; 00048 00049 SID_IDENTIFIER_AUTHORITY SystemSidAuthority= SECURITY_NT_AUTHORITY; 00050 00051 if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2, 00052 SECURITY_BUILTIN_DOMAIN_RID, 00053 DOMAIN_ALIAS_RID_ADMINS, 00054 0, 0, 0, 0, 0, 0, &psidAdmin) ) 00055 { 00056 if(!CheckTokenMembership( NULL, psidAdmin, &fReturn )) { 00057 00058 // 00059 // explicitly disallow Admin Access if CheckTokenMembership fails. 00060 // 00061 00062 fReturn = FALSE; 00063 } 00064 FreeSid ( psidAdmin); 00065 } 00066 00067 return ( fReturn ); 00068 } 00069 00070 #endif // _WIN95_ 00071 00072 /****************************************************************************** 00073 00074 List Managment functions 00075 00076 The method used here is simlar to that used in the profile Managment sheets 00077 for managing device associations. 00078 00079 We (not royal, I mean the OS and I) manage two "to-do" lists and use these 00080 to show the user the anticipated result of these lists being applied. The 00081 first list is a list of existing associations that are to be broken. The 00082 second is one of new associations to be made. This is coupled with a list 00083 of the current associations. 00084 00085 The "Removals" list is the indices of existing associations which will be 00086 borken. The "Adds" list is a list of new profiles to be associated. The 00087 "Profiles" list is the list of existing associations. 00088 00089 Adding and removing profiles could mean removing an item from one of the work 00090 lists (undoing a previous selection), or adding one. Each time such a change 00091 is made, the profile list box is emptied and refilled. This lets us avoid 00092 mapping removals and additions more directly. 00093 00094 When changes are commited, either with Apply or OK, we make or break 00095 associations as specified, then empty all of the lists, and rebuild the list 00096 of current associations. 00097 00098 We use the ITEMDATA of the UI list box to handle the associations. This lets 00099 the list remain sorted. 00100 00101 All of the list management functions can be overriden, if needed. 00102 00103 ******************************************************************************/ 00104 00105 void CDeviceProfileManagement::InitList() { 00106 00107 // Make sure the lists are empty. 00108 00109 m_cuaRemovals.Empty(); 00110 m_cpaAdds.Empty(); 00111 00112 // Determine the associations for the target device. 00113 00114 ENUMTYPE et = {sizeof et, ENUM_TYPE_VERSION, ET_DEVICENAME, m_csDevice}; 00115 00116 CProfile::Enumerate(et, m_cpaProfile); 00117 } 00118 00119 // Fill the UI list of profiles 00120 00121 void CDeviceProfileManagement::FillList(DWORD dwFlags) { 00122 00123 // Before reset list box, get current selection to restore later. 00124 00125 CString csSelect; 00126 00127 csSelect.Empty(); 00128 00129 LRESULT idSelect = LB_ERR; 00130 00131 if ( !(dwFlags & DEVLIST_NOSELECT)) { 00132 00133 // Get current selected position. 00134 00135 idSelect = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 00136 00137 // Get text length where currently selected, than allocate buffer for that. 00138 00139 DWORD dwLen = (DWORD) SendMessage(m_hwndList, LB_GETTEXTLEN, idSelect, 0); 00140 TCHAR *pszSelect = new TCHAR[dwLen + 1]; 00141 00142 // Get text itself. 00143 00144 if (pszSelect != NULL) { 00145 00146 if (SendMessage(m_hwndList, LB_GETTEXT, idSelect, (LPARAM) pszSelect) != LB_ERR) { 00147 csSelect = pszSelect; 00148 } 00149 00150 delete pszSelect; 00151 } 00152 } 00153 00154 // reset list box 00155 00156 SendMessage(m_hwndList, LB_RESETCONTENT, 0, 0); 00157 00158 // Fill the profile list box from the list of profiles 00159 00160 for (unsigned u = 0; u < m_cpaProfile.Count(); u++) { 00161 00162 // Don't list profiles tentatively disassociated... 00163 00164 for (unsigned uOut = 0; uOut < m_cuaRemovals.Count(); uOut++) 00165 if (m_cuaRemovals[uOut] == u) 00166 break; 00167 00168 if (uOut < m_cuaRemovals.Count()) 00169 continue; // Don't add this to list, it's been zapped! 00170 00171 LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0, 00172 (LPARAM) (LPCTSTR) m_cpaProfile[u] -> GetName()); 00173 00174 SendMessage(m_hwndList, LB_SETITEMDATA, id, u); 00175 } 00176 00177 // Add the profiles that have been tentatively added... 00178 00179 for (u = 0; u < m_cpaAdds.Count(); u ++) { 00180 LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0, 00181 (LPARAM) (LPCTSTR) m_cpaAdds[u] -> GetName()); 00182 SendMessage(m_hwndList, LB_SETITEMDATA, id, u + m_cpaProfile.Count()); 00183 } 00184 00185 // If we have any profiles, select the first one 00186 // Otherwise, disable the "Remove" button, as there's nothing to remove 00187 00188 unsigned itemCount = (m_cpaProfile.Count() + m_cpaAdds.Count() - m_cuaRemovals.Count()); 00189 00190 if (itemCount) { 00191 00192 // The Remove button must remain disabled 00193 // unless the user is Administrator. 00194 // This code is specific to the Monitor Profile 00195 // Property sheet. 00196 00197 if (!m_bReadOnly) { 00198 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), TRUE); 00199 } 00200 00201 if ( !(dwFlags & DEVLIST_NOSELECT)) { 00202 00203 // Find out the string selected previously. 00204 00205 idSelect = LB_ERR; 00206 00207 if (!csSelect.IsEmpty()) { 00208 idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT, 00209 (WPARAM) -1, (LPARAM) (LPCTSTR) csSelect); 00210 } 00211 00212 // if could not find, just select first item. 00213 00214 if (idSelect == LB_ERR) { 00215 idSelect = 0; 00216 } 00217 00218 // Select it. 00219 00220 SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0); 00221 } 00222 00223 } else { 00224 00225 HWND hwndRemove = GetDlgItem(m_hwnd, RemoveButton); 00226 00227 // If focus is on Remove, move it to Add button. 00228 00229 if (GetFocus() == hwndRemove) { 00230 00231 HWND hwndAdd = GetDlgItem(m_hwnd, AddButton); 00232 00233 SetFocus(hwndAdd); 00234 SendMessage(hwndRemove, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); 00235 SendMessage(hwndAdd, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); 00236 } 00237 00238 EnableWindow(hwndRemove, FALSE); 00239 } 00240 00241 // Apply button needs to remain disabled unless the 00242 // user has permision to make changes - ie. user 00243 // is Administrator. 00244 00245 if ((dwFlags & DEVLIST_CHANGED) && !(m_bReadOnly)) { 00246 EnableApplyButton(); 00247 SettingChanged(TRUE); 00248 } 00249 } 00250 00251 void CDeviceProfileManagement::GetDeviceTypeString(DWORD dwType,CString& csDeviceName) { 00252 00253 DWORD id; 00254 00255 switch (dwType) { 00256 00257 case CLASS_MONITOR : 00258 id = ClassMonitorString; 00259 break; 00260 case CLASS_PRINTER : 00261 id = ClassPrinterString; 00262 break; 00263 case CLASS_SCANNER : 00264 id = ClassScannerString; 00265 break; 00266 case CLASS_LINK : 00267 id = ClassLinkString; 00268 break; 00269 case CLASS_ABSTRACT : 00270 id = ClassAbstractString; 00271 break; 00272 case CLASS_NAMED : 00273 id = ClassNamedString; 00274 break; 00275 case CLASS_COLORSPACE : 00276 default : 00277 id = ClassColorSpaceString; 00278 break; 00279 } 00280 00281 // Load string. 00282 00283 csDeviceName.Load(id); 00284 } 00285 00286 // Constructor 00287 00288 CDeviceProfileManagement::CDeviceProfileManagement(LPCTSTR lpstrDevice, 00289 HINSTANCE hiWhere, 00290 int idPage, DWORD dwType) { 00291 m_csDevice = lpstrDevice; 00292 m_dwType = dwType; 00293 m_psp.hInstance = hiWhere; 00294 m_psp.pszTemplate = MAKEINTRESOURCE(idPage); 00295 00296 // Setting m_bReadOnly to false enables functionality 00297 00298 m_bReadOnly = FALSE; // default setting is false 00299 00300 #if defined(_WIN95_) 00301 00302 // 00303 // There is no way to detect printer supports CMYK or not on Win 9x. 00304 00305 m_bCMYK = TRUE; 00306 00307 #else 00308 00309 // we need to check the device capabilities 00310 // and determine if we're trying to associate 00311 // a cmyk printer profile to a printer that 00312 // doesn't support it. 00313 00314 m_bCMYK = FALSE; // default setting - don't support cmyk 00315 00316 // if the device is a printer 00317 00318 if (m_dwType == CLASS_PRINTER) { 00319 00320 HDC hdcThis = CGlobals::GetPrinterHDC(m_csDevice); 00321 00322 // if the printer supports CMYK 00323 00324 if (hdcThis) { 00325 if (GetDeviceCaps(hdcThis, COLORMGMTCAPS) & CM_CMYK_COLOR) { 00326 m_bCMYK = TRUE; 00327 } 00328 DeleteDC(hdcThis); 00329 } 00330 } 00331 00332 #endif // defined(_WIN95_) 00333 } 00334 00335 // UI initialization 00336 00337 BOOL CDeviceProfileManagement::OnInit() { 00338 00339 InitList(); 00340 00341 m_hwndList = GetDlgItem(m_hwnd, ProfileListControl); 00342 00343 // Fill the profile list box 00344 00345 FillList(DEVLIST_ONINIT); 00346 00347 // Disable apply button as default. 00348 00349 DisableApplyButton(); 00350 00351 // Nothing changed, yet. 00352 00353 SettingChanged(FALSE); 00354 00355 return TRUE; 00356 } 00357 00358 // Command processing 00359 00360 BOOL CDeviceProfileManagement::OnCommand(WORD wNotifyCode, WORD wid, 00361 HWND hwndCtl) { 00362 00363 switch (wNotifyCode) { 00364 00365 case BN_CLICKED: 00366 00367 switch (wid) { 00368 00369 case AddButton: { 00370 00371 unsigned i = 0, u = 0; 00372 00373 // Time to do the old OpenFile dialog stuff... 00374 00375 CAddProfileDialog capd(m_hwnd, m_psp.hInstance); 00376 00377 // See if a profile was selected 00378 00379 while(i < capd.ProfileCount()) { 00380 00381 // Check profile validity and device type 00382 00383 CProfile cpTemp(capd.ProfileName(i)); 00384 00385 // CLASS_COLORSPACE and CLASS_MONITOR can be associated to 00386 // any device. Other (CLASS_SCANNER, CLASS_PRINTER) only 00387 // can be associated to much device. 00388 00389 if ( !cpTemp.IsValid() // Wrong profile type or invalid? 00390 || ( cpTemp.GetType() != m_dwType 00391 && cpTemp.GetType() != CLASS_COLORSPACE 00392 #if 1 // ALLOW_MONITOR_PROFILE_TO_ANY_DEVICE 00393 && cpTemp.GetType() != CLASS_MONITOR 00394 #endif 00395 ) 00396 ) { 00397 00398 // Throw up a message box to inform the user of this 00399 00400 if (cpTemp.IsValid()) 00401 { 00402 CString csDeviceType; GetDeviceTypeString(m_dwType,csDeviceType); 00403 CString csProfileType; GetDeviceTypeString(cpTemp.GetType(),csProfileType); 00404 00405 CGlobals::ReportEx(MismatchDeviceType, m_hwnd, FALSE, 00406 MB_OK|MB_ICONEXCLAMATION, 3, 00407 (LPTSTR)capd.ProfileNameAndExtension(i), 00408 (LPTSTR)csProfileType, 00409 (LPTSTR)csDeviceType); 00410 } 00411 else 00412 { 00413 CGlobals::ReportEx(InstFailedWithName, m_hwnd, FALSE, 00414 MB_OK|MB_ICONEXCLAMATION, 1, 00415 (LPTSTR)capd.ProfileNameAndExtension(i)); 00416 } 00417 00418 goto SkipToNext; 00419 } 00420 00421 // See if the profile has already been listed for addition 00422 00423 for (u = 0; u < m_cpaAdds.Count(); u++) { 00424 if (!lstrcmpi(m_cpaAdds[u] -> GetName(), cpTemp.GetName())) { 00425 goto SkipToNext; // This profile is already added 00426 } 00427 } 00428 00429 // If this profile is on the existing list, either ignore 00430 // or zap it from the removal list, as the case may be 00431 00432 for (u = 0; u < m_cpaProfile.Count(); u++) { 00433 if (!lstrcmpi(m_cpaProfile[u] -> GetName(), 00434 cpTemp.GetName())) { 00435 // Is this one on the removal list? 00436 for (unsigned uOut = 0; 00437 uOut < m_cuaRemovals.Count(); 00438 uOut++) { 00439 if (m_cuaRemovals[uOut] == u) { 00440 // Was to be removed- undo that... 00441 m_cuaRemovals.Remove(uOut); 00442 FillList(DEVLIST_CHANGED); 00443 break; 00444 } 00445 } 00446 goto SkipToNext; 00447 } // End of name in existing list 00448 } 00449 00450 // We need to check the device capabilities 00451 // and determine if we're trying to associate 00452 // a cmyk printer profile to a printer that 00453 // doesn't support it. 00454 00455 if ((!m_bCMYK) && (cpTemp.GetColorSpace() == SPACE_CMYK)) { 00456 CGlobals::ReportEx(UnsupportedProfile, m_hwnd, FALSE, 00457 MB_OK|MB_ICONEXCLAMATION, 2, 00458 (LPTSTR)m_csDevice, 00459 (LPTSTR)capd.ProfileNameAndExtension(i)); 00460 goto SkipToNext; 00461 } 00462 00463 // Add this profile to the list, item (max orig + index) 00464 00465 m_cpaAdds.Add(capd.ProfileName(i)); 00466 00467 // Change has been made, update the list 00468 00469 FillList(DEVLIST_CHANGED); 00470 SkipToNext: 00471 i++; 00472 } 00473 00474 return TRUE; 00475 } 00476 00477 case RemoveButton: { 00478 00479 // Remove the selected profile 00480 00481 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 00482 unsigned u = (unsigned) SendMessage(m_hwndList, 00483 LB_GETITEMDATA, id, 0); 00484 00485 // If this is a tentative add, just drop it, otherwise 00486 // note that it's been removed... 00487 00488 if (u >= m_cpaProfile.Count()) 00489 m_cpaAdds.Remove(u - m_cpaProfile.Count()); 00490 else 00491 m_cuaRemovals.Add(u); 00492 00493 // That's it- just update the display, now... 00494 00495 FillList(DEVLIST_CHANGED); 00496 00497 // explicitly set the position of the current selection 00498 // after the list has been recomputed. 00499 00500 int listsize = m_cpaProfile.Count()+m_cpaAdds.Count()-m_cuaRemovals.Count(); 00501 if (id >= listsize) id = listsize-1; 00502 if (id < 0) id = 0; 00503 SendMessage(m_hwndList, LB_SETCURSEL, id, 0); 00504 00505 return TRUE; 00506 } 00507 } 00508 break; 00509 00510 case LBN_SELCHANGE: { 00511 00512 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 00513 00514 if (id == -1) { 00515 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE); 00516 } else { 00517 00518 // The Remove button must remain disabled on a monitor 00519 // profile property page if the user isn't the 00520 // Administrator, otherwise enable remove button. 00521 00522 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), !m_bReadOnly); 00523 } 00524 00525 return TRUE; 00526 } 00527 } 00528 00529 return FALSE; 00530 } 00531 00532 // Property Sheet notification processing 00533 00534 BOOL CDeviceProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) { 00535 00536 switch (pnmh -> code) { 00537 00538 case PSN_APPLY: 00539 00540 DisableApplyButton(); 00541 00542 if (SettingChanged()) { 00543 00544 // Apply the changes the user has made... 00545 00546 SettingChanged(FALSE); 00547 00548 while (m_cpaAdds.Count()) { 00549 if (!m_cpaAdds[0] -> IsInstalled()) { 00550 m_cpaAdds[0] -> Install(); 00551 } 00552 m_cpaAdds[0] -> Associate(m_csDevice); 00553 m_cpaAdds.Remove(0); 00554 } 00555 00556 // Now do the removals (actually just dissociations) 00557 00558 while (m_cuaRemovals.Count()) { 00559 m_cpaProfile[m_cuaRemovals[0]] -> Dissociate(m_csDevice); 00560 m_cuaRemovals.Remove(0); 00561 } 00562 00563 InitList(); 00564 FillList(); 00565 00566 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); 00567 } 00568 00569 return TRUE; 00570 } 00571 00572 return FALSE; 00573 } 00574 00575 // This hook procedure both forces the use of the old-style common dialog 00576 // and changes the OK button to an Add button. The actual button text is 00577 // a string resource, and hence localizable. 00578 00579 UINT_PTR APIENTRY CAddProfileDialog::OpenFileHookProc(HWND hDlg, UINT uMessage, 00580 WPARAM wp, LPARAM lp) { 00581 switch (uMessage) { 00582 00583 case WM_INITDIALOG: { 00584 00585 CString csAddButton; 00586 00587 OPENFILENAME *pofn = (OPENFILENAME *) lp; 00588 00589 csAddButton.Load(AddButtonText); 00590 00591 SetDlgItemText(GetParent(hDlg), IDOK, csAddButton); 00592 return TRUE; 00593 } 00594 } 00595 00596 return FALSE; 00597 } 00598 00599 // Once again, a constructor that actually does most of the work! 00600 00601 TCHAR gacColorDir[MAX_PATH] = _TEXT("\0"); 00602 TCHAR gacFilter[MAX_PATH] = _TEXT("\0"); 00603 00604 CAddProfileDialog::CAddProfileDialog(HWND hwndOwner, HINSTANCE hi) { 00605 00606 TCHAR tempBuffer[MAX_PATH*10]; 00607 00608 // Empty the profile list. 00609 00610 csa_Files.Empty(); 00611 00612 // Prepare file filter (if not yet). 00613 00614 if (gacFilter[0] == NULL) { 00615 00616 ULONG offset; /* 32bits is enough even for sundown */ 00617 CString csIccFilter; CString csAllFilter; 00618 00619 // If the filter is not built yet, build it here. 00620 00621 csIccFilter.Load(IccProfileFilterString); 00622 csAllFilter.Load(AllProfileFilterString); 00623 offset = 0; 00624 lstrcpy(gacFilter+offset, csIccFilter); 00625 offset += lstrlen(csIccFilter)+1; 00626 lstrcpy(gacFilter+offset, TEXT("*.icm;*.icc")); 00627 offset += lstrlen(TEXT("*.icm;*.icc"))+1; 00628 lstrcpy(gacFilter+offset, csAllFilter); 00629 offset += lstrlen(csAllFilter)+1; 00630 lstrcpy(gacFilter+offset, TEXT("*.*")); 00631 offset += lstrlen(TEXT("*.*"))+1; 00632 *(gacFilter+offset) = TEXT('\0'); 00633 } 00634 00635 if (gacColorDir[0] == _TEXT('\0')) { 00636 DWORD dwcbDir = MAX_PATH; 00637 GetColorDirectory(NULL, gacColorDir, &dwcbDir); 00638 } 00639 00640 // Time to do the old OpenFile dialog stuff... 00641 CString csTitle; csTitle.Load(AddProfileAssociation); 00642 00643 // Set initial filename as null. 00644 memset(tempBuffer, 0, sizeof tempBuffer); 00645 00646 OPENFILENAME ofn = { 00647 sizeof ofn, hwndOwner, hi, 00648 gacFilter, 00649 NULL, 0, 1, 00650 tempBuffer, sizeof tempBuffer / sizeof tempBuffer[0], 00651 NULL, 0, 00652 gacColorDir, 00653 csTitle, 00654 OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_HIDEREADONLY | 00655 OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK, 00656 0, 0, 00657 _TEXT("icm"), 00658 (LPARAM) this, OpenFileHookProc, NULL}; 00659 00660 if (!GetOpenFileName(&ofn)) { 00661 if (CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) { 00662 CGlobals::Report(TooManyFileSelected); 00663 } 00664 } else { 00665 if (tempBuffer[0] != TEXT('\0')) { 00666 00667 TCHAR *pPath = tempBuffer; 00668 TCHAR *pFile = tempBuffer + lstrlen(tempBuffer) + 1; 00669 00670 // remember the last access-ed directory. 00671 00672 memset(gacColorDir, 0, sizeof pPath); 00673 memcpy(gacColorDir, pPath, ofn.nFileOffset*sizeof(TCHAR)); 00674 00675 if (*pFile) { 00676 TCHAR workBuffer[MAX_PATH]; 00677 00678 // This is multiple-selection 00679 // Work through the buufer to build profile file list. 00680 00681 while (*pFile) { 00682 00683 lstrcpy(workBuffer,pPath); 00684 lstrcat(workBuffer,TEXT("\\")); 00685 lstrcat(workBuffer,pFile); 00686 00687 // Insert built profile pathname 00688 AddProfile(workBuffer); 00689 00690 // Move on to next. 00691 pFile = pFile + lstrlen(pFile) + 1; 00692 } 00693 } 00694 else { 00695 // Single selection case. 00696 AddProfile(pPath); 00697 00698 #if HIDEYUKN_DBG 00699 MessageBox(NULL,pPath,TEXT(""),MB_OK); 00700 #endif 00701 } 00702 } 00703 } 00704 00705 return; 00706 } 00707 00708 // Printer Profile Management 00709 00710 CONST DWORD PrinterUIHelpIds[] = { 00711 AddButton, IDH_PRINTERUI_ADD, 00712 RemoveButton, IDH_PRINTERUI_REMOVE, 00713 ProfileListControl, IDH_PRINTERUI_LIST, 00714 00715 #if !defined(_WIN95_) 00716 ProfileListControlText, IDH_PRINTERUI_LIST, 00717 PrinterUIIcon, IDH_DISABLED, 00718 DescriptionText, IDH_DISABLED, 00719 DefaultButton, IDH_PRINTERUI_DEFAULTBTN, 00720 AutoSelButton, IDH_PRINTERUI_AUTOMATIC, 00721 AutoSelText, IDH_PRINTERUI_AUTOMATIC, 00722 ManualSelButton, IDH_PRINTERUI_MANUAL, 00723 ManualSelText, IDH_PRINTERUI_MANUAL, 00724 DefaultProfileText, IDH_PRINTERUI_DEFAULTTEXT, 00725 DefaultProfile, IDH_PRINTERUI_DEFAULTTEXT, 00726 #endif 00727 0, 0 00728 }; 00729 00730 // Initialize lists override- call the base class, then set the default 00731 00732 void CPrinterProfileManagement::InitList() { 00733 00734 CDeviceProfileManagement::InitList(); 00735 00736 m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1; 00737 } 00738 00739 // Fill list override- write the correct default and call the base function 00740 00741 void CPrinterProfileManagement::FillList(DWORD dwFlags) { 00742 00743 // If we are initializing list box, we want to put focus on 00744 // "default" profile. here we won't below FillList set focus 00745 // to first one. 00746 00747 if (dwFlags & DEVLIST_ONINIT) { 00748 dwFlags |= DEVLIST_NOSELECT; 00749 } 00750 00751 CDeviceProfileManagement::FillList(dwFlags); 00752 00753 // There is either no default profile, an existing profile is the 00754 // default, or a newly selected one is. Some people just like the 00755 // selection operator. 00756 00757 // if there is only 1 profile in list box, we treat it as default profile. 00758 00759 if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) { 00760 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0); 00761 } 00762 00763 if (m_uDefault == -1) { 00764 00765 // There is no profile associated for this device. 00766 00767 CString csNoProfile; 00768 csNoProfile.Load(NoProfileString); 00769 SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile); 00770 00771 } else { 00772 00773 // If the default has been deleted, set default as last in list. 00774 00775 if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) { 00776 00777 m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1; 00778 } 00779 00780 // Put default profile name in UI. 00781 00782 CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \ 00783 m_cpaProfile[m_uDefault] : \ 00784 m_cpaAdds[m_uDefault - m_cpaProfile.Count()]; 00785 00786 SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName()); 00787 00788 LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT, 00789 (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName()); 00790 00791 // if could not find, just select first item. 00792 00793 if (idSelect == LB_ERR) { 00794 idSelect = 0; 00795 } 00796 00797 // Select it. 00798 00799 SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0); 00800 } 00801 00802 // 03-08-1997 Bob_Kjelgaard@Prodigy.Net Memphis RAID 18420 00803 // Disable the Default button if there aren't any profiles 00804 00805 if (m_bManualMode && m_bAdminAccess) { 00806 EnableWindow(GetDlgItem(m_hwnd, DefaultButton), 00807 m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count()); 00808 } 00809 } 00810 00811 // Printer Profile Management class constructor- doesn't need any individual 00812 // code at the moment. 00813 00814 CPrinterProfileManagement::CPrinterProfileManagement(LPCTSTR lpstrName, 00815 HINSTANCE hiWhere) : 00816 CDeviceProfileManagement(lpstrName, hiWhere, PrinterUI, CLASS_PRINTER) { 00817 } 00818 00819 // This class overrides OnInit so it can disable the UI if the user lacks 00820 // authority to make changes. 00821 00822 BOOL CPrinterProfileManagement::OnInit() { 00823 00824 // Call the base class routine first, as it does most of the work... 00825 00826 CDeviceProfileManagement::OnInit(); 00827 00828 DWORD dwSize = sizeof(DWORD); 00829 00830 // Query current mode. 00831 00832 if (!InternalGetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER, 00833 MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, &dwSize)) { 00834 00835 // Auto selection mode as default. 00836 00837 m_bManualMode = FALSE; 00838 } 00839 00840 // Now, see if we have sufficient authority to administer the printer 00841 00842 HANDLE hPrinter; 00843 PRINTER_DEFAULTS pd = {NULL, NULL, PRINTER_ACCESS_ADMINISTER}; 00844 00845 m_bAdminAccess = TRUE; 00846 m_bLocalPrinter = TRUE; 00847 00848 if (OpenPrinter(const_cast<LPTSTR> ((LPCTSTR) m_csDevice), &hPrinter, &pd)) { 00849 00850 // We can administer the printer- proceed in the normal way. 00851 00852 #if !defined(_WIN95_) 00853 00854 // If the printer is "Network Printer", we don't allow user to install 00855 // or uninstall color profile. 00856 00857 BYTE StackPrinterData[sizeof(PRINTER_INFO_4)+MAX_PATH*2]; 00858 PBYTE pPrinterData = StackPrinterData; 00859 BOOL bSuccess = TRUE; 00860 DWORD dwReturned; 00861 00862 if (!GetPrinter(hPrinter, 4, pPrinterData, sizeof(StackPrinterData), &dwReturned)) { 00863 00864 if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) && 00865 (pPrinterData = (PBYTE) LocalAlloc(LPTR, dwReturned))) { 00866 00867 if (GetPrinter(hPrinter, 4, pPrinterData, dwReturned, &dwReturned)) { 00868 00869 bSuccess = TRUE; 00870 00871 } 00872 } 00873 00874 } else { 00875 00876 bSuccess = TRUE; 00877 } 00878 00879 if (bSuccess) 00880 { 00881 m_bLocalPrinter = ((PRINTER_INFO_4 *)pPrinterData)->pServerName ? FALSE : TRUE; 00882 } 00883 else 00884 { 00885 m_bAdminAccess = FALSE; 00886 } 00887 00888 if (pPrinterData && (pPrinterData != StackPrinterData)) 00889 { 00890 LocalFree(pPrinterData); 00891 } 00892 00893 #endif // !defined(_WIN95_) 00894 00895 ClosePrinter(hPrinter); 00896 00897 } else { 00898 00899 m_bAdminAccess = FALSE; 00900 } 00901 00902 // How many profile in listbox ? 00903 00904 LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0); 00905 if (itemCount == LB_ERR) itemCount = 0; 00906 00907 // make sure the ancestor list code behaves correctly. 00908 // You need Admin Access and a Local Printer to be able to add/remove profiles 00909 00910 m_bReadOnly = !(m_bAdminAccess && m_bLocalPrinter); 00911 00912 // Enable/Disable the controls (if needed) 00913 00914 CheckDlgButton(m_hwnd, AutoSelButton, m_bManualMode ? BST_UNCHECKED : BST_CHECKED); 00915 CheckDlgButton(m_hwnd, ManualSelButton, m_bManualMode ? BST_CHECKED : BST_UNCHECKED); 00916 00917 // Only administrator can change 'auto','manual' configuration. 00918 00919 EnableWindow(GetDlgItem(m_hwnd, AutoSelButton), m_bAdminAccess && m_bLocalPrinter); 00920 EnableWindow(GetDlgItem(m_hwnd, ManualSelButton), m_bAdminAccess && m_bLocalPrinter); 00921 00922 // Only administrator and printer is at local, can install/uninstall color profile. 00923 00924 EnableWindow(GetDlgItem(m_hwnd, AddButton), m_bAdminAccess && m_bLocalPrinter); 00925 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), m_bAdminAccess && m_bLocalPrinter && itemCount); 00926 00927 EnableWindow(m_hwndList, m_bAdminAccess); 00928 EnableWindow(GetDlgItem(m_hwnd, DefaultProfileText), m_bAdminAccess); 00929 EnableWindow(GetDlgItem(m_hwnd, DefaultProfile), m_bAdminAccess); 00930 00931 // Only with manual mode, these controls are enabled. 00932 00933 EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bAdminAccess && m_bManualMode 00934 && m_bLocalPrinter && itemCount); 00935 00936 if (!m_bAdminAccess) { 00937 00938 // Set the focus to the OK button 00939 00940 SetFocus(GetDlgItem(m_hwndSheet, IDOK)); 00941 return FALSE; // Because we moved the focus! 00942 } 00943 00944 return TRUE; 00945 } 00946 00947 // Command processing- we never let them click into the edit control, to 00948 // prevent them from editing it. 00949 00950 BOOL CPrinterProfileManagement::OnCommand(WORD wNotifyCode, WORD wid, 00951 HWND hwndCtl) { 00952 00953 switch (wNotifyCode) { 00954 00955 case LBN_DBLCLK: { 00956 00957 // Retrieve the ID of the new default profile 00958 // only accept dblclk changes if the dialog 00959 // is not read only - i.e. user is admin 00960 00961 if (m_bManualMode) { 00962 00963 int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 00964 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0); 00965 00966 // Change has been made, update the list 00967 00968 FillList(DEVLIST_CHANGED); 00969 } 00970 00971 return TRUE; 00972 } 00973 00974 case BN_CLICKED: 00975 00976 switch (wid) { 00977 00978 case AutoSelButton: 00979 case ManualSelButton: { 00980 00981 // How many profile in listbox ? 00982 00983 LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0); 00984 if (itemCount == LB_ERR) itemCount = 0; 00985 00986 m_bManualMode = (wid == ManualSelButton) ? TRUE : FALSE; 00987 00988 // Only with manual mode, these controls are enabled. 00989 00990 EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bManualMode && itemCount); 00991 00992 // Configuarion has been changed, enable apply button. 00993 00994 EnableApplyButton(); 00995 SettingChanged(TRUE); 00996 00997 return TRUE; 00998 } 00999 01000 case RemoveButton: { 01001 01002 // Make sure we've tracked the default profile correctly 01003 // when a profile is removed. 01004 // All cases break, because we then want the base class to 01005 // process this message. 01006 01007 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 01008 01009 unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 01010 id, 0); 01011 01012 if (uTarget > m_uDefault || m_uDefault == (unsigned) -1) 01013 break; // Nothing here to worry about 01014 01015 if (m_uDefault == uTarget) { 01016 01017 if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE, 01018 MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) { 01019 01020 // The default has been deleted- the profile 01021 // at the top of monitor profile list will be 01022 // made the default profile, if we have 01023 01024 LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0); 01025 01026 if ((itemCount != LB_ERR) && (itemCount > 1)) { 01027 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0); 01028 if (m_uDefault == uTarget) { 01029 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0); 01030 } 01031 } else { 01032 m_uDefault = -1; 01033 } 01034 01035 break; 01036 } else { 01037 return TRUE; // opration cancelled. 01038 } 01039 } 01040 01041 if (uTarget < m_cpaProfile.Count()) 01042 break; // We're fine 01043 01044 // Must be an added profile below us in the list was 01045 // zapped- we need to decrement ourselves. 01046 01047 m_uDefault--; 01048 break; 01049 } 01050 01051 case DefaultButton: { 01052 01053 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 01054 01055 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0); 01056 01057 // Change has been made, update the list 01058 01059 FillList(DEVLIST_CHANGED); 01060 01061 return TRUE; 01062 } 01063 } 01064 01065 // Deliberate fall-through (use a break if you add a case here) 01066 } 01067 01068 // Use common command handling if not handled above 01069 01070 return CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl); 01071 } 01072 01073 // Property Sheet notification processing 01074 01075 BOOL CPrinterProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) { 01076 01077 switch (pnmh -> code) { 01078 01079 case PSN_APPLY: { 01080 01081 DisableApplyButton(); 01082 01083 // If nothing changed, nothing need to do. 01084 01085 if (!SettingChanged()) 01086 return TRUE; 01087 01088 if (m_bManualMode) { 01089 01090 // If the user hasn't selected a default, and we have 01091 // associated profiles, then we can't allow this. 01092 01093 // 03-08-1997 A-RobKj Fix for Memphis RAID 18416- if there's 01094 // only one profile left, then it must be the default. 01095 01096 if (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() + 01097 m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) { 01098 01099 CGlobals::Report(NoDefaultProfile, m_hwndSheet); 01100 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); 01101 break; 01102 } 01103 01104 // !!! This behavior is hardly depend on EnumColorProfiles() API !!! 01105 01106 // OK, if the default profile has changed, we have to delete default 01107 // profile associations, and do the association for default profile 01108 // in "last". 01109 01110 // Let the base class handle the cases where the default hasn't 01111 // changed, or we started with no profiles and still have none. 01112 // 01113 // 03-08-1997 Sleazy code note. The case where no default is 01114 // selected but only one is assigned will now fall here. Since the 01115 // default happens to be the "last", and there only is one, letting 01116 // the base class handle it is not a problem. The list filling 01117 // code will take care of the rest for us. 01118 01119 if (m_uDefault == (unsigned) -1) break; 01120 01121 // Remove default first (if default is associated), then associate later. 01122 01123 if (m_uDefault < m_cpaProfile.Count()) 01124 m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice); 01125 01126 // Now do the other removals (actually just dissociations) 01127 01128 for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) { 01129 m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice); 01130 } 01131 01132 // Add in the new ones 01133 01134 for (u = 0; u < m_cpaAdds.Count(); u++) { 01135 if (m_uDefault >= m_cpaProfile.Count()) 01136 if (u == (m_uDefault - m_cpaProfile.Count())) 01137 continue; // this is default, will be done later 01138 01139 // OK, add it back in... 01140 m_cpaAdds[u] -> Associate(m_csDevice); 01141 } 01142 01143 // Finally, associate back default profile. 01144 01145 if (m_uDefault < m_cpaProfile.Count()) 01146 m_cpaProfile[m_uDefault] -> Associate(m_csDevice); 01147 else 01148 m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice); 01149 01150 // Update the various working structures... 01151 01152 InitList(); 01153 FillList(); 01154 01155 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); 01156 01157 // Now, we have updated settings. 01158 01159 SettingChanged(FALSE); 01160 } 01161 01162 // Update "auto/manual" status. 01163 01164 InternalSetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER, 01165 MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, sizeof(DWORD)); 01166 } 01167 } 01168 01169 // Let the base class handle everything else 01170 01171 return CDeviceProfileManagement::OnNotify(idCtrl, pnmh); 01172 } 01173 01174 // Context-sensitive help handler 01175 01176 BOOL CPrinterProfileManagement::OnHelp(LPHELPINFO pHelp) { 01177 01178 if (pHelp->iContextType == HELPINFO_WINDOW) { 01179 WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE, 01180 HELP_WM_HELP, (ULONG_PTR) (LPSTR) PrinterUIHelpIds); 01181 } 01182 01183 return (TRUE); 01184 } 01185 01186 BOOL CPrinterProfileManagement::OnContextMenu(HWND hwnd) { 01187 01188 WinHelp(hwnd, WINDOWS_HELP_FILE, 01189 HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) PrinterUIHelpIds); 01190 01191 return (TRUE); 01192 } 01193 01194 // Scanner Profile Management 01195 // Scanner Profile Management class constructor- doesn't need any individual 01196 // code at the moment. 01197 01198 // Scanner Profile Management 01199 01200 CONST DWORD ScannerUIHelpIds[] = { 01201 #if !defined(_WIN95_) 01202 AddButton, IDH_SCANNERUI_ADD, 01203 RemoveButton, IDH_SCANNERUI_REMOVE, 01204 ProfileListControl, IDH_SCANNERUI_LIST, 01205 ProfileListControlText, IDH_SCANNERUI_LIST, 01206 #endif 01207 0, 0 01208 }; 01209 01210 CScannerProfileManagement::CScannerProfileManagement(LPCTSTR lpstrName, 01211 HINSTANCE hiWhere) : 01212 01213 CDeviceProfileManagement(lpstrName, hiWhere, ScannerUI, CLASS_SCANNER) { 01214 m_bReadOnly = !IsAdmin(); 01215 } 01216 01217 // This class overrides OnInit so it can disable the UI if the user lacks 01218 // authority to make changes. 01219 01220 BOOL CScannerProfileManagement::OnInit() { 01221 01222 // Call the base class routine first, as it does most of the work... 01223 01224 CDeviceProfileManagement::OnInit(); 01225 01226 // Now, see if we have sufficient authority to administer the scanner 01227 // 01228 if (m_bReadOnly) { 01229 // User is not Admin, Disable all of the controls 01230 01231 EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE); 01232 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE); 01233 01234 // Set the focus to the OK button 01235 SetFocus(GetDlgItem(m_hwndSheet, IDOK)); 01236 return FALSE; // Because we moved the focus! 01237 } 01238 01239 return TRUE; 01240 } 01241 01242 // Context-sensitive help handler 01243 01244 BOOL CScannerProfileManagement::OnHelp(LPHELPINFO pHelp) { 01245 01246 if (pHelp->iContextType == HELPINFO_WINDOW) { 01247 WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE, 01248 HELP_WM_HELP, (ULONG_PTR) (LPSTR) ScannerUIHelpIds); 01249 } 01250 01251 return (TRUE); 01252 } 01253 01254 BOOL CScannerProfileManagement::OnContextMenu(HWND hwnd) { 01255 01256 WinHelp(hwnd, WINDOWS_HELP_FILE, 01257 HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) ScannerUIHelpIds); 01258 01259 return (TRUE); 01260 } 01261 01262 01263 01264 // Monitor Profile Management class- since the mechanism for default 01265 // profile manipulation is a bit sleazy, so is some of this code. 01266 01267 CONST DWORD MonitorUIHelpIds[] = { 01268 AddButton, IDH_MONITORUI_ADD, 01269 RemoveButton, IDH_MONITORUI_REMOVE, 01270 DefaultButton, IDH_MONITORUI_DEFAULT, 01271 ProfileListControl, IDH_MONITORUI_LIST, 01272 #if !defined(_WIN95_) 01273 ProfileListControlText, IDH_MONITORUI_LIST, 01274 MonitorName, IDH_MONITORUI_DISPLAY, 01275 MonitorNameText, IDH_MONITORUI_DISPLAY, 01276 DefaultProfile, IDH_MONITORUI_PROFILE, 01277 DefaultProfileText, IDH_MONITORUI_PROFILE, 01278 #endif 01279 0, 0 01280 }; 01281 01282 // Initialize lists override- call the base class, then set the default 01283 01284 void CMonitorProfileManagement::InitList() { 01285 01286 CDeviceProfileManagement::InitList(); 01287 01288 m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1; 01289 } 01290 01291 // Fill list override- write the correct default and call the base function 01292 01293 void CMonitorProfileManagement::FillList(DWORD dwFlags) { 01294 01295 // If we are initializing list box, we want to put focus on 01296 // "default" profile. here we won't below FillList set focus 01297 // to first one. 01298 01299 if (dwFlags & DEVLIST_ONINIT) { 01300 dwFlags |= DEVLIST_NOSELECT; 01301 } 01302 01303 CDeviceProfileManagement::FillList(dwFlags); 01304 01305 // There is either no default profile, an existing profile is the 01306 // default, or a newly selected one is. Some people just like the 01307 // selection operator. 01308 01309 // if there is only 1 profile in list box, we treat it as default profile. 01310 01311 if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) { 01312 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0); 01313 } 01314 01315 if (m_uDefault == -1) { 01316 01317 // There is no profile associated for this device. 01318 01319 CString csNoProfile; 01320 csNoProfile.Load(NoProfileString); 01321 SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile); 01322 01323 } else { 01324 01325 // If the default has been deleted, set default as last in list. 01326 01327 if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) { 01328 01329 m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1; 01330 } 01331 01332 // Put default profile name in UI. 01333 01334 CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \ 01335 m_cpaProfile[m_uDefault] : \ 01336 m_cpaAdds[m_uDefault - m_cpaProfile.Count()]; 01337 01338 SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName()); 01339 01340 // If we are initialing list box, put focus on default profile. 01341 01342 if (dwFlags & DEVLIST_ONINIT) { 01343 01344 LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT, 01345 (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName()); 01346 01347 // if could not find, just select first item. 01348 01349 if (idSelect == LB_ERR) { 01350 idSelect = 0; 01351 } 01352 01353 // Select it. 01354 01355 SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0); 01356 } 01357 } 01358 01359 // 03-08-1997 Bob_Kjelgaard@Prodigy.Net Memphis RAID 18420 01360 // Disable the Default button if there aren't any profiles 01361 01362 // We do it here, because this gets called any time the list changes. 01363 // only allow Default button to be enabled if 01364 // the dialog isn't read only. 01365 // the remove button should remain dissabled 01366 // under all conditions while the user is not 01367 // administrator. 01368 01369 if (m_bReadOnly) { 01370 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE); 01371 } else { 01372 EnableWindow(GetDlgItem(m_hwnd, DefaultButton), 01373 m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count()); 01374 } 01375 } 01376 01377 // Constructor 01378 01379 CMonitorProfileManagement::CMonitorProfileManagement(LPCTSTR lpstrName, 01380 LPCTSTR lpstrFriendlyName, 01381 HINSTANCE hiWhere) : 01382 CDeviceProfileManagement(lpstrName, hiWhere, MonitorUI, CLASS_MONITOR) { 01383 01384 01385 // if the user is not the administrator, 01386 // make this property sheet read only. 01387 01388 m_bReadOnly = !IsAdmin(); 01389 01390 // Keep friendly name in MonitorProfileManagement class. 01391 01392 m_csDeviceFriendlyName = lpstrFriendlyName; 01393 } 01394 01395 // UI Initialization 01396 01397 BOOL CMonitorProfileManagement::OnInit() { 01398 01399 // Do common initializations 01400 01401 CDeviceProfileManagement::OnInit(); 01402 01403 // Mark the device name in the space provided 01404 01405 SetDlgItemText(m_hwnd, MonitorName, m_csDeviceFriendlyName); 01406 01407 // Now, see if we have sufficient authority to administer the monitor 01408 01409 if(m_bReadOnly) { 01410 01411 // User is not Admin, Disable all of the controls 01412 01413 EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE); 01414 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE); 01415 EnableWindow(GetDlgItem(m_hwnd, DefaultButton), FALSE); 01416 01417 // EnableWindow(m_hwndList, FALSE); 01418 01419 // Set the focus to the OK button 01420 01421 SetFocus(GetDlgItem(m_hwndSheet, IDOK)); 01422 return FALSE; // Because we moved the focus! 01423 } 01424 01425 return TRUE; 01426 } 01427 01428 // Command processing- we never let them click into the edit control, to 01429 // prevent them from editing it. 01430 01431 BOOL CMonitorProfileManagement::OnCommand(WORD wNotifyCode, WORD wid, 01432 HWND hwndCtl) { 01433 01434 switch (wNotifyCode) { 01435 01436 case LBN_DBLCLK: { 01437 01438 // Retrieve the ID of the new default profile 01439 // only accept dblclk changes if the dialog 01440 // is not read only - i.e. user is admin 01441 01442 if (!m_bReadOnly) { 01443 01444 int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 01445 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0); 01446 01447 // Change has been made, update the list 01448 01449 FillList(DEVLIST_CHANGED); 01450 } 01451 01452 return TRUE; 01453 } 01454 01455 case BN_CLICKED: 01456 01457 switch (wid) { 01458 01459 case RemoveButton: { 01460 01461 // Make sure we've tracked the default profile correctly 01462 // when a profile is removed. 01463 // All cases break, because we then want the base class to 01464 // process this message. 01465 01466 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 01467 01468 unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 01469 id, 0); 01470 01471 if (uTarget > m_uDefault || m_uDefault == (unsigned) -1) 01472 break; // Nothing here to worry about 01473 01474 if (m_uDefault == uTarget) { 01475 01476 if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE, 01477 MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) { 01478 01479 // The default has been deleted- the profile 01480 // at the top of monitor profile list will be 01481 // made the default profile, if we have 01482 01483 LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0); 01484 01485 if ((itemCount != LB_ERR) && (itemCount > 1)) { 01486 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0); 01487 if (m_uDefault == uTarget) { 01488 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0); 01489 } 01490 } else { 01491 m_uDefault = -1; 01492 } 01493 01494 break; 01495 } else { 01496 return TRUE; // operation cancelled. 01497 } 01498 } 01499 01500 if (uTarget < m_cpaProfile.Count()) 01501 break; // We're fine 01502 01503 // Must be an added profile below us in the list was 01504 // zapped- we need to decrement ourselves. 01505 01506 m_uDefault--; 01507 break; 01508 } 01509 01510 case DefaultButton: { 01511 01512 LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0); 01513 01514 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0); 01515 01516 // Change has been made, update the list 01517 01518 FillList(DEVLIST_CHANGED); 01519 01520 return TRUE; 01521 } 01522 } 01523 01524 // Deliberate fall-through (use a break if you add a case here) 01525 } 01526 01527 // Use common command handling if not handled above 01528 return CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl); 01529 } 01530 01531 // Property Sheet notification processing 01532 01533 BOOL CMonitorProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) { 01534 01535 switch (pnmh -> code) { 01536 01537 case PSN_APPLY: { 01538 01539 DisableApplyButton(); 01540 01541 // If nothing changed, nothing need to do. 01542 01543 if (!SettingChanged()) 01544 return TRUE; 01545 01546 // If the user hasn't selected a default, and we have 01547 // associated profiles, then we can't allow this. 01548 01549 // 03-08-1997 A-RobKj Fix for Memphis RAID 18416- if there's 01550 // only one profile left, then it must be the default. 01551 01552 if (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() + 01553 m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) { 01554 01555 CGlobals::Report(NoDefaultProfile, m_hwndSheet); 01556 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); 01557 break; 01558 } 01559 01560 // !!! This behavior is hardly depend on EnumColorProfiles() API !!! 01561 01562 // OK, if the default profile has changed, we have to delete default 01563 // profile associations, and do the association for default profile 01564 // in "last". 01565 01566 // Let the base class handle the cases where the default hasn't 01567 // changed, or we started with no profiles and still have none. 01568 // 01569 // 03-08-1997 Sleazy code note. The case where no default is 01570 // selected but only one is assigned will now fall here. Since the 01571 // default happens to be the "last", and there only is one, letting 01572 // the base class handle it is not a problem. The list filling 01573 // code will take care of the rest for us. 01574 01575 if (m_uDefault == (unsigned) -1) break; 01576 01577 // Remove default first (if default is associated), then associate later. 01578 01579 if (m_uDefault < m_cpaProfile.Count()) 01580 m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice); 01581 01582 // Now do the other removals (actually just dissociations) 01583 01584 for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) { 01585 m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice); 01586 } 01587 01588 // Add in the new ones 01589 01590 for (u = 0; u < m_cpaAdds.Count(); u++) { 01591 if (m_uDefault >= m_cpaProfile.Count()) 01592 if (u == (m_uDefault - m_cpaProfile.Count())) 01593 continue; // this is default, will be done later 01594 01595 // OK, add it back in... 01596 m_cpaAdds[u] -> Associate(m_csDevice); 01597 } 01598 01599 // Finally, associate default profile. 01600 01601 if (m_uDefault < m_cpaProfile.Count()) 01602 m_cpaProfile[m_uDefault] -> Associate(m_csDevice); 01603 else 01604 m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice); 01605 01606 // Update the various working structures... 01607 01608 InitList(); 01609 FillList(); 01610 01611 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); 01612 01613 // Now, we have updated settings. 01614 01615 SettingChanged(FALSE); 01616 } 01617 } 01618 01619 // Let the base class handle everything else 01620 01621 return CDeviceProfileManagement::OnNotify(idCtrl, pnmh); 01622 } 01623 01624 // Context-sensitive help handler 01625 01626 BOOL CMonitorProfileManagement::OnHelp(LPHELPINFO pHelp) { 01627 01628 if (pHelp->iContextType == HELPINFO_WINDOW) { 01629 WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE, 01630 HELP_WM_HELP, (ULONG_PTR) (LPSTR) MonitorUIHelpIds); 01631 } 01632 01633 return (TRUE); 01634 } 01635 01636 BOOL CMonitorProfileManagement::OnContextMenu(HWND hwnd) { 01637 01638 WinHelp(hwnd, WINDOWS_HELP_FILE, 01639 HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) MonitorUIHelpIds); 01640 01641 return (TRUE); 01642 } 01643

Generated on Sat May 15 19:39:41 2004 for test by doxygen 1.3.7