OnCreate VS OnInitialUpDate ^~^ OnPaint VS OnDraw

本文探讨了MFC编程中OnCreate与OnInitialUpdate的区别,OnPaint与OnDraw的应用场景及其实现方式。通过示例代码说明如何在不同事件中初始化控件与执行绘图操作。

OnCreate VS OnInitialUpDate ^~^ OnPaint VS OnDraw

大家通常会将接收命令行的语句放在哪个事件里呢?
ONCREATE还是ONSHOW还是ONACTIVE还是ONPAINT ?

视需要而定,ONCREATE只发生一次,ONSHOW/ONACTIVE/ONPAINT 是多次发生的,
ONSHOW是ONCREATE之后显示窗体时发生,并且在执行Hide之后执行Show又会发生。
ONACTIVE是焦点转到本窗口时发生,ONPAINT刷新窗体时发生,而且只刷新窗体
可见部分,如果窗体完全被挡住不可见,或者屏幕被锁定,就不会发生。

两者先后顺序不同,构造函数生成本类的对象,但没有产生窗口,OnCreate后窗口产生, 然后才是视图的OnInitialUpDate,一般在这里对视图的显示做初化。

  OnCreate只是产生VIEW的基本结构和变量,而在OnInitialUpDate中,主要对视图中控件等各个变量进行初始化操作。

  例:我们要在视图中添加一个button和combobox控件,则

OnCreate函数中写法如下:

int CFormView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
  if (CView::OnCreate(lpCreateStruct) == -1)

    return -1;
  // TODO: Add your specialized creation code here
  CRect rect(20,20,100,50);
  m_ctrlButton.Create("Button1",WS_CHILD|WS_VISIBLE,rect,this,NULL);

  CFont *pFont=CFont::FromHandle((HFONT)::GetStockObject(ANSI_VAR_FONT));
  CRect rect1(150,20,350,100);
  m_combobox.Create(WS_CHILD|WS_VISIBLE|CBS_SIMPLE|CBS_NOINTEGRALHEIGHT|WS_VSCROLL,rect1,this,NULL);

  return 0;
}


OnInitialUpDate中写法
void CFormView::OnInitialUpdate() 
{
  CView::OnInitialUpdate();

  // TODO: Add your specialized code here and/or call the base class
  //初始化组合框控件
  m_combobox.AddString("Mondy");
  m_combobox.AddString("Tuesday");
  m_combobox.AddString("Wednesday");
  m_combobox.AddString("Thursday");
  m_combobox.AddString("Saturday");
  m_combobox.AddString("Sunday");

}

  在MFC程序设计中,按照传统的设计,如果处理WM_PAINT消息,一般会派生一个OnPaint函数,映射到WM_PAINT消息上进行绘图处理。但是很多程序中并没有出现OnPaint,一个OnDraw函数做了更多的绘图操作。而在消息映射的列表中,也没有见到WM_PAINT到OnDraw的映射。

  实际上,OnDraw不是OnPaint的映射,出现OnDraw,是为了实现各种不同的设备上的绘图一致性。

  首先,读者需要明白的是,WM_PAINT消息是为了绘制屏幕而出现的,因此,在OnPaint中,我们只能存取屏幕DC,进行绘制,常见的代码是:

  void MyWnd::OnPaint()

  {

    CPaintDC dc(this);

    //draw code here

  }

  这里的CPaintDC的构造函数会自动调用BeginPaint,获得一个屏幕DC,并附加在dc对象上。当dc对象析构时,系统自动调用EndPaint并使invalidated rectangle变成validated状态,从而结束绘制。(注意,重复创建CPaintDC实例会失败也因为如此)

  如果我们在OnPaint中绘制,那么在打印机上绘制我们就需要再写一个OnPrint函数,重新绘制。这样,程序设计者就需要维护两套代码。为了简化操作,MFC框架把大部分绘制操作都放在OnDraw中,OnPaint和OnPrint只构造相应的DC,然后分别调用OnDraw.也就是说,OnDraw适用于所有的设备,而OnPaint只适用于屏幕。

  大家在设计过程中必须注意:OnDraw是被基类的OnPaint主动调用的,如果你继承了OnPaint,你应该要么调用基类的OnPaint(此前不得创建CPaintDC实例,也不得调用BeginPaint),要么自己创建CPaintDC实例,并调用OnDraw.

