#c #winapi #dev-mode
#c #по WinAPI #режим разработки #winapi
Вопрос:
Я пытаюсь получить имена каждого из моих мониторов, используя DEVMODE.dmDeviceName
:
dmDeviceName Имя устройства
Массив символов с нулевым завершением, который задает «понятное» имя принтера или дисплея; например, «PCL/HP LaserJet» в случае PCL/HP LaserJet. Эта строка уникальна среди драйверов устройств. Обратите внимание, что это имя может быть усечено, чтобы поместиться в массив dmDeviceName.
Я использую следующий код:
log.printf("Device Name: %s",currDevMode.dmDeviceName);
Но для каждого монитора название печатается как просто c
. Вся остальная информация из DEVMODE, похоже, печатается нормально. Что происходит не так?
Ответ №1:
Скорее всего, вы используете версию структуры в Юникоде и, таким образом, передаете широкие символы printf
. Поскольку вы используете строку формата, которая подразумевает char
данные, существует несоответствие.
Кодировка UTF-16 приводит к тому, что каждый второй байт равен 0 для символов в диапазоне ASCII, и поэтому printf
считается, что второй байт первого двухбайтового символа на самом деле является нулевым ограничителем.
Это та проблема, с которой вы сталкиваетесь printf
, которая, конечно, не имеет безопасности типов. Поскольку вы используете C , вероятно, стоит переключиться на iostream
ввод-вывод на основе.
Однако, если вы хотите использовать текст ANSI, как вы указали в комментарии, то самым простым решением является использование DEVMODEA
версии структуры ANSI и соответствующих A
версий функций API, например EnumDisplaySettingsA
, DeviceCapabilitiesA
.
Комментарии:
1. Хм, при использовании EnumDisplaySettingsA я получаю
cannot convert parameter 1 from 'WCHAR *' to 'LPCSTR'
, где параметром 1 является monitorInfo.szDevice, полученный с помощьюGetMonitorInfo
.2. Это все или ничего. Вам нужно
GetMonitorInfoA
так же, какEnumDisplaySettingsA
. Конечно, вы могли бы просто переключить конфигурацию вашего проекта на ANSI. Для справки прочитайте это: msdn.microsoft.com/en-us/library/dd374089 (VS.85).aspx3. API для преобразования wide в ANSI является
WideCharToMultiByte()
. Это не самый простой в использовании, поэтому, если вы можете вместо этого вызвать ANSI API, вам будет проще.4. Я надеюсь, что это
cdd
то, что вы ищете!5. Я только что позвонил
EnumDisplaySettings
, и я также вижу имя устройства cdd. Не спрашивайте меня, что это значит, но я почти уверен, что вы получаете правильное значение от системы.
Ответ №2:
dmDeviceName
TCHAR[]
поэтому, если вы компилируете для unicode, первый широкий символ будет интерпретироваться как ‘c’, за которым следует нулевой ограничитель.
Вам нужно будет преобразовать его в ascii или использовать процедуры печати с поддержкой unicode.
Комментарии:
1. Как бы мне преобразовать его в ascii? Я не могу изменить способ
log
работы.2. @fredley Я рассмотрел это в заключительных абзацах моего ответа.