/*---------------------------------------------
HEAD.C -- Displays beginning (head) of file
(c) Charles Petzold, 1998
---------------------------------------------*/
#include <windows.h>
#define ID_LIST 1
#define ID_TEXT 2
#define MAXREAD 8192
#define DIRATTR (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | /
DDL_DIRECTORY | DDL_ARCHIVE | DDL_DRIVES)
//DT_WORDBREAK:断开字,当一行中的字符将会延伸到由lpRect指定的矩形的边框时,此行自动地在字之间断开。
//DT_EXPANDTABS:扩展制表符,每个制表符的缺省字符数是8
//DT_NOCLIP:无裁剪绘制
//DT_NOPREFIX:关闭前缀字符的处理.通常DrawText解释助记前缀字符,&为给其后的字符加下划线,
//解释&&为显示单个&。指定DT_NOPREFIX,这种处理被关闭。
#define DTFLAGS (DT_WORDBREAK | DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ListProc (HWND, UINT, WPARAM, LPARAM) ;
WNDPROC OldList ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("head") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
//WS_CLIPCHILDREN:当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格
hwnd = CreateWindow (szAppName, TEXT ("head"),
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bValidFile ;
static BYTE buffer[MAXREAD] ;
static HWND hwndList, hwndText ;
static RECT rect ;
static TCHAR szFile[MAX_PATH + 1] ; //windows的MAX_PATH是260 盘符+:/+结尾的0+256=260
HANDLE hFile ;
HDC hdc ;
int i, cxChar, cyChar ;
PAINTSTRUCT ps ;
TCHAR szBuffer[MAX_PATH + 1] ;
switch (message)
{
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
rect.left = 20 * cxChar ;
rect.top = 3 * cyChar ; //计算得出用于显示文件具体信息的窗口区域
hwndList = CreateWindow (TEXT ("listbox"), NULL,
WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD,
cxChar, cyChar * 3,
cxChar * 13 + GetSystemMetrics (SM_CXVSCROLL),
cyChar * 10,
hwnd, (HMENU) ID_LIST,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ; //装载程序进程的当前目录到szBuffer
hwndText = CreateWindow (TEXT ("static"), szBuffer,
WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
cxChar, cyChar, cxChar * MAX_PATH, cyChar,
hwnd, (HMENU) ID_TEXT,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
//将句柄为hwndList的子窗口控件的窗口消息处理程序挂钩到ListProc函数
OldList = (WNDPROC) SetWindowLong (hwndList, GWL_WNDPROC, (LPARAM) ListProc) ;
//添加程序进程当前目录下的文件列表到清单方块控件中
SendMessage (hwndList, LB_DIR, DIRATTR, (LPARAM) TEXT ("*.*")) ;
return 0 ;
case WM_SIZE :
//得到用于显示文件具体信息的窗口区域
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_SETFOCUS :
//父窗口直接转移焦点到清单方块控件上
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND :
//如果在清单方块控件中执行双击
if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_DBLCLK)
{
//获得选中项目的索引
if (LB_ERR == (i = SendMessage (hwndList, LB_GETCURSEL, 0, 0)))
break ;
//保存双击的文件名称到szBuffer
SendMessage (hwndList, LB_GETTEXT, i, (LPARAM) szBuffer) ;
// INVALID_HANDLE_VALUE 表无效句柄值
//CreateFile(指向文件名的指针,访问模式,共享模式,指向安全属性的指针,
// 如何创建,文件属性,用于复制文件句柄); 执行成功返回文件句柄
if (INVALID_HANDLE_VALUE != (hFile = CreateFile (szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL)))
{
CloseHandle (hFile) ; //关闭文件句柄
bValidFile = TRUE ;
lstrcpy (szFile, szBuffer) ; //复制文件名到szFile
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ; //装载进程的当前目录到 szBuffer
// ‘//’第一个/为转义字符 第2个才是显示的/
//该语句将一个 / 追加在szBuffer后面
if (szBuffer [lstrlen (szBuffer) - 1] != '//')
lstrcat (szBuffer, TEXT ("//")) ;
//将选中的文件绝对路径输出到静态控件上
SetWindowText (hwndText, lstrcat (szBuffer, szFile)) ;
}
else
{
bValidFile = FALSE ;
szBuffer [lstrlen (szBuffer) - 1] = '/0' ;
//如果设置该目录不工作,也许这是一个磁盘驱动器,所以试试。
if (!SetCurrentDirectory (szBuffer + 1)) //设置当前目录,返回值非零表示成功,零表示失败
{
//如果失败,用szBuffer + 2来设置磁盘驱动器
szBuffer [3] = ':' ;
szBuffer [4] = '/0' ;
SetCurrentDirectory (szBuffer + 2) ;
}
GetCurrentDirectory (MAX_PATH + 1, szBuffer) ;
SetWindowText (hwndText, szBuffer) ;
//LB_RESETCONTENT清除清单方块中的内容
SendMessage (hwndList, LB_RESETCONTENT, 0, 0) ;
//文件目录重新写入清单方块
SendMessage (hwndList, LB_DIR, DIRATTR, (LPARAM) TEXT ("*.*")) ;
}
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT :
if (!bValidFile)
break ;
if (INVALID_HANDLE_VALUE == (hFile = CreateFile (szFile, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))
{
bValidFile = FALSE ;
break ;
}
//ReadFile(文件句柄,用于保存读入数据的缓冲区,要读入的字符数,指向实际读取字节数的指针,(没有异步操作)NULL);
ReadFile (hFile, buffer, MAXREAD, (unsigned long*)&i, NULL) ;
CloseHandle (hFile) ;
// i 现在等于缓冲区的实际字节数.
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT)) ;
SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ;
//用ASCII字符集显示读取到的数据信息
DrawTextA (hdc, (const char*)buffer, i, &rect, DTFLAGS) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
LRESULT CALLBACK ListProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//如果消息是按下回车键,便向父窗口发送清单方块双击的消息
if (message == WM_KEYDOWN && wParam == VK_RETURN)
SendMessage (GetParent (hwnd), WM_COMMAND,
//MAKELONG是一个宏,将两个16位的数联合成一个无符号的32位数。第一个参数是低十六位。
MAKELONG (1, LBN_DBLCLK), (LPARAM) hwnd) ;
return CallWindowProc (OldList, hwnd, message, wParam, lParam) ;
}