您的位置:首页 > 其它

VC+MFC 学习笔记之一(截止到2016.4.9)

2016-03-14 20:22 323 查看

摘要提示:

//===========================================================================

1.子窗体和父窗体的切换

2.子窗体中结合OpenCV显示图片

3.子窗体获取父窗体数据方法&文本框显示

4.子窗体向父窗体传递数据方法之一

5.解决子窗体默认始终在前的方法

6.在子窗体中建立初始化函数的方法

7.点击窗体的关闭按钮,返回的是IDCANCEL消息

8.修改窗体为不能改变大小,在属性的border里面修改,设置为Dialog Frame即可。

10.子窗体使用ComBox控件,不能显示子选项。解决方法

11.获得鼠标的桌面坐标,并且显示。

12.文本框多行显示 和 限制每行的长度和文本框的宽度一一致。

13.文本框输出,焦点设置在字符串最后。

14.MFC使用提示窗输出字符、查看字符串、带参数值。

15.关于进位制的两三事

16.回车不关闭窗体

17.SetTimer使用

18.获取系统时间

=============================================================================//

1.子窗体和父窗体的切换

参考:http://blog.csdn.net/HEVC_CJL/article/details/9973169
第一、在MFC下新建win32(基本对话框)工程,然后再添加一个子窗体(在资源视图中操作),子窗体设置(属性->行为->Visible->True,其他设置根据需要决定是否设置)。基本准备工作结束。

第二、在子窗体上(鼠标右键->添加类->设置如下图)给子窗口建立一个类。比如类名:CTestDlg



第三、在父窗口所在的(工程名XX) XXDlg.h文件中包含 CTestDlg.h,并且建立CTestDlg类的成员

public:

CTestDlg *m_cTest;

第四、在父窗口的构造函数(构造函数是一种可初始化其类的实例的成员函数。构造函数具有与类相同的名称,没有返回值。)中给CTestDlg类的成员分配资源:

m_cTest = new CTestDlg(this);
第五、在子窗口的函数中使用Create函数:

m_cTest->Create(IDD_DIALOG1, this);//IDD_DIALOG1为子窗口ID

第六、给子窗口添加WM_CLOSE消息。注意:是子窗口代码中(CTestDlg.cpp)添加消息事件。

在生成的OnClose函数中销毁窗口:DestroyWindow();

2.子窗体中结合OpenCV显示图片

父窗体,BOTTON1
子窗体,picture control 控件 IDD_PICTURE

第一、在子窗体中,建立初始化函数
在子窗体.h文件的类定义中,建立protected : virtual BOOL OnInitDialog() ; 声明子窗体的初始化函数
在子窗体.cpp文件中,建立BOOL CTestDlg::OnInitDialog(){}子窗体初始化函数的函数体,代码均在此区域中

第二、在子窗体.cpp文件中,建立全局变量
IplImage* src = cvLoadImage("D:\\PERSONAL\\VC++\\OpenCV\\image\\hy2head.jpg");
CRect rect;
CDC *pDC;
HDC hDC;
CWnd *pwnd;


第三、在BOOL CTestDlg::OnInitDialog()中输入
BOOL CTestDlg::OnInitDialog()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
pwnd = GetDlgItem(IDC_STATIC);
pDC =pwnd->GetDC();
hDC= pDC->GetSafeHdc();
pwnd->GetClientRect(&rect);

CvvImage m_CvvImage;
m_CvvImage.CopyOf(src,1);
m_CvvImage.DrawToHDC(hDC, &rect);

return true;

}


OK!
其中,CvvImage类的说明,见http://blog.csdn.net/u014488388/article/details/51104179 第3点。

3.子窗体获取父窗体数据方法&文本框显示

第一、文本框的显示方法

画好框架后,调用代码如下:
<span style="white-space:pre">	</span>CString str;
str.Format(_T("%d"),tx);// tx是int型变量
SetDlgItemText(IDC_EDIT1,str);  // <span style="font-family: Arial, Helvetica, sans-serif;">IDC_EDIT1 文本框的ID Num.</span>
文本框字符串读取,转化为数字。
void CvariableDlg::OnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString ww;
GetDlgItemTextW(IDC_EDIT_INPUT,ww);
k = _wtoi(ww);
m_cTest->tx = k++;
m_cTest->Create(IDD_DIALOG_SUB,this);
}


第二、数据传递
现在子类.h中定义public : int num,再定义某子类的变量XX,然后在父.cpp中使用XX->num来给num赋值

代码如下:

子类 .h 中
public:
int tx;
父类 .h 中
Public:
<span style="white-space:pre">	</span>CTestDlg *m_cTest;
父类 .cpp中消息响应函数添加
void CvariableDlg::OnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
m_cTest->tx = 250;
m_cTest->Create(IDD_DIALOG_SUB,this);//IDD_DIALOG_SUB 子类窗体的ID num.
}



显示在子类的文本框中: (此两个函数可以在类向导里添加!)
BOOL CTestDlg::OnInitDialog()//子窗体初始化
{
CDialogEx::OnInitDialog();
CString str;
str.Format(_T("%d"),tx);
SetDlgItemText(IDC_EDIT1,str);

return true;
}

void CTestDlg::OnClose()//子窗体关闭以后销毁生成的窗体
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
DestroyWindow();
CDialogEx::OnClose();
}


4.子窗体向父窗体传递数据方法之一

参考:http://www.tc5u.com/mfc/1806175.htm
使用全局静态变量:在类中名字就是 类成员静态变量,在类外面就是静态变量
首先,在父窗体.cpp中定义
#include "TestDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

int num1;//看这里!注意添加位置!是在其他函数 XX(){}之外的区域


然后,在父窗体.h文件中
#include "TestDlg.h"

#pragma once
extern int num1;


<span style="font-family: 新宋体, 宋体, Arial;">//看这里!注意添加位置!</span>


在你想要使用num1的.cpp文件的对应.h文件中添加
extern int num1;


这样,在其他子窗体.cpp文件中就都能使用num1了。

还有使用类成员静态变量的方法,待日后再研究~

5.解决子窗体默认始终在前的方法

参考:http://www.xuebuyuan.com/541854.html
问题出在:
m_cTest->Create(IDD_DIALOG_SUB,this);


鼠标点击父窗口,但是子窗口始终在前,而子窗体们的前后则可以由鼠标调整。
解决方法,将this 修改为 GetDesktopWindow() 。
m_cTest->Create(IDD_DIALOG_SUB,GetDesktopWindow());


Bingo!

6.在子窗体中建立初始化函数的方法

在默认情况下,MFC的子窗体.cpp中是没有初始化函数的,而且在类向导中也找不到。

第一、在子窗体.h文件的class中建立virtual BOOL OnInitDialog(),注意是 protected:
protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
virtual BOOL OnInitDialog();


第二、在子窗体.cpp文件中建立
BOOL CDiff::OnInitDialog()
{
CDialogEx::OnInitDialog();</span>
//在这里之下添加自己的代码
return true;
}


注意,一定要有返回值,return true;
在其中添加子窗体的初始化代码即可。

7.点击窗体的关闭按钮,返回的是IDCANCEL消息

8.修改窗体为不能改变大小,在属性的border里面修改,设置为Dialog Frame即可。

10.子窗体使用ComBox控件,不能显示子选项。解决方法

原因一、拉窗体不到位(待定)

实测MFC会自己调整下拉框的大小,在绘制控件时没有调整到合适的大小不会影响显示。
但是网上有大量的说法说会影响,可能版本问题吧,VS2012没有这个问题。若是VC6.0的话就不一定啦。
调整方法如下:


and then


原因二、子窗体的初始化函数书写不当(坑爹)
参考阅读:http://bbs.21ic.com/blog-621237-83411.html
注意1,子窗体本身不带初始化函数,要自己写,具体方法见上文所述。
注意2,初始化函数中,CDialogEx::OnInitDialog();是模仿父窗体中的初始化函数,但是解决问题了。用途不大清楚,也希望大家能赐教。
BOOL CSon::OnInitDialog()
{
CDialogEx::OnInitDialog();//不可缺少,关键所在

return true;
}


11.获得鼠标的桌面坐标,并且显示。



在主窗体的.cpp的初始化函数OnInitDialog()中添加:(大循环要在timer中来实现)
SetTimer(1,10,NULL);
在OnTimer()中添加:
void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
POINT pMouse;
GetCursorPos(&pMouse);

SetDlgItemInt(IDC_EDIT_X,pMouse.x);
SetDlgItemInt(IDC_EDIT_Y,pMouse.y);
CDialogEx::OnTimer(nIDEvent);
}


总结两种其他情况:
第一、显示的是在主窗体上的鼠标坐标,原点为主窗体的左上角点。
代码是响应主窗体.cpp下的mousemove()消息,其入口参数point就包含了鼠标的坐标信息,但是是相对于窗体的坐标。
void CMFCApplication1Dlg::OnMouseMove(UINT nFlags, CPoint point)//point入口形参就包含鼠标的坐标值(相对窗体内)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
SetDlgItemInt(IDC_EDIT_X,point.x);
SetDlgItemInt(IDC_EDIT_Y,point.y);
CDialogEx::OnMouseMove(nFlags, point);
}


第二、主窗体.cpp下的mousemove()消息是只有鼠标在主窗体区域内才响应的事件。
void CMFCApplication1Dlg::OnMouseMove(UINT nFlags, CPoint point)//point入口形参就包含鼠标的坐标值(相对窗体内)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
POINT pMouse;
GetCursorPos(&pMouse);

SetDlgItemInt(IDC_EDIT_X,pMouse.x);
SetDlgItemInt(IDC_EDIT_Y,pMouse.y);
CDialogEx::OnMouseMove(nFlags, point);
}


12.文本框多行显示 和 限制每行的长度和文本框的宽度一一致。

文本框的属性设置如下:



这样就可以支持多行显示,但是文本的一行的宽度一般都会超过文本框的宽度,解决方案如下:
限制一行的宽度
在初始化函数中添加代码:
m_edit1.SetLimitText(1);
m_edit1是定义的文本框的控制类型的变量。

13.文本框输出,焦点设置在字符串最后。

CEdit * pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);
pEdit->SetSel(-1);
pEdit->SetFocus();


14.MFC使用提示窗输出字符、查看字符串、带参数值。

str_ascii.Format(_T("%d,%d"),hexH,hexL);
AfxMessageBox(str_ascii);
要注意的是_T()是不可以直接带参数的,所以利用CString中的format。

15.关于进位制的两三事

第一、数字在内存之中都是以二进制形式存在。也就是说:
int a = 4000; 在内存中,开辟一个“a”的区域,里面存放的是4000的二进制,即1111 1010 0000。
int a = 0x0F4A0; 其实和int a = 4000(十进制默认,不需要0x之类的标识); 是等价的。所以不管是用什么进制的值来给变量赋值,变量里面都是转化为二进制的值。

第二、非十进制中,数字的显示和四则运算,其实很十进制也是一样的。
int a = 4000;
int b = 3000;//和 int b = 0x0BB8等价
a = a - b ; 所以a = 1000。这是十进制下的,没问题。但是
a = a - 0x0BB8;所得到的a也是1000,也是0x03E8。(0x0BB8 是 3000 的十六进制)。

其实,不管是几进制加减几进制,得数都一样,只是在不同进制下的写法不同罢了。
输出可以使用printf(_T("%04X"),a);来查看a的十六进制,%04X表示十六进制有四位。

16.回车不关闭窗体

是一个焦点的问题。
重载OnOK消息。OnOK()是窗体类自带的函数,直接 先在头文件中声明,再在.cpp中添加一下函数。
void CcameraDlg::OnOK()
{
if(GetDlgItem(IDOK)==GetFocus())
{
CDialog::OnOK();
}
//handle enter key
}


17.SetTimer使用

参考:http://www.sx.xinhuanet.com/fwxx/2008-11/17/content_14933678.htm
参考:http://blog.csdn.net/libin88211/article/details/25491979
UINT SetTimer(1,100,NULL);
函数反回值就是第一个参数值1,表示此定时器的ID号。
第二个参数表示要等待100毫秒时间再重新处理一次。第三个参数在这种方法中一般用NULL。
注意:设置第二个参数时要注意,如果设置的等待时间比处理时间短,程序就会出问题了。

18.获取系统时间

CString str; //获取系统时间 //	str = tm1.Format(_T("现在时间是%Y年%m月%d日 %X"));
CTime tm1;
tm1 = CTime::GetCurrentTime();
str = tm1.Format("%X");//hh:mm:ss
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: