使用 Win32 Visual C++ 在没有硬编码驱动器号的情况下弹出 CDrom 驱动器

问题描述

我试图通过单击按钮弹出我的 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)&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,(DWORD_PTR)&mciSetParms);
    
    // Close device ID
    mciFlags = MCI_WAIT;
    MCI_GENERIC_PARMS mciGenericParms = { 0 };
    mciError = mciSendCommand(mciOpenParms.wdeviceid,MCI_CLOSE,(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;
}

解决方法

MCI_OPEN_PARMS::lpstrElementName 需要一个以空字符结尾的字符串,但你没有给它。您正在将单个字符转换为字符数组,而未添加空终止符。

尝试像这样设置 elementName

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

或者:

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

然后,你需要像这样调用函数:

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