第七章(对话框一)

//控件的介绍

首先控件呢,举个例子吧,就是对话框里面的按钮啦,编辑框,静态文本,图片之类的,这些都是控件,控件有很多,还有进度条,水平滑动条之类,需要注意的是所有的控件都是由Cwnd类派生的,所以他们全部都是能调用Cwnd的函数的(例如GetWindowRect这些)

 

//对话框

对话框就分2种,模态与非模态,模态对话框就是程序运行到对话框那里就会暂停下来,暂时不执行下面的程序,知道关闭这个模态对话框才继续执行程序的其他任务;

非模态对话框显示时,允许转而执行其他任务,而不用关闭这个对话框。

图中2,3这些就是控件了,至于想在单文档程序中插入一个对话框,首先要在资源文件中创建一个对话框资源,单是资源还不够,程序中需要一个类来与这个资源联系起来,通过操作这个类来操作资源,就像我们之前弄个个位图资源,要用CBitmap类来加载位图,用CMenu类来加载菜单一样,但是对话框貌似不能直接用CDialog类,需要自己新建一个类来联系这个对话框资源,而这个类正是派生于CDialog类的。

直接在那个资源右击,选择添加类,就出现这个对话框,填写相关资料就OK。

创建的这个对话框派生类只有3个函数

1,2分别是类的析构函数,构造函数,3函数貌似很重要,用来做数据交换的,当编辑框控件与特定的变量关联起来的时候,就是用它来实现数据交换的。

 

 

模态对话框的创建

模态对话框实现相当简单,例如我们想在程序的(菜单栏->帮助->对话框->弹出模态对话框),首先在菜单资源帮助下面加个对话框,右击,选添加事件处理程序

因为菜单属于主框架类的,所以我习惯单击菜单项作为CMainFrame的函数:

添加的事件的处理函数就这个了,首先创建一个那个对话框资源类的对象,调用DoModal()函数,就可以实现模态对话框出来了,它的显示,更新什么的全部在这个函数帮你搞掂,所以模态对话框相比较起非模态简单很多。

 

///非模态对话框的创建

这里要用到CDialog::Create函数

Create()函数还不会帮你ShowWindow(),需要自己调用。

程序变成这样,运行时发现对话框出现了一瞬间就消失了,那是因为dlg是局部变量,非模态不像模态,运行到DoModal()那里暂停所以没事,非模态会继续运行下去,离开右花括号时,dlg就会析构了,对话框就更不可能存在了。解决方法:1,把dlg变成CMainFrame的数据成员;2,dlg变成指针,CTestDlg *dlg=new CTestDlg;   *dlg指向的是堆中创建的空间,不会在右花括号出现就消失的,这样也可以解决问题,但是指针这种方式有个弊端,右花括号处,虽然那个对象没消失,但是指向那个对象的*dlg会消失,同样是因为*dlg是局部变量,这样就会产生内存泄露了,要么就是把*dlg设为数据成员,在析构函数那里delete内存(⊙﹏⊙b汗,这样用指针还有什么意义呢),要么在CTestDlg类中重载一个叫PostNcDestroy的虚函数,在里面delete this;(this指向CTestDlg本身)。

综上创建非模态最方便的还是设一个数据成员来调用Create函数与ShowWindow()函数。

 

///对话框控件的访问

图中1是静态文本控件,2是编辑框控件,3是按钮控件。

1:静态文本一般就是显示文本,它的ID号也是一般设置为IDC_STATIC,而且全部静态文本基本都是这个ID了,所以静态文本也不相应什么消息,但是不代表它不能响应消息的,第一步,改变它的ID,第二步,属性中选择Notify选项,这样静态文本同样能响应消息了。

右击静态文本,选添加事件响应函数

检索指向在对话框或其他窗口中指定的控件或子窗口。

CWnd* GetDlgItem(
   int nID 
) const;

顾名思义就是找给定ID的控件,返回指向控件对象的指针,GetWindowText(CString)就是把这个控件的文本存到CString中,SetWindowText就是把参数写到控件中。

 

2,编辑框控件

实现number1与number2相加放入number3,首先要知道number1与number2中的数字是多少才行,一共又有7种方式,简单介绍几种,着重介绍关联变量的那种,

【原形】
    int GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const;
    void GetWindowText( CString& rString ) const;
【参数】
    lpszStringBuf
    指向要接收窗口标题的复制字符串的缓冲区。
    nMaxCount
    指定了要拷贝的缓冲区的最大字符数目。如果字符串比nMaxCount指定的数目还要长,则被截断。
    rString
    用于接收窗口标题的复制字符串的CString对象。

TCHAR ch1[10];

GetDlgItem(IDC_EDIT1)->GetWindowtext(ch1,10);  num1=_ttoi(ch1);   _itow_s(num3,ch3,10,10);    GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);

还有GetDlgItemText(IDC_EDIT1,ch1,10);  SetDlgItemText(IDC_EDIT3,ch3);     GetDlgItemInt(IDC_EDIT1,NULL,true);   SetDlgItemInt(IDC_EDIT3,num3,true);这样的调用也行。

GetDlgItemInt参数(ID,报错存放地址一般NULL,有没符号)

重点方法:

右击资源编辑控件,选择添加变量

