Извлечение диска CDRom без жесткого кодирования буквы диска с помощью Win32 Visual C

#variables #winapi #visual-c #drive #tchar

#переменные #winapi #visual-c #привод #tchar

Вопрос:

Я пытаюсь извлечь свой диск CDRom одним нажатием кнопки. Это работает, когда буква диска CDRom жестко задана, но я хочу сделать это без жесткого кодирования диска CDRom. Если я найду диск CDRom на своем компьютере и сохраню его в ‘TCHAR drive_letter’, как я могу включить это в приведенный ниже код? По какой-то причине это не позволяет мне выполнять ‘EjectCdTray (drive_letter);’. Код приведен ниже:

 #include <tchar.h>
#include <windows.h>
#include <mmsystem.h> // for MCI functions

// Link to winmm.lib (usually included in project settings)
#pragma comment(lib, "winmm")
#define BUTTON                  3456
LPWSTR pBuf = buf;
DWORD chrCopied = GetLogicalDriveStrings(BUF_SIZE - 1, buf);
TCHAR drive_letter[200];


void ControlCdTray(TCHAR drive, DWORD command)
{
    // Not used here, only for debug
    MCIERROR mciError = 0;

    // Flags for MCI command
    DWORD mciFlags = MCI_WAIT | MCI_OPEN_SHAREABLE | 
        MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT;

    // Open drive device and get device ID
    TCHAR elementName[] = { drive };
    MCI_OPEN_PARMS mciOpenParms = { 0 };
    mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
    mciOpenParms.lpstrElementName = elementName;    
    mciError = mciSendCommand(0, 
        MCI_OPEN, mciFlags, (DWORD_PTR)amp;mciOpenParms);

    // Eject or close tray using device ID
    MCI_SET_PARMS mciSetParms = { 0 };
    mciFlags = MCI_WAIT | command; // command is sent by caller
    mciError = mciSendCommand(mciOpenParms.wDeviceID, 
        MCI_SET, mciFlags, (DWORD_PTR)amp;mciSetParms);
    
    // Close device ID
    mciFlags = MCI_WAIT;
    MCI_GENERIC_PARMS mciGenericParms = { 0 };
    mciError = mciSendCommand(mciOpenParms.wDeviceID, 
        MCI_CLOSE, mciFlags, (DWORD_PTR)amp;mciGenericParms);
}

// Eject drive tray
void EjectCdTray(TCHAR drive)
{
    ControlCdTray(drive, MCI_SET_DOOR_OPEN);
}

// Retract drive tray
void CloseCdTray(TCHAR drive)
{
    ControlCdTray(drive, MCI_SET_DOOR_CLOSED);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
    {
        while (chrCopied)
        {
            if (DRIVE_CDROM == GetDriveType(pBuf))
            {
                wsprintf(drive_letter, L"%s", pBuf);
                size_t indexOfNull2 = _tcslen(drive_letter);
                drive_letter[indexOfNull2 - 2] = '';
            }
            size_t len = _tcslen(buf);
            chrCopied -= len   1;
            pBuf  = len   1;
        }

        HWND hwndButton = CreateWindow(
            L"BUTTON",  // Predefined class; Unicode assumed 
            L"EJECT",   // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
            180,         // x position 
            200,        // y position 
            100,        // Button width
            100,        // Button height
            hWnd,     // Parent window
            (HMENU)BUTTON,       // No menu.
            (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
            NULL);      // Pointer not needed.
    }

    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case BUTTON:
            EjectCdTray(drive_letter);            // TCHAR drive_letter = L"D";
            MessageBox(NULL, L"Please insert a CD ROM in the CD tray.", L"CD ROM Drive", 0);

            break;
        }
    }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
 

Ответ №1:

Сначала объявите drive_letter переменную,

 TCHAR drive_letter;
 

В соответствии с вашими потребностями создайте функцию, которая должна получить букву диска, а затем передать ей значение.

 drive_letter = Get_driverletter();
 

Эта строка, // TCHAR drive_letter = L"D";

Это должно быть ‘D’.

«D» => строка

‘D’ => символ

Обновлено:

Вы это имеете в виду?

  TCHAR drive_letter[100] = L"D";

 EjectCdTray(drive_letter[0]);            // TCHAR drive_letter = L"D";
 

Комментарии:

1. переменная, которая у меня есть, — это не символ, это массив, в котором есть и другие символы, но я сокращаю его, чтобы просто получить букву. У меня возникли проблемы с пониманием того, как ‘drive_letter = Get_driverletter();’ может передавать значение в ‘EjectCdTray (drive_letter);’ потому что EjectCdTray () принимает только букву, а не какие-либо переменные. Я уже получаю букву диска и сохраняю ее в TCHAR. Я просто не уверен, как использовать это в функции EjectCdTray().

2. @Alyssa хорошо, больше деталей — это хорошо. Смотрите мои обновленные.

3. Пожалуйста, ознакомьтесь с моим обновленным. Я показал, как я получил drive_letter.

4. @Alyssa EjectCdTray(drive_letter) => EjectCdTray(drive_letter[0]) , и попробуйте еще раз.

Ответ №2:

MCI_OPEN_PARMS::lpstrElementName ожидает строку с нулевым завершением, но вы этого не даете. Вы преобразуете один символ в массив символов без добавления к нему завершающегося нулем.

Попробуйте установить elementName вместо этого следующее:

 TCHAR elementName[] = TEXT("?:\");
elementName[0] = drive;
 

Или:

 TCHAR elementName[] = { drive, TEXT(':'), TEXT('\'), TEXT('') );
 

И затем вам нужно вызвать функцию следующим образом:

 EjectCdTray(drive_letter[0]);
 

В противном случае измените свою функцию так, чтобы она принимала весь путь к диску в виде строки, а не сокращала его до одного символа вообще:

 ...
TCHAR drive_path[MAX_PATH] = {};

void ControlCdTray(LPCTSTR drive, DWORD command)
{
    ...
    mciOpenParms.lpstrElementName = drive;
    ...
}

void EjectCdTray(LPCTSTR drive)
{
    ControlCdTray(drive, MCI_SET_DOOR_OPEN);
}

void CloseCdTray(LPCTSTR drive)
{
    ControlCdTray(drive, MCI_SET_DOOR_CLOSED);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    ...
    wsprintf(drive_path, L"%s", pBuf);
    EjectCdTray(drive_path); // TCHAR drive_path[] = L"D:";
    ...
    return 0;
}