Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > wnaspi32.dll


Автор: WIN32API 12.5.2006, 16:05
Здравствуйте, уважаемые... Использую wnaspi32.dll. Естественно есть заголовочные файлы к этой библиотеке. Вопрос в том, 
как добавить CD-устройства в ComboBox на чистом WIN32API. У меня есть пример, использующий TObject, а надо без него. Немогу разобрать откуда берется идентификатор, который заносится в TObject при заполнении 

Автор: Rouse_ 12.5.2006, 16:29
На АПИ? Через отпраку управляющей команды CB_ADDSTRING на хэндл ComboBox-а. 

Автор: WIN32API 12.5.2006, 19:14
Цитата

Немогу разобрать откуда берется идентификатор, который заносится в TObject при заполнении  

Єто вопрос для тех, кто работал с wnaspi32.dll без VCL. Мне сложновато сформулировать его правильно... 

Автор: Rouse_ 12.5.2006, 21:10
ComboBox.Handle даст тебе описатель оконного элемента которому необходимо послать сообщение. 

Автор: WIN32API 12.5.2006, 21:40
В чужом примере на VCL в КомбоБокс идет запись:

ComboBox1.Items.AddObject(String, tObject)

В tObject вносится идентификатор СD-устройства типа - 345677.
Откуда он берется и как его мне зацепить? 

Автор: Rouse_ 12.5.2006, 21:58
Тэкс, чуствуется что ты чего-то очень сильно не понимаешь. Здается мне что 345677 это указатель на  область памяти с экземпляром объекта типа ТObject. Давай код чужого примера... 

Автор: WIN32API 13.5.2006, 11:58
Там одна функция тянет за собой другую. Разобратся сложно. Попробую что-то вырезать... 

Автор: WIN32API 14.5.2006, 11:48
Код

var 
 fDevice : TDeviceID;

function ASPIEnumCallBack(lpUserData : pointer; Device : TDeviceID) : boolean;
var SDInfo    : TScsiDeviceInfo;
    HandleFlags,
    DriveInfo : string;
begin
   with TObject(lpUserData) as TForm1 do begin
      SCSIinquiryDeviceInfo(Device, SDInfo, SCSI_DEF);
       DriveInfo := SDInfo.ProductID + '  (' + SDInfo.VendorID + ')';
      HandleFlags := '';
      //Как перевести это на API?
      ComboBox1.Items.AddObject(ScsiDeviceIDtoStr(Device)
                              + '   '
                              + DriveInfo, TObject(Device));
   end;
   Result := True;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 if AspiEnumDevices(TSDCDROM, ASPIEnumCallBack, Form1) > 0 then
  //и это?
  fDevice := TDeviceID(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);
end;
 

Автор: Voyager 14.5.2006, 23:20
Код

//Определение колличества пунктов в ComboBox
function ComboBox_GetItemCount(hComboBox: HWND): Integer;
begin
 Result := SendMessage(hComboBox, CB_GETCOUNT, 0, 0);
end;

//Удаление определенного пункта в ComboBox
procedure ComboBox_DeleteItem(hComboBox: HWND; Index: Integer);
begin
 SendMessage(hComboBox, CB_DELETESTRING, Index, 0);
end;

//Удаление всех пунктов в ComboBox
procedure ComboBox_ClearItems(hComboBox: HWND);
begin
 SendMessage(hComboBox, CB_RESETCONTENT, 0, 0);
end;

//Добавление пункта в ComboBox
procedure ComboBox_AddItem(hComboBox: HWND; NewItem: String);
begin
 SendMessage(hComboBox, CB_ADDSTRING, 0, Integer(NewItem));
end;

//Добавление пункта в определенное место в ComboBox
procedure ComboBox_InsertItem(hComboBox: HWND; Index: Integer; NewItem: String);
begin
 SendMessage(hComboBox, CB_INSERTSTRING, Index, Integer(NewItem));
end;

//Определение имени выбранного пункта в ComboBox
function ComboBox_GetSelectedItem(hComboBox: HWND): string;
var
 Index, len: Integer;
 s: string;
 buffer: PChar;
begin
 Index := SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
 len := SendMessage(hComboBox, CB_GETLBTEXTLEN, wParam(Index), 0);
 GetMem(buffer, len + 1);
 SendMessage(hComboBox, CB_GETLBTEXT, wParam(Index), lParam(buffer));
 SetString(s, buffer, len);
 FreeMem(buffer);
 Result := s;
end;

//Определение номера выбранного пункта в ComboBox
function ComboBox_GetCountSelectedItem(hComboBox: HWND): Integer;
var
 Index, len: Integer;
 s: string;
 buffer: PChar;
begin
 Index := SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
 len := SendMessage(hComboBox, CB_GETLBTEXTLEN, wParam(Index), 0);
 GetMem(buffer, len + 1);
 SendMessage(hComboBox, CB_GETLBTEXT, wParam(Index), lParam(buffer));
 SetString(s, buffer, len);
 FreeMem(buffer);
 Result := Index;
end;

//Определение имени пункта по номеру в ComboBox
function ComboBox_GetItem(hComboBox: HWND; LbItem: Integer): string;
var
 l: Integer;
 buffer: PChar;
begin
 l := SendMessage(hComboBox, CB_GETLBTEXTLEN, LbItem, 0);
 GetMem(buffer, l + 1);
 SendMessage(hComboBox, CB_GETLBTEXT, LbItem, Integer(buffer));
 Result := StrPas(buffer);
 FreeMem(buffer);
end;

//Выбор пункта в ComboBox по счету
procedure ComboBox_SelectedItem(hComboBox: HWND; Index: Integer);
begin
 SendMessage(hComboBox, CB_SETCURSEL, Index, 0);
end;

//Выбор пункта в ComboBox по имени
procedure ComboBox_SelectedString(hComboBox: HWND; Text: String);
begin
 SendMessage(hComboBox, CB_SELECTSTRING, 0, Integer(Text));
end;

//Открытие пунктов ComboBox
procedure ComboBox_OpenItems(hComboBox: HWND);
begin
 SendMessage(hComboBox, CB_SHOWDROPDOWN, Integer(True), 0);
end;


 

Автор: WIN32API 15.5.2006, 14:53
Да это все понятно. Внимательно на код посмотрите. Там добавляется TObject(Device)???????????????

Код

ComboBox1.Items.AddObject(ScsiDeviceIDtoStr(Device)
                              + '   '
                              + DriveInfo, TObject(Device));
 

Автор: Rouse_ 16.5.2006, 09:43
Это указатель на экземпляр класса...
В твоем случе 
Код

SendMessage(ComboboxHandle, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));

А берется он отседова: SCSIinquiryDeviceInfo
Получить обратно экземпляр:
Код

type
  PObject = ^TObject;
var
  Object: TObject;
begin
  Object := PObject(SendMessage(ComboboxHandle, CB_GETITEMDATA, ItemIndex, 0)^;
 

Автор: WIN32API 16.5.2006, 12:11
На основе кода от Rouse_  и  Voyager я сделал следующее, но где-то допустил ошибку и чувствую, что не одну.... 

Код

var
 CD_ROM_DEVICE: TDeviceID; //сидюк
 Combobox1: HWND; //комбобокс
 ItemIndex: Integer;

function ASPIEnumCallBack(lpUserData : pointer; Device : TDeviceID) : boolean;
var
 SDInfo: TScsiDeviceInfo;
 DriveInfo: string;
begin
 SCSIinquiryDeviceInfo(Device, SDInfo, SCSI_DEF);
 DriveInfo := SDInfo.ProductID + '   (' + SDInfo.VendorID + ')';
 ComboBox_AddItem(combobox1, DriveInfo); //добавляем сидюки в комбобокс
  //Допустим, сидюков 10 или ItemIndex играет другую роль??????
  for ItemIndex := 1 to High(10) do
   SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));
 Result := True; //to continue scanning
end;

function DlgProc(hWin: HWND; uMsg: UINT; wp: WPARAM; lp: LPARAM): bool; stdcall;
begin
 Result := False;
  case uMsg of
   WM_INITDIALOG:
    begin
     combobox1 := GetDlgItem(hWin, 11);
      if AspiEnumDevices(TSDCDROM, @ASPIEnumCallBack, @hWin) > 0 then
       ComboBox_SelectedItem(combobox1, 0);
     //Получаем устройство
     CD_ROM_DEVICE := TDeviceID(SendMessage(combobox1, CB_GETITEMDATA, ComboBox_GetCountSelectedItem(combobox1), 0));
    end;
  WM_COMMAND:
   case LoWord(wp) of
    30: SCSIstartStopUnit(CD_ROM_DEVICE, False, True, True, SCSI_DEF); //Open CD Door
    31: SCSIstartStopUnit(CD_ROM_DEVICE, True, True, True, SCSI_DEF); //Close CD Door
   end;
   //При нажатии на кнопку "Х" в шапке программы закрываем приложение
   WM_DESTROY, WM_CLOSE: PostQuitMessage(0);
 end;
end;
 

Автор: Rouse_ 16.5.2006, 12:52
ItemIndex это индекс элемента с которым ты хочешь асоцииорвать информацию.
В твоем коде, ты добавляешь один единственный элемент, его индекс ноль
Соответственно вот этот код не имеет смысла, т.к. элементов с такими индексами не существует:
Код

  for ItemIndex := 1 to High(10) do
   SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));

Вот этот ко также не верен, т.к. ты читаешь адрес указателя, а тебе нужно читать данные по этому указателю:
Код

TDeviceID(SendMessage(combobox1, CB_GETITEMDATA, ComboBox_GetCountSelectedItem(combobox1), 0));
 

Автор: WIN32API 16.5.2006, 13:01
Так как же сделать то???????????????? Помогите!  smile  

Автор: WIN32API 17.5.2006, 10:44
С добавление вроде разобрался???? А вот с чтение траблы. Помогите.!!!!


Код

type
  PObject = ^TObject;

var
 CD_ROM_DEVICE: TDeviceID; //сидюк
 Combobox1: HWND; //комбобокс
 ItemIndex: Integer;
 _Object: TObject;

function ASPIEnumCallBack(lpUserData : pointer; Device : TDeviceID) : boolean;
var
 SDInfo: TScsiDeviceInfo;
 DriveInfo: string;
begin
 SCSIinquiryDeviceInfo(Device, SDInfo, SCSI_DEF);
 DriveInfo := SDInfo.ProductID + '   (' + SDInfo.VendorID + ')';
 
  ItemIndex := SendMessage(ComboBox1, CB_ADDSTRING, 0, Integer(DriveInfo));
 for ItemIndex := 0 to ComboBox_GetItemCount(combobox1) - 1 do
   SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));

 Result := True; //to continue scanning
end;

//Функция, обрабатывающая все команды от элементов управления окна
function DlgProc(hWin: HWND; uMsg: UINT; wp: WPARAM; lp: LPARAM): bool; stdcall;
begin
 Result := False;
  case uMsg of
   WM_INITDIALOG:
    begin
     combobox1 := GetDlgItem(hWin, 11);
      if AspiEnumDevices(TSDCDROM, @ASPIEnumCallBack, @hWin) > 0 then
       ComboBox_SelectedItem(combobox1, 0);
  //Вот здесь Рантайм эррор...
     _Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;

............
 

Автор: Rouse_ 17.5.2006, 15:01
чему равен ItemIndex на момент вызова данной функции:
Код

_Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
 

Автор: WIN32API 17.5.2006, 15:53
На момент вызова 
_Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
прога вылетает. (Рантайм эррор)

Добавлено @ 15:57 
Стоп. я понял вопрос. 
ItemIndex должен зацепить текущий выбранный пункт, а потом уже:
_Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
Или я ошибаюсь? 

Автор: Rouse_ 17.5.2006, 16:51
угу smile 
вообщето ItemIndex должен быть номером существующего итема... Не важно, выбран он или нет 

Автор: WIN32API 17.5.2006, 17:34
Так?
ItemIndex = SendMessage(Combobox1, CB_GETCURSEL, 0, 0);

Если нет, то как его определить? 

Автор: Rouse_ 17.5.2006, 17:59
да, это тебе вернет текущий выбранный элемент... 

Автор: WIN32API 18.5.2006, 10:03
CD_ROM_DEVICE в любом случае возвращает один и тот же идентификатор. какое бы устройство в комбобоксе я не выбрал, получается одно и то же. При этом я правильно обрабатываю сообщение, которое отвечает за изменения в комбобоксе. может, ошибка при добавлении - CB_SETITEMDATA?

Код

var
 CD_ROM_DEVICE: TDeviceID;
 Combobox1: HWND;
 ItemIndex: Integer;

function ASPIEnumCallBack(lpUserData : pointer; Device : TDeviceID) : boolean;
var
 SDInfo: TScsiDeviceInfo;
 DriveInfo: string;
begin
 SCSIinquiryDeviceInfo(Device, SDInfo, SCSI_DEF);
 DriveInfo := SDInfo.ProductID + '   (' + SDInfo.VendorID + ')';

 ItemIndex := SendMessage(ComboBox1, CB_ADDSTRING, 0, Integer(DriveInfo));
 SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));

 Result := True; //to continue scanning
end;

.............

WM_INITDIALOG:
 begin
  combobox1 := GetDlgItem(hWin, 11);
   if AspiEnumDevices(TSDCDROM, @ASPIEnumCallBack, @hWin) > 0 then begin
     ComboBox_SelectedItem(combobox1, 0);
         ItemIndex = SendMessage(Combobox1, CB_GETCURSEL, 0, 0);
         _Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
        CD_ROM_DEVICE := TDeviceID(_Object);
      ebd;
    end;

.............

 

Автор: WIN32API 18.5.2006, 10:31
Хочу заметить, что получаемый идентификатор неверный, т.к. немогу управлять устройством. 

Автор: Rouse_ 18.5.2006, 11:38
Естественно он вернет тебе один и тот же обьект, потомучто ты после добавление нового элемента назначешь обьект связанный с ним всем существующим элементам, затирая их предыдущее значение:
Код

 for ItemIndex := 0 to ComboBox_GetItemCount(combobox1) - 1 do
   SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));
 

