Bài giảng Lập trình C trên Windows: Thư viện đồ họa GDI (Graphics Device Interface) - Nguyễn Tri Tuấn

pdf 37 trang phuongnguyen 3100
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình C trên Windows: Thư viện đồ họa GDI (Graphics Device Interface) - Nguyễn Tri Tuấn", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfbai_giang_lap_trinh_c_tren_windows_thu_vien_do_hoa_gdi_graph.pdf

Nội dung text: Bài giảng Lập trình C trên Windows: Thư viện đồ họa GDI (Graphics Device Interface) - Nguyễn Tri Tuấn

  1. Lập trình C trên Windows Thư viện đồ họa GDI (Graphics Device Interface) Nguyễn Tri Tuấn Khoa CNTT – ĐH.KHTN.Tp.HCM Email: nttuan@ fit.hcmuns.edu.vn Nội dung  Giới thiệu  Các khái niệm cơ bản  Các ví dụ vẽ hình đồ họa  Xử lý ảnh Bitmap  In ấn (Printing) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 2 1
  2. Giới thiệu  GDI là thư viện cung cấp các hàm (functions) và các cấu trúc dữ liệu (structures) cần thiết để ứng dụng tạo ra những kết xuất dưới dạng đồ họa (hiển thị lên màn hình, in ra máy in, )  Các hàm GDI cho phép vẽ đường thẳng, đường cong, các hình đa giác, xuất ký tự, hiển thị ảnh bitmap, in ấn,  GDI không tương tác trực tiếp với thiết bị phần cứng, mà thông qua các driver C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 3 Các khái niệm cơ bản  Thiết bị đồ họa (Graphics device)  Ngữ cảnh của thiết bị (DC - Device Context)  DC trong MFC  Đối tượng vẽ (Drawing object)  Đối tượng vẽ trong MFC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 4 2
  3. Các khái niệm cơ bản - Thiết bị đồ họa  Thiết bị đồ họa (Graphics device): là những thiết bị cho phép thể hiện các kết xuất dạng đồ họa trên đó ƒ Thiết bị vật lý (physical device): là những thiết bị thật như màn hình, cửa sổ, máy in, ƒ Thiết bị “ảo” (logical device): là các thiết bị được giả lập trong bộ nhớ, còn gọI là “memory device”, có tác dụng mô phỏng thiết bị vật lý  Thư viện GDI cho phép thực hiện các lệnh vẽ trên cả thiết bị vật lý lẫn logic C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 5 Các khái niệm cơ bản - Ngữ cảnh của thiết bị  Ngữ cảnh của thiết bị (Device Context): là một cấu trúc lưu trữ các thông số của thiết bị đồ họa, ví dụ: ƒ Chế độ vẽ hiện tại (drawing mode), ƒ Vị trí bút vẽ hiện tại (pen position), ƒ Các đối tượng vẽ hiện tại (Pen, Brush, Font) ƒ  Các thông số này chi phối những thao tác vẽ lên thiết bị tại thời điểm thực hiện  Mỗi thiết bị được đặc trưng bởi 1 cấu trúc DC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 6 3
  4. Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt)  Ứng dụng thực hiện các thao tác vẽ lên thiết bị thông qua DC của thiết bị đó  DC được xem như là một phương tiện liên kết giữa ứng dụng và thiết bị, giúp tạo nên tính độc lập thiết bị (Device Independent) cho ứng dụng C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 7 Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt) Thuộc tính Gía trị mặc định Ý nghĩa/Các hàm liên quan Background White Màu nền khi xuất ký tự (SetBkColor) color Text color Black Màu ký tự (SetTextColor) Font SYSTEM_FONT Font chữ khi xuất ký tự (CreateFont, CreateFontIndirect, SelectObject) Pen BLACK_PEN Bút vẽ, sử dụng khi vẽ đường thẳng, đường cong (CreatePen, CreatePenIndirect, SelectObject) Current Pen (0, 0) Tọa độ hiện hành của Pen Position (MoveTo, LineTo) Một số thuộc tính do DC quản lý C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 8 4
  5. Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt) Thuộc tính Gía trị mặc định Ý nghĩa/Các hàm liên quan Brush WHITE_BRUSH Màu tô, sử dụng khi tô màu các vùng kín (CreateSolidBrush, CreateBrushIndirect, CreatePatternBrush, SelectObject, ) Drawing R2_COPYPEN Chế độ vẽ. Xác định cách phối hợp các mode bit màu của 2 pixel có cùng tọa độ (SetROP2) Bitmap NULL (CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, SelectObject) Một số thuộc tính do DC quản lý C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCM Summer 2004 9 Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt) Thuộc tính Gía trị mặc định Ý nghĩa/Các hàm liên quan Color DEFAULT_PALETTE Bảng màu Palette (CreatePalette, RealizePalette, SelectPalette, UnrealizeObject ) Mapping MM_TEXT Xác định đơn vị đo. VD. mode - MM_TEXT qui định đơn vị đo theo trục x,y là 1 pixel. - MM_HIMETRIC qui định đơn vị đo theo trục x,y là 0.01 milimet (SetMapMode) Một số thuộc tính do DC quản lý C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 10 5
  6. Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt)  Các loại DC: ƒ Display DC: sử dụng trong các thao tác vẽ lên màn hình/cửa sổ ƒ Printer DC: sử dụng để kết xuất dữ liệu đồ họa ra máy in ƒ Memory DC: tương ứng với thiết bị “logic”, thường dùng để “chuẩn bị” dữ liệu trước khi hiển thị ra thiết bị vật lý C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 11 Các khái niệm cơ bản - Ngữ cảnh của thiết bị (tt) Loại DC Các hàm liên quan Display DC BeginPaint, GetDC, GetDCEx EndPaint, ReleaseDC Printer DC CreateDC DeleteDC Memory DC CreateCompatibleDC DeleteDC Các hàm tạo lập/hủy bỏ DC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 12 6
  7. Các khái niệm cơ bản - DC trong MFC  Các lớp liên quan đến DC ƒ CDC: là lớp cơ sở dùng để quản lý DC ƒ CPaintDC: Dẫn xuất từ lớp CDC, Dùng với các thao tác vẽ trong vùng client của cửa sổ Chỉ sử dụng trong xử lý thông điệp WM_PAINT (hàm CWnd::OnPaint) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 13 Các khái niệm cơ bản - DC trong MFC (tt)  Các lớp liên quan đến DC (tt) ƒ CClientDC: Dẫn xuất từ lớp CDC, Dùng với các thao tác vẽ trong vùng client của cửa sổ Sử dụng bất kỳ lúc nào, ngoại trừ hàm CWnd::OnPaint ƒ CWindowDC: Dẫn xuất từ lớp CDC, Dùng với các thao tác vẽ trên cửa sổ (kể cả vùng client và non-client) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 14 7
  8. Các khái niệm cơ bản - DC trong MFC (tt) VD1. Vẽ bằng CDC CDC* pDC = GetDC(); // Các lệnh vẽ ReleaseDC(pDC); VD2. Xử lý thông điệp WM_PAINT, dùng lớp CDC PAINTSTRUCT ps; CDC* pDC = BeginPaint(&ps); // Các lệnh vẽ EndPaint(&ps); VD3. Xử lý thông điệp WM_PAINT, dùng lớp CPaintDC CPaintDC dc(this); // Các lệnh vẽ C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 15 Các khái niệm cơ bản - DC trong MFC (tt) VD4. Vẽ trên vùng client, dùng lớp CClientDC void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point) { CRect rect; GetClientRect(&rect); CClientDC dc(this); dc.MoveTo(rect.left, rect.top); dc.LineTo(rect.right, rect.bottom); dc.MoveTo(rect.right, rect.top); dc.LineTo(rect.left, rect.bottom); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 16 8
  9. Các khái niệm cơ bản - DC trong MFC (tt) Thuộc tính Gía trị mặc định Ý nghĩa/Các hàm liên quan Background White CDC::SetBkColor color CDC::GetBkColor Text color Black CDC::SetTextColor CDC::GetTextColor Font SYSTEM_FONT CDC::SelectObject Pen BLACK_PEN CDC::SelectObject Current Pen (0, 0) CDC::MoveTo Position CDC::GetCurrentPosition Drawing R2_COPYPEN CDC::SetROP2 mode CDC::GetROP2 Một số thuộc tính do lớp CDC quản lý C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 17 Các khái niệm cơ bản - DC trong MFC (tt) Hàm Ý nghĩa MoveTo Di chuyển Pen đến vị trí mới LineTo Vẽ 1 đoạn thẳng từ vị trí Pen hiện hành đến vị trí mới Polyline / Vẽ 1 dãy các cạnh PolylineTo Arc / ArcTo Vẽ 1 cung PolyBezier / Vẽ đường cong Bezier PolyBezierTo PolyDraw Vẽ đường cong Bezier và các cạnh nối giữa các điểm Một số hàm vẽ do lớp CDC cung cấp C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 18 9
  10. Các khái niệm cơ bản - Đối tượng vẽ  Đối tượng vẽ (Drawing object): là những đối tượng sẽ chi phối các thao tác vẽ của bạn. VD: ƒ Đối tượng Pen sẽ chi phối thao tác vẽ đường thẳng, đường cong; ƒ Đối tượng Brush sẽ chi phối thao tác tô màu; ƒ Đối tượng Font sẽ chi phối thao tác xuất ký tự  Đối tượng vẽ chứa các thông tin về màu sắc (color), kiểu dáng (style) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 19 Các khái niệm cơ bản - Đối tượng vẽ (tt)  Các đối tượng vẽ cần phải được tạo mới (Create) hay lấy ra từ kho (stock) để dùng ƒ Nếu tạo mới, sau khi dùng phải giải phóng ƒ Nếu lấy từ kho có sẵn, sau khi dùng không cần giải phóng VD1. Tạo mới 1 Pen HPEN hPen1 = CreatePen(PS_SOLID, 2, RGB(255, 0, 0); VD2. Lấy 1 Pen từ “kho” có sẵn HPEN hPen2 = (HPEN) GetStockObject(WHITE_PEN); VD3. Xoá đối tượng hPen1 sau khi sử dụng DeleteObject(hPen1); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 20 10
  11. Các khái niệm cơ bản - Đối tượng vẽ (tt)  Các đối tượng vẽ cần được “gán” vào DC trước khi thực hiện thao tác vẽ. VD: // “Gán” đối tượng hPen vào DC HPEN hOldPen = (HPEN) SelectObject(hdc, hPen); // Vẽ 1 đoạn thẳng, sử dụng đối tượng hPen vừa tạo MoveTo(hdc, 50, 50); LineTo(hdc, 100, 100);  Cần phải “lấy” đối tượng vẽ ra khỏi DC trước khi giải phóng đối tượng hay giải phóng DC // “Lấy” đối tượng vẽ ra khỏi DC SelectObject(hdc, hOldPen); // Giải phóng DC và đối tượng vẽ (nếu đối tượng được // tạo mới) ReleaseDC(hFrameWnd, hdc); DeleteObject(hPen); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 21 Các khái niệm cơ bản - Đối tượng vẽ (tt)  Các đối tượng vẽ: ƒ Pen (HPEN) ƒ Brush (HBRUSH) ƒ Font (HFONT) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 22 11
  12. Các khái niệm cơ bản - Đối tượng vẽ (tt)  Pen: có các thuộc tính ƒ Style: kiểu dáng ƒ Width: độ rộng (pixel) ƒ Color: màu sắc (RGB) VD1. Tạo mới 1 Pen HPEN hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0); VD2. Tạo mới 1 Pen, sử dụng cấu trúc LOGPEN LOGPEN lp; lp.lopnStyle = PS_DOT; lp.lopnWidth.x = 3; lp.lopnWidth.y = 0; // không sử dụng lp.lopnColor = RGB(0, 255, 0); HPEN hPen = CreatePenIndirect(&lp); VD3. Lấy 1 Pen từ “kho” có sẵn HPEN hPen; hPen = (HPEN) GetStockObject(WHITE_PEN); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 23 Các khái niệm cơ bản - Đối tượng vẽ (tt)  Brush: có các thuộc tính ƒ Style: kiểu dáng ƒ Color: màu sắc (RGB) ƒ Hatch: mẫu tô Hatch brush Stock brush Pattern brush C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 24 12
  13. Các khái niệm cơ bản - Đối tượng vẽ (tt)  Brush (tt): VD1. Tạo mới 1 Brush LOGBRUSH lb; HBRUSH hbr1; lb.lbStyle = BS_HATCHED; lb.lbColor = RGB(255, 0, 0); lb.lbHatch = HS_CROSS; hbr1 = CreateBrushIndirect(&lb); VD2. Lấy 1 Brush từ “kho” có sẵn HBRUSH hbr2; hbr2 = (HBRUSH) GetStockObject(LTGRAY_BRUSH); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 25 Các khái niệm cơ bản - Đối tượng vẽ (tt)  Font: có các thuộc tính ƒ Typeface: loạI font (Times, Courier, Arial, ) ƒ Style: kiểu dáng (normal, thin, bold, ) ƒ Size: kích cỡ chữ, được xác định theo đơn vị point, 1 point = 1/72 inch = 0.013837 inch  Có thể tạo đối tượng font bằng cách: ƒ Thay đổI mẫu font có sẵn ƒ Chọn thuộc tính Font từ hộp thoạI ChooseFont C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 26 13
  14. Các khái niệm cơ bản - Đối tượng vẽ (tt)  Font (tt) VD1. Tạo mới 1 font từ mẫu có sẵn LOGFONT lf; // Lấy font mẫu từ “kho” HFONT hFont = (HFONT) GetStockObject(SYSTEM_FONT); // Lấy thuộc tính của font mẫu GetObject(hFont, sizeof(LOGFONT), (LOGFONT *) &lf); // Sửa đổi các thuộc tính cho phù hợp yêu cầu lf.lfHeight = -28; lf.lfWidth = 0; strcpy(lf.lfFaceName, "VNI-Helve"); // Tạo lập font mới hFont = CreateFontIndirect(&lf); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 27 Các khái niệm cơ bản - Đối tượng vẽ (tt)  Font (tt) VD2. Chọn thuộc tính font từ hộp thoại ChooseFont LOGFONT lf; CHOOSEFONT cf; HFONT hFont; // Khởi tạo cấu trúc CHOOSEFONT ZeroMemory(&cf, sizeof(CHOOSEFONT)); cf.lStructSize = sizeof(CHOOSEFONT); cf.hwndOwner = hFrameWnd; cf.lpLogFont = &lf; // Nhận thuộc tính font trả về cf.Flags = CF_SCREENFONTS | CF_EFFECTS; cf.rgbColors = RGB(0, 255, 255); // light blue cf.nFontType = SCREEN_FONTTYPE; if (ChooseFont(&cf)) { // Tạo lập font mới hFont = CreateFontIndirect(&lf); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 28 14
  15. Các khái niệm cơ bản - Đối tượng vẽ trong MFC Đối tượng Lớp MFC Pen CPen Brush CBrush Font CFont VD1. tạo đối tượng Pen (C1) CPen pen(PS_SOLID, 1, RGB (255, 0, 0)); VD2. tạo đối tượng Pen (C2) CPen pen; pen.CreatePen(PS_SOLID, 1, RGB (255, 0, 0)); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 29 Các khái niệm cơ bản - Đối tượng vẽ trong MFC (tt) VD3. tạo đối tượng Pen,dùng cấu trúc LOGPEN (C3) CPen pen; LOGPEN lp; lp.lopnStyle = PS_SOLID; lp.lopnWidth.x = 1; lp.lopnColor = RGB(255, 0, 0); pen.CreatePenIndirect(&lp); VD4. sử dụng đối tượng Pen để vẽ CPen* pOldPen = dc.SelectObject(&pen); dc.Ellipse(0, 0, 100, 100); VD5. hai cách để tạo solid brush CBrush brush(RGB(255, 0, 0)); CBrush brush; brush.CreateSolidBrush(RGB(255, 0, 0)); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 30 15
  16. Các khái niệm cơ bản - Đối tượng vẽ trong MFC (tt) VD6. tạo Hatch brush và dùng để tô bên trong HCN CBrush brush(HS_DIAGCROSS, RGB(255, 255, 255)); dc.SelectObject(&brush); dc.SetBkColor(RGB(192, 192, 192)); // tô trên nền xám dc.Rectangle(0, 0, 100, 100); VD7. tạo đối tượng Font có cỡ chữ 12 point CFont font; font.CreatePointFont(120, _T("Times New Roman")); VD8. tạo đối tượng Font bằng cấu trúc LOGFONT LOGFONT lf; ::ZeroMemory(&lf, sizeof(lf)); lf.lfHeight = 120; lf.lfWeight = FW_BOLD; lf.lfItalic = TRUE; ::lstrcpy(lf.lfFaceName, _T("Times New Roman")); CFont font; font.CreatePointFontIndirect(&lf); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 31 Các khái niệm cơ bản - Đối tượng vẽ trong MFC (tt) VD9. tạo font và dùng để xuất ký tự CClientDC dc(this); CFont font; font.CreatePointFont(120, _T("Arial"))); CFont* def_font = dc.SelectObject(&font); dc.TextOut(5, 5, _T("Hello, World !"), 14); dc.SelectObject(def_font); font.DeleteObject(); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 32 16
  17. Các ví dụ vẽ hình đồ họa VD1. Vẽ 1 đoạn thẳng dc.MoveTo(0, 0); dc.LineTo(0, 100); VD2. Vẽ 1 tứ giác POINT aPoint[5]={0, 0, 0, 100, 100, 100, 100, 0, 0, 0}; dc.Polyline(aPoint, 5); VD3. Vẽ 1 cung CRect rect (0, 0, 200, 100); CPoint point1 (0, -500); CPoint point2 (-500, 0); dc.Arc (rect, point1, point2); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 33 Các ví dụ vẽ hình đồ họa (tt) VD4. Vẽ 1 đường cong hình sin bằng Polyline #include #define SEGMENTS 500 #define PI 3.1415926 void CMainWindow::OnPaint() { CRect rect; GetClientRect(&rect); int nWidth = rect.Width(); int nHeight = rect.Height(); CPaintDC dc(this); CPoint aPoint[SEGMENTS]; for (int i=0; i<SEGMENTS; i++) { aPoint[i].x = (i*nWidth)/SEGMENTS; aPoint[i].y = (int)((nHeight/2)*(1-(sin((2*PI*i) / SEGMENTS)))); } dc.Polyline (aPoint, SEGMENTS); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 34 17
  18. Các ví dụ vẽ hình đồ họa (tt) VD5. Vẽ 1 đường cong với hàm PolyBezier POINT aPoint1[4] = {120,100,120,200,250,150,500,40}; POINT aPoint2[4] = {120,100,50,350,250,200,500,40}; dc.PolyBezier(aPoint1, 4); dc.PolyBezier(aPoint2, 4); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 35 Xử lý ảnh Bitmap  DDB và DIB  Vẽ một DDB C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 36 18
  19. Xử lý ảnh Bitmap - DDB và DIB  DDB (Device Dependent Bitmap) ƒ Có nhiều loại thiết bị khác nhau để lưu trữ/hiển thị ảnh bitmap Æ cần có nhiều định dạng (format) khác nhau để lưu ảnh trên thiết bị ƒ Các định dạng này gọi là DDB  DIB (Device Independent Bitmap) ƒ Các định dạng DDB sẽ không tương thích trên các loại thiết bị khác nhau ƒ DIB là một định dạng do Windows cung cấp nhằm đảm bảo ảnh được lưu trữ “độc lập với thiết bị” Æ tương thích với nhiều loại thiết bị ƒ Khi ta load một DIB, device driver sẽ chuyển đổi nó thành dạng DDB ứng với thiết bị C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 37 Xử lý ảnh Bitmap - Vẽ một DDB  Hàm BitBlt (CDC::BitBlt): copy 1 ảnh bitmap từ DC nguồn (hdcSrc) sang DC đích (hdcDest) BOOL BitBlt(HDC hdcDest, DC int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);  Hàm StretchBlt (CDC::StretchBlt): copy 1 ảnh bitmap từ DC nguồn (hdcSrc) sang DC đích (hdcDest), đồng thời co/giãn ảnh BOOL StretchBlt(HDC hdcDest, int nXDest, int nYDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXSrc, int nYSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 38 19
  20. Xử lý ảnh Bitmap - Vẽ một DDB (tt)  Lấy thông tin của ảnh bitmap: ƒ API: Hàm GetObject BITMAP bm; GetObject(hBitmap,sizeof(BITMAP),&bm); ƒ MFC: hàm CBitmap::GetBitmap BITMAP bm; bitmap.GetBitmap(&bm); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 39 Xử lý ảnh Bitmap - Vẽ một DDB (tt) VD. Load bitmap từ resource,vẽ lên cửa sổ View CxxxView::OnDraw(CDC* pDC) { CBitmap bitmap; CBitmap oldBitmap; BITMAP bm; CDC dcMemory; bitmap.LoadBitmap(IDB_SAMPLE); bitmap.GetBitmap(&bm); dcMemory.CreateCompatibleDC(pDC); oldBitmap = dcMemory.SelectObject(&bitmap); pDC->BitBlt(100, 100, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY); dcMemory.SelectObject(&oldBitmap); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 40 20
  21. In ấn (Printing)  Tổng quan về in ấn trong Windows  In ấn trong MFC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 41 In ấn (Printing) - Tổng quan về in ấn trong Windows  Nguyên tắc cơ bản về in ấn  Print job  Banding  Spooling  Printer DC  Một chương trình in đơn giản dùng API C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 42 21
  22. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt)  Nguyên tắc cơ bản về in ấn ƒ Tạo DC của máy in bằng cách dùng lệnh CreateDC hoặc dùng hộp thoại PrintDlg ƒ Gọi hàm StartDoc để bắt đầu in một tài liệu mới ƒ Gọi hàm StartPage để bắt đầu 1 trang in ƒ Gọi các hàm vẽ của GDI để thể hiện văn bản (text) hay hình ảnh (bitmap, graphics) ra trang in ƒ Gọi hàm EndPage để kết thúc 1 trang in ƒ Gọi hàm EndDoc để kết thúc in tài liệu Note: ƒ Các hàm StartDoc/EndDoc, StartPage/EndPage đều thuộc thư viện GDI ƒ Bước [3], [4], [5] có thể làm nhiều lần nếu muốn in trên nhiều trang C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 43 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 44 22
  23. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt)  Print job (tác vụ in) ƒ Là một tài liệu cần in ƒ Có thể chứa 1 hay nhiều trang in ƒ Print job được định nghĩa bởi 1 cặp lệnh StartDoc/EndDoc ƒ Cấu trúc dữ liệu được dùng cho print job là Enhanced Metafile (EMF) ƒ EMF: cấu trúc dùng để lưu trữ các lệnh vẽ text, vẽ đồ họa, C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 45 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt)  Banding ƒ GDI lưu trữ các lệnh vẽ lên máy in trong một file có dạng ~EMF*.TMP (Enhanced Metafile) ƒ Khi ứng dụng kết thúc in ấn 1 trang (bằng lệnh EndPage), printer driver sẽ chuyển đổi các lệnh vẽ trong metafile thành các kết xuất thực sự trên máy in Æ cần thiết phải tạo ra 1 trang đồ họa ƒ Kích thước bộ nhớ cho 1 trang đồ họa khá lớn (VD. Máy in 600DPI, giấy letter cần khoảng 4MB) ƒ Do đó, printer driver thường sử dụng kỹ thuật “chia band”: chia 1 trang đồ họa thành nhiều vùng hình chữ nhật ƒ GDI sẽ lấy kích thước band từ printer driver (tùy thuộc máy in) và thực hiện các lệnh vẽ trong metafile lên các band của 1 trang C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 46 23
  24. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt)  Spooling ƒ Windows quản lý quá trình in ấn bằng trình quản lý in (Printer Spooler) ƒ Printer spooler được tự động nạp khi Windows khởi động và kết thức khi HĐH shutdown ƒ Printer spooler giúp:  Xác định trình điều khiển máy in; nạp vào bộ nhớ  Lập lịch cho việc in ấn  Gởi dữ liệu ra máy in qua cổng (parallel, serial)  Xoá các file TMP sau khi in xong  User có thể tắt cơ chế Spooling đối với một máy in (trong Printer properties/Ports) ƒ Để in nhanh hơn, vì GDI không lưu dữ liệu cần in lên file mà gởi trực tiếp ra máy in ƒ Hoặc dùng một trình điều khiển spooling khác (VD. Máy in mạng) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 47 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 48 24
  25. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 49 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt)  Printer DC ƒ Việc đầu tiên khi in là phải tạo ra Printer DC ƒ Sử dụng Printer DC trong các lệnh GDI giống như dùng Window DC ƒ User có thể cài đặt nhiều máy in, nhưng chỉ có 1 máy in mặc định (default) ƒ Mỗi máy in đều có trình điều khiển tương ứng ƒ Cần phải xác định tên của máy in khi tạo Printer DC ƒ Có 2 cách tạo Printer DC  Tạo Printer DC trực tiếp  Tạo Printer DC bằng cách dùng hộp thoại chuẩn PrintDlg C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 50 25
  26. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) VD1. Tạo Printer DC trực tiếp HDC GetPrinterDC() { DWORD dwNeeded, dwReturned; HDC hdc; PRINTER_INFO_4 * pinfo4; PRINTER_INFO_5 * pinfo5; if (GetVersion() & 0x80000000) // Windows 98 { EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, NULL, 0, &dwNeeded, &dwReturned); pinfo5 = malloc(dwNeeded); EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, (PBYTE)pinfo5,dwNeeded,&dwNeeded,&dwReturned); hdc = CreateDC(NULL, pinfo5->pPrinterName, NULL, NULL); free(pinfo5); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 51 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) VD1. Tạo Printer DC trực tiếp (tt) else // Windows NT { EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned); pinfo4 = malloc(dwNeeded); EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE)pinfo4,dwNeeded,&dwNeeded,&dwReturned); hdc = CreateDC(NULL, pinfo4->pPrinterName, NULL, NULL); free(pinfo4); } return hdc; } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 52 26
  27. In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) VD 2. Tạo Printer DC: dùng hộp thoại chuẩn PrintDlg HDC GetPrinterDC() { PRINTDLG pd; HWND hwnd = GetFocus(); // Initialize PRINTDLG ZeroMemory(&pd, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.hwndOwner = hwnd; pd.hDevMode = NULL; pd.hDevNames = NULL; pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; pd.nCopies = 1; pd.nFromPage = 0xFFFF; pd.nToPage = 0xFFFF; pd.nMinPage = 1; pd.nMaxPage = 0xFFFF; if (PrintDlg(&pd)==TRUE) return pd.hDC } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 53 In ấn (Printing) - Tổng quan về in ấn trong Windows (tt) VD. Một chương trình in đơn giản dùng API int doPrint() { DOCINFO di={sizeof(DOCINFO), TEXT(“SamplePrinting")}; HDC dcPrint = GetPrinterDC(); if (dcPrint != NULL) { if (StartDoc(dcPrint, &di) <= 0) return 0; if (StartPage(dcPrint) <= 0) { EndDoc(dcPrint); return 0; } // các lệnh thể hiện text, graphics lên trang in EndPage(dcPrint); EndDoc(dcPrint); DeleteDC(dcPrint); } return 1; // thành công } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 54 27
  28. In ấn (Printing) - In ấn trong MFC  Sử dụng các kỹ thuật in của Windows trong MFC  Kỹ thuật in của MFC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 55 In ấn trong MFC - Sử dụng các kỹ thuật in của Windows  VD1. Tạo Printer DC trực tiếp  VD2. Tạo Printer DC từ máy in mặc định  VD3. Tạo Printer DC dùng hộp thoại Print  VD4. Một chương trình in C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 56 28
  29. In ấn trong MFC - Sử dụng các kỹ thuật in của Windows (tt) VD1. Tạo Printer DC trực tiếp CDC dc; dc.CreateDC(NULL, _T("HP LaserJet IIP"), NULL, NULL); VD2. Tạo Printer DC từ máy in mặc định CDC dc; CPrintDialog dlg(FALSE); dlg.GetDefaults(); dc.Attach(dlg.GetPrinterDC()); VD3. Tạo Printer DC dùng hộp thoại Print CDC dc; CPrintDialog dlg(FALSE); if (dlg.DoModal()==IDOK) dc.Attach(dlg.GetPrinterDC()); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 57 In ấn trong MFC - Sử dụng các kỹ thuật in của Windows (tt) VD4. Một chương trình in DOCINFO di; ::ZeroMemory(&di, sizeof (DOCINFO)); di.cbSize = sizeof(DOCINFO); di.lpszDocName = _T(“Sample of print"); if (dc.StartDoc(&di) > 0) { BOOL bContinue = TRUE; for (int i=1; i<=nPageCount && bContinue; i++) { dc.StartPage(); // Xác lập các tham số cho Printer DC // In trang thứ i // if (dc.EndPage() <= 0) bContinue = FALSE; } if (bContinue) dc.EndDoc(); else dc.AbortDoc(); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 58 29
  30. In ấn trong MFC - Kỹ thuật in của MFC  Một ví dụ đơn giản với chức năng Print và Print Preview  Tổng quan  In trên nhiều trang C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 59 Kỹ thuật in của MFC  Một ví dụ đơn giản với chức năng Print và Print Preview ƒ Tạo 1 ứng dụng bằng MFC AppWizard ƒ Chọn option Single Document ƒ Chọn option Print and Print Preview ƒ Thêm dòng lệnh sau vào hàm CxxxView::OnDraw pDC->Rectangle(100, 100, 200, 200); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 60 30
  31. Kỹ thuật in của MFC Chọn option hỗ trợ in trong AppWizard C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 61 Kỹ thuật in của MFC Ứng dụng đơn giản có hỗ trợ Print và Print Preview của MFC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 62 31
  32. Kỹ thuật in của MFC - Tổng quan  Giới thiệu ƒ MFC framework tích hợp sẵn kỹ thuật in ấn, thực hiện phần lớn các công việc; giúp người lập trình tiết kiệm rất nhiều công sức và loại bỏ nhiều sự phức tạp như khi sử dụng Windows SDK  Tự động tạo và xóa Printer DC  Tự động gọi StartDoc/EndDoc, StartPage/EndPage  Hỗ trợ hộp thoại theo dõi trạng thái của print job; khả năng hủy bỏ in (Abort procedure)  Khả năng Print Preview, C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 63 Kỹ thuật in của MFC - Tổng quan (tt)  Giới thiệu (tt) ƒ Các hàm quan trọng của CView liên quan đến in ấn OnPreparePrinting() Được gọi khi bắt đầu print job. Xác định số trang in; OnBeginPrinting() Được gọi trước khi việc in bắt đầu. Định nghĩa các tài nguyên sử dụng cho việc in (Font, Brush, ) OnPrepareDC() Được gọi trước khi in mỗi trang. Thay đổi tính chất của Printer DC OnPrint() Được gọi để thực hiện in mỗi trang. In Header, Footer, và gọi đến hàm OnDraw để in phần chính của trang OnEndPrinting() Được gọi khi kết thúc print job. Giải phóng các tài nguyên C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 64 32
  33. Kỹ thuật in của MFC - In trên nhiều trang  Tạo 1 ứng dụng bằng MFC AppWizard với các options Single Document và Print and Print Preview  Thêm đoạn lệnh sau vào hàm CxxxView::OnDraw // Chuyển đổi 1 pixel = 1/100 inch pDC->SetMapMode(MM_LOENGLISH); // m_numRects: số hình chữ nhật muốn vẽ // W = H = 100 pixel, khoảng cách 20 pixel for (int i=0; i Rectangle(0, -i*120, 100, -(i+1)*120+20); C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 66 33
  34. Kỹ thuật in của MFC - In trên nhiều trang (tt) Các hình chữ nhật không hiển thị đúng trên nhiều trang in C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 67 Kỹ thuật in của MFC - In trên nhiều trang (tt)  Các bước thực hiện để in nhiều trang ƒ B1. Thông báo cho MFC biết số trang cần in void CxxxView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo) { CxxxDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); int pageHeight = pDC->GetDeviceCaps(VERTRES); int logPixelsY = pDC->GetDeviceCaps(LOGPIXELSY); int rectHeight = (int)(1.2 * logPixelsY); int numPages = pDoc->m_numRects*rectHeight/pageHeight + 1; pInfo->SetMaxPage(numPages); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 68 34
  35. Kỹ thuật in của MFC - In trên nhiều trang (tt) Các hình chữ nhật đã hiển thị trên nhiều trang in, nhưng nội dung các trang giống hệt nhau C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 69 Kỹ thuật in của MFC - In trên nhiều trang (tt)  Các bước thực hiện để in nhiều trang (tt) ƒ B2. Định nghĩa lại hàm CxxxView::OnPrepareDC void CxxxView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { if (pDC->IsPrinting()) { int pageHeight = pDC->GetDeviceCaps(VERTRES); int originY = pageHeight * (pInfo->m_nCurPage - 1); pDC->SetViewportOrg(0, -originY); } CView::OnPrepareDC(pDC, pInfo); } C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 70 35
  36. Kỹ thuật in của MFC - In trên nhiều trang (tt) Dùng ClassWizard định nghĩa lại hàm OnPrepareDC C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 71 Kỹ thuật in của MFC - In trên nhiều trang (tt) Các hình chữ nhật đã hiển thị đúng trên nhiều trang C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 72 36
  37. Cám ơn - Hỏi & Đáp C4W - GDI - Nguyen Tri Tuan - DH.KHTN Tp.HCMSummer 2004 73 37