Show toolbar
顯示具有 MFC 標籤的文章。 顯示所有文章
顯示具有 MFC 標籤的文章。 顯示所有文章

2013年8月27日 星期二

MFC draw face and lighting using OpenGL

標題:MFC使用OpenGL繪製面並打光
MFC (OpenGLglutLight.cpp):
#include <afxwin.h>
#include "OpenGLglut.h"
#include "glut.h"
 
class DocBoxy : public CDocument {
public:
    CClientDC *m_pDC;
    HGLRC hrc;
    DECLARE_DYNCREATE(DocBoxy) //宣告run-time類別
};
 
IMPLEMENT_DYNCREATE(DocBoxy, CDocument) //宣告DocBoxy為run-time類別
 
class FrameBoxy : public CFrameWnd {
public:
    afx_msg void OnExit() { //宣告關閉檔案事件
        if(MessageBox( TEXT("Are you sure you want to close this window?"), TEXT("DocViewBoxy"), MB_OKCANCEL | MB_ICONQUESTION ) == 1 ) {
            DestroyWindow();
        }
    }
    afx_msg void OnAbout() { //宣告關於事件
        MessageBox( TEXT("DocViewBoxy Version 1.0\nCopyright (C) 2013, By QQBoxy Huang.\nEmail: gs1458@gmail.com"), TEXT("About"), MB_OK );
    }
 
    DECLARE_DYNCREATE(FrameBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(FrameBoxy, CFrameWnd) //宣告FrameBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(FrameBoxy, CFrameWnd) //建立訊息映射表
    ON_COMMAND(ID_FILE_EXIT, OnExit)
    ON_COMMAND(ID_HELP_ABOUT, OnAbout)
END_MESSAGE_MAP()
 
class ViewBoxy : public CView {
public:
    void OnDraw(CDC * aDC) { //必須覆寫的虛擬函數
        DocBoxy *doc = (DocBoxy *)GetDocument();
        ASSERT_VALID(doc);
         
        glLoadIdentity();
 
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        glTranslatef(0.0f, 0.0f, -7.0f);
        glRotatef(-35.0f, 1.0f, 0.0f, 0.0f);
        glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
         
        /*glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_LINES);
            glVertex3f(0.0f, 0.0f, 0.0f);
            glVertex3f(20.0f, 0.0f, 0.0f);
        glEnd();
         */

        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_TRIANGLES);
         
        glNormal3f(-0.8944272f, 0.4472136f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
 
        glNormal3f(0.8944272f, 0.4472136f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, 0.4472136f, -0.8944272f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, 0.4472136f, 0.8944272f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        //glutWireTeapot(5.0);
        //glutSolidTeapot(5.0);

        glEnd();
 
        glFinish();
        SwapBuffers( doc->m_pDC->GetSafeHdc() );
    }
 
    BOOL PreCreateWindow(CREATESTRUCT& cs) {
        cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        return CView::PreCreateWindow(cs);
    }
     
    BOOL OnEraseBkgnd(CDC* pDC) {
        return true;
    }
 
    void OnDestroy() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        HGLRC hRC;
        hRC= wglGetCurrentContext();
        wglMakeCurrent(NULL, NULL);
        if (doc->hrc)
            wglDeleteContext(hRC);
        if (doc->m_pDC)
            delete doc->m_pDC;
        CView::OnDestroy();
    }
 
    bool bSetupPixelFormat() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
            1,                             // version number
            PFD_DRAW_TO_WINDOW |             // support window
            PFD_SUPPORT_OPENGL |           // support OpenGL
            PFD_DOUBLEBUFFER,              // double buffered
            PFD_TYPE_RGBA,                 // RGBA type
            24,                            // 24-bit color depth
            0, 0, 0, 0, 0, 0,              // color bits ignored
            0,                             // no alpha buffer
            0,                             // shift bit ignored
            0,                             // no accumulation buffer
            0, 0, 0, 0,                    // accum bits ignored
            32,                            // 32-bit z-buffer
            0,                             // no stencil buffer
            0,                             // no auxiliary buffer
            PFD_MAIN_PLANE,                // main layer
            0,                             // reserved
            0, 0, 0                        // layer masks ignored
        };
 
        int pixelformat;
 
        if( (pixelformat = ChoosePixelFormat(doc->m_pDC->GetSafeHdc(), &pfd)) == 0 ) {
            MessageBox(_TEXT("ChoosePixelFormat failed"));
            return false;
        }
 
        if(SetPixelFormat(doc->m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE) {
            MessageBox(_TEXT("SetPixelFormat failed"));
            return false;
        }
 
        return true;
    }
 
    void init() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        PIXELFORMATDESCRIPTOR pfd; //宣告一個PixelFormat物件
        int n;
        doc->m_pDC = new CClientDC(this); //建立一個視窗繪圖物件
        ASSERT(doc->m_pDC != NULL);
        if (!bSetupPixelFormat()) return; //設定應用所需的像素格式
        n = GetPixelFormat(doc->m_pDC->GetSafeHdc()); //從Windows裡找尋符合我們設定的
        DescribePixelFormat(doc->m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd); //PixelFormat的索引值,並將之指定給pfd
        doc->hrc = wglCreateContext(doc->m_pDC->GetSafeHdc()); //將RC物件給DC物件
        wglMakeCurrent(doc->m_pDC->GetSafeHdc(), doc->hrc); //讓這個RC設定為作用中的物件
        glDepthFunc(GL_GREATER);
        glEnable(GL_DEPTH_TEST);
        glClearDepth(-2.0f);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }
 
    void setLight() {
        GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };  //環境光強度
        GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };  //光源漫射強度
        GLfloat LightPosition[]= { 1.0f, 0.0f, 0.0f, 0.0f }; //表示在x方向無限遠
 
        glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
        glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
        glEnable(GL_LIGHT0); //使用光源0
        glEnable(GL_LIGHTING); //打光
        glEnable(GL_COLOR_MATERIAL); //啟用材質顏色
    }
 
    int OnCreate(LPCREATESTRUCT lpCreateStruct) {
        if (CView::OnCreate(lpCreateStruct) == -1)
            return -1;
        init();
        setLight();
        return 0;
    }
     
    void OnSize(UINT nType, int cx, int cy) {
        CView::OnSize(nType, cx, cy);
 
        GLfloat nRange=20.f;
        if(cy == 0)
        {  cy = 1;  }
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
 
        if (cx <= cy) {
            glOrtho(-nRange, nRange, -nRange*cy/cx, nRange*cy/cx, -nRange, nRange);
        } else {
            glOrtho(-nRange*cx/cy, nRange*cx/cy, -nRange, nRange, -nRange, nRange);
        }
 
        glMatrixMode(GL_MODELVIEW);
        glViewport(0, 0, cx, cy);
    }
 
    DECLARE_DYNCREATE(ViewBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(ViewBoxy, CView) //宣告ViewBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(ViewBoxy, CView) //建立訊息映射表
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_SIZE()
END_MESSAGE_MAP()
 
class AppBoxy : public CWinApp {
public:
    BOOL InitInstance() {
        CDocument *doc;    //宣告指向文件的指標
        CSingleDocTemplate* DocTemplate; //宣告指向單文件樣版物件的指標
 
        DocTemplate = new CSingleDocTemplate( //建立具有單文件樣版物件
            IDR_MENU, //用於單文件框架之資源的識別子
            RUNTIME_CLASS(DocBoxy), //單文件視窗的Document
            RUNTIME_CLASS(FrameBoxy),    //單文件視窗的視窗框架
            RUNTIME_CLASS(ViewBoxy)      //單文件視窗的View
        );
 
        AddDocTemplate(DocTemplate);   //將單文件樣版物件設定給MyApp
        doc = DocTemplate->CreateNewDocument();    //建立新的文件
 
        m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立一個視窗框架
        DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc ); //起始化視窗框架物件,並連結View物件
        m_pMainWnd->ShowWindow(SW_SHOW); //顯示視窗
 
        return true;
    }
};
 
AppBoxy appboxy; //建立應用程式物件

說明:
基礎MFC使用OpenGL繪製面並且打光。

MFC draw face using OpenGL

標題:MFC使用OpenGL繪製面
MFC (OpenGLglut.cpp):
#include <afxwin.h>
#include "OpenGLglut.h"
#include "glut.h"
 
class DocBoxy : public CDocument {
public:
    CClientDC *m_pDC;
    HGLRC hrc;
    DECLARE_DYNCREATE(DocBoxy) //宣告run-time類別
};
 