Автор: WIN32API 18.5.2006, 19:44
Все равно получаю один и тот же идентификатор, который так и неработает.

Код

type
  PObject = ^TObject;

var
 CD_ROM_DEVICE: TDeviceID; //type TdeviceID  = type DWORD;
 Combobox1: HWND;
 ItemIndex: Integer;
 _Object: TObject;

function ASPIEnumCallBack(lpUserData : pointer; Device : TDeviceID) : boolean;
var
 SDInfo: TScsiDeviceInfo;
 DriveInfo: string;
begin
 SCSIinquiryDeviceInfo(Device, SDInfo, SCSI_DEF);
 DriveInfo := SDInfo.ProductID + '   (' + SDInfo.VendorID + ')';
 ItemIndex := SendMessage(ComboBox1, CB_ADDSTRING, 0, Integer(DriveInfo));
  for ItemIndex := 0 to ComboBox_GetItemCount(ComboBox1) -1 do
   SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(@TObject(Device)));
 Result := True; //to continue scanning
end;

function DlgProc(hWin: HWND; uMsg: UINT; wp: WPARAM; lp: LPARAM): bool; stdcall;
begin
 Result := False;
  case uMsg of
   WM_INITDIALOG:
    begin
     combobox1 := GetDlgItem(hWin, 11);
      if AspiEnumDevices(TSDCDROM, @ASPIEnumCallBack, @hWin) > 0 then
       ComboBox_SelectedItem(combobox1, 0);
     ItemIndex := SendMessage(Combobox1, CB_GETCURSEL, 0, 0);
     _Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
     CD_ROM_DEVICE := TDeviceID(_Object);
    end;
  WM_COMMAND:
   begin
    case HIWORD(wp) of
     //При изменениях в Combobox1 меняем устройство - CD_ROM_DEVICE
     CBN_SELCHANGE:
      begin
       ItemIndex := SendMessage(Combobox1, CB_GETCURSEL, 0, 0);
       _Object := PObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0))^;
       CD_ROM_DEVICE := TDeviceID(_Object);
       //messagebox(0,pchar(inttostr(CD_ROM_DEVICE)),'',0);
      end;
    end;
    //Обработка кнопок на диалоговом окне
    case LoWord(wp) of
     30: SCSIstartStopUnit(CD_ROM_DEVICE, False, True, True, SCSI_DEF); //Open CD Door
     31: SCSIstartStopUnit(CD_ROM_DEVICE, True, True, True, SCSI_DEF); //Close CD Door
      1: EndDialog(hWin, 0);
    end;
   end;
  WM_DESTROY, WM_CLOSE: PostQuitMessage(0);
 end;
end;
 

Автор: Rouse_ 19.5.2006, 11:09
Блин, чудак человек, закоментируй вот эту строку:
Код

for ItemIndex := 0 to ComboBox_GetItemCount(ComboBox1) -1 do
 

Автор: WIN32API 19.5.2006, 11:50
Да тоже самое. Я уже запахался честно говоря... 

Автор: Rouse_ 19.5.2006, 13:22
Что тоже самое? Для всех элементов один и тот же обьект возвращается или теперь они разные? 

Автор: WIN32API 19.5.2006, 17:34
Для всех элементов один и тот же обьект возвращается!!! Бред какой-то... 

Автор: Rouse_ 22.5.2006, 08:09
Давай сюда проект... 

Автор: WIN32API 23.5.2006, 08:44
Мой проект можно закачать по адресу:
http://depositfiles.com/files/70083/Wnaspi32.rar.html 

Автор: Rouse_ 23.5.2006, 13:38
Делай так:

Код

SendMessage(combobox1, CB_SETITEMDATA, ItemIndex, Integer(Device));

_Object := TObject(SendMessage(Combobox1, CB_GETITEMDATA, ItemIndex, 0));
 

Автор: WIN32API 23.5.2006, 22:46
Огромнейшее спасибо!

И чтобы подитожить все, я хотел бы узнать, то, что возврашает _Object в данном случае может менятся? Мне интерестно будет ли он другим, если пользователь подключит или отключит еще один сидюк? Знать это полезно, если надо будет запоминать выбранное устройство, например, в реестре. 

Автор: Rouse_ 24.5.2006, 09:35
Конечно будет меняться - это значение действительно только от момента создания обьекта до его разрушения, если создать такойже обьект после разрушения то число будет другим... 

Автор: WIN32API 24.5.2006, 18:56
Сенкс!!!!
На этом можно считать тему закрытой. 

Автор: ShEriF 30.5.2006, 21:28
Привет всем, а можно мне примерчик добавления названий CD-ROMs , как в демке от WIN32API. тока написанный на Delphi v7 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)