Tài liệu tóm tắt lý thuyết ngắn gọn, cùng với các bài tập minh họa dễ hiểu sẽ giúp các bạn tiếp cận nhanh với chủ đề lập trình windows. Tóm tắt nội dung tài liệu:1. Lập trình Win32 API là gì?2. Cấu trúc chương trình trên HĐH Windows3. Ứng dụng Win32 API cơ bản4. Menu5. Popup Menu6. Dialog7. Control Static8. Button9. CheckBox10. GroupBox and Radio Button11. Tracker Bar12. Combo box13. Progress bar14. Tree View15. Tab Control16. List Box
Trang 1Đây là Tutorial cho lập trình Windows API Tutorial này sẽ hướng dẫn bạn những kiến thức
cơ bản và nâng cao cho phần lập trình trong Windows API với ngôn ngữ C Ở đây không bao hàm phần MFC (Microsoft Foundation Classes sử dụng thư viện C++ để phát triển các ứng dụng C++ trên Windows)
Tutorial này sẽ hướng dẫn các bạn tạo và test 1 ứng dụng Win32 trên Windows OS Các bài viết trong Tutorial này được viết và complier trên Visual C++ (Visual Studio 2008 )
2 Windows API
Windows API là các hàm được sử dụng để tạo các ứng dụng Windows Windows SDK(
Software Development Kit) bao gồm header file, library (Windows API) , sample,
documentation và các tool (Windows SDK đã được tích hợp trong Visual Studio )
Widows API có thể chia ra thành các loại sau :
- Graphics bao gồm các GDI (Graphic Device Interface),GDI+, DirectX hoặc OpenGL
- User Interface cung cấp các function để tạo ra các window, các control
- Multimedia cung cấp các tool để làm việc với video, sound, và các thiết bị đầu vào
Trang 2Cấu trúc chương trình trong Windows
Chú ý: từ bây giờ cho đến hết Tutorial này Chúng ta sẽ dùng windows : cửa sổ, còn
Windows : hệ điều hành Windows
1 windows
Theo quan điểm của người lập trình, mọi thứ trong ứng dụng đều là cửa sổ (windows)
2 Cấu trúc chương trình trong Windows
Mọi chương trình ứng dụng trong Windows bắt buộc phải có 2 hàm:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR
lpCmdLine, int nCmdShow );
hInstance là một thể hiện của chương trình Nó là số nguyên 32bit, số nguyên này sẽ được cho bởi Windows khi chương trình ứng dụng bắt đầu thực hiện
hPrevInstance : là thông số để NULL
lpCmdLine:
nCmdShow: chỉ ra cửa sổ sẽ được hiển thị như thế nào (Minimumized, maximized, Hidden) Hàm WinMain() sẽ kết thúc khi nó nhận được bản tin WM_QUIT
Hàm WinMain() được xây dựng theo các bước sau:
Bước 1: Đăng kí cửa sổ (Register windows)
Trước khi chúng ta tạo cửa sổ, chúng ta cần phải đăng kí cửa sổ đó với HĐH Windows Tất
cả các cửa sổ cần phải được đăng kí
HĐH Windows định nghĩa cửa sổ dưới dạng một cấu trúc WNDCLASS.Cấu trúc này chứa các thông số quy định các đặc tính cho cửa sổ(tên cửa sổ, màu background, ) Chúng ta sẽ xét
cụ thể trong ví dụ
Cuối cùng ta gọi hàm RegisterClass() để đăng kí cửa sổ với HĐH Windows
Bước 2: Tạo cửa sổ
Để tạo một cửa sổ ta gọi hàm CreateWindow()
Code:
HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int
nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam );
Trang 3Parameter :
lpClassName: tên đăng kí với HĐH Windows
lpWindowName: tên sẽ hiển thị lên cửa sổ
dwStyle:
x,y: hoành độ, tung độ để hiển thị cửa sổ
nWidth: độ rộng của cửa sổ
nHeight: độ cao của cửa sổ
hWndParent: handle tới cửa sổ cha
hMenu: handle tới các menu
hInstance: handle tới các thể hiện của chương trình
- Message là giá trị integer chỉ ra một sự kiện cụ thể VD: Khi chúng ta click vào button, thay đổi kích thước cửa sổ hoặc đóng ứng dụng,…v.v Thì sẽ có rất nhiều message được tạo
ra Các message này có thể không được xử lí đồng thời, mà các message này sẽ được đưa vào 1 hàng đợi thông điệp (message queue) và đợi để xử lí lần lượt từng message một
- Hàm GetMessage() được sử dụng để lấy các bản tin từ message queue
- Hàm TranslateMessage() translate virtual-key message thành character message
( HĐH Windows tạo ra các Virtual-key message khi người dùng ấn các phím trên key-board (nhưng không phải là giá trị character) Ứng dụng muốn lấy được message này thì cần phải
có hàm để translate virtual-key message thành character message)
- Hàm DispatchMessage() dùng để phát message tới window produce
2.3 Window Procedure
Code:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam);
- Hàm WindowProc() sẽ nhận và xử lí các message gửi đến Các message nào không được
xử lí trong hàm này sẽ được xử lí trong hàm DefWindowProc() của HĐH Windows
- hwnd: handle to the windows
- uMsg:
- wParam, lParam: chứa các thông tin về message
2.4 Các Message cơ bản
WM_CHAR Khi nhập 1 kí tự từ bàn phím
WM_COMMAND Khi lựa chọn các item trong popup menu
WM_CREAT Khi windows được tạo
WM_DESTROY Khi windows bị destroy
WM_LBUTTONDOWN Khi click chuột trái
WM_RBUTTONDOWN Khi click chuột phải
WM_MOUSEMOVE Khi di chuyển con trỏ chuột
WM_PAINT Khi windows được vẽ lại
Trang 4WM_QUIT Khi close windows
Dưới đây là hình vẽ mô tả quá trình nhận và xử lí message của ứng dụng Win32
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
Trang 5wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
là header của của chương trình C
Nó chứa việc gọi các hàm API, các macro và tất cả dữ liệu cơ bản
Code:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
Khai báo hàm xử lí message
Trang 6Code:
wc.style = CS_HREDRAW | CS_VREDRAW;
Đây là style của cửa sổ CS_HREDRAW và CS_VREDRAW được thiết lập Khi người dùng thay đổi kích thước cửa sổ thì cửa sổ sẽ được vẽ lại
wc.lpszClassName = TEXT( "Window" );
Tên của class Chúng ta sẽ dùng tên này để tạo cửa sổ (Các bạn có thể thay đổi tên khác tùy theo
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Đặt biểu tượng con trỏ và Icon trong ứng dụng
Trang 7return DefWindowProc(hwnd, msg, wParam, lParam);
Đoạn code xử lý các message
Khi người dùng close ứng dụng, bản tin WM_DESTROY gửi tới win procedure
Hàm PostQuitMessage() sẽ gửi bản tin WM_QUIT tới hàng đợi thông điệp để chờ xử lí Bản tin WM_QUIT sẽ được xử lí trong tại thủ tục mặc định của Windows
Trang 8Demo
Menu
Menubar được thấy rất nhiều trong các ứng dụng Menubar được đặt bên dưới phần tên ứng dụng Menubar có thể bao gồm rất nhiều các menu nhỏ (submenu hoặc menu items) Ví dụ dưới đây sẽ hướng dẫn bạn tạo một menubar gồm các submenu
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
Trang 9AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("New"));
AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, TEXT("Open"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, TEXT("Quit"));
Code:
AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("New"));
AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, TEXT("Open"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, TEXT("Quit"));
Đoạn code trên tạo menu gồm 3 item menu New,Open,Quit Giữa Item Open và Quit có đường kẻ phân chia
Trang 10Code:
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, TEXT("File"));
Gắn các menu item lên thanh menubar File
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
Trang 11AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("&New"));
AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, TEXT("&Open"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, TEXT("&Quit"));
Trang 12TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
Hàm này hiển thị popup menu tại vị trí chúng ta click chuột phải trên ứng dụng
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
void CreateDialogBox(HWND);
Trang 13void RegisterDialogClass(HWND);
HINSTANCE ghInstance;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
Trang 14WS_VISIBLE | WS_SYSMENU | WS_CAPTION , 100, 100, 200, 150,
NULL, NULL, ghInstance, NULL);
}
Giải thích:
Trong ví dụ trên, chúng ta khai báo 2 hàm xử lí message
Code:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
- Hàm thứ nhất, xử lí các message phát sinh tại cửa sổ “Window” được tạo ban đầu ngay khi chạy ứng dụng
- Khi ta click vào button “Show dialog” chương trình sẽ tạo ra cửa sổ thứ hai Nếu người sử dụng thao tác trên cửa sổ “Dialog Box” thì hàm xử lí message thứ hai sẽ được gọi
Demo
Trang 15VD2:Colour Dialog Box
Code:
#include "windows.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK PanelProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
Trang 16return (int) msg.wParam;
Trang 17rwc.lpszClassName = TEXT( "Panel" );
rwc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
Trang 18Hàm này trả về giá trị màu được chọn
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
Khởi tạo màu trên Dialog Box
InvalidateRect (hwndPanel, NULL, TRUE);
Sau khi lấy được màu đã chọn Chúng ta gọi hàm InvalidateRect(), hàm này sẽ gửi tới child
window message WM_PAINT
Code:
SetBkColor(hdc, gColor);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, TEXT(""), 0, NULL);
Hàm SetBkColor() cài đặt màu của background Hàm ExtTextOut() có chức năng hiển thị văn bản và màu lên device context Ở đây ETO_OPAQUE là hằng số đã được định nghĩa, khia giá trị này được khai báo thì hàm ExtTextOut() chỉ hiển thị màu lên background
Demo
Trang 19Control Static
Code:
#include "windows.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow)
Trang 20while( GetMessage(&msg, NULL, 0, 0)) {
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
static wchar_t *lyrics = L"Hi all.\n\
My name's Viet\n\
I come from Thai Nguyen City\n\
06/2012 : I graduated from HN University of Technology \n\
hwnd, (HMENU) 1, NULL, NULL);
Hàm CreateWindowW giúp tạo cửa sổ (đối tượng) static Nếu thay “STATIC” bằng “Button” thì chương trình sẽ tạo ra 1 nút bấm
Demo
Trang 21Button
Code:
#include "windows.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow ) {
Trang 22return (int) msg.wParam;
CreateWindow(TEXT("button"), TEXT("Quit"),
WS_VISIBLE | WS_CHILD ,
120, 50, 80, 25, hwnd, (HMENU) 2, NULL, NULL);
Trang 23CreateWindow(TEXT("button"), TEXT("Quit"),
WS_VISIBLE | WS_CHILD ,
120, 50, 80, 25, hwnd, (HMENU) 2, NULL, NULL);
Button thứ nhất có nhãn là “Beep” và ID=1
Button thứ hai có nhãn là “Quit” và ID=2
Khi ta bấm button thì message WM_COMMAND được phát đi Hàm WndProc() sẽ xử lí
Khi bấm vào button “Beep” hàm Beep(40, 50) được gọi (tiếng Beep)
Khi bấm vào button “Quit” hàm PostQuitMessage(0) sẽ gửi message tới Window yêu cầu đóng ứng dụng
Demo
CheckBox
Trang 24Code:
#include "windows.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR title[] = TEXT("Check Box");
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow ) {
CreateWindow(TEXT("button"), TEXT("Show Title"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
20, 20, 185, 35,
hwnd, (HMENU) 1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
Trang 25CreateWindow(TEXT("button"), TEXT("Show Title"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
20, 20, 185, 35,
hwnd, (HMENU) 1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
Để tạo checkbox ta sử dụng hàm CreateWindow() để tạo button loại checkbox Ta chọn hằng số BS_CHECKBOX
Trang 26Group box và radio button
Ở bài này,chúng ta sẽ đi tìm hiểu về group box và radio button
• Group box là 1 đường bao hình chữ nhật bao quanh các 1 bộ các control Control thường các các radio button Group box được đánh nhãn để mô tả về control này Group control được dùng để nhóm các control cùng loại
• Radio button là 1 loại button đặc biệt có thể lựa chọn nhưng không xóa được Nó cho phép người dùng lựa chọn 1 trong nhóm các option
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
HBRUSH hBrush, holdBrush;
HPEN hPen, holdPen;
switch(msg)
Trang 27{
case WM_CREATE:
CreateWindow(TEXT("button"), TEXT("Choose Color"),
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
10, 10, 120, 110, hwnd, (HMENU) 0, g_hinst, NULL);
CreateWindow(TEXT("button"), TEXT("Blue"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 30, 100, 30, hwnd, (HMENU)ID_BLUE , g_hinst, NULL);
CreateWindow(TEXT("button"), TEXT("Yellow"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 55, 100, 30, hwnd, (HMENU)ID_YELLOW , g_hinst, NULL); CreateWindow(TEXT("button"), TEXT("Orange"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 80, 100, 30, hwnd, (HMENU)ID_ORANGE , g_hinst, NULL);
holdPen = (HPEN)SelectObject(hdc, hPen);
holdBrush = (HBRUSH) SelectObject(hdc, hBrush);
Trang 28Giải thích :
Trong bài viết này, chúng ta có 1 group box gồm 3 radio button Ta có thể lựa chọn
background cho hình chữ nhật bên phải bằng cách click vào radio button
Code:
CreateWindow(TEXT("button"), TEXT("Choose Color"),
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
10, 10, 120, 110, hwnd, (HMENU) 0, g_hinst, NULL);
Group box được tạo với thông số BS_GROUPBOX
Code:
CreateWindow(TEXT("button"), TEXT("Blue"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 30, 100, 30, hwnd, (HMENU)ID_BLUE , g_hinst, NULL);
Radio button “Blue” được tạo với thông số BS_AUTORADIOBUTTON
Tương tự các hàm tiếp theo tạo ra các radio button “Yellow” và “Orange”
Code:
case ID_BLUE:
g_color = RGB(0, 76, 255);
break;
Nếu button “Blue” được chọn thì biến g_color sẽ được fill màu blue Biến g_color được dùng
để tạo brush để fill màu cho hình chữ nhật bên phải
Code:
InvalidateRect(hwnd, NULL, TRUE);
Hàm này invalidate hình chữ nhật (trong trường hợp này là toàn bộ window), khiến cho toàn
bộ window được vẽ lại
Trong case WM_PAINT sẽ vẽ hình chữ nhật
Demo
Trang 29Trackbar
Trackbar bao gồm 1 slider + 1 tick mark Chúng ta có thể sử dụng chuột hoặc bàn phím để
di chuyển thanh slider Trackbar được dùng để lựa chọn 1 giá trị xác định trong 1 dải giá trị liên tục
Chúng ta tạo trackbar bằng 3 static text control 2 đối tượng static được đặt ở bên trái và bên phải của slider Khi ta kéo slider trượt thì text của đối tượng static còn lại sẽ thay đổi.Code:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow)
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam )
Trang 30WS_CHILD | WS_VISIBLE, 0, 0, 30, 30, hwnd, (HMENU)2, NULL, NULL);
hlbl = CreateWindowW(L"STATIC", L"0", WS_CHILD | WS_VISIBLE,
270, 20, 30, 30, hwnd, (HMENU)3, NULL, NULL);
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
hTrack = CreateWindowW(L"msctls_trackbar32", L"Trackbar Control",
WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS,
20, 20, 170, 30, hwnd, (HMENU) 3, NULL, NULL);
SendMessageW(hTrack, TBM_SETRANGE, TRUE, MAKELONG(0, 100));
SendMessageW(hTrack, TBM_SETPAGESIZE, 0, 10);
SendMessageW(hTrack, TBM_SETTICFREQ, 10, 0);
SendMessageW(hTrack, TBM_SETPOS, FALSE, 0);
SendMessageW(hTrack, TBM_SETBUDDY, TRUE, (LPARAM) hLeftLabel);
SendMessageW(hTrack, TBM_SETBUDDY, FALSE, (LPARAM) hRightLabel);