// 地籍宗地图参数设置 class CDJZDTSetupChildPage : public CXTPPropertyPage; // 绘制地物参数设置 class CRuoHaiDrawDwSetupChildPage : public CXTPPropertyPage ////////////////////////////////////////////////////////////////////////// struct DiaLogSetUpTreeNode { CString caption; std::vector<CString> children; }; class CCategoriesTreeNavigator : public CXTPPropertyPageTreeNavigator { public: // 构造函数,支持传入树视图样式 CCategoriesTreeNavigator(DWORD dwStyle = TVS_SHOWSELALWAYS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT) : CXTPPropertyPageTreeNavigator(dwStyle) { } CCategoriesTreeNavigator(const CString& NodeName, DWORD dwStyle = TVS_SHOWSELALWAYS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT) : CXTPPropertyPageTreeNavigator(dwStyle) { } CCategoriesTreeNavigator(std::vector<CString> TreeNodes, DWORD dwStyle = TVS_SHOWSELALWAYS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT) : CXTPPropertyPageTreeNavigator(dwStyle) { } CCategoriesTreeNavigator(std::vector<DiaLogSetUpTreeNode> TreeNode, DWORD dwStyle = TVS_SHOWSELALWAYS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT) : CXTPPropertyPageTreeNavigator(dwStyle) { } /// <summary> /// 添加单个节点 /// </summary> /// <param name="NodeName"></param> /// <returns></returns> BOOL CreateTree(const CString& NodeName) { if (NodeName == _T("")) { return FALSE; } HTREEITEM hItemOptions = InsertItem(NodeName); for (int i = 0; i < m_pSheet->GetPageCount(); i++) { CXTPPropertyPage* pPage = m_pSheet->GetPage(i); CString strCaption = pPage->GetCaption(); HTREEITEM hItem = InsertItem(strCaption, -1, -1, hItemOptions); SetItemData(hItem, (DWORD_PTR)pPage); pPage->m_dwData = (DWORD_PTR)hItem; } return TRUE; } BOOL CreateTree(const std::vector<CString>& TreeNodes) { if (TreeNodes.size() < 0) { return FALSE; } ASSERT(m_pSheet->GetPageCount() == TreeNode.size()); for (size_t i = 0; i < TreeNodes.size(); ++i) { CString rootName = TreeNodes[i]; // 根节点标题 CreateTree(rootName); } return TRUE; } /// <summary> /// 添加多个节点 /// </summary> /// <param name="TreeNode"></param> /// <returns></returns> BOOL CreateTree(const std::vector<DiaLogSetUpTreeNode>& TreeNode) { if (TreeNode.size() < 0) { return FALSE; } ASSERT(m_pSheet->GetPageCount() == TreeNode.size()); for (size_t i = 0; i < TreeNode.size(); ++i) { DiaLogSetUpTreeNode element = TreeNode[i]; // 显式声明类型为 std::pair CString rootName = element.caption; // 根节点标题 std::vector<CString> subNodes = element.children; // 子节点标题 // 插入根节点 HTREEITEM hRoot = InsertItem(rootName); // 遍历子节点 for (size_t j = 0; j < subNodes.size(); ++j) { const CString& subNodeName = subNodes[j]; // // 插入子节点 HTREEITEM hSubNode = InsertItem(subNodeName, -1, -1, hRoot); CXTPPropertyPage* pPage = m_pSheet->GetPage(i); SetItemData(hSubNode, (DWORD_PTR)pPage); // 设置子节点数据 pPage->m_dwData = (DWORD_PTR)hSubNode; } } return TRUE; } BOOL CreateTree() { CreateTree(TreeNode_); return TRUE; } public: std::vector<DiaLogSetUpTreeNode> TreeNode_; }; ////////////////////////////////////////////////////////////////////////// class CDeepMapSetUpPropSheetPaletteWnd : public CXTPCommandBarsSiteBase<CWnd> { public: CDeepMapSetUpPropSheetPaletteWnd(); void SetBshow(bool bshow); //修改成员b_show bool GetBshow(); //获取成员b_show static void LoadSetUpPale(); static void UnLoadSetUpPale(); static void RegistrationHotkeysAltAnd6();//注册热键 Alt+6 static void UnRegistrationHotkeysAltAnd6();//卸载arx程序前卸载钩子函数 protected: DECLARE_DYNCREATE(CDeepMapSetUpPropSheetPaletteWnd) public: CCategoriesTreeNavigator* pTreeNavigator_; // 导航器指针 CXTPPropertySheet* pCustomPropSheet_; // 自定义属性表指针 CDJZDTSetupChildPage* mDjzdtChildPage_; CRuoHaiDrawDwSetupChildPage* mDrawDwChildPage_; UINT m_nRibbonStyle; bool isShow_;//是否显示了 // 客户区矩形 CRect rect_; public: virtual void OnInitialUpdate(); protected: virtual ~CDeepMapSetUpPropSheetPaletteWnd(); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual void OnDraw(CDC* pDC); virtual void PostNcDestroy(); protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // 用于客户区绘制 afx_msg void OnPaint(); // 用于非客户区绘制 afx_msg void OnNcPaint(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnDestroy(); afx_msg void OnSetFocus(CWnd* pOldWnd); afx_msg void OnClose(); DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// // CDeepMapSetUpPropSheetPaletteWnd IMPLEMENT_DYNCREATE(CDeepMapSetUpPropSheetPaletteWnd, CWnd) BEGIN_MESSAGE_MAP(CDeepMapSetUpPropSheetPaletteWnd, CWnd) ON_WM_PAINT() ON_WM_NCPAINT() ON_WM_SIZE() ON_WM_ERASEBKGND() ON_WM_SETFOCUS() ON_WM_DESTROY() ON_WM_CLOSE() ON_WM_CREATE() END_MESSAGE_MAP() CDeepMapSetUpPropSheetPaletteWnd::CDeepMapSetUpPropSheetPaletteWnd() { isShow_ = false; mDrawDwChildPage_ = new CRuoHaiDrawDwSetupChildPage(); mDjzdtChildPage_ = new CDJZDTSetupChildPage(); } CDeepMapSetUpPropSheetPaletteWnd::~CDeepMapSetUpPropSheetPaletteWnd() { } void CDeepMapSetUpPropSheetPaletteWnd::SetBshow(bool bshow) { isShow_ = bshow; } bool CDeepMapSetUpPropSheetPaletteWnd::GetBshow() { return isShow_; } void CDeepMapSetUpPropSheetPaletteWnd::LoadSetUpPale() { CRuoHaiFreeReleaseFile* reFile = new CRuoHaiFreeReleaseFile(); reFile->MakeFileOutfromResource(); reFile->MakeGdalFileOutfromResource(); CString strVS2015DLL; strVS2015DLL = reFile->ThirdPartyPath_; strVS2015DLL += _T("\\VisualStudio2015.dll"); if (!CHyFile::IsFileExist(strVS2015DLL)) { //VS2015dllproject->MakeVisualStudioDllFromRes(); AfxMessageBox(strVS2015DLL + _T("文件不存在!")); } g_hModuleVisualStudio2015.LoadLibrary(strVS2015DLL); // TODO: Add your initialization code here if (g_pSetUpPaneManager == NULL) { CRect rect = CRect(0, 0, 420, 300); CMDIFrameWnd* pAcadFrame = acedGetAcadFrame(); g_pSetUpPaneManager = new CXTPDockingPaneManager; g_pSetUpPaneManager->InstallDockingPanes(pAcadFrame); XTPResourceImages()->SetHandle(g_hModuleVisualStudio2015, xtpIniVisualStudio2015Dark); g_pSetUpPaneManager->SetTheme(xtpPaneThemeVisualStudio2015); g_pSetUpWndPane = g_pSetUpPaneManager->CreatePane(IDR_PANE, XTP_DPI(rect), xtpPaneDockLeft); g_pSetUpPaletteWnd = new CDeepMapSetUpPropSheetPaletteWnd; g_pSetUpPaletteWnd->Create(_T("STATIC"), NULL, WS_CHILD, rect, pAcadFrame, 0); ((CDeepMapSetUpPropSheetPaletteWnd*)g_pSetUpPaletteWnd)->OnInitialUpdate(); g_pSetUpWndPane->Attach(g_pSetUpPaletteWnd); g_pSetUpWndPane->SetTitle(_T("SETUP")); // 窗格的布局 CXTPDockingPaneLayout layoutNormal(g_pSetUpPaneManager); if (layoutNormal.Load(_T("NormalLayout"))) { g_pSetUpPaneManager->SetLayout(&layoutNormal); g_pSetUpPaneManager->RecalcFramesLayout(); } // 拖动窗格时可以停靠的位置 g_pSetUpPaneManager->SetAlphaDockingContext(TRUE); // 在拖动对接窗格时使用Visual Studio 2005样式对接上下文贴纸 g_pSetUpPaneManager->SetShowDockingContextStickers(TRUE); g_pSetUpPaneManager->SetShowContentsWhileDragging(TRUE); // 调用此成员在拖动时设置“显示窗口内容”选项 //pPaneManager->SetDefaultPaneOptions(xtpPaneHasMenuButton); g_pSetUpPaneManager->SetThemedFloatingFrames(FALSE); delete reFile; reFile = NULL; } delete reFile; reFile = NULL; } void CDeepMapSetUpPropSheetPaletteWnd::UnLoadSetUpPale() { if (g_pSetUpPaletteWnd) { delete g_pSetUpPaletteWnd; g_pSetUpPaletteWnd = NULL; } if (g_pSetUpPaneManager) { delete g_pSetUpPaneManager; g_pSetUpPaneManager = NULL; acedGetAcadFrame()->RecalcLayout(); } ////将焦点放在当前视图 //acedGetAcadDwgView()->SetFocus(); //acDocManager->lockDocument(curDoc()); //acDocManager->sendStringToExecute(curDoc(), _T("UNote "), false, true, false); //acDocManager->unlockDocument(curDoc()); } void CDeepMapSetUpPropSheetPaletteWnd::RegistrationHotkeysAltAnd6() { if (BRegiHotCtrl6Ok) { if (acDocManager->curDocument() != NULL) { acutPrintf(_T("\n%s 热键已经注册了。\n"), Str_HOTKEY_ALT_6); //如果钩子已经注册,则返回 } return; } if (acedRegisterWatchWinMsg(WatchAltAnd6) == FALSE) { if (acDocManager->curDocument() != NULL) { acutPrintf(_T("\n%s 热键注册失败。\n"), Str_HOTKEY_ALT_6); //无法注册钩子 } } else { if (acDocManager->curDocument() != NULL) { acutPrintf(_T("\n%s 热键注册成功,此热键是打开关闭DeepMap停靠面板。\n"), Str_HOTKEY_ALT_6); //快捷命令已经定义 } BRegiHotCtrl6Ok = true; } return; } //卸载arx程序前卸载钩子函数 void CDeepMapSetUpPropSheetPaletteWnd::UnRegistrationHotkeysAltAnd6() { if (BRegiHotCtrl6Ok == true) { acedRemoveWatchWinMsg(WatchAltAnd6); acutPrintf(_T("\n%s 热键卸载成功。\n"), Str_HOTKEY_ALT_6); } } BOOL CDeepMapSetUpPropSheetPaletteWnd::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; return CWnd::PreCreateWindow(cs); } void CDeepMapSetUpPropSheetPaletteWnd::OnDraw(CDC* pDC) { } void CDeepMapSetUpPropSheetPaletteWnd::OnPaint() { CPaintDC dc(this); } void CDeepMapSetUpPropSheetPaletteWnd::OnNcPaint() { // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CXTPCommandBarsSiteBase::OnNcPaint() } int CDeepMapSetUpPropSheetPaletteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; CAcModuleResourceOverride resourceOverride; /*if (!mChildDlg.Create(IDD_DrawDwSETUP_DIALOG, this)) { acedAlert(_T("创建对话框失败!\n")); return -1; } mChildDlg.ShowWindow(SW_SHOW); mChildDlg.MoveWindow(0, 0, 50, 100, TRUE);*/ if (!mDjzdtChildPage_->CXTPPropertyPage::Create(IDD_DJZDT_SETUP_DIALOG, this)) { acedAlert(_T("创建对话框失败!\n")); return -1; } mDjzdtChildPage_->ShowWindow(SW_SHOW); mDjzdtChildPage_->MoveWindow(0, 0, 50, 100, TRUE); if (!mDrawDwChildPage_->CXTPPropertyPage::Create(IDD_DrawDwSETUP_DIALOG, this)) { acedAlert(_T("创建对话框失败!\n")); return -1; } mDrawDwChildPage_->ShowWindow(SW_SHOW); mDrawDwChildPage_->MoveWindow(0, 0, 50, 100, TRUE); return 0; } void CDeepMapSetUpPropSheetPaletteWnd::OnInitialUpdate() { // 初始化命令栏 if (!InitCommandBars()) { TRACE0("初始化命令栏失败!\n"); return; } CXTPCommandBars* pCommandBars = GetCommandBars(); if (pCommandBars == NULL) { TRACE0("创建命令栏对象失败!\n"); return; } CXTPPaintManager::SetTheme(xtpThemeVisualStudio2015); XTPResourceImages()->SetHandle(g_hModuleVisualStudio2015, xtpIniVisualStudio2015Dark); pCommandBars->GetCommandBarsOptions()->ShowKeyboardCues(xtpKeyboardCuesShowWindowsDefault); pCommandBars->GetCommandBarsOptions()->bShowExpandButtonAlways = FALSE; pCommandBars->GetPaintManager()->m_bAutoResizeIcons = TRUE; pCommandBars->GetCommandBarsOptions()->SetDPIScallingOptions(TRUE); LoadCommandBars(_T("CommandBars")); RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposDefault); std::vector<CString> TreeNodes; TreeNodes.push_back(_T("地物绘制设置")); TreeNodes.push_back(_T("地籍宗地图设置")); pCustomPropSheet_ = new CXTPPropertySheet(_T("CXTPPropertyPageTreeNavigator Sample")); pTreeNavigator_ = new CCategoriesTreeNavigator(TreeNodes); pCustomPropSheet_->SetNavigator(pTreeNavigator_); pCustomPropSheet_->m_psh.dwFlags |= PSH_NOAPPLYNOW; pCustomPropSheet_->AddPage(mDjzdtChildPage_); pCustomPropSheet_->AddPage(mDrawDwChildPage_); pCustomPropSheet_->SetResizable(); pTreeNavigator_->CreateTree(TreeNodes); } void CDeepMapSetUpPropSheetPaletteWnd::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); CRect rcClient(0, 0, cx, cy); RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, 0, 0, &rcClient); RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &rcClient, &rcClient); if (mDrawDwChildPage_->GetSafeHwnd()) { mDrawDwChildPage_->MoveWindow(rcClient); } if (mDjzdtChildPage_->GetSafeHwnd()) { mDjzdtChildPage_->MoveWindow(rcClient); } } BOOL CDeepMapSetUpPropSheetPaletteWnd::OnEraseBkgnd(CDC* pDC) { return TRUE; } void CDeepMapSetUpPropSheetPaletteWnd::OnSetFocus(CWnd* /*pOldWnd*/) { } void CDeepMapSetUpPropSheetPaletteWnd::OnDestroy() { CWnd::OnDestroy(); // TODO: 在此处添加消息处理程序代码 } void CDeepMapSetUpPropSheetPaletteWnd::OnClose() { // Save the current state for command bars. SaveCommandBars(_T("CommandBars")); CWnd::OnClose(); } void CDeepMapSetUpPropSheetPaletteWnd::PostNcDestroy() { // TODO: 在此添加专用代码和/或调用基类 CWnd::PostNcDestroy(); } 我想实现树形控件的效果,但是这个代码把两个对话框都Create出来重叠在一起了没有到达树形控件点击切换对话框的效果
06-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值