IMPLEMENT_DYNCREATE(DocBoxy, CDocument) //宣告DocBoxy為run-time類別
 
class FrameBoxy : public CFrameWnd {
public:
    afx_msg void OnExit() { //宣告關閉檔案事件
        if(MessageBox( TEXT("Are you sure you want to close this window?"), TEXT("DocViewBoxy"), MB_OKCANCEL | MB_ICONQUESTION ) == 1 ) {
            DestroyWindow();
        }
    }
    afx_msg void OnAbout() { //宣告關於事件
        MessageBox( TEXT("DocViewBoxy Version 1.0\nCopyright (C) 2013, By QQBoxy Huang.\nEmail: gs1458@gmail.com"), TEXT("About"), MB_OK );
    }
 
    DECLARE_DYNCREATE(FrameBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(FrameBoxy, CFrameWnd) //宣告FrameBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(FrameBoxy, CFrameWnd) //建立訊息映射表
    ON_COMMAND(ID_FILE_EXIT, OnExit)
    ON_COMMAND(ID_HELP_ABOUT, OnAbout)
END_MESSAGE_MAP()
 
class ViewBoxy : public CView {
public:
    void OnDraw(CDC * aDC) { //必須覆寫的虛擬函數
        DocBoxy *doc = (DocBoxy *)GetDocument();
        ASSERT_VALID(doc); //斷言,確認doc是否存在(在發行版本不會執行)
         
        glLoadIdentity();
 
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        glTranslatef(0.0f,0.0f,-1.0f);
        glColor3f(0.0f,0.0f,0.0f);
 
        /*glBegin(GL_LINES);
            glVertex3f(0.0f, 1.0, 0.0f);
            glVertex3f(-1.0, -1.0, 0.0f);
             
            glVertex3f(-1.0f, -1.0, 0.0f);
            glVertex3f(1.0f, -1.0, 0.0f);
 
            glVertex3f(1.0f, -1.0f, 0.0f);
            glVertex3f(0.0f, 1.0f, 0.0f);
        glEnd();*/
 
        glBegin(GL_TRIANGLES);
            glColor3f(1.0f,0.0f,0.0f); //Red
            glVertex3f( 0.0f, 1.0f, 0.0f); // Top
            glColor3f(0.0f,1.0f,0.0f); //Green
            glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
            glColor3f(0.0f,0.0f,1.0f); //Blue
            glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
        glEnd();
 
        glFinish(); //繪圖完畢
        SwapBuffers( doc->m_pDC->GetSafeHdc() ); //
    }
 
    BOOL PreCreateWindow(CREATESTRUCT& cs) {
        cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; //加入 WS_CLIPSIBLINGS 及 WS_CLIPCHILDREN 旗標
        return CView::PreCreateWindow(cs); //避免OpenGL畫到別的視窗
    }
     
    BOOL OnEraseBkgnd(CDC* pDC) {
        return true; //不要重繪視窗
    }
 
    void OnDestroy() { //清除記憶體
        DocBoxy *doc = (DocBoxy *)GetDocument();
        HGLRC hRC;
        hRC= wglGetCurrentContext();
        wglMakeCurrent(NULL,  NULL);
        if (doc->hrc)
            wglDeleteContext(hRC);
        if (doc->m_pDC)
            delete doc->m_pDC;
        CView::OnDestroy();
    }
 
    bool bSetupPixelFormat() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR), // 像素的結構大小
            1,                             // 版本號
            PFD_DRAW_TO_WINDOW |           // 緩衝特性:視窗支援
            PFD_SUPPORT_OPENGL |           // 緩衝特性:OpenGL支援
            PFD_DOUBLEBUFFER,              // 緩衝特性:雙精度緩衝
            PFD_TYPE_RGBA,                 // 設定顏色類型為RGBA
            24,                            // 色彩深度:24-bit color depth
            0, 0, 0, 0, 0, 0,              // color bits ignored
            0,                             // no alpha buffer
            0,                             // shift bit ignored
            0,                             // no accumulation buffer
            0, 0, 0, 0,                    // accum bits ignored
            32,                            // 深度緩衝:32-bit z-buffer
            0,                             // no stencil buffer
            0,                             // no auxiliary buffer
            PFD_MAIN_PLANE,                // main layer
            0,                             // reserved
            0, 0, 0                        // layer masks ignored
        };
 
