MFC入门

1 篇文章 0 订阅

VS2010新建工程
选择CDialogEx
默认创建出一个带有确认和取消按键的对话框

例如创建的程序名为TestOne
则创建出一个CTestOneApp类,继承自CWinApp
在CWinApp中的InitInstance函数中

CTestOneDialog dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if(nResponse== IDOK){

}else if(nResponse == IDCANCEL){

}

类似Qt中的QDialog

QDialog dialog;
int response = dialog.exec();
if(response == Qt::Acceptted){

}else if(response == Qt::Rejectted){

}

添加新的按键并给按键添加事件
菜单-视图-资源管理器 打开资源管理器
窗口的视图布局在此管理器中管理
双击打开Dialog对应的图形化布局
打开右侧工具栏的小图标,点击选择按键就可以生成按键
在生成的按键上右击选择创建事件,选择对应的事件触发类型,即可添加事件处理函数

AfxMessageBox(_T("测试成功!"));//简单的信息提示对话框

各种视图类的介绍
1.CView 最基本的视图类
2.CScrollView类,滚动窗口
void CScrollView::SetCrollSizes(int nMapMode,SIZE sizeTotal,const SIZE& sizePage = sizeDefault,const SIZE& sizeLine = sizeDefault) 坐标转换后续看一下
上面函数中的引用使用默认值,其实是有疑问的,不同编译器应该支持的不同,看情况吧???
3.CFormView类,提供用户在资源文件中定义界面的能力,并可以将子窗口和变量进行绑定。通过UpdateData函数让数据在变量和子窗口间交换。 这部分可以重点看看
4.CTreeView类利用TreeCtrl界面作为视图界面,通过调用CTreeCtrl& CTreeView::GetTreeCtrl() const的到CTreeCtrl的引用
5.CListView类,类似上面
6.CEditView类利用Edit接收用户输入,它具有输入框的功能
7.CRichEditView 富文本输入的视图类,提供了按照格式显示文本的能力,在使用时需要CRichEditDoc的支持

MFC文档和视图结构
类似Model View吗????
类似Scene和View吗????(编辑组织Item,View来显示)
文档和视图是一对多的关系,类似上面的
使用文档视图结构开发应用程序时,涉及4个部分
1.文档模板
2.文档 是字符文档,还是类似DataStream这种非字符文档????
3.视图
4.框架窗口

高级编辑空间开发????

视图类
派生关系
CView :: CWnd
CMainFrame :: CFrameWnd :: CWnd

文档
文档类CDocumment负责维护应用程序所需要的数据,提供对哲学数据进行操作的方法,为视图类提供所需要的数据

吕鑫教程
HWND FindWindow(窗口类型,窗口名字串)
HWND是窗口句柄
MessageBox(父对象【可以是窗口句柄】,文本字串,标题字串,按键组合枚举【图标和文字可以叠加】)
返回值:按键ID
上面两个函数都是Win32的API
在线搜索时,搜索MessageBox Function 否则搜不到

VS2015 工具 ---- spy++ ---- 查找窗口
拖动靶子图标,拖动到要确定属性的窗口,就能得到窗口的句柄、类型名等窗口属性

上面的功能测试成功
空项目是源文件的固定格式
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev,LPSTR lpCmd, int nCmdShow){
return 0;
}

VS2015资源种类
快捷键
位图
光标
对话框
HTML
菜单
Ribbon
String Table
工具栏
版本信息

其中对话框Dialog的属性
有些类似Qt Creator,但是好像没有布局等等
属性ID 主对话框可以自己定义一个ID 如ID_MAIN_DIALOG
属性Caption 定义标题名

Win32 API
DialogBox 函数
添加资源dialog定义dialog的属性等等
调用编辑好的dialog资源
HINSTANCE是资源总管 WinMain中的hInstance是资源总管
所以编辑好的dialog作为一个对话框模板资源
DialogBox(HINSTANCE hInstance,资源DialogID,父窗口HWND,回调函数)

回调函数
INT_PTR CALLBACK myCallBack1(HWND hwndDlg,UINT uMsg,WPARAM wParam, LPARAM lParm);
其中第二个参数是窗口事件消息的类型
那么可以知道,这个回调函数其实是,处理对应窗口发出的消息。在Qt中例如鼠标事件由MouseEvent处理,但是这个更像是Qt中的Event函数,属于还没有分类的事件消息,而且也没有控件写好的默认处理函数
与Qt的其他异同
事件消息,包含了子对象的操作,如视图中按键的操作
在Qt中按钮的操作,一般在窗口的初始化函数中,将子对象的信号和this的槽函数绑定,或者干脆使用connect的lamda表达式形式。这种回调函数的形式,更像是Qt中的eventFilter(),将子对象注册到父对象,然后子对象的事件,先传给父对象处理,并决定是否需要子对象二次处理。Win32的这种形式,省去了子对象注册,子对象的所有事件消息都由父对象处理。
uMag的枚举
WM_COMMAND 命令消息????鼠标事件不需要分类吗????
其中第二个参数wParam
其低字LOWORD(wParam)对应发送事件消息的子对象ID
GetDlgItemInt(窗口句柄,子对象ID,参数3,bool【是否支持正负】)
SetDlgItemInt(窗口句柄,子对象ID,要赋值的值【一般为表达式】,bool【是否支持正负】)
计算器例程测试成功
但是好像掉的都是Win32的公共函数
并没有使用对象形式…
注意回调函数的返回值若为False则系统需要执行默认处理
返回值为true则系统不处理
GetItemText()获取控件的文字或者窗口的标题

https://studiostyl.es/ 一个可以配置任何版本VS代码颜色的网址,很好用 vs2008好像有点问题???看起来像是应用了C#的颜色配置

VS2015 快速注释操作
注释 CTRL+K CTRL+C
取消注释 CTRL+K CTRL+U

#define 一行末尾加
在宏定义中末尾加\是指连接上下两行为一行
__stdcall有什么用????callback函数需要声明这个????暂不考虑原因,后续再看 __stdcall是标准C++函数,因为还有标准C程序等等,参数入栈和参数回收处理有所区别所以要声明

持续更新中。。。。。

Dialog回调函数的消息类型
WM_INITDIALOG 初始化消息,在窗口显示之前发出
WM_CLOSE 系统关闭消息 ALT+F4 和点击×号时会发送该消息,并不是退出窗口就会发出,而且此时是在窗口关闭之前
如果在处理该消息的时候,return true的话,那么可以阻断后续的关闭操作,也可以给它隐藏和最小化

WM_LBUTTONDOWN 左键按下
经过测试 只有按窗口的不响应鼠标的消息的地方有效,如Edit Control和Button等,而像Static Text则窗口会接收到消息。
此机制可能类似Qt中子对象先处理消息,在将消息向父对象传递
lParam存放有鼠标的x,y坐标 低字 存 x 高字 存 y
wParam存放有修饰按键的信息

WM_MOSEMOVE
在鼠标连续移动时,10秒钟打印相应了350次 依然在接收鼠标消息的控件上窗口会没有响应
capture 绑定后 鼠标离开该可视区域 依旧生效?????setCapture

send与post
send消息 马上执行 post 不一定立即执行

WindowsAPI
MoveWindow(hWnd,位置x,y,高,宽,是否刷新)
GetWindowRect(hWnd,LPRECT)
通过上面两个API可以移动窗口 测试完成

WindowsAPI
MesssageBox 返回值为按键的枚举
FindWindow 根据窗口名、窗口类型返回窗口句柄,桌面上所有的窗口都可以,可以用VS自带工具SPY++测试
DialogBox
EndDialog
GetDlgItemInt
SetDlgItemInt
GetDlgItemText
SetDlgItemText

SetWindowText(hWnd,char[])

Windows Message 常用消息类型
WM_SETFOCUS 得到焦点
WM_KILLFOCUS 失去焦点
WM_ENABLE 被激活或者禁用
WM_SETREADRAW 被设置刷新或者不刷新????
WM_SETTEXT 被设置文字
WM_GETTEXT 被获取文字
WM_PAINT 绘图消息???何时???
WM_CLOSE 系统关闭消息

WM_MOUSEMOVE 光标移动
WM_LBUTTONDOWN 左键按下
WM_LBUTTONUP 左键抬起
WM_LBUTTONDBLCLK 左键双击
WM_RBUTTONDOWN 右键按下
WM_RBUTTONUP 右键抬起
WM_RBUTTONDBLCLK 右键双击

Win32的开发和MFC开发的区别
MFC把API封装为类,开发效率更高

对字符串操作比较难用
#include<stdio.h>
char s[256];
sprintf(s,“x=%d,y=%d”,x,y);

WIN32 API设计的思考
dll动态库 提供的都是 全局函数
创建对象,和对对象的操作都是由全局函数来操作
其中对象作为参数传入函数时使用ID的形式,那么动态库中就需要维护一个ID对应对象指针的表或者图
相对于静态库,在调用的者的视角,接口更加简洁,可靠性更高
但是,无法调用成员函数,缺少一些灵活性,并且封装接口的工作量较大

当窗口类需要嵌入的其他开发环境,怎么做???
需要消息传递的机制,那么此机制需要初始化,WinMain函数一般来说就不能有了,是不是要另开一个线程,执行一个类似WinMain的函数以维持此机制????
Qt调用MFC的图形,是否可行???
Qt嵌入MFC是可行的,方法是怎么样的????

自定义一个结构体类型的别名
typedef struct tagPoint{
int x;
int y;
} POINT,*PPOINT,*LPPOINT;

MFC的工程
其中WinMain函数没有了
那么App函数中的InitInstance大致做之前WinMain函数的功能,主要是一些初始化的功能

MFC形式,右键控件,有和Qt类似的自动生成消息处理函数
由消息映射表完成,后续可以看看消息映射表的数据结构,可以得到什么形式比较高效的访问映射关系,HashMap????HashSet????(HashSet是什么?????)

消息处理函数前面有afx_msg
#define afx_msg
加不加都可以,应该只是用来提示该函数是个消息处理函数,并没有实际作用

VS2015中 项目----类向导
可以在此添加消息处理函数
VS2008中没有类向导
若要添加《包含的控件》的事件处理函数
类视图------选中需要添加消息处理函数的类------在属性框中------有一个闪电的标志点击(事件)--------选中包含的控件中的消息-------点击下拉框-------点击添加消息处理函数即可
若要添加

若要添加《窗口自身》的事件处理函数
类视图------选中需要添加消息处理函数的类------在属性框中------有一个闪电的标志点击(事件)--------选中包含的控件中的消息-------点击下拉框-------点击添加消息处理函数即可
若要添加

发现的问题
如MFC中的Dialog窗口D添加一个按键A
点击按键A,但是需要D去使用MouseDown函数去响应(比如需要用到MouseDown的函数参数有坐标值信息)
对于Qt来说,先派生一个QPushButton,在MousePressEvent中调用event()->ignore();此时事件被忽略 事件就是流转到父对象D进行处理
而对于MFC来说,可能没有类似的处理方式
代替的方式
一是由子对象再次发送消息(可能不太好用,坐标之类的计算不好弄,舍弃)
二是在virtual BOOL PreTranslateMessage(MSG* pMsg中处理????)后续需要看一下怎么处理的,应该是类似Qt中的EventFilter,注意Qt中使用EventFilter会大大降低事件处理的效率

Qt事件消息事件处理机制
消息最先传递到子对象
先由子对象处理
若子对象调用event->ignore(),则其父对象会处理
事件分发函数QWidget::event()的调用者可以后续再看看????可以理解一下,Qt如何实现的消息分发的机制

MFC问题
在PreTranslateMessage中添加MessageBox()模态窗口,会导致,后续的消息不在向子控件传递,有问题?????一般来说不应该有这样的问题,可能某些机制不太合理

VS2008 MFC添加重载函数的方式
在VS2015中有类向导,在VS2008中,打开类视图,点击要操作的类,在属性窗口中,点击小方块图标(重载),点击要添加的函数

MFC 子控件的事件 由父对象来处理
例如按钮按下的消息处理函数中的参数信息有限,
所以可以把按钮按钮的消息,交给PreTranslateMessage(Msg* pMsg)处理
其中pMsg->message 包含消息类型,如WM_LBUTTONDOWN
pMsg->hwnd
句柄转ID的方式 LONG id = GetWindow(hwnd,GWL_ID);
其中当句柄为自身时,id == 0;
通过ID判断是哪个组件
????MFC的消息分发函数???除此防水,还有其他方法将按钮按下的消息,分发给Dialog而不是按钮????后续再看,很可能不行…

CString 格式化输出方式
例如
int id = 1000;
CString s;
s.Format("%d",id);

CString 裁剪函数 Trim 后续再看吧?????

MFC中
如何调用老的WIN32接口函数
因为在MFC类的成员函数中与WIN32的接口函数有许多同名的
所以使用双冒号来区分全局函数和成员函数
::GetItemInt() 调用WIN32 API
GetItemInt() 调用类的成员函数

CString和LPSTR转换
LPSTR根据编码形式就是char* 或unsigned char*
一般老的Win32 API接口会用到 LPSTR
那么就需要CString转换为LPSTR
可以这样使用
CString str;
LPSTR lpStr = str.GetBuffer(1000);
::GetSystemDirectory(lpStr,1000);
str.Release();//执行此函数才能str才能正常使用

virtual BOOL CWinApp::InitInstance();
重载
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWndd->UpdateWindow();
}

Window::OnPaint() 重载
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.DrawText(“Hello”,-1,&rect,DT_SINGLELLINE|DC_VCENTER);
}

CWinApp的可重载函数
若在InitInstance中分配了资源
那么在ExitInstance中释放资源
还可以使用ExitInstance在应用程序终止后清屏
OnIdle在应用程序空闲时才会调用,所以可以做垃圾回收之类的工作
重载Run自定义消息循环 重点看一下?????
想要消息在被调度以前执行一些专门处理,可以重载PreTranslateMessage

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值