Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получение имени устройства, Получение имени устройства GetDeviceName 
:(
    Опции темы
Sonechka
Дата 6.2.2012, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Доброго времени суток, уважаемые! Имеется у меня исходник на Delphi, который выводит список всех устройств в TreeView, как в "Диспетчере устройств", дополнительно выводит в  ListBox сетевые устройства и дисковые накопители. Ввиду того, что мной изучался Delphi (давненько по программистским меркам это и было), а он сейчас (да и тогда) был не актуален, появилось у меня желание овладеть C++ (2 недели уже овладеваю). Начал не с самых азов (все языки ведь похожи). Начал с простого, стал переписывать более-менее понятный мне код. Для начала, переписал кнопочки для вывода сетевых и дисковых устройств в соответствующие ListBox'ы, но в обоих обработчиках события OnClick есть функция GetDeviceName (понятно из названия зачем она), а перевести её не могу. Ниже привожу пример её, написанной на Delphi (вроде она простая, понять не трудно будет):

Код

function GetDeviceName(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData): string;
var
  BytesReturned: DWORD;
  RegDataType: DWORD;
  Buffer: array [0..256] of CHAR;
begin
  BytesReturned := 0;
  RegDataType := 0;
  Buffer[0] := #0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_FRIENDLYNAME,
    RegDataType, PByte(@Buffer[0]), SizeOf(Buffer), BytesReturned);
  Result := Buffer;
  if Result<>'' then exit;
  BytesReturned := 0;
  RegDataType := 0;
  Buffer[0] := #0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_DEVICEDESC,
    RegDataType, PByte(@Buffer[0]), SizeOf(Buffer), BytesReturned);
  Result:=Buffer;
end;


Собственно о том, что может быть непонятно в коде (сам этого не помню, специально искал):
#0 - признак окончания строки;
@ - адрес переменной;

Дополнительно привожу пример обработчика для вывода дисковых устройств (для сетевых всё то же самое, только одна переменная иначе названа (А то подумаете, что за халявой пришёл smile). А я не за халявой, а чтобы показали и объяснили smile Я учится хочу , но без помощи не получается.

Код

                 /* ------------------ ДЛЯ ДИСКОВЫХ УСТРОЙСТВ ------------------ */
        private: System::Void button7_Click(System::Object^  sender, System::EventArgs^  e) {
                // Импровизированный раздел описания переменных (НАД ЭТИМ НЕ СМЕЙТЕСЬ, ПРОСТО МНЕ ТАК УДОБНО, Я К ДЕЛЬФЯМ ПРИВЫКШИЙ)
                HDEVINFO DrivePnPHandle; // Этот, да и все остальные типы данных описаны соответственно в setupapi.h
                DWORD DeviceNumber;
                PSP_DEVINFO_DATA DevData;
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData;
                BOOL RES; 
                
                // Раздел кода программы
                DrivesListBox->Items->Clear();
                DrivePnPHandle = SetupDiGetClassDevs((LPGUID)&GUID_DEVCLASS_DISKDRIVE, 0, 0, DIGCF_PRESENT /*or DIGCF_PROFILE*/); // GUID_DEVCLASS_DISKDRIVE - чтобы работало #include "devguid.h" написал.
                if  (DrivePnPHandle = INVALID_HANDLE_VALUE) {
                    return;
                };
                DeviceNumber = 0;
                do { // В исходнике использовался дельфийский цикл repeat - until not, как мне кажется do - while - альтернатива в C++
                    DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                    DevData->cbSize = sizeof(SP_DEVINFO_DATA);
                    RES = SetupDiEnumDeviceInfo(DrivePnPHandle, DeviceNumber, DevData);
                    if (RES) {
                        DrivesListBox->Items->Add(GetDeviceName(DrivePnPHandle, DevData)); // Функция в процессе написания...
                        DeviceNumber++;
                    };
                }
                while (RES);
                SetupDiDestroyDeviceInfoList(DrivePnPHandle);
                DrivesListBox->Enabled = true;
         }


Для сетевых код такой же, только вместо DrivePnPHandle - NetPnPHandle, ну и ListBox не DrivesListBox, а NetDevicesListBox.

Заодно проверите этот код для кнопки, но компилятор только ругается на GetDeviceName.

Показывать то, что я навоял в процессе переписывания GetDeviceName стыдно, но вот:

Код

        int GetDeviceName(HDEVINFO PnPHandle, const PSP_DEVINFO_DATA DevData) {
            // Импровизированный раздел описания переменных
            PDWORD BytesReturned = 0;
            PDWORD RegDataType = 0;
            CHAR Buffer[257];

            // Раздел кода программы
            Buffer[0] = #0; // Тут конечно не так должно быть, не нашёл как обзывается признак конца строки
            SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_FRIENDLYNAME, RegDataType, PBYTE(@Buffer[0]), sizeof(Buffer), BytesReturned);
            return Buffer;
            if (Buffer!="") { 
                return;    // Тут тоже не так
            };
            BytesReturned = 0;
            RegDataType = 0;
            Buffer[0] = #0; // Тут тоже не так
            SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_FRIENDLYNAME, RegDataType, PBYTE(@Buffer[0]), sizeof(Buffer), BytesReturned);
            return Buffer;
        }


В общем, хочу чтобы вы мне показали и объяснили (прошу не отсылать к литературе, лучше понимаю на примерах).
PM MAIL   Вверх
xvr
Дата 6.2.2012, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



У вас почти все правильно. Должно быть так -
Код

        AnsiString GetDeviceName(HDEVINFO PnPHandle, const PSP_DEVINFO_DATA DevData) {
            // Импровизированный раздел описания переменных
            DWORD BytesReturned = 0; // P* не нужен
            DWORD RegDataType = 0;
            CHAR Buffer[257];
            // Раздел кода программы
            Buffer[0] = 0; // # не нужен. В С++ символы и целые числа - одно и тоже
            SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_FRIENDLYNAME, &RegDataType, Buffer, sizeof(Buffer), &BytesReturned);           
            if (Buffer[0]!="") return Buffer; // Непустая строка имеет вервым символом не 0
            BytesReturned = 0;
            RegDataType = 0;
            Buffer[0] = 0;
            SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_DEVICEDESC, &RegDataType, Buffer, sizeof(Buffer), &BytesReturned);
            return Buffer;
        }
Но и тут есть много лишнего - переменные BytesReturned и RegDataType можно вообще убрать, а вместо ссылко на них передать в SetupDiGetDeviceRegistryProperty NULL


PM MAIL   Вверх
feodorv
Дата 12.2.2012, 05:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Девятая строка кода выглядит как-то неправильно ;)
Цитата(xvr @  6.2.2012,  14:20 Найти цитируемый пост)
            if (Buffer[0]!="") return Buffer; // Непустая строка имеет вервым символом не 0




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
xvr
Дата 12.2.2012, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(feodorv @  12.2.2012,  05:12 Найти цитируемый пост)
Девятая строка кода выглядит как-то неправильно ;)

Угу, посыпаю голову пеплом  smile Там доджен быть просто  0
Код

if (Buffer[0]!=0) return Buffer; // Непустая строка имеет вервым символом не 0

PM MAIL   Вверх
maxfox
Дата 15.2.2012, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 43
Регистрация: 29.7.2009

Репутация: нет
Всего: нет



Подскажите пожалуйста, почему не получается скомпилировать описанный выше код?
На сам код студия не ругается, но выдаёт кучу ошибок во включаемых файлах setupapi.h, и prsht.h и spapidef.h.
При этом в проект я включил файл: #include <setupapi.h>
Я предполагаю, что необходимо ещё включить какие то заголовочные файлы или библиотеки, но не знаю, какие. Подскажите пожалуйста!
PM MAIL   Вверх
xvr
Дата 15.2.2012, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(maxfox @  15.2.2012,  14:02 Найти цитируемый пост)
Подскажите пожалуйста, почему не получается скомпилировать описанный выше код?

Судя по наличию типа AnsiString код предназначался не для студии, а для Bulder'а

Цитата(maxfox @  15.2.2012,  14:02 Найти цитируемый пост)
На сам код студия не ругается, но выдаёт кучу ошибок во включаемых файлах setupapi.h, и prsht.h и spapidef.h

windows.h в начале включен?

PM MAIL   Вверх
maxfox
Дата 16.2.2012, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 43
Регистрация: 29.7.2009

Репутация: нет
Всего: нет



xvr, 
Мне кажется, что судя по синтаксису заголовка процедуры:
Код

        private: System::Void button7_Click(System::Object^  sender, System::EventArgs^  e) {

-это студия и проект Windows Forms. Но. могу и ошибаться.

windows.h - не было. когда включил, все предыдущие ошибки ушли, но появилась другая:
В проекте пользуюсь NET библиотекой, чтобы взять путь, от куда запущена программа: System::IO::Directory::GetCurrentDirectory();
однако в библиотеке WinBase.h, есть такая строчка: #define GetCurrentDirectory  GetCurrentDirectoryW
На сколько я понял, эта строчка переопределяет(или что то в этом роде) функцию из NET - библиотеке.
В общем. выдаёт такую ошибку: error C2039: GetCurrentDirectoryW: не является членом "System::IO::Directory"
Я не понимаю сути этой ошибки, т.к. у меня в тексте нигде нет переменной:  GetCurrentDirectoryW

PM MAIL   Вверх
xvr
Дата 16.2.2012, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(maxfox @  16.2.2012,  13:46 Найти цитируемый пост)
Мне кажется, что судя по синтаксису заголовка процедуры:

Этот исходник да - на .NET (C++/CLI)

Цитата(maxfox @  16.2.2012,  13:46 Найти цитируемый пост)
windows.h - не было. когда включил, все предыдущие ошибки ушли, но появилась другая:

Это проблема с совместимостью .NET и WinAPI. windows.h расчитана на чистый С, и она явно передралась с .NET заголовками.

В WinAPI #define GetCurrentDirectory  GetCurrentDirectoryW - это стандартный способ настройки приложения под Unicode.
Советую не рожать помесь ужа с ежём, а писать либо на C# либо на чистом С++. С++/CLI - это порождение проблем совместимости, и делать на нем проект с нуля это явный идиотизм и самоубийство  smile 

PM MAIL   Вверх
GremlinProg
Дата 16.2.2012, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(maxfox @  16.2.2012,  15:46 Найти цитируемый пост)
В общем. выдаёт такую ошибку: error C2039: GetCurrentDirectoryW: не является членом "System::IO::Directory"

после включения windows.h можно конечно прописать:
Код

#undef GetCurrentDirectory

но не факт, что не появится чего-то другого,

вобщем, это будет куча undef'ов, пока не появятся проблемы с дублированием типов данных и функций ( и это будет финиш ),

p.s.: вот потом посмотришь на эту гору костылей и наверное поймешь, что проще было пользоваться чем-то одним  smile 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0601 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.