实现滚动显示
#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)
#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("Program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("head"),
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|ES_AUTOVSCROLL|WS_VSCROLL,
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];
static int readSize;
static bool isRollText;
static int vScrollRange, hScrollRange;
static int c_lineOfPage, c_widthOfPage;
static int cxChar, cyChar;
static int iVscrollPos, iHscrollPos;
HANDLE hFile;
HDC hdc;
int i;
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);
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);
OldList = (WNDPROC)SetWindowLong(hwndList, GWL_WNDPROC, (LPARAM)ListProc);
SendMessage(hwndList, LB_DIR, DIRATTR, (LPARAM)TEXT("*.*"));
return 0;
case WM_SIZE:
rect.right = LOWORD(lParam)/*-GetSystemMetrics(SM_CXVSCROLL)*/;
rect.bottom = HIWORD(lParam)/*-GetSystemMetrics(SM_CYHSCROLL)*/;
c_lineOfPage = rect.bottom / cyChar - 3;
c_widthOfPage = rect.right / cxChar - 20;
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;
}
SendMessage(hwndList, LB_GETTEXT, i, (LPARAM)szBuffer);
if (INVALID_HANDLE_VALUE != (hFile = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))
{
CloseHandle(hFile);
bValidFile = TRUE;
lstrcpy(szFile, szBuffer);
GetCurrentDirectory(MAX_PATH + 1, 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[3] = ':';
szBuffer[4] = '\0';
SetCurrentDirectory(szBuffer + 2);
}
GetCurrentDirectory(MAX_PATH + 1, szBuffer);
SetWindowText(hwndText, szBuffer);
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;
}
hdc = BeginPaint(hwnd, &ps);
if (isRollText)
{
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
RECT myWirte;
myWirte.left =( 20-iHscrollPos) * cxChar;//超过画面的方式实现滚动
myWirte.top = (3 - iVscrollPos)*cyChar;//超过画面的方式实现滚动
myWirte.right = rect.right;
myWirte.bottom = rect.bottom;
DrawTextA(hdc, (LPCSTR)buffer, -1, &myWirte, DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);//第三个参数填负-1
//TextOutA(hdc, 20 * cxChar, (3 + (j - iVscrollPos))*cyChar, (LPCSTR)(dataLine[j].c_str() + iHscrollPos), dataLine[j].size());
//DrawTextA(hdc, (LPCSTR)buffer, readSize, &rect, (DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX));
//DrawTextA(hdc, (LPCSTR)buffer, readSize, &rect, DTFLAGS);
//DrawTextA(hdc, NULL, 0, &myWirte, (DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX));
isRollText = false;
}
else
{
memset(buffer,0, sizeof(buffer));
ReadFile(hFile, buffer, MAXREAD, (LPDWORD)&readSize, NULL);
if (readSize == MAXREAD)
{
buffer[readSize - 1] = '\0';
if (buffer[readSize - 2] == '\r')
{
buffer[readSize - 2] = '\0';
}
}
else
{
buffer[readSize] = '\0';
}
CloseHandle(hFile);
SetScrollPos(hwnd, SB_VERT, 0, TRUE);
SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
DrawTextA(hdc, (LPCSTR)buffer, readSize, &rect, /*DTFLAGS*/DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);
hScrollRange = 0;
int cur = 0;
int line = 0;
int countOfline = 0;
while (cur < readSize)
{
if (buffer[cur] == '\r')
{
if ((cur + 1 < readSize) && buffer[cur + 1] == '\n')
{
line++;
hScrollRange = max(hScrollRange, countOfline);
cur += 2;
countOfline = 0;
continue;
}
}
if (buffer[cur] == '\t')
{
countOfline += 8;//'\t'占8个字符
}
else
{
countOfline++;
}
cur++;
}
line++;
hScrollRange = max(hScrollRange, countOfline);
vScrollRange = max(0, line - c_lineOfPage);
hScrollRange = max(0, hScrollRange - c_widthOfPage);
SetScrollRange(hwnd, SB_VERT, 0, vScrollRange, true);
SetScrollRange(hwnd, SB_HORZ, 0, hScrollRange, true);
}
EndPaint(hwnd, &ps);
return 0;
case WM_VSCROLL:
switch (LOWORD(wParam))
{
case SB_LINEUP:
iVscrollPos -= 1;
break;
case SB_LINEDOWN:
iVscrollPos += 1;
break;
case SB_PAGEUP:
iVscrollPos -= c_lineOfPage;
break;
case SB_PAGEDOWN:
iVscrollPos += c_lineOfPage;
break;
case SB_THUMBPOSITION:
iVscrollPos = HIWORD(wParam);
break;
default:
break;
}
iVscrollPos = max(0, min(iVscrollPos, vScrollRange));
if (iVscrollPos != GetScrollPos(hwnd, SB_VERT))
{
SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
isRollText = true;
InvalidateRect(hwnd, &rect, TRUE);//不全部重绘,只重绘文字部分
}
return 0;
case WM_HSCROLL:
switch (LOWORD(wParam))
{
case SB_LINELEFT:
iHscrollPos -= 1;
break;
case SB_LINERIGHT:
iHscrollPos += 1;
break;
case SB_PAGELEFT:
iHscrollPos -= c_widthOfPage;
break;
case SB_PAGERIGHT:
iHscrollPos += c_widthOfPage;
break;
case SB_THUMBPOSITION:
iHscrollPos = HIWORD(wParam);
break;
default:
break;
}
iHscrollPos = max(0, min(iHscrollPos, hScrollRange));
if (iHscrollPos != GetScrollPos(hwnd, SB_HORZ))
{
SetScrollPos(hwnd, SB_HORZ, iHscrollPos, TRUE);
isRollText = true;
InvalidateRect(hwnd, &rect, TRUE);//不全部重绘,只重绘文字部分
}
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(1, LBN_DBLCLK), (LPARAM)hwnd);
}
return CallWindowProc(OldList, hwnd, message, wParam, lParam);
}