        int pixelformat;
 
        if ( (pixelformat = ChoosePixelFormat(doc->m_pDC->GetSafeHdc(), &pfd)) == 0 ) {
            MessageBox(_TEXT("ChoosePixelFormat failed"));
            return false;
        }
 
        if (SetPixelFormat(doc->m_pDC->GetSafeHdc(), pixelformat, &pfd) == false) {
            MessageBox(_TEXT("SetPixelFormat failed"));
            return false;
        }
 
        return true;
    }
 
    void init() {
        int n;
        DocBoxy *doc = (DocBoxy *)GetDocument();
        PIXELFORMATDESCRIPTOR pfd; //宣告一個PixelFormat物件
        doc->m_pDC = new CClientDC(this); //建立一個視窗繪圖物件
        ASSERT_VALID(doc->m_pDC); //斷言,確認視窗繪圖物件是否存在(在發行版本不會執行)
        if (!bSetupPixelFormat()) return; //設定應用所需的像素格式
        n = GetPixelFormat(doc->m_pDC->GetSafeHdc()); //從Windows裡找尋符合我們設定的
        DescribePixelFormat(doc->m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd); //PixelFormat的索引值,並將之指定給pfd
        doc->hrc = wglCreateContext(doc->m_pDC->GetSafeHdc()); //將RC物件給DC物件
        wglMakeCurrent(doc->m_pDC->GetSafeHdc(), doc->hrc); //讓這個RC設定為作用中的物件
        glDepthFunc(GL_GREATER); //深度資訊
        glEnable(GL_DEPTH_TEST); //深度測試
        glClearDepth(-2.0f); //初始化深度
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //初始化顏色

        //PixelFormat:視窗的所有3D特徵設定,包括緩衝區、 顏色深度等集合的名稱
        //RC:背景渲染,OpenGL裡負責紀錄目前顏色,狀態設定等資訊的物件
    }
 
    int OnCreate(LPCREATESTRUCT lpCreateStruct) {
        if(CView::OnCreate(lpCreateStruct) == -1) { //判斷視窗生成
            return -1;
        }
        init();
        return 0;
    }
     
    void OnSize(UINT nType, int cx, int cy) {
        CView::OnSize(nType, cx, cy);
 
        GLfloat nRange = 5.0f; //比例係數
        if(cy == 0) { //防止分母為零
            cy = 1;
        }
 
        glMatrixMode(GL_PROJECTION); //透視場景
        glLoadIdentity(); //重新設定矩陣
 
        if (cx <= cy) { //調整視窗比例
            glOrtho(-nRange, nRange, -nRange*cy/cx, nRange*cy/cx, -nRange, nRange);
        } else {
            glOrtho(-nRange*cx/cy, nRange*cx/cy, -nRange, nRange, -nRange, nRange);
        }

        glMatrixMode(GL_MODELVIEW); //重新設定觀點矩陣
        glViewport(0, 0, cx, cy); //設定觀點
    }
 
    DECLARE_DYNCREATE(ViewBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(ViewBoxy, CView) //宣告ViewBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(ViewBoxy, CView) //建立訊息映射表
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_SIZE()
    //ON_WM_KEYDOWN()
    //ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
 
class AppBoxy : public CWinApp
{
public:
    BOOL InitInstance()
    {
        CDocument *doc;    //宣告指向文件的指標
        CSingleDocTemplate* DocTemplate; //宣告指向單文件樣版物件的指標
 
        DocTemplate = new CSingleDocTemplate( //建立具有單文件樣版物件
            IDR_MENU, //用於單文件框架之資源的識別子
            RUNTIME_CLASS(DocBoxy), //單文件視窗的Document
            RUNTIME_CLASS(FrameBoxy),    //單文件視窗的視窗框架
            RUNTIME_CLASS(ViewBoxy)      //單文件視窗的View
        );
 
        AddDocTemplate(DocTemplate);   //將單文件樣版物件設定給MyApp
        doc = DocTemplate->CreateNewDocument();    //建立新的文件
 
        m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立一個視窗框架
        DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc ); //起始化視窗框架物件,並連結View物件
        m_pMainWnd->ShowWindow(SW_SHOW); //顯示視窗
 
        return true;
    }
};
 
AppBoxy appboxy; //建立應用程式物件

說明:
基礎MFC使用OpenGL繪製面。

2013年8月5日 星期一

Create Static Splitter Window using MFC

標題:使用MFC建立靜態分割視窗
VC++ (SplitterWindow.cpp):
範例結果:


動態教學:
Open
直接下載:
http://docs.google.com/uc?id=0B8HdyDgIiLuHREdOUmVuSUtoZzA

說明:
在MFC中建立分割視窗,左視窗為CFrameWnd類別可設計表單,右視窗為CView類別可進行繪圖,注意須建立『IDD_FORMVIEW』之Dialog資源。

2013年4月26日 星期五

Create Document/View using MFC

標題:MFC之Document/View架構
VC++ (DocView.cpp):
#include <afxwin.h>
#include "DocView.h"

class DocBoxy : public CDocument //Document
{
    //在此撰寫Document內容
    DECLARE_DYNCREATE(DocBoxy) //宣告run-time類別
};

IMPLEMENT_DYNCREATE(DocBoxy, CDocument) //宣告DocBoxy為run-time類別

class FrameBoxy : public CFrameWnd //Frame
{
public:
    afx_msg void OnExit() //宣告關閉檔案事件
    {
        if(MessageBox( TEXT("Are you sure you want to close this window?"), TEXT("DocViewBoxy"), MB_OKCANCEL | MB_ICONQUESTION ) == 1 )
        {
            DestroyWindow();
        }
    }

    //在此撰寫Frame內容
    DECLARE_DYNCREATE(FrameBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};

//宣告FrameBoxy為run-time類別
IMPLEMENT_DYNCREATE(FrameBoxy, CFrameWnd)

//建立訊息映射表
BEGIN_MESSAGE_MAP(FrameBoxy, CFrameWnd)
    ON_COMMAND(ID_FILE_EXIT, OnExit)
END_MESSAGE_MAP()

class ViewBoxy : public CView //View
{
public:
    void OnDraw(CDC * aDC) //必須覆寫的虛擬函數
    {
        for(int i=0;i<10;i++)
        {
            aDC->TextOut(20 * i, 20 * i, L"HelloBoxy!!");
        }
    }
    //在此撰寫View內容
    DECLARE_DYNCREATE(ViewBoxy) //宣告run-time類別
};

IMPLEMENT_DYNCREATE(ViewBoxy, CView) //宣告ViewBoxy為run-time類別

class AppBoxy : public CWinApp
{
public:
    BOOL InitInstance() //程式進入點
    {
        CDocument *doc;
        CSingleDocTemplate* DocTemplate;

        DocTemplate = new CSingleDocTemplate(
            IDR_MENU,
            RUNTIME_CLASS(DocBoxy),   //Document
            RUNTIME_CLASS(FrameBoxy), //Frame
            RUNTIME_CLASS(ViewBoxy)   //View
        );

        AddDocTemplate(DocTemplate);
        doc = DocTemplate->CreateNewDocument();

        m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL );
        DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc );
        m_pMainWnd->ShowWindow(SW_SHOW);

        return true;
    }
};

AppBoxy appboxy; //建立應用程式物件
範例結果:


說明:
在Win32模式下建立MFC之Document/View架構之範例程式碼, 須建立『DocView.rc』資源檔及自動產生『DocView.h』並加入Menu指定ID為『IDR_MENU』。

2012年8月28日 星期二

VtkSDI draw 3D in MFC

標題:VtkSDI 3D 繪製範例
C++ (VtkSDIView.h):
// VtkSDIView.h : interface of the CVtkSDIView class
//

#pragma once

// Include the required header files for the vtk classes we are using
#include <vtkRenderer.h>
#include <vtkWin32OpenGLRenderWindow.h>
#include <vtkWin32RenderWindowInteractor.h>
 
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkGlyph3D.h>
#include <vtkElevationFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCubeAxesActor2D.h>

class CVtkSDIView : public CView
{
protected: // create from serialization only
    CVtkSDIView();
    DECLARE_DYNCREATE(CVtkSDIView)

// Attributes
public:
    CVtkSDIDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
    virtual void OnDraw(CDC* pDC);  // overridden to draw this view
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
    virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
    virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
    virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Implementation
public:
    void Pipeline ( void );
    virtual ~CVtkSDIView();
    vtkWin32OpenGLRenderWindow *renWin;
    vtkRenderer *ren;
    vtkWin32RenderWindowInteractor *iren;
            
