Показать сообщение отдельно
  #2  
Старый 05.03.2009, 10:45
Koluna Koluna вне форума
Прохожий
 
Регистрация: 27.02.2009
Сообщения: 5
Репутация: 10
По умолчанию

Привожу свой код функции (работоспособный), которая выключает/включает устройство по коду экземпляра устройства.
Критика и полезные советы очень приветствуются. Хотелось бы в результате обсуждения получить не только работоспособный, но и простой, красивый и оптимизированный код

Код:
function On_Off_Device(PnPID: PAnsiChar; State: Boolean): Boolean;

var
  DeviceInfoSet_ : HDEVINFO; // Хендл набора информации об устройствах.
  DeviceInfoData_ : TSPDevInfoData; // Структура информации об устройстве.
  SPPropChangeParams_ : TSPPropChangeParams;

begin
  DeviceInfoSet_ := nil;
// Получение хендла набора информации об устройстве по коду экземпляра устройства.
  DeviceInfoSet_ := SetupDiGetClassDevs(nil, PnPID, 0, DIGCF_ALLCLASSES or DIGCF_DEVICEINTERFACE);
  if Integer(DeviceInfoSet_) = INVALID_HANDLE_VALUE then
  begin
// Ошибка.
    Result := False;
    Exit;
  end
  else
  begin
// Хендл набора информации об устройстве получен.
    FillChar(DeviceInfoData_, SizeOf(TSPDevInfoData), 0);
    DeviceInfoData_.cbSize := SizeOf(TSPDevInfoData);
// Заполнение структуры информации об устройстве.
    if not SetupDiEnumDeviceInfo(DeviceInfoSet_, 0, DeviceInfoData_) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

// Установка полей структуры
    SPPropChangeParams_.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
    SPPropChangeParams_.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
    SPPropChangeParams_.Scope := DICS_FLAG_GLOBAL;

    if State then SPPropChangeParams_.StateChange := DICS_ENABLE
    else SPPropChangeParams_.StateChange := DICS_DISABLE;

// Изменение состояния устройства.
    if not SetupDiSetClassInstallParams(DeviceInfoSet_,
                                        @DeviceInfoData_,
                                        @SPPropChangeParams_,
                                        SizeOf(TSPPropChangeParams)) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;
// Подтверждение изменения состояния устройства
// (повторный вызов функции SetupDiSetClassInstallParams).
    if not SetupDiSetClassInstallParams(DeviceInfoSet_,
                                        @DeviceInfoData_,
                                        @SPPropChangeParams_,
                                        SizeOf(TSPPropChangeParams)) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

// Вызов установщика классов.
    if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DeviceInfoSet_, @DeviceInfoData_) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

  end; // Integer(DeviceInfoSet_) <> INVALID_HANDLE_VALUE

  Result := True;
// Освобождение хендла набора информации об устройствах.
  SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
end;

Попутно - несколько вопросов.

1. При вызове моей функции с параметром False для отключении устройства N раз подряд, чтобы включить устройство приходится вызывать эту функцию с параметром True тоже N раз подряд. Как будто где-то есть счётчик включения/выключения... Почему и зачем?
2. Хотелось бы прояснить работу SetupDiGetClassDevs. Без флага DIGCF_DEVICEINTERFACE - моя функция не работает. Хотя в других примерах видел вызывы и без этого флага (с параметром Enumerator!). Не понятна связь между параметром Enumerator и флагом DIGCF_DEVICEINTERFACE.
3. Хотелось бы знать как можно назвать по-русски следующие структуры, используемые при вызове функций: HDEVINFO (хендл на структуру ...), TSPDevInfoData (структура ...), TSPPropChangeParams (структура...). Не могу перевести нормально, а название поиметь хочется
Ответить с цитированием