是否有人有一个工作代码示例显示对Windows Color System函数的调用 WcsGetDefaultColorProfile 以获取特定设备的默认颜色配置文件?当我为pDeviceName参数传递null时,它适用于我,但是当我尝试传递监视器的设备名称时,我总是返回错误代码ERROR_FILE_NOT_FOUND。
我更喜欢C#示例,但我会接受任何我能得到的东西。我无法在任何地方找到任何新的WCS配置文件管理功能的示例代码。
答案 0 :(得分:5)
我遇到了同样的问题,令人沮丧的原因是MSDN文档对于WcsGetDefaultColorProfile的pDeviceName参数不正确(或者最好是误导)。
MSDN doc(http://msdn.microsoft.com/en-us/library/dd372247(v=vs.85).aspx)表示pDeviceName是指“设备名称”,对于显示设备,人们会认为它是Windows显示设备名称,例如“\。\ DISPLAY1”,如从EnumDisplayDevices中的DISPLAY_DEVICE结构的DeviceName参数返回。
实际上,这里需要的是监视器的DeviceKey参数,特别是在EnumDisplayDevices中使用EDD_GET_DEVICE_INTERFACE_NAME标志时获得的DeviceKey。
所以工作代码看起来像这样,假设szDisplayDeviceName已设置为显示您关心的设备名称,例如“\。\ DISPLAY1”:
WCHAR szPath[MAX_PATH];
DISPLAY_DEVICE dd;
dd.cb = sizeof(dd);
if (EnumDisplayDevices(szDisplayDeviceName, 0, &dd, EDD_GET_DEVICE_INTERFACE_NAME))
{
if (WcsGetDefaultColorProfile(WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER,
dd.DeviceKey,
CPT_ICC,
CPST_PERCEPTUAL,
1, // dwProfileID -- doesn't seem to matter what value you use here
MAX_PATH * sizeof(WCHAR),
szPath))
{
PROFILE profile;
profile.cbDataSize = (DWORD)(wcslen(szPath) + 1) * sizeof(WCHAR);
profile.dwType = PROFILE_FILENAME;
profile.pProfileData = (PVOID)szPath;
HPROFILE hProfile = OpenColorProfile(&profile,
PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);
// now do something with the profile
}
}
答案 1 :(得分:1)
跟进上面的Matt M的答案(谢谢!):如果你想匹配其他应用程序所做的事情,那么使用EnumDisplayDevices返回的第一个监视器,如上所述。
但请注意,这可能会在多显示器设置中返回不正确(无效/禁用)显示器,其中一个或多个显示器已禁用但仍连接。当然,微软并没有在任何地方记录这一点,所以很多应用程序,包括像Photoshop这样的大型应用程序都在这方面被打破:(
如果您想要做正确的事情,您必须多次调用EnumDisplayDevices,直到找到活动监视器(如果多个监视器与显示器关联,则标记DISPLAY_DEVICE_ACTIVE和DISPLAY_DEVICE_MULTI_DRIVER)。
答案 2 :(得分:1)
尝试将Mark的代码翻译成C#:
SUBTOTAL(5,OFFSET(A1:D1,ROW(A1:D4)-MIN(ROW(A1:D4)),))
答案 3 :(得分:0)
添加以下结构:
public const uint ProfileRead = 1;
public enum FileShare : uint
{
Read = 1,
Write = 2,
Delete = 4
};
public enum CreateDisposition : uint
{
CreateNew = 1,
CreateAlways = 2,
OpenExisting = 3,
OpenAlways = 4,
TruncateExisting = 5
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class ProfileFilename
{
public uint type;
[MarshalAs(UnmanagedType.LPTStr)]
public string profileData;
public uint dataSize;
public ProfileFilename(string filename)
{
type = ProfileFilenameType;
profileData = filename;
dataSize = (uint)filename.Length * 2 + 2;
}
};
[DllImport("mscms.dll", SetLastError = true, EntryPoint = "GetStandardColorSpaceProfileW", CallingConvention = CallingConvention.Winapi)]
static extern bool GetStandardColorSpaceProfile( uint machineName,
LogicalColorSpace profileID,
[MarshalAs(UnmanagedType.LPTStr), In, Out] StringBuilder profileName,
ref uint size);
[DllImport("mscms.dll", SetLastError = true, EntryPoint = "OpenColorProfileW", CallingConvention = CallingConvention.Winapi)]
static extern IntPtr OpenColorProfile( [MarshalAs(UnmanagedType.LPStruct)] ProfileFilename profile,
uint desiredAccess,
FileShare shareMode,
CreateDisposition creationMode);
打开默认配置文件的示例:
public openDefaultColorProfile()
{
StringBuilder profileName = new StringBuilder(256);
uint size = (uint)profileName.Capacity * 2;
success = GetStandardColorSpaceProfile(0, LogicalColorSpace.WindowsColorSpace, profileName, ref size);
ProfileFilename sRGBFilename = new ProfileFilename(profileName.ToString());
IntPtr hSRGBProfile = OpenColorProfile(sRGBFilename, ProfileRead, FileShare.Read, CreateDisposition.OpenExisting);
}
答案 4 :(得分:0)
文档根本没有显而易见,但从之前的答案中我拼凑了一个完整的解决方案(为了清楚起见,这里没有错误检查)。此外,这只会返回用户指定的默认值,如果他们从未设置默认值,则需要使用GetStandardColorSpaceProfile
来获取“其他”默认值。
DISPLAY_DEVICE displayDevice = {};
displayDevice.cb = sizeof(DISPLAY_DEVICE);
// First, find the primary adaptor
std::stringw adaptorName;
DWORD deviceIndex = 0;
while (::EnumDisplayDevicesW(nullptr, deviceIndex++, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP &&
displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
adaptorName = displayDevice.DeviceName;
break;
}
}
// Second, find the first active (and attached) monitor
std::string deviceName;
deviceIndex = 0;
while (::EnumDisplayDevicesW(adaptorName, deviceIndex++, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE &&
displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED)
{
deviceName = displayDevice.DeviceKey;
break;
}
}
// Third, find out whether to use the global or user profile
BOOL usePerUserProfiles = FALSE;
WcsGetUsePerUserProfiles(deviceName, CLASS_MONITOR, &usePerUserProfiles);
// Finally, get the profile name
const WCS_PROFILE_MANAGEMENT_SCOPE scope = usePerUserProfiles ? WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER : WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE;
DWORD profileNameLength = 0; // In bytes
WcsGetDefaultColorProfileSize(scope, deviceName, CPT_ICC, CPST_RGB_WORKING_SPACE, 0, &profileNameLength);
wchar_t *const profileName = new wchar_t[profileNameLength / sizeof(wchar_t)];
WcsGetDefaultColorProfile(scope, deviceName, CPT_ICC, CPST_RGB_WORKING_SPACE, 0, profileNameLength, profileName);
// Do something with your profile name
delete[] profileName;