在CFormView或对话框中动态添加CScrollView、CFormView

在CFormView或对话框中动态添加CScrollView、CFormView

本代码可以在CFormView中,根据事先画好的控件位置创建CScrollView

也可以在CDialog中创建CScrollView、CFormView等

注:

若以下代码放在CMainRightView::OnCreate(LPCREATESTRUCT lpCreateStruct)内,则GetDlgItem()函数将调用失败,因为此时控件都还未被创建!

void CMainRightView::OnInitialUpdate()
{
    CFormView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class
    //获得目标位置控件
    UINT TargetCtrlID = IDC_STATIC_SCROLLVIEW;
    CWnd *pWnd = this->GetDlgItem(TargetCtrlID);
    CRect RectTargetCtrl;
    pWnd->GetWindowRect(RectTargetCtrl);
    pWnd->DestroyWindow();
    this->ScreenToClient(RectTargetCtrl);

//在目标位置动态创建CScrollView
    CEMapView *pEMapView = (CEMapView*)RUNTIME_CLASS(CEMapView)->CreateObject();
    pEMapView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, RectTargetCtrl, this, TargetCtrlID);
    //使用CreateView创建的视图 不能自动调用OnInitialUpdate函数,需要人工调用OnInitialUpdate函数或者发送 WM_INITIALUPDATE消息
    pEMapView->OnInitialUpdate();
    //SetScrollSizes()必须被调用,否则运行时会出ASSERT错误,当然,也可以在目标View内的OnInitialUpdate()中调用
    pEMapView->SetScrollSizes(MM_TEXT, CSize(RectTargetCtrl.Width()-10, RectTargetCtrl.Height()-10));
    // 使用CreateView创建的视图不会自动显示并且激活,需要人工操作 
    pEMapView->ShowWindow(SW_SHOW);
}

注:如果需要在CDialog中创建CScrollView、CFormView,则需要在View中overload、override这些View中以下的4个方法,否则会出ASSERT错误

afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
    afx_msg void OnDestroy();
    virtual void PostNcDestroy();
    virtual void OnActivateFrame(UINT nState, CFrameWnd* pDeactivateFrame);

int CFormViewPrint::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    // TODO: Add your message handler code here and/or call default

return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

void CFormViewPrint::OnDestroy()
{
    CWnd::OnDestroy();

// TODO: Add your message handler code here
}

void CFormViewPrint::PostNcDestroy()
{
    // TODO: Add your specialized code here and/or call the base class

CWnd::PostNcDestroy();
}

void CFormViewPrint::OnActivateFrame(UINT nState, CFrameWnd* pDeactivateFrame)
{
    // TODO: Add your specialized code here and/or call the base class

CWnd::OnActivateFrame(nState, pDeactivateFrame);
}

原因可参考

View和Control的区别(如何在对话框上使用CView类)

CView继承类,和其他窗口类的区别,很重要的就是对CDocument类和CFrameWnd类的操作,而其中,涉及CDocument类的操作,都进行了有效性判断(m_pDocument != NULL),CView类初始化的时候,m_pDocument = NULL,因此并不影响CView类作为控件的使用。涉及CFrame类的操作,有这么几个地方:

  第一个地方:CView::OnDestroy()

void CView::OnDestroy()
{
 CFrameWnd* pFrame = GetParentFrame();
 if (pFrame != NULL && pFrame->GetActiveView() == this)
  pFrame->SetActiveView(NULL);    //
deactivate during death
 CWnd::OnDestroy();
}

  第二个地方:CView::OnActivateFrame()

void CView::OnActivateFrame(UINT , CFrameWnd* )
{
}

  这里,其实是空的,在CView继承类中,只有CFormView类继承了这个虚函数

void CFormView::OnActivateFrame(UINT nState, CFrameWnd* )
{
 if (nState == WA_INACTIVE)
  SaveFocusControl();     // save focus when
frame loses activation
}

  实际上都不需要真的CFrame指针,对CView类作为控件使用没有障碍。

  第三个地方:CView::OnMouseActivate()

int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
 int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
 if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
  return nResult;   // frame does not want to activate

 CFrameWnd* pParentFrame = GetParentFrame();
 if (pParentFrame != NULL)
 {
  // eat it if this will cause activation
  ASSERT(pParentFrame == pDesktopWnd ||
pDesktopWnd->IsChild(pParentFrame));

  // either re-activate the current view, or set this view to be
active
  CView* pView = pParentFrame->GetActiveView();
  HWND hWndFocus = ::GetFocus();
  if (pView == this &&
   m_hWnd != hWndFocus && !::IsChild(m_hWnd, hWndFocus))
  {
   // re-activate this view
   OnActivateView(TRUE, this, this);
  }
  else
  {
   // activate this view
   pParentFrame->SetActiveView(this);
  }
 }
 return nResult;
}

  另外,在CView::PostNcDestroy(),实现了CView类的自我销毁,这是因为CView类是可以动态生成的(DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)。

// self destruction
void CView::PostNcDestroy()
{
 // default for views is to allocate them on the heap
 //  the default post-cleanup is to ‘delete this‘.
 //  never explicitly call ‘delete‘ on a view
 delete this;
 

  基本上,修改了CView继承类的这几个地方,直接返回不要调用基类相应的成员函数,就可以在对话框上使用。

  下面举例,用向导生成对话框应用程序,对话框类为CMyDigalog

  从CHTMLView类继承一个CHTMLCtrl类,建立相应的消息处理函数并修改以下几个地方:

// CHTMLCtrl 消息处理程序

int CHTMLCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT
message)
{
 // TODO:
在此添加消息处理程序代码和/或调用默认值
 return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);

 //return CHtmlView::OnMouseActivate(pDesktopWnd,
nHitTest, message);
}

void CHTMLCtrl::OnDestroy()
{
 //CHtmlView::OnDestroy();

 // TODO: 在此处添加消息处理程序代码
 CWnd::OnDestroy();
}

void CHTMLCtrl::PostNcDestroy()
{
 // TODO:
在此添加专用代码和/或调用基类

 //CHtmlView::PostNcDestroy();
}

 

void CHTMLCtrl::OnActivateFrame(UINT nState, CFrameWnd*
pDeactivateFrame)
{
 // TODO:
在此添加专用代码和/或调用基类

 //CHtmlView::OnActivateFrame(nState,
pDeactivateFrame);
}

  增加一个成员函数CreateFromCtrl

public:
 BOOL CreateFromCtrl(UINT nID, CWnd* pParent);

  这个函数通过对话框上的控件创建一个CHTMLCtrl控件,目的是在对话框设计的时候便于布局:

BOOL CHTMLCtrl::CreateFromCtrl(UINT nID,
CWnd* pParent)
{
 if (!pParent || !pParent->GetSafeHwnd())
  return FALSE;
 CWnd *pCtrl = pParent->GetDlgItem(nID);
 if (!pCtrl)
  return FALSE;
 CRect rcCtrl;
 pCtrl->GetWindowRect(rcCtrl);
 pParent->ScreenToClient(rcCtrl);
 UINT style = ::GetWindowLong(pCtrl->GetSafeHwnd(), GWL_STYLE);
 pCtrl->DestroyWindow();

return Create(NULL, NULL, style |
WS_CHILD | WS_VISIBLE, rcCtrl, pParent, nID, NULL);

}

  还应注意,默认的从CView继承的类,其构造函数和析构函数是protected的,需要修改成public。

  还应注意,默认的从CView继承的类,其构造函数和析构函数是protected的,需要修改成public。

public:
 CHTMLCtrl();           //
动态创建所使用的受保护的构造函数
 virtual ~CHTMLCtrl();


  然后,在对话框模板中(使用资源编辑器),插入一个Static Text控件,IDIDC_HTML

  在对话框头文件中,插入包含文件:

#include "htmlctrl.h"

  增加CHTMLCtrl类型的成员变量:

CHTMLCtrl m_ctlHTML;

  在对话框初始化的时候,创建这个CHTMLCtrl控件:

BOOL CMyDialog::OnInitDialog()
{
 CDialog::OnInitDialog();
 ...

 m_ctlHTML.CreateFromCtrl(IDC_HTML, this);

 return TRUE;
}

  下面,再添加一个按钮,在按钮的消息响应函数中打开HTML文件:

void CMyDialog::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}

在CFormView或对话框中动态添加CScrollView、CFormView,布布扣,bubuko.com

时间: 2024-10-08 19:35:00