    vtkSphereSource *sphere;
    vtkPolyDataMapper *sphereMapper;
    vtkElevationFilter *sphereElevation;
    vtkActor *sphereActor;
    vtkConeSource *cone;
    vtkGlyph3D *glyph;
    vtkPolyDataMapper *spikeMapper;
    vtkActor *spikeActor;
    vtkCubeAxesActor2D *sphereAxis;

#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
    afx_msg void OnFilePrintPreview();
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};

#ifndef _DEBUG  // debug version in VtkSDIView.cpp
inline CVtkSDIDoc* CVtkSDIView::GetDocument() const
   { return reinterpret_cast<CVtkSDIDoc*>(m_pDocument); }
#endif

C++ (VtkSDIView.cpp):
// VtkSDIView.cpp : implementation of the CVtkSDIView class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "VtkSDI.h"
#endif

#include "VtkSDIDoc.h"
#include "VtkSDIView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CVtkSDIView

IMPLEMENT_DYNCREATE(CVtkSDIView, CView)

BEGIN_MESSAGE_MAP(CVtkSDIView, CView)
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CVtkSDIView::OnFilePrintPreview)
    ON_WM_CONTEXTMENU()
    ON_WM_RBUTTONUP()
    ON_WM_SIZE()
    ON_WM_ERASEBKGND()
    ON_WM_CREATE()
END_MESSAGE_MAP()

// CVtkSDIView construction/destruction

CVtkSDIView::CVtkSDIView()
{
    // Create the the renderer, window and interactor objects.
    this->ren = vtkRenderer::New();
    this->renWin = vtkWin32OpenGLRenderWindow::New();
    this->iren = vtkWin32RenderWindowInteractor::New();
            
    // Create the the objects used to form the visualisation.
    this->sphere = vtkSphereSource::New();
    this->sphereElevation = vtkElevationFilter::New();
    this->sphereMapper = vtkPolyDataMapper::New();
    this->sphereActor = vtkActor::New();
    this->cone = vtkConeSource::New();
    this->glyph = vtkGlyph3D::New();
    this->spikeMapper = vtkPolyDataMapper::New();
    this->spikeActor = vtkActor::New();
    this->sphereAxis = vtkCubeAxesActor2D::New();
}

CVtkSDIView::~CVtkSDIView()
{
    // Delete the the renderer, window and interactor objects.
    this->ren->Delete();
    this->iren->Delete();
    this->renWin->Delete();
 
    // Delete the the objects used to form the visualisation.
    this->sphere->Delete();
    this->sphereElevation->Delete();
    this->sphereMapper->Delete();
    this->sphereActor->Delete();
    this->cone->Delete();
    this->glyph->Delete();
    this->spikeMapper->Delete();
    this->spikeActor->Delete();
    this->sphereAxis->Delete();
}

BOOL CVtkSDIView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs

    return CView::PreCreateWindow(cs);
}

// CVtkSDIView drawing

void CVtkSDIView::OnDraw(CDC* pDC)
{
    CVtkSDIDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    if ( !this->iren->GetInitialized() )
    {
        CRect rect;

        this->GetClientRect(&rect);
        this->iren->Initialize();
        this->renWin->SetSize(rect.right-rect.left,rect.bottom-rect.top);

        this->ren->ResetCamera();
 
    }

    // Invoke the pipeline
    Pipeline();

    if ( pDC->IsPrinting() )
    {
        this->BeginWaitCursor();

        // Obtain the size of the printer page in pixels.
        int cxPage = pDC->GetDeviceCaps(HORZRES);
        int cyPage = pDC->GetDeviceCaps(VERTRES);

        // Get the size of the window in pixels.
        int *size = this->renWin->GetSize();
        int cxWindow = size[0];
        int cyWindow = size[1];
        float fx = float(cxPage) / float(cxWindow);
        float fy = float(cyPage) / float(cyWindow);
        float scale = min(fx,fy);
        int x = int(scale * float(cxWindow));
        int y = int(scale * float(cyWindow));
        this->renWin->SetupMemoryRendering(cxWindow, cyWindow, pDC->GetSafeHdc());
        this->renWin->Render();
        HDC memDC = this->renWin->GetMemoryDC();
        StretchBlt(pDC->GetSafeHdc(),0,0,x,y,memDC,0,0,cxWindow,cyWindow,SRCCOPY);
        this->renWin->ResumeScreenRendering();

        this->EndWaitCursor();

    }
    else
    {
        this->renWin->Render();
    }
}


