| 
| 
 | Вопрос # 2 405/ вопрос открыт / | 
 |  Здравствуйте, эксперты!Может сможет кто помочь с решением след. проблемы.
 Не получается отловить сообщение "О извлечении флэшки из USB"
 Использую след. код
 uses ..., DBT;
 ...
 procedure WMDEVICECHANGE(var Msg:TMessage);message WM_DEVICECHAGE;
 ...
 procedure WMDEVICECHANGE(var Msg:TMessage);
 begin
 case Msg.WParam of
 DBT_DEVICEARRIVAL:; // подключение устройства
 DBT_DEVICEREMOVECOMPLETE:; // отключение устройства
 else // ? - а вот здесь никак, только 7 и LParam=0
 end;
 end;
 
 Т.е. сообщение об извлечении устройства поступают, но как узнать, что это именно устройство извлечено, ведь такие сообщени и при подключении и отключении?
 
 Заранее благодарен.
 
|  |   Вопрос задал: Светлов (статус: Посетитель)Вопрос отправлен: 9 февраля 2009, 15:14
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, Светлов!Можно взять и проанализировать биты, где будет записано, что произошло, но там чуточку хитро. Где то дома есть код, можно поискать.
 Но можно сделать гораздо проще. с помощью функции GetDriveType можно пробежаться по всем дискам. и сравнить с предыдущим запомненным состоянием (например в массиве disk:array[A..Z] of byte;).
 набросок кода можно глянуть тут http://www.codenet.ru/progr/delphi/stat/System-Information.php.
 
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 9 февраля 2009, 15:43
 Оценка за ответ: 4
 Комментарий к оценке: Хотелось бы узнать на счет бит и где их искать Msg=WM_DEVICECHANGE, Msg.WParam=7, Msg.LParam=0 ??? А ссылка не работает. |  
 Мини-форум вопросаВсего сообщений: 2; последнее сообщение — 9 февраля 2009, 23:55; участников в обсуждении: 2. 
|   | Пупкин В.В. (статус: 1-ый класс), 9 февраля 2009, 15:55 [#1]:все уже написано, есть готовый компанент, ищите в нете авторство не знаю и дабы не нарушать прав постить не могу.
 |  
|   | Вадим К (статус: Академик), 9 февраля 2009, 23:55 [#2]:в ссылке надо удалить точку в конце. заработает. а код... Написал же - приду домой - п2mоищу, нет надо ставить сразу минус единицы... аж расхотелось писать.  ну вот код, прикручиваем самостоятельно
 
 //...................
type
 
  TMainForm = class(TForm)
 
    Label1:      TLabel;
 
    Label2:      TLabel;
 
    ListBox1:    TListBox;
 //Здесь будет список флешек!
    buttonClose: TButton;
 
    procedure FormCreate(Sender: TObject);
 
  private
    { Private declarations }
    procedure WMDev(var msg: TMessage); message WM_DEVICECHANGE;
  public
    { Public declarations }
    procedure UpdateList;
  end;
//............
//как я долго всё это вытягивал с мсдн.... 
//извиняйте за мой английский.
//нормальный программист обязан учить
const
 
  // Win32 constants
  DBT_DEVTYP_DEVICEINTERFACE = 5;
  DBT_DEVTYP_HANDLE    = 6;
  BROADCAST_QUERY_DENY = $424D5144;
  WM_DEVICECHANGE      = $0219;
  DBT_DEVICEARRIVAL    = $8000; // system detected a new device
  DBT_DEVICEQUERYREMOVE = $8001;
  // Preparing to remove (any program can disable the removal)
  DBT_DEVICEREMOVECOMPLETE = $8004; // removed
  DBT_DEVTYP_VOLUME    = $00000002; // drive type is logical volume
 
type
 
  DEV_BROADCAST_VOLUME = record
    dbcv_size:     DWORD;
    dbcv_devicetype: DWORD;
    dbcv_reserved: DWORD;
    dbcv_unitmask: DWORD;
    dbcv_flags:    word;
  end;
 
  PDEV_BROADCAST_VOLUME = ^DEV_BROADCAST_VOLUME;
 
var
  disks: array['A'..'Z'] of boolean;
 
//decode 4 byte (32 bit) to disk letter
function DriveMaskToLetter(mask: integer): char;
const
  drives = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  letter: char;
  cnt:    integer;
  pom:    integer;
begin
  cnt := 0;
  pom := mask div 2;
  while (pom <> 0) do
  begin
    // while there is any bit set in the mask
    // shift it to the righ...
    pom := pom div 2;
    Inc(cnt);
  end;
  if (cnt < Length(drives)) then
    letter := drives[cnt + 1]
  else
    letter := '?';
  Result := letter;
end;
//find all flash drive when we start
procedure TMainForm.FormCreate(Sender: TObject);
var
  c: char;
begin
  for c := 'A' to 'Z' do
    disks[c] := GetDriveType(PAnsiChar(c + ':\')) = DRIVE_REMOVABLE;
  UpdateList;
end;
 
//display disk list in Listbox
procedure TMainForm.UpdateList;
var
  c: char;
begin
  ListBox1.Clear;
  for c := 'A' to 'Z' do
    if disks[c] then
      ListBox1.Items.Add(c + ':\');
end;
 
procedure TMainForm.WMDev(var msg: TMessage);
var
  devType: integer;
  c:   char;
  vol: PDEV_BROADCAST_VOLUME;
begin
  if (msg.Msg = WM_DEVICECHANGE) then
  begin
    // WM_DEVICECHANGE can have several meanings depending on the WParam value...
    case msg.WParam of
      // New device has just arrived
      DBT_DEVICEARRIVAL:
      begin
        vol     := PDEV_BROADCAST_VOLUME(msg.LParam);
        devType := vol.dbcv_devicetype;
        if (devType = DBT_DEVTYP_VOLUME) then
        begin
          // Get the drive letter
          c := DriveMaskToLetter(vol^.dbcv_unitmask);
          disks[c] := True;
          UpdateList;
        end;
      end;
 
      // Device has been removed
      DBT_DEVICEREMOVECOMPLETE:
      begin
        vol     := PDEV_BROADCAST_VOLUME(msg.LParam);
        devType := vol.dbcv_devicetype;
        if (devType = DBT_DEVTYP_VOLUME) then
        begin
          c := DriveMaskToLetter(vol^.dbcv_unitmask);
          disks[c] := False;
          UpdateList;
        end;
      end;
    end;
  end;
end;
//..............Галочка "подтверждения прочтения" - вселенское зло. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |