导图社区 MFC思维导图
微软基础类库,简称MFC,是一个微软公司提供的类库,以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量,收藏下图了解吧!
编辑于2021-08-25 18:46:44MFC
基本概念
Microsoft Foundation Class Library
微软基础类库,封装了windows应用程序的各种API及相关机制
程序的流程也包括
程序的创建,显示等
一个大的类库 一个程序应用框架
减少开发周期和成本
字符串
多字节转宽字节L
TEXT/_T可自适应多字节或者宽字节
宽字节声明wchar_t
宽字节统计wcslen
char* CString
char* to CString: CString(pChar)
CString to char* :str.GetBuffer()
char* to string
c_str()
常用头文件
afx.h
包含mfc的所有头文件
afxwin.h
包含各种mfc窗口类,包含afx.h和windows.h
afxext.h
扩展窗口类,工具栏,状态栏等
MFC程序分类
控制台程序
能调用MFC库
main函数多了一个参数
::上冒号开头 来自win32 API
修改字符编码 右键属性->Character Set
Use Multi-byte Character Set
afx开头全局的
::Afx 微软派遣写法 可直接去掉就是原来的了
MFC静态库
MFC动态库
使用静态MFC 库
使用动态MFC shared DLL
规则库可被其他各种程序使用
扩展库只能MFC程序使用
MFC窗口程序
单文档程序框架
CWinApp应用程序类,负责管理应用程序的流程
CFrameWnd框架窗口类 负责管理框架窗口
CView 视图窗口类 负责显示数据
CDocument 文档类 负责管理数据
多文档视图架构程序
CWinApp 应用程序类
CMDIFrameWnd多文档主框架窗口类
CMDIChildWnd多文档子框架窗口类
CView视图窗口类,显示数据
CDocument 文档类
对话框应用程序
CWinApp 应用程序类
CDIalog 对话框窗口类
MFC类库结构
Hierachy Chart
CObject
MFC中绝大多数类的父类,提供MFC类库中的一些基本机制
运行时类信息的支持
动态创建机制的支持
序列化的支持
CWinApp
应用程序类,封装了应用程序,线程等信息
继承自CWinThread
CDocument
文档类,管理数据
Frame Windows
框架窗口类
CSplitterWnd
用来拆分窗口的类 不规则窗口类
Control Bars控件条类
DialogBoxes 对话框类
View
Controls
Exceptions
异常处理类
CDC CGdiObject 绘图类
数据集合类。 CArray Clist CMap
非CObject子类
CPoint CTime CString等
第一个MFC程序
Win32改
头文件afxwin.h
使用mfc using shared dll
定义自己的框架类继承CFrameWnd
定义自己的应用程序类
派生自CWinApp
构造函数
重写virtual BOOL InitInstance
CMyFrameWnd *pFrame=new CMyFrameWnd;
pFrame->Create(NULL, "MFCMy")
m_pMainWnd=pFrame
pFrame.ShowWindow(SW_SHOW)
pFrame.UpdateWindow()
return TRUE;
定义全局CMyWinApp类的对象 程序爆破点
MFC程序如何启动
入口函数WinMain,MFC已经实现
MFC负责安排程序的流程(1)
CWinApp构造函数 先父类再自己的构造
AFX_MODULE_STATE* pModuleState=_AFX_CMDTARGET_GETSTATE()获取全局变量aaa地址
一个有三个
全部变量:在某个地方存,在另外一个地方拿出来
aaa 当前程序模块状态信息
_AFX_CMDTARGET_GETSTATE()=AfxGetModuleState()
AFX_MODULE_THREAD_STATE * pThreadState=pModuleState->m_thread 获取全局变量bbb
bbb 当前程序线程状态信息
aaa的成员变量
pThreadState->m_pCurrentWinThread=this 将全局变量theApp保存到bbb中
AfxGetThread 获取theApp
AFX_MODULE_THREAD_STATE * pThreadState=AfxGetModuleThreadState 获取全局变量&bbb
return (CwinThread*)pTheadState->m_pCurrentWinThread
pModuleState->m_pCurrentWinApp=this
将theApp保存在aaa的成员中
AfxGetApp() 返回&theApp=this
return AfxGetModuleState()->m_pCurrentWinApp
程序启动,构造theApp对象,调用父类CWinApp的构造函数
将theApp对象地址保存在线程状态信息中
将theApp对象地址保存在模块状态信息中
进入WinMain函数,调用AfxWinMain函数
调用InitInstance
WinMain函数 theApp在指导流程
CWinThread* pThread=AfxGetThread() CWinApp* pApp=AfxGetApp() 两行代码都是获取&theApp
pApp->InitApplication//利用theApp对象调用应用程序类成员虚函数
pThread->InitInstance() //利用theApp对象调用应用程序类成员虚函数,完成窗口创建,显示
重写virtual BOOL InitInstance this为theApp地址
CMyFrameWnd *pFrame=new CMyFrameWnd;
pFrame->Create(NULL, "MFCMy")
this->m_pMainWnd=pFrame
pFrame.ShowWindow(SW_SHOW)
pFrame.UpdateWindow()
return TRUE;
nReturnCode=pThread->Run()//消息循环,theApp调用的
父类CWinApp::Run
爷爷类CWinThread::Run
for(::)死循环
while(没有消息) [this->]OnIdle()空闲处理
do{ 如果GetMessage抓到WM_QUIT则退出 if !PumpMessage() ExitInstance()//theApp成员虚函数,善后处理
return AfxInternalPumpMessage()
GetMessage()..... return FALSE//ON_WM_QUIT
总结:进入入口函数WinMain
获取theApp地址,
利用theApp调用InitApplication,初始化当前应用程序的数据
利用theApp调用InitInstance初始化程序,在函数中我们创建并显示窗口
利用theApp调用CWinApp的Run虚函数进行消息循环
如果没有消息,则调用theApp的OnIdle虚函数,实现空闲处理
程序退出利用theApp地址调用ExitInstance虚函数实现退出前的善后处理工作
MFC窗口创建机制(2)和消息
钩子技术Win32
95%木马和病毒
优先处理消息的权利
创建钩子(埋钩子)
HHOOK SetWindowHookEx( int idHook//钩子类型,WH_CBT 只对WM_CREATE消息感兴趣 HOOKPROC lpfn//钩子处理函数 HINSTANCE hMod//限制哪个程序 DWORD dwThreadId //限制线程ID
钩子处理函数
LRESULT CALLBACK CBTProc( int nCode//钩子码 HCBT_CREATEWND与类型唯一对应 WPARAM wParam, 创建成功的窗口句柄 LPARAM lParam
SetWindowLongPtr 更改窗口处理函数
LONG SetWindowLongPtr( HWND hwnd窗口句柄 int nIndex //GWLP_WNDPROC LONG_PTR dwNewLong 新的窗口处理函数名 函数地址
还可以改窗口风格 ,第二个参数决定
CFrameWnd Create(NULL,"title")
流程
加载菜单
子主题
CreateEx(...,NULL,....)
CREATESTRUCT cs;
cs.lpszClass=NULL;
AfxGetInstanceHandle() 可拿到WinMain的第一个参数
PreCreateWindow(cs)
注册窗口类,把窗口类名称赋值
AfxDeferRegisterClass
WNDCLASS wndcls
wndcls.lpfnWndProc=DefWindowProc窗口处理函数
_AfxRegisterWithIcon(&wndcls,"afxFrameOrView100sd",...)
&wndcls->lpszClassName="AfxFrameOrView100sd""
AfxRegisterClass(pWndCls)
cs.lpszClass=_afxWndFrameOrView
"afxFrameOrView100sd"
AfxHookWindowCreate(this) 更改窗口处理函数
_AFX_THREAD_STATE* pThreadState =_afxThradState.GetData();//获取全局变量ccc 当前程序线程信息
::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook)利用win32的API函数,埋了一个WM_CREATE的钩子
AfxCbtFilterHook
真正代表窗口的只能是窗口句柄, 因此必须把pFrame与窗口句柄建立一对一联系
_AFX_THREAD_STATE* pThreadState =_afxThradState.GetData();//获取全局变量ccc 当前程序线程信息
CWnd* pWndInit=pThreadState->m_pWndInit获取pFrame==pWndInit
HWND hWnd=(HWND)wParam 刚刚创建成功的窗口句柄
pFrame->Attach(hWnd) 建立窗口句柄和pFrame的对应关系
CHandleMap * pMap=faxMapHWND(TRUE)
获取BBB地址 pState
pState->m_pmapHWND=new CHandleMap(RUNTIME_CLASS(CWND), ConstructDestruct........ 创建映射类对象,保存到BBB中,并返回
this是pFrame
pMap->SetPermanent([this->]m_hWnd=hWndNew,this) 实现:已知pFrame找句柄
实现已知句柄找pFrame this->m_permanentMap[hWnd]=pFrame;
SetWindowLongPtr 重新设置窗口处理函数
(WINDPROC)SetWindowLongPtr(hWnd,GWLP_WNDPROC,(DWORD_PTR)AfxWndProc)
pTreadState->m_pWndInit=pFrame; 将自己new的框架类对象保存到全局ccc中
::AfxCreateWindowEx
此处窗口类名称已不为NULL
发出WM_CREATE消息
一旦执行成功就转到钩子处理函数,操作系统自动调用
MFC窗口消息处理流程
AfxWndProc
WM_CREATE 编号1
CWnd*pWnd=CWnd::FromHandlePermanent(hWnd) 拿到窗口pFrame
afxMapHWND()
AFX_MODULE_THREAD_STATE* pState =AfxGetModuleThreadState() 获取&bbb
return pState->m_pmapHWND;
pMap->LookupPermanent(hWnd)
return m_permanentMap[hWnd]
AfxCallWndProc(pWnd, hWnd, nMsg,wParam,lParam)
pWnd->WindowProc(nMsg.wParam,lParam
流程
当收到消息时候,进入AfxWndProc函数
AfxWndProc根据hwnd找到pFrame
pFrame调用重写的成员虚函数
virtual LRESULT WindowProc(UINT msgID,WPARAM wParam,LPARAM lParam){ switch(msgID){ case WM_CREATE: AfxMessageBox("创建") break; } return CFrameWnd::WindowProc(msgID,wParam,lParam)}
case WM_PAINT: { PAINTSTRUCT ps={0} HDC hdc=::BeginPaint(this->hWnd.&ps) ::TextOut(hdc,100,100,"hello",5) ::EndPaint(m_hWnd,&ps); }
消息映射机制(3)
消息映射建立
类必须具备两个使用条件
类内声明宏DECLARE_MESSAGE_MAP()
类外添加实现宏
BEGIN_MESSAGE_MAP(theClass,baseClass)
END_MESSAGE_MAP()
可以在不重写WindowProc的前提下,仍然能够处理消息
具体操作
BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP之间添加ON_MESSAGE(WM_CREATE,OnCreate)宏
在CMyFrameWnd类中添加OnCreate函数的声明和定义
public: LRESULT OnCreate(WPARAM wParam,LPARAM lParam)
函数原型声明定义
具体实现
DECLAERE_MESSAGE_MAP()展开
protected: static const AFX_MSGMAP* PASCAL GetThisMessageMap() virtual const AFX_MSGMAP* GetMessageMap() const;
声明宏 声明一个静态函数和虚函数
BEGIN_MESSAGE_MAP
PTM_WARNING_DISABLE 可以用类的函数名代替函数地址,等效于&OnCreate PTM_WARNIGN_RESORE
const AFX_MSGMAP* CMyFrameWnd::GetMessageMap const{ return GetThisMessageMap(); }
虚函数返回静态函数,获取链表头
const AFX_MSGMAP* PSCAL CMyFrameWnd::GetThisMessageMap(){ static const AFX_MSGMAP_ENTRY _messageEntries[]={
struct AFX_MSGMAP_ENTRY 结构体 静态数组的每个元素类型
UINT nMessage 消息ID
UINT nCode 通知码
UINT nID 命令ID 菜单项或快捷键
UINT nLastID 最后一个命令ID
UINT_PTR nSig 消息处理函数类型
AFX_PMSG pfn 处理消息的函数名(地址)
作用:数组每个元素保存为消息ID和消息处理函数的地址
ON_MESSAGE()展开
{WM_CREATE,0,0,0,AfxSig_lwl,(AFX_PMSG)(AFX_PMSGW) (static_cast<LRESULT(AFX_MSG_CALL CWnd::*)(WPARMA,LPARAM)>(&OnCreate)}
{WM_CREATE,。。。(&OnCreate)}
END_MESSAGE_MAP()展开
{0,0,0,0, AfxSig_end,(AFX_PMSG)0} };
static const AFX_MSGMAP messageMap={&CFrameWnd::GetThisMessageMap,&_messageEntries[0]}; return &messageMap;
struct AFX_MSGMAP
const AFX_MSGMAP(PASCAL * pfnGetBaseMap)()
const AFX_MSGMAP_ENTRY* lpEntries;
在其静态函数中定义了一个静态数组 _messageEntries【】和一个静态变量 messageMap 并返回本类的静态变量地址 (获取链表头)
静态变量messageMap中包含,静态数组_messageEntries的首地址
以及父类的静态变量的地址
这就形成了一个静态链表
_messageEntries 和 messageMap均为进程级别生命周期
消息处理流程
AfxWndProc窗口消息处理函数
CWnd*pWnd=CWnd::FromHandlePermanent(hWnd) 通过句柄拿到窗口pFrame
AfxCallWndProc(pWnd
pWnd->WindowProc(...)
如果此处重写了,就调用子类自己的窗口处理函数,否则下一步
this为pFrame
CWnd::WindowProc
OnWndMsg
WM_COMMAND和CREATE路线不一样
WM_NOTIFY也不一样
const AFX_MSGMAP* pMessageMap=GetMessageMap(); 虚函数拿到本类链表头
const AFX_MSGMAP_ENTRY* lpEntry;
for(;pMessageMap->pfnGetBaseMap!=null; pMessageMap=(*pMessageMap->pfnGetBaseMap)())
lpEntry=AfxFindMessageEntry(pMessageMap->lpEntries,message,0,0)
遍历链表找与消息匹配的数组元素地址
找到就跳出并调用lpEntry->pfn,完成消息处理,没有就往上找
消息分类
ON_MESSAGE通用型
鼠标 键盘 定时器
都是往静态变量里面扔 ID和处理函数
LRESULT OnXXX(WParam. LParam)
触发消息 ::PostMessage(m_hWnd, WM__MYMSGXXX)
ON_WM_XXX 标准window消息,都有专职宏
函数名和原型(形参,返回值类型)都定死了
ON_WM_CREATE()
int OnCreate(LPCREATESTRUCT pcs);
返回父类的处理函数 return CFrame::OnCreate(pcs);
原来自己没写,父类帮忙处理的,现在重写了父类的就被屏蔽了,所以调用
ON_WM_PAINT
void OnPaint();
PAINTSTRUCT ps={0} HDC hdc=::BeginPaint(this->m_hWnd,&ps) ::TextOutA(hdc, m_x,m_y,"hello",5) ::EndPaint(m_hWnd,&ps)
ON_WM_MOUSEMOVE
void OnMouseMove(UINT nKey, CPoint pt){ m_x=pt.x; m_y=pt.y; ::InvalidateRect(this->m_hWnd,NULL,TRUE)
自定义消息
#define WM_MY_MSG WM_USER+1001
::PostMessage(this->m_hWnd,WM_MY_MSG,XX,XX)
ON_MESSAGE(WM_MY_MSG, OnMyMsg)
LRESULT CMyFrameWnd::OnMyMsg(WPARAM wParam,LPARAM lParam){ CString str; str.Format("%s, %s",wParam.lParam)}
ON_COMMAND命令型
活动视图窗口 点一下
在框架类的OnCreate中加一句 m_pViewActive=pView
处理顺序
视图类》 框架类 》应用程序类
菜单和工具栏
菜单
简介
HMENU-win32
CMenu对象和句柄的关联
封装菜单的各种操作函数
m_hMenu菜单句柄
类似框架类和窗口句柄建立关联
简介
使用
添加菜单资源,设置ID
将菜单设置到窗口
利用pFrame的Create函数中传参
pFrame->Create(NULL, "MFCCreate",WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,(CHAR*)IDR_MENU1)
或者在处理框架类窗口的WM_CREATE消息的时候,利用LoadMenu
CMenu menu 改成类的成员对象
menu.LoadMenu(IDR_MENU1)
this.SetMenu(&menu)
等价于 ::SetMenu(this->m_hWnd, menu.m_hMenu)
处理菜单点击事件
ON_COMMAND(ID_NEW, OnNew)
afx_msg void OnNew(); afx_msg 给人看的,表示为消息处理函数,机器不看这个
设置菜单状态
处理WM_INITMENUPOPUP消息,对应消息宏ON_WM_INITMENUPOPUP
实现 void OnInitMenuPopup(CMenu *pPopup, UNIT nPos, BOOL i)
调用CheckMenuItem/EnableMenuItem
pPopup->CheckMenuItem(ID_NEW, MF_CHECKED)
上下文菜单(右键菜单)
WM_CONTEXTMENU处理菜单消息
ON_WM_CONTEXTMENU
void OnContextMenu(CWnd*pWnd,CPoint pt)
TrackPopupMenu只能显示弹出菜单
::TrackPopupMenu(::GetSubMenu(menu.m_hMenu,0),TPM_LEFTALIGN|TPM_TOPALIGN,pt,x,pt.y,0,this->m_hWnd,NULL)
或者:CMenu*pPopup=menu.GetSubMenu(0); pPopup.TrackPopupMenu(xxx)
工具栏
相关类
<afxext.h>
CToolBarCtrl 父类CWnd 封装了关于工具栏控件的各种操作
控件
CToolBar 父类CControlBar 封装了关于工具栏的操作以及和框架窗口的关系
容器
父子关系和停靠关系
使用
添加工具栏资源,绘制添加,拖拽删除
WM_CREATE 创建工具栏 CToolBar:: CreateEx
CToolBar toolbar;类成员对象
toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP)
加载 CToolBar::LoadToolBar
toolbar.LoadToolBar(IDR_TOOLBAR1)
可与菜单项的ID保持一致,MFC自动绑定
ON_COMMAND处理点击消息
拖拽
增加风格toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP|CBRS_GRIPPRER)
CToolBar::EnableDocking(CBRS_ALIGN_ANY)
想停哪里
CFrameWnd::EnableDocking
窗口允许停哪里
CFrameWnd::DockControlBar
设置现在停在哪里
MFC运行时类信息机制(4)
实现在程序运行中可以获取对象的类的相关信息(对象是否属于某一个类 CObject::IsKindOf)
使用条件
派生自CObject
类内添加声明宏 DECLARE_DYNAMIC(theClass)
public: static const CRuntimeClass calssCDog; virtual CRuntimeClass* GetRuntimeClass() const;
声明一个静态变量和静态函数
类外添加实现宏 IMPLEMENT_DYNAMIC(theClass,BaseClass)
IMPLEMENT_RUNTIMECLASS(CDog,CAnimal,NULL,NULL)
AFX_COMDAT const CRuntimeClass CDog::classDog={ "CDog",sizeof(class Dog), 0xFFFF, NULL. RUNTIME_CLASS(CAnial)//父类的静态变量,由此可以管理链表 NULL, NULL,}
初始化该静态变量,保持类的各种信息,以及父类的静态变量地址
CRuntimeClass* CDog::GetRuntimeClass() const{ return RUNTIME_CLASS(CDog)}
return ((CRuntimeClass*)&CDog::classDog)
实现虚函数,返回本类保存了本类类信息的静态变量的地址
即链表头
一个“#”是加引号的意思
两个## 是前后拼接的意思
相关实现
CRuntimeClass
struct{
LPCSTR m_lpszClassName//类名称
int m_nObjectSize 类大小
UINT m_wSchema//类版本,0xFFFF
CObject*(PASCAL*m_pfnCreateObject)()//动态创建机制使用,这里为NULL
CRuntimeClass* m_pBaseClass父类宏展开静态变量地址
形成一个链表
CRuntimeClass*m_pNextClass 不适用为NULL
const AFX_CLASSINIT* m_pClassInit不使用为NULL
}
RUNTIME_CLASS
(CRuntimeClass*)(&CAnimal::classAnimal)
获取某一个类的静态变量,其中保存了该类的类信息
也是链表头节点
执行过程
IsKindOf(RUNTIME_CLASS(CDog))
参数为链表头节点
CRuntimeClass *pClassThis=GetRuntimeClass()返回调用者自身类的静态变量地址,链表头节点
return pClassThis->IsDerivedFrom(pClass)
const CRuntimeClass*pClassThis=this
while(pClass!=NULL)
if(pClass==参数的静态变量地址) return TRUE
pClassThis=pClassThis->m_pBaseClass
MFC动态创建机制
目的
在不知道类名的情况下,将类的对象创建出来
意义在于,让MFC自己帮你创建类的对象
使用条件
派生自CObject
类内必须添加声明宏, DECLARE_DYNCREATE(theClass)
类外实现宏 IMPLEMENT_DYNCREATE(theClass,baseClass)
之后,可通过,CRuntimeClass::CreateObject(对象加工厂)函数创建类的对象
相关实现
DECLARE_DYNCREATE(theClass)
DECLARE_DYNAMIC(CDog)
动态类信息展开的宏
static const CRuntimeClass calssCDog; virtual CRuntimeClass* GetRuntimeClass() const;
static CObject* PASCAL CreateObject()//不是CRuntimeClass的成员函数
IMPLEMENT_DYNCREATE(theClass,baseClass)
CObject* PASCAL CDog::CreateObject() { return new CDog;}
IMPLEMENT_RUNTIMECLASS(CDog,CAnimal,0xFFFF,CDog::CreateObject,NULL)
AFX_COMDAT const CRuntimeClass CDog::classDog={ "CDog",sizeof(class Dog), 0xFFFF, CDog::CreateObject//新增的静态函数的地址 RUNTIME_CLASS(CAnial)//父类的静态变量,由此可以管理链表 NULL, NULL,}
初始化该静态变量,保持类的各种信息,以及父类的静态变量地址
CRuntimeClass* CDog::GetRuntimeClass() const{ return RUNTIME_CLASS(CDog)}
return ((CRuntimeClass*)&CDog::classDog)
实现虚函数,返回本类保存了本类类信息的静态变量的地址
即链表头
执行过程
对象创建机制RUNTIME_CLASS(CDog)->CreateObject
pObject=(*(this->m_pfnCreateObject))()//就是新增加的那个CreateObject静态函数
return pObject
利用CDog类的静态对象,调用其静态函数CreateObject,该静态函数再调用类新增的静态函数(第四个成员),实现对象创建,并返回对象地址
文档和视图
视图窗口
作用
提供了一个用于显示数据的窗口
就是画图
相关类
CView
父类为CWnd类
封装了关于视图窗口的各种操作
以及和文档类的数据交互
使用
CMyView派生自CView.
重写父类纯虚函数OnDraw
pDC->TextOut(100,100,"123")
OnPaint()也可以绘图
PAINTSTRUCT pcs={0}; HDC hdc=::BeginPaint(this->m_hWnd,&pcs) ::TextOut(hdc,200,200,"Hello",strlen("Hello")); ::EndPaint(this->m_hWnd,&pcs)
WM_PAINT处理了,ondraw就不画了
在处理框架窗口的WM_CREATE消息时,定义CMyView对象,并调用Create函数,创建窗口
pView->Create(NULL,"FMCxianshibule", WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(0,0,200,200),this,1001)
视图窗口的ID为AFX_IDW_PANE_FIRST
关系
m_pMainWnd=pFrame
m_pViewActive=pView
theApp
m_pMainWnd(框架类对象地址)
m_pViewActive(视图类对象地址)
文档CDocument
作用
管理数据(提取转换,存储)
与视图类进行数据交互
使用
CMyDoc继承自CDocument
CCreateContex cct; cct.m_pNewViewClass=RUNTIME_CLASS(CMyView)
cct.m_pCurrentDoc=pDoc//文档类对象地址
pFrame->LoadFrame(IDR_MENU1.WS_OVERLAPPEDWNDOW,NULL, &cct)
pFrame->ShowWindow(SW_SHOW)
pFrame->UpdateWindow()
创建过程
利用框架内对象地址pFrame调用LoadFrame函数,创建框架窗口
函数内this指针为pFrame
Create(..... &cct)
依旧为pFrame
CreateEx(...&cct)
内部指针与i就为pFrame
cs.lpCreateParams=&cct
::CreateWindowEx(.....&cct)
父类在处理框架窗口的WM_CREATE消息时,动态创建视图类对象,并创建视图窗口
内部指针为pFrame, 参数为cs
CCreateContext* pContext=lpcs->lpCreateParams//获取cct
OnCreateHelper(...pContext)
OnCreateClient(cs, cct)
函数this依旧为pFrame
CreateView(pContext,AFX_IDW_PANE_FIRST)
CWnd *pView=pContext->m_pNewViewClass->CreateObject()
pContext->m_pNewViewClass==RUNTIME_CLASS(CMyView)
pView->Create(....pContext)
函数内部为pView, pContext==cct
CreateEx(...cct)
cs.lpCreateParams=pContext
CreateWindowEx(...pContext)
产生WM_CREATE消息
在处理视图窗口的WM_CREATE消息时,将文档类对象和视图类对象建立关联关系
CView::OnCreate(pcs)
内部this为pView, 参数为创建视图窗口时cs的全部12个参数
CCreateContext* pContext=lpcs->lpCreateParams//获取cct
pContext->m_pCurrentDoc->AddView(this)
函数内部this为pDoc, 参数为视图类对象
m_viewList.AddTail(pView)
文档类的链表成员保存视图类的对象地址
pView->m_pDocument=this//将文档类对象保存到视图类的普通成员中
对象关系图
theApp
m_pMainWnd(保存pFrame)
m_pViewActive(保存活动视图对象pView)
m_pDocument(保存文档类对象pDoc)
m_viewList(所有视图类对象)
CDocument
一个文档类对象可以对应多个视图类对象(视图窗口)
CView
一个视图窗口只能对应一个文档类对象
CFrameWnd
CApp
窗口切分
相关类
CSplitterWnd 不规则窗口类,封装了关于不规则框架窗口(有多个客户区)的操作
只有一个视图的叫规则框架窗口
CSplitterWnd的GetPane(0,0)可以得到相应客户区的视图类对象
m_pViewActive=(CView*)split.GetPane(0,0)
使用
重写CFrameWnd类成员虚函数OnCreateClient
在虚函数中调用CSplitterWnd::CreateStatic创建不规则框架窗口
CSplitterWnd split//不规则窗口,放到类的成员变量,提升生命周期
split.CreateStatic(this.1,2)
在虚函数中调用CSplitterWnd::CreateView创建视图窗口,填充CSplitterWnd的各个客户区
split.Create(0,0,RUNTIME_CLASS(CMyView),CSize(100,100),pContext)
split.Create(0,1,pContext->m_pNewViewClass ,CSize(100,100),pContext)
return TRUE
命令消息WM_COMMAND处理流程
总图
CObject
CCmdTarget
CWnd
CFrameWnd
CMyFrameWnd
CView
CMyView
CDocument
CMyDocument
CWinThread
CWinApp
CMyWinApp
加粗的均具有静态数组,消息处理能力,实现了消息处理机制
处理顺序
视图类》文档类》 框架类 》应用程序类
其他消息在哪个类发生,就在其对应的消息映射中处理
流程
AfxWndProc窗口消息处理函数
CWnd*pWnd=CWnd::FromHandlePermanent(hWnd) 通过句柄拿到窗口pFrame
AfxCallWndProc(pWnd
pWnd->WindowProc(...)
如果此处重写了,就调用子类自己的窗口处理函数,否则下一步
this为pFrame
CWnd::WindowProc
OnWndMsg
WM_COMMAND和CREATE路线不一样
OnCommand(wParam,lParm)
内部this为pFrame
CWnd::OnCommand(内部this依旧为pFrame)
OnCmdMsg(this依旧为pFrame
CView*pView=GetActiveView()
return m_pViewActive活动视图窗口的消息处理
pView->OnCmdMsg//看视图类和文档类
CWnd::OnCmdMsg
CCmdTarget::OnCmdMsg终点 此函数内部this为pView
遍历视图类的静态数组,查找相应的消息处理函数 for(pMessageMap=this->GetMessageMap();pMessageMap->pfnGetBaseMap!=null; pMessageMap=(*pMessageMap->pfnGetBaseMap)())
前面没有的话 this->m_pDocument->OnCmdMsg
CCmdTarget::OnCmdMsg终点 此函数内部this为pDoc
遍历文档类的静态数组,查找相应的消息处理函数 for(pMessageMap=this->GetMessageMap();pMessageMap->pfnGetBaseMap!=null; pMessageMap=(*pMessageMap->pfnGetBaseMap)())
this->CWnd::OnCmdMsg//然后再去框架类查找
CCmdTarget::OnCmdMsg终点 此函数内部this为pFrame
遍历框架类的静态数组,查找相应的消息处理函数 for(pMessageMap=this->GetMessageMap();pMessageMap->pfnGetBaseMap!=null; pMessageMap=(*pMessageMap->pfnGetBaseMap)())
AfxGetApp()->OnCmdMsg最后去应用程序类中查找
CCmdTarget::OnCmdMsg终点 此函数内部this为&theApp
WM_NOTIFY也不一样
const AFX_MSGMAP* pMessageMap=GetMessageMap(); 虚函数拿到本类链表头
const AFX_MSGMAP_ENTRY* lpEntry;
for(;pMessageMap->pfnGetBaseMap!=null; pMessageMap=(*pMessageMap->pfnGetBaseMap)())
lpEntry=AfxFindMessageEntry(pMessageMap->lpEntries,message,0,0)
遍历链表找与消息匹配的数组元素地址
找到就跳出并调用lpEntry->pfn,完成消息处理,没有就往上找
文档类和视图类的关联
文档类成员函数
UpdateAllViews (NULL)可以刷新与该文档类对象关联的所有视图窗口,参数填谁就是不刷新哪个view
m_viewList不可直接访问,没有接口,只能用迭代器访问,所有MFC链表皆如此,只有GetFirstXXXPosition
Position pos=this->GetFirstViewPosition()//指向链表头节点的前一个位置
CView* firstView=this->GetNextView(pos)
视图类成员函数
GetDocument获取文档类对象,任意地方都可以访问m_pDocument
单文档程序
相关类
使用
新建一个AFX_IDS_UNTITILED字符串
流程
new CSingleDocTemplate::CSingleDocTemplate(nIDResource, RUNTIME_CLASS(CMyDocument), RUNTIME_CLASS(CMyFrameWnd). RUNTIME_CLASS(CMyView))
m_pOnlyDoc=null
唯一的文档类对象
this->m_pDocClass=pDocClass;
this->m_pFrameClass=pFrameClass
this->m_pView=pViewClass
AddDocTemplate(pTemplate)
this为theApp
theApp->m_pDocManager=new CDocManage
文档管理类对象地址
m_pDocManager->m_templateList.AddTail(pTemplate)
OnFileNew()
this为theApp
this->m_pDocManager->OnFileNew()
this为文档管理类对象
CDocTemplate* pTemplate=this->m_templateList.GetHead() 取出单文档模板类对象
pTemplate->OpenDocumentFile
函数this为单文档模板类对象
OpenDocumentFile
pDocument=CreateNewDocument()
函数this为单文档模板类对象
CDocument* pDocument=(CDocument*)m_pDocClass->CreateObject()动态创建文档类对象
AddDocument(pDocument)
函数this为单文档模板类对象
m_pOnlyDoc=pDocument
pFrame=CreateNewFrame(pDocument,NULL)
函数this为单文档模板类对象
CCreateContext context;
context.m_pCurrentFrame=NULL.
context.m_pCurrentDoc=pDocument
context.m_pNewViewClass=RUNTIEM_CLASS(CMyView)
context.m_pNewDocTemplate=this
CFrameWnd* pFrame=(CFrameWnd*)m_pFrameClass->CreateObject(动态创建框架类对象)
pFrame.LoadFrame(&context)动态创建框架窗口
多文档程序
可以管理多个文档
使用
参与构建的类
CMIDFrameWnd
CMDIChildWnd
CWinAPp
CView
CDocument
其他类
CDocTemplate文档模板类
CMultiDocTemplate多文档模板类
CDocManager文档管理类
创建主框架
CMyFrameWnd *pFrame=new CMyFrameWnd
pFrame->LoadFrame(IDR_MENU1)
m_pMainWnd=pFrame
pFrame->ShowWindow(SW_SHOW)
pFrame->UpdateWindow()
创建多视图
CMultiDocTemplate* pTemplate=new CMultiDocTemplate(IDR_MENU2,RUNTIME_CLASS(CMyDoc).RUNTIME_CLASS(CMyChild).RUNTIME_CLASS(CMyView))
AddDocTemplate(pTemplate)
OnFIleNew()
OnFileNew()
OnFileNew()
执行过程
CMIDFrameWnd::LoadFrame
this指针为pFrame
CFrameWnd::LoadFrame
Create
CreateEx创建主框架窗口
CMultiTemplate(...)
父类CDocTemplate()的构造里面复制保存了传进来的三个类的类信息对象
m_docList.IsEmpty()
m_docList保存多个文档类对象的地址
AddDocTemplate
this为&theApp
m_pDocManager=new CDocManager
m_pDocManager->AddDocTemplate(pTemplate)
this为CDocManager
this->m_templateList.AddTail(pTemplate)
OnFileNew创建文档类对象,子框架对象,子窗口,创建视图窗口,创建视图窗口,文档对象和视图对象关联
MFC绘图编程
基础
Windows下绘图,需要绘图设备
WIN32 绘图设备句柄HDC
MFC 类对象 CDC 必须和设备句柄绑定
CDC类绘图设备类
封装了各种绘图相关函数,m_hDC, m_hAttribDC
子类
CPaintDC 类,封装了在WM_PAINT消息中绘图的绘图设备
CClientDC类,封装了在客户区绘图的绘图设备
CPaintDC使用
使用CPaintDC dc(this)
this==pView
Attach(::BeginPaint(pView->m_hWnd,&m_ps)
内部this为&dc, BeginPaint返回绘图句柄
this->m_hDC=hDC 将BeginPaint获取的绘图句柄保存到dc对象的成员m_hDC中
SetAttriDC(m_hDC)
m_hAttribDC=m_hDC、、dc对象的另一个成员变量也保存了绘图句柄
dc.Rectangle(100,100,300,300)
::Rectangle(m_hDC,100xxx)
CPaintDC的析构函数中会调用::EndPaint
CClientDC使用
CClientDC dc(this) 在this的客户区画图
窗口大小改变后就不见了
CGdiObject类 绘图对象类
封装了各种绘图对象的相关操作,以及一个非常重要的成员变量m_hObject
相关类
CPen画笔
CClientDC dc(this)
CPen pen(PS_SOLID),2,RGB(255,255,255)
CPen构造
内部this pen对象
Attach(::CreatePen(nPenStyle.nWidth,crColor))
m_hObject=hObject将CreatePen获取的画笔句柄保存到m_hObject中
CPenb* oldPen=dc.SelectObject(&pen)
dc.Rectangel(100,100,200,200)
dc.SelectObject(oldPen)
CBrush画刷
ClientDC dc(this)
CBrush brush(0,245,4)
CBrush*oldBrush=dc.SelectObject(&brush)
dc.Rectangle(100,100,300,300)
dc.SelectObject(oldBrush)
brush.DeleteObject()
CFont字体
CFont font
font.CreatePointFont(30,"黑体")
CBitmap位图
添加位图资源(右键资源添加)
新建一个和当前DC相匹配的内存DC
CClientDC dc(this)
CDC memCD
memDC.CreateCompatibaleDC(&dc)
拿到dc的句柄和memDC进行绑定
将位图的数据送给内存DC
CBitmap bmp
bmp.LoadBitmap(IDB_BITMAP1)
CBitmap*oldbmp=memDC.SelectObject(&bmp)
成像
dc.BitBlt(100,100,48,48,&memDC,0,0,SRCCOPY)
将位图数据要回来
dc.SelectObject(oldbmp)
销毁位图
bmp.DeleteObject()
销毁内存DC
memDC.DeleteDC()
MFC序列化机制
目的保存文件,减少文件读写操作次数
相关类
CFile 文件操作类,封装硬盘文件读写操作
Open
file.Open("./data.txt",CFile::modeCreate|CFile::modeReadWrite)
Write.Read
Close
SeekAt SeekToBegin
CArchive归档类,完成内存数据读写操作
序列化使用
创建打开文件CFile::Open
定义归档类对象CArchieve ar; 维护缓冲区
CArchive ar(&file, CArchive::store,4096)
数据序列化 ar<<数据
把数据插入ar中
string 类型前面会放字符长度的一个字节
关闭ar.Close
关闭文件file.Close
反序列化加载
ar>>变量
CFile file; file.Open("we.txt",CFile::modeRead)
CArchive ar(&file,CArchieve::load,4096)
long age; ar>>age;
ar.Close()
file.Close()
读取第一个数据的时候就把缓冲区读满了
序列化基本类型
以二进制流形式读写硬盘文件
效率高
先写到内存缓存区,然后一次性写入硬盘
写满了缓冲区,就先把缓冲区写入硬盘,然后重置后接着写
过程解析
CArchive
Mode{ store存储,load=1 bNoFlushOnDelete=2,bNoByteSwap=4}
bool m_nMode访问方式
int m_nBufSize buff的大小
CFile* m_pFile操作的文件对象
BYTE* m_lpBufCur当前指向
BYTE* m_lpBufMax终止指向
BYTE* m_lpBufStart开始指向
CArchive(&file,CArchive::store.4096)
this->m_nMode=0_
m_pFile=file
m_nBufSize=4096
m_lpBufStart=new BYTE[m_nBufSize]
m_lpBufMax=m_lpBufStart+4096
m_lpBufCur=(IsLoading())?m_lpBufMax: m_lpBufStart
CArchive::operator<<(age)
if(m_lpBufCur+sizeof(LONG)>m_lpBufMax
Flush()
*m_lpBufCUr=age
m_lpBufCur+=sizeof(LONG)
将age保存到指针指向的当前位置,并将指针后移相应字节数
CArchive::operator<<(score)
if(m_lpBufCur+sizeof(float)>m_lpBufMax
Flush()
*m_lpBufCUr=score
m_lpBufCur+=sizeof(float)
将score保存到指针指向的当前位置,并将指针后移相应字节数
CArchive::operator<<(name)
AfxWriteStringLength(ar,8)
ar<<(unsigned char)nLength
Write(name,8)
memcpy_s(m_lpBufCur,(size_t)(m_lpBufMax-m_lpBufCur),name,8(
m_lpBufCur+=8;
ar.Close()
Flush()
m_pFile->Write(m_lpBufStart,ULONG(m_lpBufCur-m_lpBufStart));
m_lpBufCur=m_lpBufStart重置当前指向
序列化类对象
序列化对象就是 把类的各个成员变量序列化
类支持序列化要求
派生自CObject
DECLARE_SERIAL(theClass)
_DECLARE_DYNCREATE(CMyDoc)
AFX_API friend CArchive& AFX_API operator>>(CArchive& ar, CMyDoc*&pOb)操作符重载
类外 IMPLEMENT_SERIAL(CMyDoc,CDocument,1)
动态创建机制的XXX
CArchive & AFX_API opearator>>(CArchive&ar, CMyDoc* &pOb){ pOb=(class_name*)ar.ReadObject(RUNTIIME_CLASS(CMyDoc)); return ar;}
必须重写虚函数Serialize(CArchive&ar)
if(ar.IsStoring())
arr<<m_age<<name;
序列化基本类型变量
else
arr>>m_age>>name
反序列化基本类型
实例
CFile file
file.Open("./data.txt". CFile::modeRead)
CArchive ar(&file,CArchive::load,4096)
CMyDoc *pData=null
ar>>pData
ar.Close()
file.Close()
执行流程
ar<<&data===operator<<(ar,const&data)
ar.WriteObject(data)
CRuntimeClass* pClassRef=&data->GetRuntimeClass()//获取类信息
WriteClass(pClassRef)将类的相关信息(类名,大小,类版本)存入ar缓存中
&data->Serialize(ar)
ar>>pdata===operator>>(ar,pdata)
pdata=ar.ReadObject(RUNTIME_CLASS(CMyDoc))
CRuntimeClass* pClassRef=ReadClass(pClassRef)从文件中读取类的相关信息(类名,大小,类版本)和RUNTIME_CLASS比较
如果相同创建对象,赋值后返回pOb=RUNTIME_CLASS(CMyDoc)->CreateObject()
pOb->Seralize(ar)//反序列化基本类型变量
return pOb
MFC对话框架构
Win32
HWND hDlg=CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_DIALOG1).hWnd,DlgProc);直接创建非模态对话框
销毁非模态对话框只能用DestroyWIndow
EndWindow只能隐藏非模态对话框,可销毁模态对话框
非模态假装是模态:把主窗口禁用
EnableWIndow(hWnd,FALSE)
在非模态对话框的关闭消息中EnableWindow(GetParent(HChid),TRUE)
MFC
全部为非模态对话框
间接创建
添加资源
查找资源FindResource
HRSRC hRs=FindResource(g_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),RT_DIALOG)
加载资源LoadResource
HGLOBAL hGl=LoadResource(g_hInstance,hRs)
锁定资源
LPCDLGTEMPLATE pTemplate=(LPCDLGTEMPLATE) LockResource(hGl)
创建非模态对话框
HWND hDlg=CreateDialogIndirect(g_hInstance,pTemplate,hWnd,DlgProc)
ShowWIndow(hDlg,SW_SHOW)
非模态创建
派生自CDialog
CWinApp
InitInstance
CMyDlg*pdlg=new CMyDlg;
pdlg->Create(IDD_DIALOG1)
m_pMainWnd=pdlg
pdlg->ShowWindow(SW_SHOW)
return TRUE
父类处理点击OK按钮的WM_COMMAND消息
CDialog::OnOK()只能将对话框隐藏
使用::DestroyWindow或者对应的成员函数
OnOK()
EndDialog(IDOK)
::EndDialog(m_hWnd,nResult)只能将非模态对话框隐藏
模式对话框(假的)
派生自CDialog
CWinApp
InitInstance
CMyDlg dlg;//没有使用new ,对象存在栈中,不是堆,生命周期很短,却能一直保存对话框
m_pMainWnd=pdlg
dlg.DoModal()
return FALSE
不再执行MFC中的Run函数
执行过程
WinMain入口函数
AfxWniMain
AfxGetAp()获取theApp
pApp->InitApplication
pThread(pApp)->InitInstance利用theApp
CMyDlg dlg;/
CDialog::(IDD)
m_lpszTemplateName=MAKEINTRESOURCE(IDD)将对话框资源ID保存到dlg的一个成员变量中
dlg.DoModal()
HRSRC hResource=::FindResource()
HGLOBAL hTemplate=LoadResource
LPCDLGTEMPLATE pTemplate=(LPCDLGTEMPLATE) LockResource(hGl)
HWND hWndParent=PreModal()获取父窗口的句柄
::EnableWindow(hWndParent,FALSE)设置父窗口不可用
CreateDlgIndirect
::CreateDialogIndirect以间接方式创建非模态对话框
RunModalLoop(...)
for(;;)就是自带消息循环,不再执行CWinApp的Run函数
for(;;)
while(没有消息的时候::Peekmesage)
OnIdle()空闲处理
do{ 消息循环的函数 if(!ContinueModal()) goto ExitModal; 如果::GetMessage()找到WM_QUIT 返回0 return ExitInstance }while(:)
ContinueModal()
m_nFlags(24)&0x0010(16)
ExitModal: return m_nModalResult
::EnableWindow(hWndParent,true)
DestroyWindow()
return m_nModalReuslt
OnOK()
EndDialog(IDOK) IDOK=1
EndModalLoop(1)
函数内部this为dlg
this->m_nModalResult=1
m_nFlag=8
::EndDialog(m_hWnd,nResult)只能将非模态对话框隐藏
初始化操作虚函数OnInitDialog
MFC控件的使用
对象和控件的绑定
控件和数据类对象绑定,对象和控件可以进行数据交换
重写父类成员函数DoDataExchange 在函数内部通过一系列DDX_XX函数,实现控件和数据类型的数据交互
如果需要数据交互,调用UpdateData函数
UpdateData(True)
控件向变量传递
一般放在前面
UpdateData(False)
变量向控件传递
一般放在后面一些
实例
void CMyDlg::DoDataExchange(CDataExchange*pDx){
DDX_Text(pDX,IDC_EDIT1,m_strEdit);
l类向导
如果和控件类对象绑定,对象就可以代表整个控件
重写父类成员虚函数DoDataExchange(CDataExchange*pDX)
DDX_Control(pDX,IDC_EDIT1,m_ctrlEdit)
控件对象即控件,无需UpdateData
控件消息的基本原理
控件消息
WM_COMMAND
LOWORD(wParam) 菜单项ID,控件ID
HIWORD(wParam)菜单项,控件通知码BN_CLICKED=0,CN_COMMAND=0,BN_DOUBLECLICKED=5
ON_COMMAND只能处理控件点击消息,其他的例如双击不行,通知码不一样
ON_BN_CLICKED
ON_BN_DOUBLECLICKED
控件Notify属性手动改成True
基本控件的使用
控件如何做数据交换,数据类型的绑定
控件和控件类对象的绑定
控件消息的处理
基本控件
下压按钮CButton 父类为CWnd
WM_COMMAND/BN_CLICKED
使用类向导做一些事情
编辑框CEdit
获取编辑框内容
char strEdit[256];
edit.GetWindowText(strEdit,256)
AfxMessageBox(strEdit)
设置编辑框内容
SetWindowText("456")
消息WM_COMMAND
文本改变:通知码EN_CHANGE
复选框按钮,带对勾,CheckBox
CButton类绑定
设置状态Set/GetCheck()
WM_COMMAND附带的消息码也是BN_CLICKED
设置PushLike属性True 就变成Button了
单选框按钮 Radio Button
CButton类绑定
CButton::Get/SetCheck
不出现在类向导里面把Group改成True就可以了
WM_COMMAND附带的通知码也是BN_CLICKED
分组框按钮 GroupBox
控件分组显示,提高界面友好型
IDC_STATIC先改掉才能绑定
静态文本框 Static Text
IDC_STATIC先改掉才能绑定
提高界面友好性
CStatic类绑定
SetWindowText()
静态图像框
IDC_STATIC先改掉才能绑定,随便换个名字即可
设置图标CStatic::SetIcon/SetBitmap
m_sp.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IBM_1)))
AfxGetInstanceHandle()可以获得当前程序的句柄 ,即WinMain的第一个参数
修改Type属性Bitmap/Icon
组合框Combobox
在拖拽进入Dialog的时候,滑动一下,框选出一个区域,方便下拉展开
简单式Type改成Simple
下拉式Dropdown 支持键盘编辑
下拉列表式Drop List不可修改项
CComboBox类,父类CWnd,封装了控件的各种操作
操作
CComboBox::AddString
CComboBox::DeleteString
获取选择项索引 CComboBox::GetCurSel
ResetContent清空
Sort属性 False不排序,按添加顺序来
设置当前选择项SetCurSel(10)
获取选择项文本GetLBText
设置选项附加数据SetItemData(index ,100)
获取选项附加数据GetItemData
DWORD nData=m_simple.GetItemData(m_simple.GetCurSel())
CString strData;
strData.Format("%d",nData)
AfxMessageBox(strData)
消息WM_COMMAND
选择项发生变化通知码CB_SELCHANGE
文本发生编辑变化CB_EDITCHANGE
列表框CListBox类
AddString
DeleteString
GetCurSel
获取选项文本内容GetItemText
滑块控件 CSliderCtrl
设置范围 SetRange
设置位置SetPos
获取位置GetPos
消息
位置改变WM_COMMAND
通知码NM_CUSTOMDRAW
进度条控件CProgressCtrh
滑块控件 CSliderCtrl
设置范围 SetRange
设置位置SetPos
获取位置GetPos
列表控件ListControl
CListCtrl类 父类CWnd
风格View属性
图标 LVS_ICON
windows文件管理器默认样式
小图标LVS_SMALLICON
列表LVS_LIST
报表LVS_REPORT
windows文件管理器详情样式
分列
修改风格ModifyStyle
设置图标风格:m_list.ModifyStyle(LVS_SMALLICON|LVS_LIST|LVS_REPORT, LVS_ICON) 第一个参数是要去掉的风格,第二个是要添加的风格
操作
添加选项CListCtrl::InsertItem(0,"目录",图)
删除选项DeleteItem/DeleteAllItem
添加列InsertColumn 报表样式使用
m_list.InsertColumn(0,"名称",LVCFMT_LEFT,150)
m_list.SetExtendedStyle(LVS_EX_GRIDLINES)设置网格线
设置列文本内容
CListCtrl::InsertItem(0,"目录",图像链表的节点序号)
m_list.SetItemText(0,1,"2021.5.1")设置第一行第二列显示的内容
设置图片
添加位图资源
添加图像列表列CImageList 链表
CImageList* pImageLst=new CImageList;
pImage->Create(IDB_BITMAP1,24,1,RGB(2525,255,255)
参数: 图片资源ID,每次裁切的宽度,图片资源不够增加多少个节点,屏蔽哪种颜色去底色)
m_list.SetIamgeList(pImageLst,LVSIL_NORMAL) 将图片链表应用在图标风格上
m_list.SetIamgeList(pImageLst,LVSIL_SMALL) 将图片链表应用在其他风格上
设置/获取附加数据 Set/GetItemData 把路径放进去
CString*filePath=new CString; *filePath=find.GetFilePath();
m_list.InsertItem(i,fileName,0);
m_list.SetItemData(i,(DWORD*)filePath)
函数指针传参,要保证指针所指向对象不被销毁,放在堆上
且函数内不能修改指针指向,只能修改指针所指内容
消息WM_COMMAND
双击通知码NM_DBLCLK
pNMItemActive->Item选中选项
文件搜索类对象
CFileFind类 封装了文件遍历的操作
CSring strPath=path
strPath+="/*.*"
CFileFind find;
BOOL goFind=find.FindFile(strPath)
while(goFind){ goFind=find.FindNextFile() CString fileName=find.GetFileName() CString filePath=find.GetFilePath() if(find.IsDirectory()&&!find.IsDots()){ Find(filePath);
CFileFind::FindFile开启查找,失败后返回FALSE,
CFileFind::FindNextFile找到当前文件,返回下一文件是否存在,找到的文件信息在find里面存着
获取文件信息
CFileFind::GetFileName
CFileFind::GetFIlePath;
GetXXX
find.Close
树控件TreecControl
CTreeCtrl 父类CWnd
属性
Has Button显示展开的按钮
Has Line有线
Lines At Root 根节点也显示展开按钮
操作
插入选项InsertItem
HTREEITEM nRoot=m_tree.InsertItem("编程语言",0,0,NULL)
m_tree.InsertItem("Java",0,0,nRoot)
删除DeleteItem、DeleteAllItem
获取选择项GetSelectedItem
m_tree.DeleteItem(m_tree.GetSelectedItem())
获取选项文本GetItemText
设置选项高度SetItemHeight
设置图像SetImageList
浮动主题