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