// CVtkSDIView printing


void CVtkSDIView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
    AFXPrintPreview(this);
#endif
}

BOOL CVtkSDIView::OnPreparePrinting(CPrintInfo* pInfo)
{
    // default preparation
    return DoPreparePrinting(pInfo);
}

void CVtkSDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add extra initialization before printing
}

void CVtkSDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add cleanup after printing
}

void CVtkSDIView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
    ClientToScreen(&point);
    OnContextMenu(this, point);
}

void CVtkSDIView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
    theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CVtkSDIView diagnostics

#ifdef _DEBUG
void CVtkSDIView::AssertValid() const
{
    CView::AssertValid();
}

void CVtkSDIView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}

CVtkSDIDoc* CVtkSDIView::GetDocument() const // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVtkSDIDoc)));
    return (CVtkSDIDoc*)m_pDocument;
}
#endif //_DEBUG


// CVtkSDIView message handlers


void CVtkSDIView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);

    CRect rect;
    this->GetClientRect(&rect);
    this->renWin->SetSize(rect.right-rect.left,rect.bottom-rect.top);
}


BOOL CVtkSDIView::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}


int CVtkSDIView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    this->renWin->AddRenderer(this->ren);
    // setup the parent window
    this->renWin->SetParentId(this->m_hWnd);
    this->iren->SetRenderWindow(this->renWin);

    return 0;
}


LRESULT CVtkSDIView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        //case WM_PAINT: 
        case WM_LBUTTONDOWN: 
        case WM_LBUTTONUP: 
        case WM_MBUTTONDOWN: 
        case WM_MBUTTONUP: 
        case WM_RBUTTONDOWN: 
        case WM_RBUTTONUP: 
        case WM_MOUSEMOVE:
        case WM_CHAR:
        case WM_TIMER:
        if (this->iren->GetInitialized())
        {
            return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
        }
        break;
    }

    return CView::WindowProc(message, wParam, lParam);
}

void CVtkSDIView::Pipeline()
{
    // Construct the sphere
    this->sphere->SetRadius(1);
    this->sphere->SetThetaResolution(18);
    this->sphere->SetPhiResolution(18);
    this->sphere->LatLongTessellationOn();
    // Generate elevations
    this->sphereElevation->SetInput(this->sphere->GetOutput());
    this->sphereElevation->SetLowPoint(0,0,-1);
    this->sphereElevation->SetHighPoint(0,0,1);
    this->sphereElevation->SetScalarRange(-1,1);
    // Link the mapper
    this->sphereMapper->SetInput(this->sphereElevation->GetPolyDataOutput());
    this->sphereMapper->SetColorModeToMapScalars();
    this->sphereMapper->SetScalarRange(-1,1);
    // Link the actor
    this->sphereActor->SetMapper(this->sphereMapper);
    // Add it to the renderer
    this->ren->AddActor(this->sphereActor);
 
    // Construct the cone
    this->cone->SetResolution(8);
 
    // Construct the glyphs on the spherical surface
    this->glyph->SetInput(this->sphere->GetOutput());
    this->glyph->SetSource(this->cone->GetOutput());
    this->glyph->SetVectorModeToUseNormal();
    this->glyph->SetScaleModeToScaleByVector();
    this->glyph->SetScaleFactor(0.1);
    // Link the mapper to the glyph
    this->spikeMapper->SetInput(this->glyph->GetOutput());
    // Link the actor
    this->spikeActor->SetMapper(this->spikeMapper);
    // Add it to the renderer
    this->ren->AddActor(this->spikeActor);
 
    // Add in the cube axis actor
    this->sphereAxis->SetInput(this->sphereElevation->GetOutput());
    this->sphereAxis->SetCamera(this->ren->GetActiveCamera());
    // Add it to the renderer
    this->ren->AddActor(this->sphereAxis);
}

說明:
MFC使用VTK 5.10.0繪製3D模型範例。