BOOL CImageUtility::GetDisplayMonitorICC( wchar_t* full_path, int char_count ) { if( !IS_Vista_Or_More() ) return FALSE; DISPLAY_DEVICE device_info; device_info.cb = sizeof( DISPLAY_DEVICE ); int card_id=0; while( TRUE ) { BOOL ret = EnumDisplayDevices( NULL, card_id, &device_info, 0 ); if( !ret ) break; if(device_info.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) { int monitor_id=0; wchar_t card_name[256]; ::memcpy( card_name,device_info.DeviceName,32*2); ret = EnumDisplayDevices( card_name, monitor_id, &device_info, 0 ); if( !ret ) return FALSE; DWORD buf_size = char_count*2; ret = GetColorDirectory( NULL, full_path, &buf_size ); if( !ret ) return FALSE; if( char_count*2 < buf_size+10 ) return FALSE; full_path[buf_size/2-1] = L'\\'; WcsGetDefaultColorProfileType func_ptr = GetProfileFunctionAddress(); if( func_ptr == NULL ) return FALSE; ret = func_ptr(WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER,device_info.DeviceID,CPT_ICC, CPST_NONE, 0, char_count*2 - buf_size, full_path + buf_size/2 ); return ret; } ++card_id; } return FALSE; }
bool GetMonitorProfile(char *path, int buf_len, const void *hwnd) { std::list<std::string> profile_descriptions; std::map<std::string, std::string> profile_paths; // path to the monitor's profile char monitor_profile_path[256] = { '\0' }; DWORD path_size = 256; BOOL get_icm_result = GetICMProfile(GetDC((HWND)hwnd), &path_size, monitor_profile_path); // directory where Windows stores its profiles char profile_directory[256] = { '\0' }; DWORD dir_name_size = 256; BOOL get_color_dir_result = GetColorDirectory(NULL, profile_directory, &dir_name_size); // Get the profile file names from Windows ENUMTYPE enum_type; enum_type.dwSize = sizeof(ENUMTYPE); enum_type.dwVersion = ENUM_TYPE_VERSION; enum_type.dwFields = ET_DEVICECLASS; // alternately could use ET_CLASS enum_type.dwDeviceClass = CLASS_MONITOR; BYTE *buf = NULL; DWORD buf_size = 0; DWORD num_profiles = 0; BOOL other_enum_result = EnumColorProfiles(NULL, &enum_type, buf, &buf_size, &num_profiles); if(buf_size > 0 && num_profiles > 0) { buf = (BYTE *)malloc(buf_size); other_enum_result = EnumColorProfiles(NULL, &enum_type, buf, &buf_size, &num_profiles); if(other_enum_result) { // build a list of the profile descriptions // and a map to return the paths char *prof_name = (char *)buf; for(int i=0; i < num_profiles; i++) { std::string prof = prof_name; std::string prof_path = std::string(profile_directory) + "\\" + prof_name; cmsHPROFILE hProfile = cmsOpenProfileFromFile(prof_path.c_str(), "r"); // Note: Windows will give us profiles that aren't ICC (.cdmp for example). // Don't worry, LittleCMS will just return NULL for those. if(hProfile) { char profile_description[256]; cmsUInt32Number got_desc = cmsGetProfileInfoASCII(hProfile, cmsInfoDescription, "en", "US", profile_description, 256); if(got_desc) { profile_descriptions.push_back(profile_description); profile_paths[ profile_description ] = prof_path; } cmsCloseProfile(hProfile); } prof_name += strlen(prof_name) + 1; } } free(buf); } if(profile_descriptions.size() > 0) { // set a vector and selected index for building the profile menu profile_descriptions.sort(); profile_descriptions.unique(); std::vector<std::string> profile_vec; int selected = 0; for(std::list<std::string>::const_iterator i = profile_descriptions.begin(); i != profile_descriptions.end(); i++) { profile_vec.push_back( *i ); if( profile_paths[ *i ] == monitor_profile_path) { selected = profile_vec.size() - 1; } } // run the dialog g_profile_vec = &profile_vec; g_selected_item = selected; int status = DialogBox(hDllInstance, (LPSTR)"PROFILEDIALOG", (HWND)hwnd, (DLGPROC)DialogProc); if(status == -1) { // dialog didn't open, my bad return true; } else if(g_item_clicked == DLOG_Cancel) { return false; } else { strncpy(path, profile_paths[ profile_vec[ g_selected_item ] ].c_str(), buf_len); return true; } } else return true; }