THỜI GĨAN 4.1. MỞ ĐẦU
4.2.5. Đoạn chương trĩnh minh họa
Đoạn chương ữình dưới đây minh họa một chương trình nhỏ nhập các kí tự từ bàn phím và xuất ra màn hình.
#define BUFSIZE 65535;
#define SHIFTED 0x8000;
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc; // Thiết bị ngữ cảnh
TEXTMETRIC tm; // c ấ u trúc metric của văn bần static DWORD dwCharX; //B ề ngang của kí tự static DWORD dwCharY; // Chiêu dài của kí tự
static DWORD dwClientX; //B ê ngang của vùng làm việc static DWORD dwClientY; //C hiều dài của vùng làm việc static DWORD dwLineLen; // Chiều dài của một dòng
static DWORD dwLines; // s ô dòng văn bẩn trong vùng làm việc static int nCaretPosX = 0; //T ọ a độ X của caret
static int nCaretPosY = 0; //T ọ a đ ộ y của caret static int nCharWidth = 0; //B ề dày của kí tự static int cch = 0; // SỐ kí tự trong buffer
static int nCurChar = 0; // Chỉ đến kí tự hiện thời trong buffer static PTCHAR pchlnputBuf; //K í tự tạm đưa vào buffer
NGÔN NGỮ LẬP TRÌNH LẬP TRÌNH c TRÊN W INDOW S
int i, j; //Biến ¡ặp
int cCR = 0; //S Ố kí tự xuống dòng
int nCRIndex = 0; //C h ỉ đến kí tự xuống dòng cuối cùng
int nVirtKey; //M ã phím ảo TCHAR szBuf [128]; //Buffer tạm TCHAR ch; //K í tự
PAINTSTRUCT ps; //Dùng cho hàm BeginPaint RECT rc; //Hình chữ nhật trong hàm DrawText SIZE sz; //K ích thước của chuỗi
COLORREF crPrevText; //M à u của văn bẩn
COLORREF crPrevBk; //M àu nền switch ( message )
{
case WM_CREATE:
/* Lấy thông tin font hiện thời */
hdc = GetDC ( hWnd );
GetTextMetrics ( hdc, &ĩ11 );
ReleaseDC ( hWnd, hdc );
dwCharX = tm.tmAveCharWidth;
dwCharY = tm.tmHeight;
/* Cấp phát bộ nhớ đệm đ ể lưu kí tự nhập vào */
pchlnputBuf = (LPTSTR)GlobalAlloc( GPTR,BUFSIZE * sizeof ( TCHAR ) );
return 0;
case WM_SIZE:
/* LƯU g iữ kích thước của vùng làm v iệ c */
dwClientX = LOWORD ( lParam );
WINDOWS
dwClientY = HI WORD ( IParam );
/* Tính kích thước tối đa của một dòng và s ố dòng tối đa trong vùng làm việc */
dwLineLen = dwClientX - dwCharX;
dwLines = dwClientY / dwCharY;
break;
case WM_SETFOCUS:
/* Tạo và hiển thị caret khi cửa s ổ nhận được s ự quan tâm */
CreateCaret ( hWnd, ( HBITMAP ) 1, 0, dwCharY );
SetCaretPos ( nCaretPosX, nCaretPosY * dwCharY );
ShowCaret ( hWnd );
break;
case WMJKILLFOCUS:
/*Án caret và hủy khi cửa s ổ không còn nhận được s ự quan tăm */
HideCaret ( hWnd );
DestroyCaret ( );
break;
case WM_CHAR:
switch ( wParam ) {
case 0x08: // Backspace case 0x0A: //Linefeed case OxlB: //Escape MessageBeep( ( UINT ) -1 );
return 0;
case 0x09: // tab
NGÔN NGỮ LẬP TRÌNH LẬP TRÌNH c TRÊN W INDOW S
/* Chuyển phím tab thành 4 kí tự trắng liên tục nhau */
for ( i = 0; i < 4; i ++ )
SendMessage (hWnd, WM_CHAR, 0x20, 0);
return 0;
case OxOD: //X uống dòng
/* Lưu kí tự xuống dòng và tạo dòng mới đưa caret xuống vị t r í m ới * /
pchlnputBuf [ cch++ ] = OxOD;
nCaretPosX = 0;
nCaretPosY += 1;
break;
default: / / x ử lý những kí tự có th ề hiển thị được ch = ( TCHAR ) wParam;
HideCaret ( hWnd );
/* Lấy bề dày của kí tự và xuất ra */
hdc = GetDC ( hWnd );
GetCharWidth32 ( hdc, (UINT) wParam, (UINT)wParam,
&nCharWidtli );
TextOut(hdc, nCaretPosX, nCaretPosY*dwCharY, &ch, 1);
ReleaseDC ( hWnd, hdc );
/ * Lưu k í tự vào buffer */
pchlnputBuf [ cch++ ] = ch;
/* Tính lại vị trí ngang cúa caret. N ếu vị trí này tới cuối dòng thì chèn thêm k í tự xuống dòng và di chuyển caret đến dòng mới */
nCaretPosX += nCharWidth;
if ( ( DWORD ) nCaretPosX > dwLineLen ) {
WINDOWS
nCaretPosX = 0;
pchlnputBuf [ cch++ ] = OxOD;
++nCaretPosY;
}
nCurChar = cch;
ShowCaret ( hWnd);
break;
}
SetCaretPos ( nCaretPosX, nCaretPosY * dwCharY);
break;
case WM_KEYDOWN:
switch ( wParam) {
case VKJLEFT: //LEFTarrow
/* Caret di chuyển qua trái và chỉ đến đầu dòng */
if ( nCaretPosX > 0 ) {
HideCaret ( hWnd);
/* Tính toán lại vị trí của caret khi qua trái */
ch = pchlnputBuf [—nCurChar ];
hdc = GetDC ( hWnd);
GetCharWidth32 ( hdc, ch, ch, &nCharWidth);
ReleaseDC ( hWnd, hdc );
nCaretPosX=max(nCaretPosX-nCharWidth,0);
ShowCaret ( hWnd);
>
NGÔN NGỮ LẬP TRÌNH LẬP TRÌNH c TRÊN WINDOWS
break;
case VKJRIGHT: //RIG H T arrow /* Di chuyển caret sang phải */
if (nCurChar < cch) {
HideCaret ( hWnd);
/* Tính toán lại vị trí của caret khi sang phải */
ch = pchlnputBuf [ nCurChar ];
if ( ch == OxOD) {
nCaretPosX = 0;
nCaretPosY++;
>
/* N ếu kí tự không phải là enter thì kiểm tra xem phím shift có được nhấn hay không. N ếu có nhấn thì đổi màu và xuất ra màn hình. */
else {
hdc = GetDC ( hWnd);
nVirtKey = GetKeyState ( VK_SHIFT);
if ( nVirtKey & SHIFTED ) {
crPrevText=SetTextColor( hdc,RGB (255, 255, 255));
crPrevBk= SetBkColor(hdc,RGB(0,0,0));
TextOut(hdc,nCaretPosX,nCaretPo5Y*dwCharY,
& ch,l);
SetTextColor ( hdc, crPrevText);
SetBkColor ( hdc, crPrevBk);
WINDOWS }
GetCharWidth32(hdc,ch,ch,&nCharWidth);
ReleaseDC ( hWnd, hdc );
nCaretPosX = nCaretPosX + nCharWidth;
}
nCurChar++;
ShowCaret ( hWnd);
break;
}
break;
case VK_UP: //Phím mũi tên lên case VK_DOWN: //Phím mũi tên xuống MessageBeep ( (UINT) -1 );
return 0;
case VK_HOME: //Phím home
/* Thiết lập vị trí cúa caret ớ dòng đầu tiên */
nCaretPosX = nCaretPosY = 0;
nCurChar = 0;
break;
case VK_END: //Phím end
/* Di chuyển vè cuối văn bán và lưu vị trí của kí tự xuống dòng cuối */
for ( i=0; i < cch; i++) {
if ( pchlnputBuf [ i ] == OxOD) {
cCR++;
NGÔN NGỮ LẬP TRÌNH LẬP TRÌNH c TRÊN WINDOWS
nCRIndex = i + l ; }
>
nCaretPosY = cCR;
/* Chép tất cả các kí tự từ kí tự xuống dòng cuối đến kí tự hiện thời vừa nhập từ bàn phím vào bộ nhớ đệm. */
for ( i = nCRIndex, j = 0; i < cch; i++, j++ ) szBuf [ j ] = pchlnputBuf [ i ];
szBuf [ j ] = TEXT (\ ữ);
/* Tính vị trí dọc của caret */
hdc = GetDC ( hWnd);
GetTextExtentPoint32(hdc,szBuf, Istrlen(szBuf), & S Z );
nCaretPosX = sz.cx;
ReleaseDC ( hWnd, hdc );
nCurChar = cch;
break;
default:
break;
}
SetCaretPos( nCaretPosX, nCaretPosY*dwCharY);
break;
case WM_PAINT:
if ( cch == 0 ) break;
hdc = BeginPaint ( hWnd, &ps );
HideCaret ( hWnd );
SetRect (&TC, 0, 0, dwLineLen, dwClientY);
WINDOWS
DrawText ( hdc, pchlnputBuf, -1, &rc, DT_LEFT );
ShowCaret ( hWnd );
EndPaint ( hWnd, &ps );
break;
case WM_DESTROY:
PostQuitMessage ( 0 );
/* Giải phóng buffer */
GlobalFree ( ( HGLOBAL) pchlnputBuf );
UnregisterHotKey ( hWnd, O x A A A A );
break;
default:
return DefWindowProc ( hWnd, message, wParam, IParam );
>
return NULL;
}
4.3. TH IÊT BỊ CHUỘT
Trong một môi trường giao tiếp đổ họa, việc sử dụng thiết bị định vị chuột là hết sức cẩn thiết. Nhờ thiết bị chuột ta có thể di chuyển đến một điểm bất kì trên khung màn hình và thực hiện thao tác kích các nút chuột. Đối với một sô Lftig dụng đổ họa không quá phức tạp thì công cụ đ ể thực hiện chủ yếu là chuột, riêng đối với các Lftig dụng đòi hỏi sự phức tạp khi v ẽ thì người ta dùng bút vẽ.
v ớ i Windows thì thiết bị chuột là một thành phẩn quan trọng, nêu chúng ta bỏ thiết bị chuột thì vẫn khởi động bình thường và các chương trình vẫn có thể chạy được. Tuy nhiên khi đó ta sẽ lúng túng nhiều khi x ử lý các ứng dụng trực quan tương tác với người dùng theo tọa độ hay định vị.
Cũng tương tự như bàn phún, thiết bị chuột cũng được dùng đ ể nhập dữ liệu từ người dùng vào ứíig dụng nhưng dữ liệu đây không phải là văn bản như khi nhập từ bàn phím mà là các thao tác vẽ hay xử lý các đối tượng đồ họa.