Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Trang 1 của 2 12 CuốiCuối
Kết quả 1 đến 10 của 17
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Tutorial - Tạo một chương trình MFC đơn giản trong VC++ 2008 bằng hình ảnh

    Trên diễn đàn hiện này có khá nhiều bạn đang mới bắt đầu học VC++ MFC. Tớ xin mạo muội làm một Tút nhỏ, hướng dẫn anh em viết một chương trình MFC nhỏ từng bước một giúp các bạn đỡ phần gian nan ,bỡ ngỡ trong việc học MFC ban đầu, hướng dẫn bằng hình ảnh trong VC++ 2008:

    Bước 1: Tạo một Project mới ->Visual C++ -> Win32 Project -> Đặt tên cho Project là SimpleMFC, sau đó chọn Empty Project


    Bước 2: Cấu hình để ứng dụng của ta sử dụng thư viện MFC:
    Trong cửa sổ Solution Explorer nhấn chuột phải vào Project SimpleMFC sau đó chọn Properties
    Tìm và chọn mục Use MFC in Shared Dll


    Bước 3:
    Sau đó trong cửa số Solution Explorer->Source Files
    Nhấn chuột phải vào đây Chọn Add->New Item.
    Sau đó chọn C++ Source File (*.cpp) gõ vào name là
    SimpleMFCApp.cpp .

    Sau đó sửa nội dung của File đó như sau

    Mã:
    //SimpleMFCApp.cpp#pragma once//======== Thêm dòng này vào đây nếu chưa có để khai báo sử dụng thư viện MFC ==============#include "afxwin.h"  //=== Khai báo có lớp MainWnd là lớp cửa sổ chính của chương trình kế thừa từ CFrameWnd ====class MainWnd:public CFrameWnd{    public:        //Constructor khởi tạo        MainWnd()        {            //Tạo cửa sổ cho trình ứng dụng của ta            Create(NULL,_T("Simple MFC Application"));        }         //Destructor        ~MainWnd(){};};  //============== Lớp của ứng dụng kế thừa từ CWinApp ==============class CSimpleMFCApp :    public CWinApp{public:    CSimpleMFCApp(void){};    ~CSimpleMFCApp(void){};    //Viết đè hàm Khởi tạo Application của lớp CWinApp    virtual BOOL InitApplication()    {        //Đăng ký lớp cửa sổ chính của ứng dụng là một đối tượng MainWnd        //Sau này đa phân bạn sẽ làm việc với lớp MainWnd để tùy biến ứng dụng của mình        m_pMainWnd=new MainWnd();                //Hiển thị cửa sổ        m_pMainWnd->ShowWindow(SW_SHOW);        m_pMainWnd->UpdateWindow();        return TRUE;    }; }theApp;
    Bầm F5 để Build and Run. Bạn sẽ thấy thành quả.
    Part2 : Drawing on client size of MainWnd. Vẽ vời trong vùng client của cửa sổ chính chương trình.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Part2[IMG]images/smilies/biggrin.png[/IMG]rawing in client Area

    Việc vẽ trong MFC cũng giống như vẽ trong Win32API, sử dụng đáp ứng sự kiện WM_PAINT của hệ thống gửi cho cửa sổ chính.

    Trong một cửa sổ Windows, chia làm hai vùng chính là vùng Client (Vùng cho phép bạn vẽ và thao tác) và vùng None-Client (Được Windows tự động vẽ, bao gồm Title chứa caption và các nút Button Minimized, Maximized, và Close Button).

    Để mục đích chính của ta trong phần này là vẽ trong trong vùng Client của ứng chương trình. Để vẽ được bạn cần phải có DC (Device Context - là một khái niệm, một thành phần của cửa số dùng để lưu các thông tin về phương thức, định dạng hiển thị bao gồm màu nền, màu của text, hệ tọa độ, viewport and so on..)
    Tip: Nếu bạn không tìm thấy bất kỳ cửa sổ nào trong hình dưới đây, bạn có thể tìm thấy chúng qua menu View hoặc View->Other Windows trong Visual C++ 2008
    Bước 1: Trong cửa sổ Class Explorer bạn chọn lớp MainWnd, sau khi chọn cửa lớp này, cửa sổ Properties của lớp sẽ được tự động mở ra ở bên dưới. Lúc đó trên thanh công cụ nhỏ của Properties bạn tìm button Message

    Sau khi bạn chọn thì một list các Message sẽ hiện ra ngay trong cửa sổ Properties, lúc đó bạn tìm đến message WM_PAINT. VC++ IDE sẽ tựng động thêm cho bạn code cho bạn trong SimpleMFCApp.cpp

    Mã:
    class MainWnd{ //......    DECLARE_MESSAGE_MAP()    afx_msg void OnPaint(); //......}; //......BEGIN_MESSAGE_MAP(MainWnd, CFrameWnd)    ON_WM_PAINT() //Đăng ký đáp ứng Message WM_PAINT cho lớp cửa sổ MainWnd bởi hàm OnPaint() của MFC FrameWorkEND_MESSAGE_MAP()//....... //.......void MainWnd::OnPaint(){    CPaintDC dc(this); // device context for painting    // TODO: Add your message handler code here    // Do not call CFrameWnd::OnPaint() for painting messages }//......
    Lúc này bạn thấy có một phương thức OnPaint() của lớp MainWnd và công việc của bạn là thêm code vẽ vào đây.
    Chú ý: Theo mặc định, vùng client của bạn có gốc tọa độ Đề các Oxy nằm ở góc trên cùng bên trái vùng client. Từ gốc này sang bên phải là (Góc trên cùng bên trái -> Góc trên cùng bên phải)trục Ox , từ điểm O xuống dưới (Góc trên cùng bên trái -> Góc dưới cùng bên trái) là chiều của Oy
    Do đó bạn có thể bắt đầu vẽ từ tọa độ (0,0) đến (Width,Heigth) của vùng client, thì hình của bạn sẽ hiển thị được trên vùng client Client.
    Tips: Để lấy thông tin về vùng client bạn sử dụng hàm GetClientRect()

    Để xác kiểu nét vẽ,định màu và độ rộng nét vẽ, bạn sử dụng CPen, để xác định màu nền tô cho hình vẽ bạn sử dụng lớp CBrush.

    Bạn thêm và sửa hàm OnPaint như sau:

    Mã:
    void MainWnd::OnPaint(){    CPaintDC dc(this); // device context for painting    // TODO: Add your message handler code here    // Do not call CFrameWnd::OnPaint() for painting messages        //Sử dụng hàm GetClientRect() để lấy thông tin về vùng client    CRect clRect;    GetClientRect(clRect);     //Đưa thông tin của client rect lên title bar thông qua hàm SetWindowText()    CString info;    info.Format(_T("x=%d y=%d width=%d height=%d"),clRect.left,clRect.top,clRect.Width(),clRect.Height());    SetWindowText(info);     //Lấy DC để vẽ vùng client    CClientDC clDC(this);    //Vẽ một đoạn Text ở chính giữa cửa sổ vùng Client    clDC.DrawText(_T("Hello MFC"),clRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);     //Xác định nét vẽ.    CPen pen(PS_ALTERNATE,2,RGB(0,255,0));     //Xác đỉnh chổi tô màu là màu của Caption khi activate (màu thanh title bar khi cửa số có Focus)        CBrush brush;    brush.CreateSysColorBrush(COLOR_GRADIENTACTIVECAPTION);     CPen *oldPen=clDC.SelectObject(&pen);    CBrush *oldBrush=clDC.SelectObject(&brush);     //Vẽ một hình chữ nhật ở toạ độ khác  có tô màu viền bằng Pen và màu nền bằng màu của CBrush    clDC.Rectangle(10,10,100,100);        //Vẽ một hình chữ nhật có Text ở bên trong    CRect rect(150,150,250,250);    clDC.Rectangle(rect);        //Vẽ text trong Rectanlge với Transparent Background    clDC.SetBkMode(TRANSPARENT);    clDC.DrawText(_T("Text"),rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);     //Khôi phục lại Pen cũ mặc định và chổi vẽ tô màu mặc định    clDC.SelectObject(oldPen);    clDC.SelectObject(oldBrush);}
    F5 Build and Run để thấy thành quả.

    Bạn có thể tự khám phá vẽ các hình cơ bản từ clDC bằng cách clDC. Intellisence của VC++ sẽ tự động liệt kê các phương thức vẽ các hình cơ bản như vẽ Elipse vẽ cung Arc, AngleArc, ArcTo, vẽ đường thẳng Line, LineTo..

    Đặc biệt có hai hàm là SetPixel() và GetPixel() để bạn vẽ/ lấy thông tin từng điểm ảnh một,sử dụng cho các bác đang học môn Đồ họa máy tính để tiện thực hành

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Nếu có gì chưa rõ xin các bạn cứ hỏi.

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Sẵn đây mình có câu hỏi này, các bạn trả lời giúp mình nhé.
    Trước tiên, đây là code toàn bộ ví dụ:

    //Hello.h

    Mã:
    class CMyApp:public CWinApp{public:        virtual BOOL InitInstance();};class CMyFrame:public CFrameWnd{public:         CMyFrame();protected:        afx_msg void OnPaint();        DECLARE_MESSAGE_MAP()};
    //Hello.cpp

    Mã:
    #include<afxwin.h>#include"Hello.h" BOOL CMyApp::InitInstance(){        m_pMainWnd=new CMyFrame;        m_pMainWnd->ShowWindow(SW_NORMAL);        m_pMainWnd->UpdateWindow();        return TRUE;}CMyFrame::CMyFrame(){        Create (NULL, _T ("Hello"), WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,CRect (32, 64, 352, 304));        }BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)    ON_WM_PAINT()END_MESSAGE_MAP() void CMyFrame::OnPaint(){        /*CPaintDC dc(this);        CRect rect;        GetClientRect(&rect);                dc.DrawText(_T("Hello World!"),-1,&rect,DT_SINGLELINE |DT_CENTER| DT_VCENTER);        */                CPaintDC dc(this);        CRect rect(0, 0,320, 240);                dc.DrawText(_T("Hello World!"),-1,&rect,DT_SINGLELINE |DT_CENTER| DT_VCENTER);                }CMyApp theApp;
    Mình muốn viết dòng "Hello MFC!" ở giữa màn hình. Hàm OnPaint như thế này:

    Mã:
    void CMyFrame::OnPaint(){                    CPaintDC dc(this);        CRect rect;        GetClientRect(&rect);                dc.DrawText(_T("Hello World!"),-1,&rect,DT_SINGLELINE |DT_CENTER| DT_VCENTER); }
    Và kết quả là thành công.



    Thay vì phải dùng hàm GetClientRect(&rect) để lấy kích thước vùng Client, mình tính toán và đặt thẳng cái kích thước vùng client đó vào đối tượng rect (mình chỉ làm để kiểm tra hiểu biết của bản thân mình thôi). Và đoạn code trên được sửa lại thế này:



    Mã:
    CPaintDC dc(this);        CRect rect(0, 0,320, 240);                dc.DrawText(_T("Hello World!"),-1,&rect,DT_SINGLELINE |DT_CENTER| DT_VCENTER);
    Và kết quả là nó in bị lệch so với dự tính của mình. Nếu phóng to cửa sổ và nó in lệch thì mình không thắc mắc vì nó cứ nhằm toạ độ mình định sẵn của Client mà in.



    Mình không hiểu tại sao lại bị thế này nữa, các bạn giải thích giúp mình với.

    Đây là source code của nó.

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Không rõ câu hỏi.

    Vùng Client của Windows sẽ bị thay đổi khi bạn Resize kích thước cửa sổ.
    Sau khi resize Window sẽ được vẽ lại trong OnPaint() vì thế mà GetClientRect() luôn lấy được kích thước của vùng Client sau khi quá trình Resize cửa sổ hoàn tất.

    Còn việc bạn đặt kích thước xác định cho rect để DrawText thì nghiễn nhiên nó hoạt động đúng. Việc text "Hello" được vẽ ở chính giữa màn hình khi và chỉ khi rect mà bạn đặt chính là bằng ClientRect của cửa sổ.

    Hàm drawText với các tham số định dạng DT_SINGLELINE|DT_CENTER|DT_VCENTER sẽ vẽ text được căn chỉnh ở chính giữa bên trên (theo chiều dọc DT_VCENTER và chính giữa theo chiều ngang DT_CENTER)

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi Tadius
    Việc text "Hello" được vẽ ở chính giữa màn hình khi và chỉ khi rect mà bạn đặt chính là bằng ClientRect của cửa sổ.
    Thì mình đặt rect bằng kích thước Client của cửa sổ khi vừa được khởi tạo đấy bạn.Bạn có thể kiểm tra lại bằng cách vẽ hình chữ nhật có kích thước rect(0, 0,320, 240); Khi đó hình chữ nhật này nó có kích thước đúng bằng hình chữ nhật lấy được bằng lệnh GetClientRect(&rect).

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi thanhphongcttv
    Thì mình đặt rect bằng kích thước Client của cửa sổ khi vừa được khởi tạo đấy bạn.Bạn có thể kiểm tra lại bằng cách vẽ hình chữ nhật có kích thước rect(0, 0,320, 240); Khi đó hình chữ nhật này nó có kích thước đúng bằng hình chữ nhật lấy được bằng lệnh GetClientRect(&rect).
    Vậy thử lấy GetClientRect() sau đó compare với cái Rect của bạn xem chúng nó có bằng nhau chưa. Sau dám chắc rằng 2 cái Rect đó bằng nhau.
    Nên nhớ là ClientRect khác với WindowRect.
    Cái bạn mô tả trong hàm tạo Frame là WindowRect chứ ko phải ClientRect @@

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi AlexBlack
    mình làm y đúc như các bạn ở bước 2 chỗ
    Use of MFC mình chọn Use MFC in a Shared DLL// không thấy cái không có chữ a
    rồi add file cpp vào. kết quả được cái màn hình trống trơn chả có gì hết. không có đoạn code như các bạn ghi. là sao vậy?
    Là mình phải gõ vào chứ sao. [IMG]images/smilies/17.gif[/IMG]
    Làm từng bước một mà. Tạo từ đầu không sử dụng Wizard

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    mình hiểu rồi. cảm ơn bạn nhiều.

  10. #10
    Trích dẫn Gửi bởi aydada
    hix, XP SP 2 không cài được C++0x >.<
    Ngay trong bản VC++ 2008 có cài SP1 đã hỗ trợ C++0x rồi nằm trong namespace TR1. Còn bản VC++ 2010 thì tích hợp sẵn.

 

 
Trang 1 của 2 12 CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •