1.文本框,静态文本,按钮
2.获取文本框信息:
1.不绑定变量,直接用成员函数或者API
GetDlgItemText
::GetWindowText
2.绑定变量,使用UpdateData,给变量赋值
UpdateData(TRUE)-控件中的值赋给变量
UpdateData(FALSE)-变量的值赋给控件
3.UpdateData函数原理
UpdateData(TRUE)
->DoDataExchange
->DDX_Text
->::GetWindowTextLength
::GetWindowText
流程:
CMyApp::InitInstance()
->定义对话框对象,创建并显示
CMyDlg dlg;
INT_PTR nRet = dlg.DoModal();
DoModal中有消息循环
确定按钮中:UpdateData
CDialogEx::OnOK();(消息循环退出,DoModal函数返回)
判断返回值为IDOK时再创建另一个对话框
画圆Ellipse
画直线MoveToLineTo
画矩形Rectangle
使用DC绘图
CPaintDC只能用在OnPaint
::BeginPaint
::EndPaint
CClientDC用在非OnPaint函数中
::GetDC()
::ReleaseDC()
双缓冲:所有的图形先画在内存DC中
然后画完之后,再一并拷贝到屏幕DC
创建兼容dc:CreateCompatibleDC
兼容位图:CreateCompatibleBitmap
流程:1.鼠标响应
按下,弹起,鼠标移动
2.完成响应函数
按下:记录按下标记
记录按下坐标
弹起:重置按下标记
记录弹起标记
移动:。。。
3.完成绘制
OnPaint中实现绘制
4.扩充功能
实现定制:样式,属性。。。
遍历窗口的程序
1. C++封装一个遍历窗口的类
成员:List或者vector存储窗口信息
函数:获取所有窗口信息
::EnumWindows(EnumWindowsProc,
(LPARAM)this);
2.对话框程序
用控件ListCtrl存储窗口信息
为控件ListCtrl绑定一个变量m_WCtrl
(方便操作控件)变量类型:CListCtrl
CListCtrl::InsertColumn插入列
CListCtrl::InsertItem插入行第0列
CListCtrl::SetItemText设置指定行指定列
3.设置定时器:
1.使用消息 WM_TIMER 处理定时器事件
对话框中添加消息响应函数OnTimer
设置定时器:::SetTimer(窗口句柄,ID,时间,NULL);
卸载定时器:::KillTimer(窗口句柄,ID);
2.使用回调函数处理定时器事件
定义回调函数:
VOID CALLBACK TimerProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime
){}
通过SetTimer设置:
::SetTimer(窗口句柄,ID,时间,函数);
成员函数:SetTimer(ID,时间,函数);
4.对话类中处理消息,需要重写虚函数
WindowProc
番外篇.处理消息队列中的消息之前
想做些操作
对话框中需要重写虚函数
PreTranslateMessage
mfc 常用技巧
ListCtrl控件:
m_MyListCtrl1 . InsertColumn( 0 ,L "路径" , LVCFMT_LEFT , 200);
m_MyListCtrl1 .InsertColumn ( 1, L "PID", LVCFMT_LEFT, 100 );
m_MyListCtrl1 .InsertColumn ( 2, L "镜像大小" , LVCFMT_LEFT ,100 );
m_MyListCtrl1 .InsertColumn ( 3, L "镜像大小" , LVCFMT_LEFT ,100 );
2014.12.18~12.19-GDI编程
以下是指定了DC访问权限与未指定DC访问权限的两个例子:
//例子1
CRect rect;
GetClientRect (&rect );
CClientDC (this );
dc .MoveTo ( rect. left ,rect . top);
dc .LineTo ( rect. right ,rect . bottom);
dc .MoveTo ( rect. right ,rect . top);
dc .LineTo ( rect. left ,rect . bottom);
CClientDC dc( NULL );
dc .Ellipes ( 0, 0 ,100 , 100);
void CMFCApplication1Dlg:: OnPaint ()
{
CPaintDC objDC ( this);
CRect objRect ;
GetClientRect (objRect );
objDC .DrawText ( L"Hello MFC!" ,- 1, objRect ,DT_CENTER );
}
- 绘制图形1-绘制线条
//1.创建客户区DC对象
CClientDC dc(this);
//2.创建一个画笔对象
CPen objPen(0,0,RGB(0,0,0));
//3.将画笔对象加入到客户区DC对象中
CPen *pOldPen = dc.SelectObject(&objPen);
//将其选入设备表
//4.将DC对象移动到一个点,然后这个点画线
dc.MoveTo(120,120);
dc.LineTo(200,120);
//5.将原来的画笔对象选入到DC中
dc.SelectObject(pOldPen);
- 绘制矩形
dc.Rectangle(160,180,180,240);
- 绘制椭圆
dc.Ellipse(160,180,180,240);
使用鼠标绘图的逻辑是,当鼠标按下时记录原点,然后在鼠标移动时动态绘图举行,当鼠标
弹起后充值绘图状态
//
图片控件的编写:
1.派生按钮类:CButton CMyButton
1.派生按钮类:CButton CMyButton
2.在派生类处理消息
鼠标按下,鼠标弹起,鼠标移动
3. 按钮窗口的DC需要SelectObject(位图对象) ,在什么地方绘制图片(onPaint
2014.12.17.mfc的控件的使用
在共享dll中使用MFC
mfc中控件绑定变量
定时器自动更新窗口中的数据?
定时器:设置定时器: SetTimer
删除定时器 :KillTimer
1.c++ 封装一个遍历窗口的类
成员:List 或者 vector 存储窗口信息
函数: 获取所有窗口信息
2. 对话框程序
用控件ListCtrl存储窗口信息
为控件ListCtrl绑定一个变量m_WCtrl(方便操作控件)
变量类型:CListCtrl
CListCtr::InsertColumn 插入列
CListCtrl::InsertItem 插入行 第0列
CListCtrl::SetItemText 设置指定行指定列
3.设置定时器:
1.使用消息 WM_TIMER
对话框中添加消息响应函数OnTimer
设置定时器:SetTimer(ID,时间,NULL)
卸载定时器:KillTimer(ID)
2.使用回调函数处理定时器事件
定义回调函数:VOID CALLBACK TimerProc(
HWND hwnd,UINT uMsg,
UINT_PTR idEvent, DWORD dwTime);
通过SetTimer设置
SetTimer(ID,时间,函数)
4.对话框中处理消息,需要重写虚函数 WindowProci
5.PreTranslateMessage 处理消息队列中的消息之前,想做些操作,对话框中需要重写虚函数PreTranslateMessage
mfc中控件绑定变量
- OnInitDialog函数中初始化控件信息
- 怎么添加控件变量
选中对应控件,点右键,添加变量,两种类别,Control 操作控件 value值
3. 怎么更新所有控件变量的值
UpdateData(TRUE);
4.怎么更新所有控件的值
UpdateData(FALSE);
1.文本框,静态文本,按钮
2.获取文本框信息,直接用成员函数或者API
1.GetDlgItemText ::GetWindowText
2.获取变量,使用UpdateData,给变量赋值
TRUE 控件中的值到变量
FALSE 变量 到控件中的值
3.UpdateData函数原理:
UpdateData(TRUE)
->DoDataExchange
->DDX_TEXT
->::GetWindowTextLength
::GetWindowText
流程:
CMyApp::InitInstance()
->定义对话框对象
CMyDlg dlg;
INT_PTR nRet = dlg.DoModal();
DoModal 函数里面有消息循环
确定按钮中:UpdateData
CDialogEx::OnOK();->让对话框退出(消息循退出,DoModal 返回 ,判断返回值为IDOK时再创建另一个对话框
- 对话框与选项卡介绍
选项卡是一个将程序功能有序划分的有力手段,从编程角度上来看,选项卡其实就是一个对话框的容器,每一页选项卡的本质
都是一个对话框。
CTabCtrl是MFC提供给我们的一个选项卡类,其重要作用就是对若干个对话框类进行有效管理,操作,以使得我们更加容易的控制
率属于选项卡类管理的各个对话框类上的控件行为。
- 对话框选与选项卡创建步骤:
- 创建若干个类型(Style)为子集(Child),边框(Border)为无(None)的对话框用于创建选项卡,并调整好资源ID名称。
- 为每个对话框添加派生与CDialog的类,并仔细为各个新建类取好名字
- 使用AppWizard创建一个派生自CTabCtrl的自定义类CMyTabCtrl,并在CMyTabCtrl的头文件包含各个对话框类的头文件,并声明
好各个对话框类的对象指针(别忘记初始化与销毁),然后使用AppWizard为我们的CMyTabCtrl类添加一个相应TCN_SELCHANGE
消息的消息处理函数(当用鼠标进行选项卡进行切换的时候,则会产生TCN_SELCHANGE通知消息)
我们可以再此消息处理函数中写下类似一下代码:
CRect rect;
GetClientRect(rect);
rect.DeflateRect(1,22,3,3);//收缩坐标
switch(this->GetCurSel())
//获取Tab的选择项
{
case 0 :
m_pobjTabA->ShowWindow(SW_SHOW);//<-show
m_pobjTabA->MoveWindow(rect);
m_pobjTabB->ShowWindow(SW_HIDE);
break;
case 1 :
m_pobjTabA->ShowWindow(SW_HIDE);//<-show
m_pobjTabB->ShowWindow(SW_SHOW);
m_pobjTabB->MoveWindow(rect);
break;
Invalidate();//将窗口置为无效状态,从而引发重绘
- 在主窗口添加TabControl控件,并设好资源ID
- 包含自定义CMyTabCtrl类的头文件
- 为此空间添加一个CMyTabCtrl类的对象
- 在主窗口的OnInitDialog()的函数中添加一下类似代码
//为Tab添加两个选项卡
m_objTab.InsertItem(0,L"TabA");
m_objTab.InsertItem(1,L"TabB");
//分别创建用于填充Tab的对话框
m_objTab.m_pobjTabA = new CTabA();
m_objTab.m_pobjTabA->Create(DLG_TAB_A,&m_objTab);
m_objTab.m_pobjTabB = new CTabb();
m_objTab.m_pobjTabB->Create(DLG_TAB_B,&m_objTab);
//默认显示第一个选项卡
CRect rect;
m_objTab.GetClientRect(rect);
rect.
InflateRect(-1,-22,-3,-3);
m_objTab.m_pobjTabA->MoveWindow(rect);
m_objTab.m_pobjTabB->ShowWindow(SW_SHOW);
创建类的时候的ID是否已经包含
显示窗口的时候 为什么隐藏其他窗口
GetClientRect
多参数列表
2014.12.16
c++ 三大特性 :封装性, 继承性 ,多态性。
c++ 模板 : 模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数。
c++ 模板 : 模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数。
函数重载构成的条件:1.函数的参数类型 2.函数参数的个数
using std::endl; endl是函数。
推荐的书:深入解析 MFC,深入浅出MFC 候俊杰,visual c++ 深入详解,mfc-windows 程序设计-Jeff Prosise
Mircrosoft Foundation Classes 中的各种类结合起来构成了一个应用程序框架,他的目的就是让程序员在此基础上来建立Window下的应用程序,相对于SDK更为简单方便。
一段mfc源码:
MFC的核心就是基于CWinApp类的应用程序对象
但由于c++ 标准在1998年形成。
CObject 是MFC的根类
ExitInstance 退出时释放
以下mfc 是一段最简单的代码:
#include<afxwin.h>
#include<afxwin.h>
//CWinApp theApp;//只保留本行代码会有什么效果
class MyApp:public CWinApp
{
BOOL InitInstance()
//初始化程序实例
{
CFrameWnd *Frame = new CFrameWnd();//创建窗口框架
m_pMainWnd = Frame;
//保存窗口框架
Frame->Create(NULL,L"最简单的窗口");
//创建窗口
Frame->ShowWindow(SW_SHOW);
//显示窗口
return true;
}
};
MyApp theApp;
//建立应用程序
//下面是有消息的mfc简单的程序
class CMyApp:public CWinApp
{
public:virtual BOOL InitInstance();
};
class CMainWindows:pubic CFrameWnd
{
public:
CMainWindows(){Create(NULL,L"My First MFC APP");
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP();
};
BEGIN_MESSAGE_MAP(CMainWindows,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWindows;
m_pMainWnd->ShowWIndow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
void CMainWindows::OnPaint()
{
CPaintDC objDC(this);
CRect objRect;
GetClientRect(objRect);
objDC.DrawText(L"Hello MFC!",-1,objRect,DT_CENTER);
}
CMyApp g_objApp;
MFC 抽象出众多类的共同特性,设计一些基类作为实现其他类的基础。
最重要的类是CObject和CCmdTarget
CObject是MFC的根类,绝大多数MFC类是其派生的,包括CCmdTarget
CObject实现了一些重要的特性,包括动态类信息,动态创建,对象序列化,对程序调试的支持,等等,所有从CObject派生的类具备或者可以具备CObject所拥有的特性。
CCmdTarget通过封装一些属性和方法,提供了消息处理的架构,在MFC中,任何可以处理消息的类是从CCmdTarget派生。
MFC实现了对应用程序概念的封装,把类,类的继承,类的多态,类的关系和相互作用等封装起来,这样封装的结果对程序员来说,是一套开发模板(或者说模式),针对不同的
应用和目的,程序员采用不同的模板。
例如SDI应用程序模板,MDI应用程序模板。这些模板都采用了以文档/视图为中心的思想,每一个模板都包含一组特定的类。
使用向导建立一个多文档视图的工程,会创建6个类
生成的类 对应的基类
CAboutDlg CDialogEx
CChildFrame CMDIChildWnd
CMainFrame CMDIFrameWnd
CMFCSDIApp CWinApp
CMFCSDIDoc CDocument
CMFCSDIView CView
并非所有MFC提供的函数都是类成员函数,MFC以全局函数形式提供了自己各类的API函数,这些函数通常以Afx开头,以下是一些常用的函数
AfxAbout 无条件的终止-应用程序
AfxBeginThread 创建新的线程并开始执行它
AfxEndThread 终止当前执行的线程
AfxMessageBox 显示Windows消息框
AfxGetApp 返回应用程序对象指针
AfxGetAppName 返回应用程序名称
AfxGetMainWnd 返回指向应用程序主窗口的指针
AfxGetInstanceHandle 返回标识当前应用程序实例的句柄
一段mfc源码:
const AFX_MSGMAP*PASCAL theClass::GetThisMessageMap()
{
static const AFX_MSGMAP_ENTRY_messageEntries[] = {
{"消息类型",0,0,0,AfxSig_vv,函数指针},
{0, 0,0,0,,AfxSig_end,(AFX_PMSG)0}};
static const AFX_MSGMAP messageMap = {
&TheBaseClass::GetThisMessageMap,&_messageEntries[0]};
return &messageMap;
}
MFC的核心就是基于CWinApp类的应用程序对象
CWinApp::InitStance是一个虚函数,它的作用是让我们重定义后,提供一个初始化
自身的机会。
我们在重定义的InitStance中将CWinApp::m_pMainWnd指向一个我们继承自
CFrameWnd的主窗口类,在这个窗口类中我们调用了CFrameWnd::Create创建了
一个框架窗口对象,然后再向我们自己的主窗口类中做了一系列的消息处理操作。
除InitInstance以外,CWinApp还有很多可以重定义的成员函数,他们中比较有用
的是用于在应用程序空闲时执行任务的OnIdle函数,可以用于自定义消息循环的
Run函数,以及可以用于消息处理的PreTranslateMessage函数。
在CMyApp类的cpp文件中,定义全局对象:
CMyApp g_objApp;
在CMyApp类的头文件中,外部申明全局独享:
extern CMyApp g_objApp;
修改CMyApp类中的构造函数为public权限
sdk最重要的。
控制台程序 不等于 dos程序
windows dos
多任务 ? 单任务
虚拟内存 物理内存
具有特权级别 无特权级别
这些特性 并非windows 创造,而是80x86架构 提供的特性
UNREFERNCED_PARAMETER();
windows下共有以下3种消息类型 :
1 标准windows消息
2.外界输入事件消息
3.程序之间发送的消息
消息队列 非线程安全的。?
#define WM_MY_MESSAGE (WM_USER+100) 0~0X7FF 这个区间
消息是跨进称
_______________________________________________________________
essiential 看到了204页
非模态对话框
HWND hWnd = CreateDialog(hInstance,LPTSTR(IDD_DIALOG),0,(DLGPROC)WndProc);
ShowWindow(hWnd,nCmdShow);
Msg msg;
while(GetMessage(&msg,NULL,NULL,NULL))
{
if(msg.message == WM_KEYDOWN)
{
SendMessage(hWnd,WM_KEYDOWN,msg.wParam,msg.lParam);
}
else
{
if(!IsDialogMessage(hWnd,&msg)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
卷:逻辑驱动器
拷贝构造函数
——————————————————————————————————————————————————————————————————————————————
createfile 新建或打开一个文件 并获取其文件句柄 没有把数据进内存
不单指文件。
进程 还有线程:
进程是操作系统结构的基础,是一个正在执行的程序;计算机中、
B
创建进程 就是创建了内核对象 就是一个大结构体,不负责进程运不运行起来。
bool CreateChildProcess(LPWSTR lpPath,BOOL bWait)
{
STARTUPINFO si = {0}; //新进程窗口的特性
PROCESS_INFORMATION pi = {0}; //新进程信息结构体
si.cb = sizeof(si);
//1.创建子进程,并判断是否成功
if(!CreateProcess(lpPath,NULL,NULL,NULL,FALSE,0,NULL,NLL,&si,&pi))
return false;
//2.是否需要等待进程执行结束
if(bWait)
WaitForSingleObject(pi.hProcess,INFINITE);
//3.关闭进程句柄和线程句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}
一个线程就是操作系统的一个内核对象 进程只针对 3环而言
整个操作系统内核就是一个大进程(理解)
进程 只不过是在逻辑上对一组线程及其相关的的资源的封装。
线程是进程 中某个单一的顺序的控制流,也被称为轻量进程
我们创建线程时额需要指定一个线程函数。
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
return 0;
}
//指定程序入口函数MyFun();
#pragma comment(linker,"/entry:\"MyFun\"")
——————————————————————————————————————————————————————————————————————————————————————————
DLL 是一个包含可由多个程序同时使用的代码和数据的库,函数的导出 资源
根据操作系统语言版本自动选择
BOOL APIENTRY DllMain(HMODULE hModule,//模块句柄
DWORD ul_reason_for_call,//调用原因
LPVOID lpReserved) //保留
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: //进程附加(只调用一次)
case DLL_THREAD_ATTACH: //线程附加
case DLL_THREAD_DETACH: //线程分离
case DLL_PROCESS_DETACH: //进程分离(只调用一次)
break;
}
return true;
}
DLL 文件有两种导出方式:
A:声明导出
extern "C" _declspec(dllexport) void 函数声明
B:定义一个def文件
LIBRARY dll名
EXPORTS
1.建立一个Win32的DLL工程
2.建立时别忘记勾选"导出符号"
3.保留需要导出的函数,删除无用的导出类
4.在导出宏前面加上extern "C" ,使其以C的方式导出
5.编译DLL
6建立一个EXE工程
7.将DLL生成目录下的xxx.lib与工程目录下的XXX.h 拷贝到 EXE工程目录中
8.将DLL生成目录下的xxx.DLL 拷贝到EXE生成目录中
9.在exe工程中包含拷贝过来的头文件和静态库(.lib)
10.在exe工程中调用导出函数,编译运行之
[注1:“生成目录”指的是工程目录下的Debug或Release目录
注2:“工程目录"指的是工程下存放源文件的目录
#pragma comment(lib,"xxx.lib")
DLL加载
动态加载:
typedef int(*PFUN)(void);
int _tmain(int argc,_TCHAR *argv[])
{
HMODULE hDll = LoadLibrary(L"FirstDll.dll");
PFUN funTest = (PFUN)GetProcAddress(hDll,"fnFirstDLL");
funTest();
return 0;
}
静态加载:
静态链接库与 动态链接库相对应 但是静态链接库不能使用动态加载的方式
静态链接库最终会与调用程序融为一体,而不像动态链接库一样有一个单独的DLL文件
静态链接库的函数只需要声明,不需要使用_declspec(dllexport)导出符号,否则会导致连接报错
使用静态链接库时需要使用一下代码将静态库包含到指定工程
#pragma comment(lib,"xxx.lib")
遍历窗口的两种方法