类别选value,这样添加的就是与这个编辑控件关联起来的值,选control就会创建一个代表控件本身的对象(用这个对象直接调用GetWindowtext()这些函数:m_edit1.GetWindowtext(str);就会变成这样),选value,那么编辑框的数就会赋值给m_num1了。

数据交换的实现由一开始介绍的那个函数实现:

不过一般不会直接调用这个函数,而是调用UpdateDate(bool )函数来间接调用它,UpdateData(true)就会获取对话框数据,UpdateDate(false)就会初始化控件内容;

所以在按Add按钮的响应函数中应该是:UpdateData(true);  num3=num1+num2;  UpdateData(false);就这样就实现了相加的功能了

 

//对话框的伸缩

如图的伸缩,实现最主要的就是搞清楚伸缩前后,对话框的坐标大小,中间那条线是图片控件,同样也是一个窗口类,在这里主要是学习2个函数:

分别用rectLarge记录原来大的对话框的矩形,用rectSmall来记录缩小后对话框的矩形,大的好记录,小的与大的对比下,左上角坐标没变化,变的是右下角的坐标,右下角的坐标就是那个同样属于窗口类的图片控件的右下角坐标,那么大的,小的矩形都知道了,怎样使对话框按那个矩形显示出来呢,又另外一个函数:
BOOL SetWindowPos(
   const CWnd* pWndInsertAfter,
   int x,
   int y,
   int cx,
   int cy,
   UINT nFlags 
);

  
  
   
   pWndInsertAfter 
  
  
  
  

标识将前面的 CWnd 对象(大于)对Z顺序的此 CWnd 对象。 此参数可以是指向 CWndPointer 为下列值之一:

  • wndBottom 将窗口底部的z-顺序。 如果此 CWnd 是一个最顶层窗口,窗口丢失其最顶层的状态;系统将窗口在其他窗口底部。

  • wndTop 将窗口在z-顺序的顶部。

  • wndTopMost 将windows首先非最顶层窗口。 即使当停用,窗口保留其最顶层的位置它。

  • wndNoTopMost 在任何非最顶层窗口的顶部重新定位窗口(即所有最顶层窗口)后。 如果窗口已非最顶层窗口,此标志将不起作用。

有关如何的规则使用此参数,请参见“备注”本主题的一部分。

x

指定窗口的左侧的新位置。

y

指定窗口顶部的新位置。

cx

指定窗口的新的宽度。

cy

指定窗口的新高度。

nFlags

指定大小调整和定位选项。

  • SWP_NOMOVE 保留当前位置(忽略 xy 参数)。

  • SWP_NOSIZE 保留当前范围(忽略 cxcy 参数)。

  • SWP_NOZORDER 保留当前排序(忽略 pWndInsertAfter)。 所以SetWindowPos(NULL,0,0,recrLarge.width(),rectLarge.Height(),SWP_NOMOVE | SWP_NOZORDER);这样调用就OK了。

     

    焦点传送问题

    我们在编辑框打完一个数,按TAB可以跳到下一个框,按回车对话框却转为按确定按钮了,修改这个功能,令按回车也能跳到下一个框去,这就是用回车实现了焦点传送,事实上回车按钮被设置为默认按钮了。

    所以按回车才会这样,要按回车焦点传送必须先令对话框不消失才行,确定按钮的处理函数OnOk()是虚函数,在CTestDlg类中重载这个函数,注释里面的内容就能断掉它的功能。之后,编辑框本身是个窗口,它有自己对回车的响应函数,要修改它可以修改它的过程函数,把新的过程函数赋给编辑框(要是消息是回车键就焦点传送,不是就用编辑框原来的过程函数来处理),这里有个问题就是编辑框早就定义好了,过程函数也指定好,修改就要用到SetWindowLong函数

    LONG WINAPI SetWindowLong( _In_  HWND hWnd, _In_  int nIndex, _In_  LONG dwNewLong);

    参数一:想要改变属性的窗口句柄 参数二:DWL_DLGPROC 改变过程函数 GWL_STYLE 设置新的窗口风格 GWL_ID 为窗口设新ID 。。。。

    参数三:新的过程函数地址   返回值:修改的属性的旧值

     

    待对话框,控件什么的都创建完了,才能修改过程函数,这里有个BOOL CTestDlg::OnInitDialog()这样的虚函数,右击CTestDlg类,类向导->虚函数就有了,这个虚函数是对话框,控件创建完,将要显示前要运行的函数,在这个函数里面设过程函数

    WNDPROC prevproc;//过程函数变量吧,可以这样理解

    prevproc=(WNDPROC)SetWindowLong(m_edit1.m_hWnd,GWL_WNDPROC,(LONG)NewEditProc);

    而新的过程函数定义为:

    LRESULT CALLBACK NewEditProc(
    		HWND hwnd,
    		UINT uMsg,
    		WPARAM wParam,
    		LPARAM lParam
    )
    {
    	if(uMsg==WM_CHAR && wParam==0x0d)//如果是回车键
    	{
    		::SetFocus(GetNextWindow(hwnd,GW_HWNDNEXT));//设置焦点
    		return 1;
    	}
    	else 
    	{
    		return prevproc(hwnd,uMsg,wParam,lParam);//不是回车就用原来的过程函数处理
    	}
    }


     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值