C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Открыть и закрыть привод CD-DVD
Grigoriy
Отправлено: 16.03.2006, 17:46


Мастер участка

Группа: Участник
Сообщений: 381



Вот узнал, что есть библиотека winmm.dll
и в ней есть функция позволяющая открыть и закрыть привод CD-DVD.

mciSendStringA

Я реализовал пример использования этой функции так
CODE

//---------------------------------------------------------------------------
TForm1 *Form1;
char* strb ="Set cdaudio door open\0";
char* str1 ="Set cdaudio door closed\0";
HINSTANCE a;
void* h;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
a=LoadLibrary("winmm.dll");
h=GetProcAddress(a,"mciSendStringA");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
asm
{
push 0;
push 0;
push 0;
push strb;
call h;
};
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
asm
{
push 0;
push 0;
push 0;
push str1;
call h;
};
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
FreeLibrary(a);
}


Но на моем компьютере два привода и открывается и закрывается только один из них.
А как то же самое проделать со вторым ?
Gal
Отправлено: 16.03.2006, 18:39


Станционный диспетчер

Группа: Участник
Сообщений: 124



Для начала определим вспомогательные переменные и функции, которые облегчат передачу команд:
CODE

#include <mmsystem.h>
#include <stdio.h>
#pragma comment(lib,"winmm.lib")

/* Команды */
char * CdCmdSet = "set";
char * CdCmdStatus = "status";
char * CdCmdPlay = "play";
char * CdCmdPause = "pause";
char * CdCmdStop = "stop";
char * CdCmdResume = "resume";

/* Флаги команд */
char * CdCmdFlagOpen = "door open";
char * CdCmdFlagClose = "door closed";
char * CdCmdCurTrack = "current track";
char * CdCmdCurMode = "mode";
char * CdCmdFlagEmpty = "";

/* Флаги выполнения */
char * CdFlagWait = "wait";
char * CdFlagEmpty = "";

/* Буфер, в котором будем создавать команды */
char CdCommandBuffer[256];

/* Создание команды без указания имени CD-ROM'а */
char * CreateCdCommand(char * pBuffer, char * pCommand, char * pCmdFlags, char * pFlags) {
  sprintf(pBuffer,"%s cdaudio %s %s",pCommand,pCmdFlags,pFlags);
  return pBuffer;
}

/* Создание команды с указанием имени CD-ROM'а */
char * CreateCdCommandEx(char * pBuffer, char DriveLetter, char * pCommand, char * pCmdFlags, char * pFlags) {
  sprintf(pBuffer,"%s cdaudio!%c: %s %s",pCommand,DriveLetter,pCmdFlags,pFlags);
  return pBuffer;
}


Теперь, используя вспомогательные функции и переменные, отдавать команды управления CD-ROM'ом не просто, а очень просто.

1.Открыть CD-ROM, ожидая выполнения этой команды:

CODE

mciSendStringA(CreateCdCommand(CdCommandBuffer,CdCmdSet,CdCmdFlagOpen,CdFlagWait),
 NULL,
 0,
 INVALID_HANDLE_VALUE);

2.
CODE

mciSendStringA(CreateCdCommand(CdCommandBuffer,CdCmdSet,CdCmdFlagClose,CdFlagWait),
 NULL,
 0,
 INVALID_HANDLE_VALUE);


Если в системе присутствует несколько приводов CD, то для задания конкретного привода вместо функции CreateCdCommand следует использовать CreateCdCommandEx.


Отредактировано Gal — 16/03/2006, 18:45
Павел
Отправлено: 16.03.2006, 23:03


Не зарегистрирован







У меня есть пара исходников, но они на Delphi, если надо могу скинуть
Grigoriy
Отправлено: 16.03.2006, 23:38


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (Павел @ 16/03/2006, 23:03)
У меня есть пара исходников, но они на Delphi, если надо могу скинуть

Я хотел разобраться на каком принципе формируются строки от
CreateCdCommand

Кстати, а что означают остальные три опреранда функции
mciSendStringA
?
Grigoriy
Отправлено: 17.03.2006, 03:05


Мастер участка

Группа: Участник
Сообщений: 381



Что возвращает функция
mciSendStringA
?
Как использовать команду
status
?
Gal
Отправлено: 17.03.2006, 12:18


Станционный диспетчер

Группа: Участник
Сообщений: 124



function mciSendStringA(lpstrCommand, lpstrReturnString: PChar; uReturnLength: UINT; hWndCallback: HWND): MCIERROR;

Посылает командную строку для MCI-устройства.

lpstrReturnString — Строка возврата информации об исполнении команды
uReturnLength — Размер буфера исполняемой строки
hWndCallback — Хендл (Handle) окна для возврата сообщения о событии, если это оговорено в посылаемой команде.

Возвpащаемое значение: В случае успеха 0, или ошибку в противном случае. Младшее слово возвращаемой величины содержит код ошибки. Если ошибка вызвана устройством, то старшее слово возвращаемой величины, является идентификатором драйвера, в противном случае равно 0. Получить строку с ошибкой, можно с помощью функции mciGetErrorString.

См. также mciSendCommand

Функция находится в файле winmm.dll

Отредактировано Gal — 17/03/2006, 12:19
X-Phantom
Отправлено: 24.03.2007, 08:43


Ученик-кочегар

Группа: Участник
Сообщений: 3



CODE

void __fastcall TForm1::Button1Click(TObject *Sender)
{
char res[256];
mciSendString("status cdaudio mode",res,256,Handle);
Label1->Caption=res;
}


Почему в независимости от того, открыт или закрыт привод, функция всегда возвращает open?
Gedeon
Отправлено: 24.03.2007, 12:35


Ветеран

Группа: Модератор
Сообщений: 1742



Вот моя прожка для открытия/закрытия любых приводов, определяет приводы, на форме для каждого рисует пару кнопок: откр./закр. ну и собственно работает.
CODE

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{

   #define BUFSIZE 512
   TCHAR szTemp[BUFSIZE];

   static int i = 15;
   if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
   {
    TCHAR szDrive[3] = TEXT(" :");
       BOOL bFound = FALSE;
       TCHAR* p = szTemp;

       do
       {
           // Copy the drive letter to the template string
           *szDrive = *p;

           if(GetDriveType(szDrive)==DRIVE_CDROM)
           {
            TButton *btn = new TButton(this);
               btn->Top = i;
               btn->Width = 40;
               btn->Caption = szDrive;
               btn->Parent = this;
               btn->OnClick = btn1Click;

               btn = new TButton(this);
               btn->Left = 41;
               btn->Top = i;
               btn->Width = 40;
               btn->Caption = szDrive;
               btn->Parent = this;
               btn->OnClick = btn2Click;

               i=i+25;
           }

           // Go to the next NULL character.
        while (*p++);
       } while (!bFound && *p); // end of string
   }
   this->Height = i+27;
   this->Width = 87;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::btn1Click(TObject *Sender)
{
   TButton *btn = dynamic_cast<TButton*> (Sender);

   DriveLetter = "\\\\.\\" + btn->Caption;
hCDDevice = CreateFile(DriveLetter.c_str(),
                                                  GENERIC_READ,
                                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
                                                   NULL,
                                                   OPEN_EXISTING,
                                                   FILE_ATTRIBUTE_NORMAL,
                                                  0);
   if(hCDDevice!=INVALID_HANDLE_VALUE)
   {
    DeviceIoControl(hCDDevice,/*IOCTL_DISK_EJECT_MEDIA*/0x074808,NULL,0,NULL,0,&lpBytesReturned,NULL);
   CloseHandle(hCDDevice);
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btn2Click(TObject *Sender)
{
   TButton *btn = dynamic_cast<TButton*> (Sender);
   DriveLetter = "\\\\.\\" + btn->Caption;

hCDDevice = CreateFile(DriveLetter.c_str(),
                                                  GENERIC_READ,
                                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
                                                   NULL,
                                                   OPEN_EXISTING,
                                                   FILE_ATTRIBUTE_NORMAL,
                                                  0);
   if(hCDDevice!=INVALID_HANDLE_VALUE)
   {
    DeviceIoControl(hCDDevice,/*IOCTL_DISK_LOAD_MEDIA*/0x07480C,NULL,0,NULL,0,&lpBytesReturned,NULL);
   CloseHandle(hCDDevice);
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{

for(int i=0; i<this->ComponentCount; i++)
   {

    TButton *btn = dynamic_cast<TButton*> (this->Components[i]);
       if(btn)
       {
        delete btn;
           i=0; // так как кол-во компонентов изменилось, то цикл проходим заново
       }
   }
}
//---------------------------------------------------------------------------

Полностью готовый и рабочий код.
ЗЫ. Была написана т.к. комп на балконе — бегать харит.
aquanet sk
Отправлено: 24.03.2007, 13:12


Станционный диспетчер

Группа: Участник
Сообщений: 87



Могу кинуть и свой исходник (смиксован с примера Билдера и примера из инета), если подойдет принцип работы (см. exe`шник)

User Attached Image Скачать файл
CyDexAqua.exe


X-Phantom
Отправлено: 24.03.2007, 18:55


Ученик-кочегар

Группа: Участник
Сообщений: 3



А как узнать текущее состояние привода, открыт он или закрыт?

Кстати написал прожку на основе кода Gal'а. Кому интересно, вот она Drive Manager v.1.1 (343 KB)

Поддерживает максимум два привода (не уверен, что у кого-либо больше, не считая виртуалок)

Отредактировано X-Phantom — 25.03.2007, 22:23

Вернуться в Вопросы программирования в C++Builder