工程應用需在可停駐/浮動視窗中同時顯示三維模型的「主視圖」與兩個「子視圖」(如頂/前/側視圖)。核心挑戰:
wglMakeCurrent 切換至對應 RCCChildOGLView(子視圖基類)標準流程:
// Header
public:
CClientDC* m_pDC;
HGLRC m_hRC;
// OnCreate / OnInitialUpdate
m_pDC = new CClientDC(this);
m_hRC = wglCreateContext(m_pDC->GetSafeHdc());
// OnDraw / Render 函式
wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC); // 切換至本視圖 RC
// ... OpenGL 指令 ...
glFinish();
SwapBuffers(wglGetCurrentDC());
注意:wglMakeCurrent 必須在**同一執行緒**呼叫;MFC 視圖類別天然符合單執行緒 UI 模型。
定義列舉:
enum ViewType { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
主視圖類型存於 CMainFrame::m_ViewArrange.m_MainViewType;子視圖類型存於 m_ChildViewAType、m_ChildViewBType。
子視圖自我識別:因兩子視圖共用同一 CChildOGLView 類別,需在建立時指派唯一 ID:
// CChildOGLView.h
int m_ViewID; // 1 = ChildA, 2 = ChildB
// CMainFrame::OnCreate
void CMainFrame::AssignViewID() {
CEdit3DMDoc* pDoc = (CEdit3DMDoc*)m_pMainView->GetDocument();
POSITION pos = pDoc->GetFirstViewPosition();
int id = 1;
while (pos) {
CView* pView = pDoc->GetNextView(pos);
if (pView->IsKindOf(RUNTIME_CLASS(CChildOGLView))) {
((CChildOGLView*)pView)->m_ViewID = id++;
}
}
}
子視圖建立時自動註冊到文件:
// CChildOGLView::OnCreate
void CChildOGLView::AddMetoDoc() {
CEdit3DMDoc* pDoc = (CEdit3DMDoc*)GetDocument();
if (pDoc) pDoc->AddView(this); // 文件維護視圖清單
}
主視圖:
ViewType vt = ((CMainFrame*)GetParentFrame())->m_ViewArrange.m_MainViewType;
pDoc->m_3DMani.SetProjection(vt, 0);
pDoc->m_3DMani.DrawBound(vt);
子視圖:
ViewType vt = (m_ViewID == 1) ?
((CMainFrame*)AfxGetMainWnd())->m_ViewArrange.m_ChildViewAType :
((CMainFrame*)AfxGetMainWnd())->m_ViewArrange.m_ChildViewBType;
pDoc->m_3DMani.SetProjection(vt, 0);
pDoc->m_3DMani.DrawBound(vt);

三視圖同步旋轉/縮放,浮動視窗拖曳分離無閃爍。
CChildOGLView 模板化,支援任意數量子視圖CViewArrangeManager 封裝類型切換/持久化邏輯DrawBoundwglCreateContextAttribsARB + SetProcessDpiAwareness完整專案碼已開源,歡迎依專案需求裁剪擴充。