/*----------------------------------------
TESTMCI.C -- 交谈式输入MCI命令
(c) Charles Petzold, 1998
----------------------------------------*/
#include <windows.h>
#include "resource.h"
#define ID_TIMER 1
BOOL CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName [] = TEXT ("TestMci") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
if (-1 == DialogBox (hInstance, szAppName, NULL, DlgProc))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
}
return 0 ;
}
BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndEdit ;
int iCharBeg, iCharEnd, iLineBeg, iLineEnd, iChar, iLine, iLength ;
MCIERROR error ;
RECT rect ;
TCHAR szCommand [1024], szReturn [1024],
szError [1024], szBuffer [32] ;
switch (message)
{
case WM_INITDIALOG: // 对话框建立时
// 获取对话框大小
GetWindowRect (hwnd, &rect) ;
// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序
SetWindowPos (hwnd, NULL,
// 获取屏幕宽度 - 窗口右边坐标 + 窗口左边坐标 = 减去程序窗口后屏幕所剩宽度 / 2
// 该参数用于定位窗口水平位置(上面的算法使窗口水平居中)
(GetSystemMetrics (SM_CXSCREEN) - rect.right + rect.left) / 2,
// 使窗口垂直居中
(GetSystemMetrics (SM_CYSCREEN) - rect.bottom + rect.top) / 2,
// 0,0 这两个参数用于改变窗口大小
// SWP_NOZORDER 维持当前Z序(忽略参数二)
// SWP_NOSIZE 维持当前尺寸(忽略之前两个参数)
0, 0, SWP_NOZORDER | SWP_NOSIZE) ;
// 索检对话框中的文字编辑控件的句柄
hwndEdit = GetDlgItem (hwnd, IDC_MAIN_EDIT) ;
// 使文字输入控件具有键盘焦点
SetFocus (hwndEdit) ;
// 向windows传回FALSE,这告诉系统不用设置焦点
return FALSE ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDOK:
// Find the line numbers corresponding to the selection
// 向文字编辑控件发送EM_GETSEL消息,获取当前选择的字符开始和结尾的偏移量
// 如果没有选取任何字符,则缓冲区中记录的是当前插入符的位置
SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iCharBeg,
(LPARAM) &iCharEnd) ;
// EM_LINEFROMCHAR 消息获取文字编辑控件中 wParam 参数位置所在的行号,从零开始
iLineBeg = SendMessage (hwndEdit, EM_LINEFROMCHAR, iCharBeg, 0) ;
iLineEnd = SendMessage (hwndEdit, EM_LINEFROMCHAR, iCharEnd, 0) ;
// 遍历选择的所有行
for (iLine = iLineBeg ; iLine <= iLineEnd ; iLine++)
{
// Get the line and terminate it; ignore if blank
* (WORD *) szCommand = sizeof (szCommand) / sizeof (TCHAR) ;
// EM_GETLINE 消息复制一行字符到指定的缓冲区中,返回复制的字符数
iLength = SendMessage (hwndEdit, EM_GETLINE, iLine,
(LPARAM) szCommand) ;
szCommand [iLength] = '/0' ;
// 如果该行为空,则立刻执行下一次循环迭代
if (iLength == 0)
continue ;
/* 向MCI发送命令
szCommand 指向以null结尾的命令字符串:"命令 设备[ 参数]"
szReturn 指向接收返回信息的缓冲区,为NULL时不返回信息
参数三 指出接收返回信息的缓冲区的大小
hwnd 在命令串中含notify时,它指定一个回调窗口的句柄 */
error = mciSendString (szCommand, szReturn,
sizeof (szReturn) / sizeof (TCHAR), hwnd) ;
// 将返回信息显示在IDC_RETURN_STRING控件中
SetDlgItemText (hwnd, IDC_RETURN_STRING, szReturn) ;
// 获取错误字符串字段(即使没有错误)
mciGetErrorString (error, szError,
sizeof (szError) / sizeof (TCHAR)) ;
// 输出错误信息在IDC_ERROR_STRING控件中
SetDlgItemText (hwnd, IDC_ERROR_STRING, szError) ;
}
// Send the caret to the end of the last selected line
// 获取iLineEnd行号的第一个字符在编辑控件中以零开始的偏移量
iChar = SendMessage (hwndEdit, EM_LINEINDEX, iLineEnd, 0) ;
// EM_LINELENGTH 消息获取iCharEnd 字符所在行的字符长度
iChar += SendMessage (hwndEdit, EM_LINELENGTH, iCharEnd, 0) ;
// 由于最后两个参数一样,所以只是设置插入符的位置到用户选择的字符所在行的下一行
SendMessage (hwndEdit, EM_SETSEL, iChar, iChar) ;
// EM_REPLACESEL 消息替换当前选中的字符
// FALSE 表示替换的字符不可撤销
// 由于当前未选中字符,所以只是插入了一个换行符
// /r 是回车,return /n 是换行,newline (历史遗留问题)
SendMessage (hwndEdit, EM_REPLACESEL, FALSE,
(LPARAM) TEXT ("/r/n")) ;
SetFocus (hwndEdit) ;
return TRUE ;
case IDCANCEL:
EndDialog (hwnd, 0) ;
return TRUE ;
case IDC_MAIN_EDIT:
// 无法分配足够的内存来满足特定的要求时
if (HIWORD (wParam) == EN_ERRSPACE)
{
MessageBox (hwnd, TEXT ("Error control out of space."),
szAppName, MB_OK | MB_ICONINFORMATION) ;
return TRUE ;
}
break ;
}
break ;
// 当mciSendString函数传回控制权后,如果指定notify标记,则收到此消息
case MM_MCINOTIFY:
// 使IDC_NOTIFY_MESSAGE控件接受鼠标键盘输入
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_MESSAGE), TRUE) ;
wsprintf (szBuffer, TEXT ("Device ID = %i"), lParam) ;
SetDlgItemText (hwnd, IDC_NOTIFY_ID, szBuffer) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_ID), TRUE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_SUCCESSFUL),
wParam & MCI_NOTIFY_SUCCESSFUL) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_SUPERSEDED),
wParam & MCI_NOTIFY_SUPERSEDED) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_ABORTED),
wParam & MCI_NOTIFY_ABORTED) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_FAILURE),
wParam & MCI_NOTIFY_FAILURE) ;
SetTimer (hwnd, ID_TIMER, 5000, NULL) ;
return TRUE ;
case WM_TIMER:
KillTimer (hwnd, ID_TIMER) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_MESSAGE), FALSE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_ID), FALSE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_SUCCESSFUL), FALSE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_SUPERSEDED), FALSE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_ABORTED), FALSE) ;
EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_FAILURE), FALSE) ;
return TRUE ;
case WM_SYSCOMMAND:
switch (LOWORD (wParam))
{
case SC_CLOSE:
EndDialog (hwnd, 0) ;
return TRUE ;
}
break ;
}
return FALSE ;
}