Ejecting CDRom Drive without hardcoding drive letter using Win32 Visual C++

早过忘川 提交于 2021-01-29 06:11:48

问题


I am trying to eject my CDRom Drive at the click of a button. This works when the CDRom drive letter is hardcoded, but I am wanting to do it without hardcoding the CDRom Drive. If I find the CDRom drive on my computer and save it to 'TCHAR drive_letter', how can I pull that in to the code below? For some reason, it does not allow me to do 'EjectCdTray(drive_letter);'. The code is shown below:

#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)&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)&mciSetParms);
    
    // Close device ID
    mciFlags = MCI_WAIT;
    MCI_GENERIC_PARMS mciGenericParms = { 0 };
    mciError = mciSendCommand(mciOpenParms.wDeviceID, 
        MCI_CLOSE, mciFlags, (DWORD_PTR)&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] = '\0';
            }
            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:


First declare the drive_letter variable,

TCHAR drive_letter;

According to your needs, create a function that needs to get the drive letter, and then pass the value to it.

drive_letter = Get_driverletter();

This line, // TCHAR drive_letter = L"D";

It should be 'D'.

"D" => string

'D' => character

Updated:

Do you mean this?

 TCHAR drive_letter[100] = L"D";

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



回答2:


MCI_OPEN_PARMS::lpstrElementName expects a null-terminated string, but you are not giving it that. You are converting the single character into a character array without a null terminated added to it.

Try setting the elementName like this instead:

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

Or:

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

And then, you need to call the function like this instead:

EjectCdTray(drive_letter[0]);

Otherwise, change your function to accept the entire drive path as a string, don't reduce it to a single character at all:

...
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;
}


来源:https://stackoverflow.com/questions/65715553/ejecting-cdrom-drive-without-hardcoding-drive-letter-using-win32-visual-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!