在CFormView或对话框中动态添加CScrollView、CFormView的相关文章

android 在布局中动态添加控件

第一步 Java代码 final LayoutInflater inflater = LayoutInflater.from(this); 第二步:获取需要被添加控件的布局 Java代码 final LinearLayout lin = (LinearLayout) findViewById(R.id.LinearLayout01); 第三步:获取需要添加的布局(控件) Java代码 LinearLayout layout = (LinearLayout) inflater.inflate( R

Android 在布局容器中动态添加控件

这里,通过一个小demo,就可以掌握在布局容器中动态添加控件,以动态添加Button控件为例,添加其他控件同样道理. 1.addView 添加控件到布局容器 2.removeView 在布局容器中删掉已有的控件 3.使用,来个小demo就明白了 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(save

Android在布局中动态添加view的两种方法

一.说明 添加视图文件的时候有两种方式:1.通过在xml文件定义layout:2.java代码编写 二.前言说明 1.构造xml文件 2.LayoutInflater 提到addview,首先要了解一下LayoutInflater类.这个类最主要的功能就是实现将xml表述的layout转化为View的功能.为了便于理解,我们可以将它与findViewById()作一比较,二者都是实例化某一对象,不同的是findViewById()是找xml布局文件下的具体widget控件实例化,而LayoutI

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感)

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感) 效果图: 运行原理和技术: 当页面加载完毕,利用jquery向后台发送ajax请求,去后台拼接<select></select>中的option字符串.让后将字符串响应回来,动态添加到<select>中.其中的字符串中包含了后台的数据. 页面js代码: 1 <script type="text/javascript"> 2 //加载部门 3 function loa

vue中动态添加div

知识点:vue中动态添加div节点,点击添加,动态生成div,点击删除,删除对应的div,其中数组的长度是动态改变的,如在from表单中应用,直接在提交方法中,获得list,获取所填的元素即可 效果: 核心代码说明(样式代码可自行修改,详细代码请参照源码): <div v-for="(v,i) in list"> <div class="form-group m-form__group row" style="padding-top: 1

ASP.NET中Literal控件的使用方法(用于向网页中动态添加内容)

原文:https://www.jb51.net/article/82855.htm 可以将 Literal 控件用作网页上其他内容的容器.Literal 控件最常用于向网页中动态添加内容.简单的讲,就是可以把 HTML 代码写到 Literal 控件上,直接呈现出来. 一.常见Literal属性 属性 描述 Text 指定 Literal 控件中显示的文本.在用户的浏览器中,这会显示为 HTML. Mode 指定控件如何处理添入其中的标记. 二.基础用法 前台 LiteralTest.aspx

MFC中动态添加控件----寻找多年的秘籍,吐血推荐

原文作者tianwaik 动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态控件 为了对照,我们先来看一下静态控件的创建. 放置静态控件时必须先建立一个容器(一般是对话框),这时我们在对话框编辑窗口中,从工具窗口中拖出所需控件放在对话框中即可,再适当修改控件ID,设置控件属性,一个静态控件就创建好了,当对话框被显示时,其上的控件也会显示. 相比之下,静态控件不需要调用Create()函数来创建. 而创建动态控件有很大不同,以下以按钮为例,看一下

如何获取jQuery中动态添加的元素

一.问题描述 用jQuery的append()方法动态添加了一段html代码之后,发现在为新添加的元素绑定click事件时无法获取该新元素. 二.解决方法 度娘推荐的方法基本是用live()方法 live()的官方定义和用法: live() 方法为被选元素附加一个或多个事件处理程序,并规定当这些事件发生时运行的函数.通过 live() 方法附加的事件处理程序适用于匹配选择器的当前及未来的元素(比如由脚本创建的新元素). live()的详细使用方法可以查看jQuery live() live()和

Unity NGUI中动态添加和删除sprite

转自:http://www.cnblogs.com/vitah/p/3897664.html (以后,参考链接和作者将在文章首部给出,转载请保留此部分内容) 参考链接:http://www.narkii.com/club/thread-299977-1.html,作者:纳金网 比巴卜: 参考链接:http://game.ceeger.com/forum/read.php?tid=2852,作者:Unity圣典论坛 kuku小夭 动态添加和删除Sprite可以在很多地方用到,这里以实现显示技能CD