阅读笔记《孙鑫VC++深入详解》

《VC++深入详解》

       ——————2012/8

 

颜色对话框 CColorDialog

保存另存为对话框 CFileDialog  

字体对话框 CFontDialog    

 

1  (用API创建一个窗口)

 

2  C++类的基本知识)

 

3  MFC单文档执行流程)

 

4  (消息映射机制;

     MoveTo Lineto

     获取客户区DC,绘画CPen    CBrush

     使窗口无效 Invalidate();

  刷新视图时默认的调用过程:CDocument::UpdateAllViews()   ->   CView::OnUpdate()   ->   CWnd::Invalidate()   ->   OnPaint()   ->   OnDraw()

 

5  txt文本制作,插入符、路径程? 

     GetTextExtentGetTextMetrics区别

     卡拉OK字幕变色(DrawTextTextOut)

     定时器)

 

得到客户窗口矩形坐标 GetClientRect(&rect);

 

Class 6 .menu 

 若四个类(AppMainFrameDocView)都有一个菜单按钮的响应函数,那么响应优先级是前面列出的反序,且只有一个函数会响应。

  菜单命令的路由过程:首先MainFrame类接受到消息,它将把消息传递给view类,若view类无处理函数,则转交给doc类,若也无处理函数则交还  给view类,view类再交还给mainframe类处理,若MainFrame也没有处理函数,则交给app来处理了。

创建一个弹出式菜单CreatePopupMenu;  添加到菜单栏最后AppendMenu;  删除指定的菜单DeleteMenu;  插入到菜单栏指定位置InsertMenu

 

Class 7 .dialog

GetDlgItem (控件ID )获取该对话框指定ID的控件指针

GetWindowText     获取控件的文本

SetWindowText     设置控件的文本

 

GetDlgItemText  /  SetDlgItemText      atoi     itoa

GetDlgItemInt  /  SetDlgItemInt

GetDlgItem->SendMessage ( ,WM_GETTEXT / WM_SETTEXT , , )

SendDlgItemMessageEM_SETSEL  :   SetFoucs

 

Edit控件

在聊天的时候,除了要滚动到最后一行显示外,还要把光标定位到最后。

m_edit.SetFocus(); 

int   n   =   m_edit.GetWindowTextLength(); 

m_edit.SetSel(n,   n,   FALSE);

 

在编辑框中输入文本立即做出反映,可利用消息响应EN_CHANGE

 

对话框上创建一个控件按钮,风格一般是WS_VISIBLE | WS_CHILDE

 

Class 8.propertysheet & propertyPage

CPropertySheet sheet(_T("Simple PropertySheet"));

 

CStylePage pageStyle;

CColorPage pageColor;

CShapePage pageShape;

 

sheet.AddPage(&pageStyle);

sheet.AddPage(&pageColor);

sheet.AddPage(&pageShape);

 

sheet.SetWizardMode();//若在此处添加该函数则属性页变为属性向导

 

sheet.DoModal();

 

设置属性向导的上一页下一页和完成按钮:

CPropertyPage::OnSetActive函数中调用  CPropertySheet::SetWizardButtons 

CPropertyPage::OnWizardNext函数中处理点击下一步按钮时的消息。先刷新updatedata

 

Group Box  +  Radio Button 

(第一个Radio的属性要选中group,并为它定义一个int变量,当updatedata刷新后,变量的值即为以0为开始的该组Radio的索引)  OnWizardNext()

在组框中绘图:CRect  rect ;   GetDlgItem(组框ID)->GetWindowRect(&rect);  ScreenToClient(&rect) ;  

这样就可以利用该矩形的坐标绘图了。

List Box   

 在对话框即将显示之前调用虚函数OnInitDialog()为该控件添加显示内容:((CListBox*)GetDlgItem(ID_LISTBOX))->AddString()

为该控件定义一个CString变量,updatedata之后该变量值被用户选中的值刷新。

 

Grouo Box  +  check box

为每一个check关联一个bool变量。

 

Combo Box

Setcursel设置初始化edit默认的显示为索引为0string

列表会自动排序,在控件属性上去掉sort选项,那么就会和自己添加的顺序一样。

为该控件定义一个变量 int型的索引  和 string型均可以。

对用户的选择结果可以不用updatedata实现映射,用getcurselgetlbtext组合也可。

 

向导框结束后,用户点击完成,domodal返回WIZFINISH。向导页的关联变量定义为public方便完成后在view类中访问。CPropertySheet为局部变量,此时窗口销毁了,但是对象还在,依然可以访问其中的成员。 调用InValidate函数使窗口无效,然后在OnDraw函数中实现在窗口中输出。

 

 

Class 9 修改窗口外观

修改图标,标题栏在框架窗口中修改。  修改客户区背景在view类中修改。(因为view覆盖在MainFrame上面的)

函数CMainFrameCView::PreCreateWindow(CREATESTRUCT& cs)中修改窗口的外观(窗口创建前)

OnCreate函数末尾修改窗口外观(窗口创建后)

 

1. (修改光标,背景等)自定义并注册一个窗口类,注册并赋给cs.lpszClass

(修改标题栏,图标)直接修改cs的各成员变量。

因为:窗口的背景,消息处理函数,光标等是在定义窗口类时确定的,而窗口风格,最大最小化按钮,窗口大小是在注册窗口类之后创建窗口时设置的,所以可以通过cs直接改。

(创建后)调用全局函数SetWindowLong

 

2. (比上面的方法更方便)  cs.lpszClass = AfxRegisterWndClass  (创建前)

(常用)全局函数SetClassLong      (创建后(OnCreate函数)Cview中没有OnCreate函数,需自己添加WM_CREATEX的消息处理。

 

IsWindowVisible     ShowWindow( SW_SHOW / SW_HIDE )

ShowControlBar            SetCheck (复选标记,选上之后会在菜单栏前面加个勾)

 

设置状态栏创建进度栏。。。。。。。   

 

 

Class 10

CClientDC   dc(this);

画点:    dc.SetPoxel 

画线:    dc.MoveTo     LineTo

画矩形:  dc.Rectangle(CRect( ,))  

画椭圆:  dc.Ellipse

 

dc.SelectObject

画笔CPen

画刷CBrush[要使新画的图形不覆盖原来的线条,应该将画刷设置为透明的,CBrush *p = CBrush::FromHandle ((HBRUSH)GetStockObject(NULL_BRUSH))得到一个透明的画刷,选入dc即可]

 

颜色对话框,字体对话框

 

设置对话框背景色WM_CTLCOLOR 消息响应函数OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor),返回一个用于绘制的指定画刷句柄。        会多次调用,对话框创建时调用,然后子窗口控件绘画时也要调用,pDCpWnd均指向要绘制的控件,如果只绘制指定控件的颜色,可以在该函数中判断if(pWnd->GetDlgCtrID()==指定控件ID) { return 你要用的画刷}

SetWindowText设置文字的颜色   SetBkMode(TRANSPARENT)设置文字背景透明 

SetBkColor设置背景色

 

若要改变CButton的字体颜色和背景色需要 派生CButton类并重写DrawItem函数,然后把该派生类对象与对话框中的按钮控件相关联。且在按钮控件的属性中要选中OwnerDraw

 

GetClientRect

位图:BitBlt按位拷贝   StretchBlt压缩放大拷贝.GetBitmap获取位图的宽高。

使窗口无效,窗口重绘经过两步:1,擦除背景OnEraseBkgnd2,绘图OnDraw        

如果重绘时窗口闪动大,则把绘图的操作写到OnEraseBkgnd中会好一点,因为在这个函数中绘图则不调用基类的OnEraseBkgnd,即不擦除背景就直接绘制了。

 

 

Class 11 图形的绘制和保持

MFC 集合类 CPreArray

Win32相应WM_PAINT消息绘图时,获取DC只能使用BeginPaintEndPaint,且只能在painting消息中使用。它们封装在CPaintDc中。    而CClientDC封装了GetDCReleaseDC

 

CScrollView 带滚动条的窗口

视口与窗口,  页面坐标(逻辑)   设备坐标(物理)

虚函数OnInitialUpdate  窗口刚完全创建时第一个调用的函数,可用来完成一些完后创建窗口后的初始化工作。

OnPrepareDC调整例如带滚动条之类的窗口。(逻辑坐标到设备坐标的映射)

Class 12  文件读写

memset    memcpy    memmove

 

C文件操作:

FILE * pFile = fopen(filename, openmode);

fwrite 、 fread 、 fclose 、  fseek(移动文件指针到指定位置)、 ftell(从当前指针位置得到文件长度)    rewind(重新放置文件指针到开始处)

对文本的写入和读取应该保持一样,文本方式、二进制方式。因为文本方式的读写会做一些转换。如果以文本方式写二进制方式读则可能出现错误。

C++文件操作:

类: ofstream  ifstream  fstream

常用成员函数:write  read  close

Win32 API文件操作:

创建或打开(不仅文件)CreateFile ,关闭(CloseHandle) ,可设置共享,安全性,异步同步读写等等

写入:WrireFile         读取:ReadFile

MFC文件操作:

类:   CFile     (使用很方便)无缓冲

 

打开、保存对话框     CFileDialog

CFileDialog类中一个重要的结构类型:m_ofn

win.ini文件信息存储与删除

::WriteProfileString函数用于兼容16系统写win.ini文件(一般用在CApp类的InitInstance虚函数中对注册表操作函数(SetRegistryKey)之下。)

::GetProfileString     获取键相关的字符串

 

CWinApp也继承了这两个函数,但是有区别,win2000以上的系统是写在注册表之中。

32位系统中应该直接对注册表进行操作。

可查看注册表目录:HKEY_CURRENT_USER\Software\应用程序向导生成的本地应用程序

 

注册表操作

RegCreateKey(HEY_LOCAL_MACHINE,Software\\ www.sunxin.org\\admin,&hKey)

RegSetValue(hKey,NULL,REG_SZ,zhangsan,strlen(zhangsan)) //使用该函数只能设置REG_SZ类型的值    

若要设置其他值则应该用RegSetValueEx

RegCloseKey(hKey)

 

RegQueryValue(HKEY_LOCAL_MACHINE, Software\\ www.sunxin.org\\admin,pBuf,&value)

RegSetValueEx设置的其他类型值查询用 RegOpenKey  +  RegQueryValueEx

 

文档串行化

类:   CArchive   必须在创建之前先创建一个CFile对象与之关联,而且访问文件的模式要相同                         输入输出串行化,重载了  >>    <<

 

 

MFC文档类串行化

一个文档对象与一个文件关联,通过CArchive操作。        集合类CObArray

有关文件读写操作在CDoc::Serialise(CArchive &ar);函数中,点击窗口的打开和保存按钮触发函数的消息相应。由语句if(ar.IsStoring())判断是保存还是打开。

编写自己的可串行化的类时,要保存自己定义的这个类的对象要为该类定义自己的serialise函数,doc类的函数在执行保存打开时会自动调用你定义的serialise函数。支持串行化的mfc类都定义了serialise函数

 

CWinApp管理文档链表,而每个文档关联一个框架和视图类(一个文档可以和多个视类关联,一个视类只能和一个文档关联),文档负责保存和加载数据(serialize),视图负责显示数据(ondraw)

 

在文档类获取视图类的指针:

POSITION  pos = GetFirstViewPosition();

CGraghView  *pView = (CGrangh*)GetNextView(pos);

 

示图类获取文档类的指针:视图类自己定义了一个函数能获取文档类的指针。

 

关闭文档、onopendocument 和 onnewdocument 都会调用 deletecontents,特别是单文档分配了堆内存记得使用该函数释放。

 

Class14 网络编程

16位端口,1024及以下保留。

TCP/IP采用16位或32位整数高位先存。

 

TCP

服务器端:

1、 创建套接字(socket)。

2、 将套接字绑定到一个本地地址和端口上(bind)。

3、 将套接字设为监听模式,准备接受客户请求(listen)。

4、 等待客户请求到来:当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。

5、 用返回的套接字和客户端进行通信(send/recv)。

6、 返回,等待另一个客户请求。

7、 关闭套接字。(closesocket)

客户端:

1、 创建套接字(socket)。

2、 向服务器发出连接请求(connect)。

3、 和服务器端进行通信(send/recv)。

4、 关闭套接字

 

UDP

服务器(接收端):

1、 创建套接字(socket)。

2、 将套接字绑定到一个本地地址和端口上(bind)。

3、 等待接受数据(recvfrom)。

4、 关闭套接字。

客户端(发送端):

1、 创建套接字(socket)。

2、 向服务器发送数据(sendto)。

3、 关闭套接字。

 

开始时应该调用WSAStartup启动库,结束后调用WSACleanup

 

Class 1516 多线程、同步、聊天室

创建线程: CreateThread  //创建返回线程的句柄应立即用CloseHandle关闭。

线程函数形式DWORD WINAPI ThreadProc(LPVOID lpParameter)

互斥对象: HANDLE  hMutex= CreateMutex  //如果创建命名的对象先前已经存在,且调用GetLastError()返回ERROR_ALREADY_EXISTS,则返回之前创建的对象的句柄。(可用于一个程序只能有一个实例的实现。)  

WaitForSingleObject(hMutex,INFINITE)   (使用之前申请)无信号时等待  

ReleaseMutex(hMutex)        (不使用时释放)让互斥量有信号

互斥对象里有一个计数器和访问线程的ID。谁拥有互斥对象只能由谁释放(请求多少次就应该释放多少次)。     若请求得到之后,线程关闭,但未释放,则操作系统会自动释放。其他线程任然能申请到。

 

lesson 16事件对象(线程同步)

CreateEvent,  SetEvent,  ResetEvent    申请用WaitForSingleObject

注意:人工重置,有信号时,所有的等待线程都能运行,需要手动调用reset,但还是不能实现同步。所以最好使用自动重置,有信号时只能有一个线程变为可调度,同时os会设置该对象为非信号,不需手动调用reset

(可用于一个程序只能有一个实例的实现。)

 

lesson 16关键代码段(线程同步)

InitializeCriticalSection    EnterCriticalSection,  LeaveCriticalSection     DeleteCriticalSection

 

互斥对象、事件对象、关键代码段:

前两者属于内核对象,进行线程同步较慢,可以实现多个进程间的线程同步。关键代码段是工作在用户方式下,同步速度快,但是容易出现死锁,因为等在时无法设定超时值。 

 

 

聊天室

MFC中加载套接字可用AfxSocketInit1.1版本,结束时系统会自动调用WSACleanup

//Call this function in your CWinApp::InitInstance override to initialize Windows Sockets

使用这个函数应该在预编译头文件(stdafx)中加入afxsock.h,这样也不需要手动连接库文件。

 

线程函数可以定义为类静态函数。或全局函数。

 

CEdit控件中要支持换行,则属性中应该选择multiline,然后在CString中有\r\n则换行。

CIPAddressCtrl   IP控件类。

DWORD  dwIP;

((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);//获取控件中的ip地址(主机字节序)

 

消息传递:

#define   WM_   (WM_USER+1)

::PostMessage(hWnd,WM_,wParam,lParam)  

ON_MESSAGE(WM_ , proc)

 

非阻塞的套接字异步选择机制:

利用消息传递机制(性能更高)

WSAAsyncSelect设置抛出消息    WSAEnumProtocols     WSASocket (socket函数的扩展)   WSA的均为windows的扩展。

WSARecvFrom,  WSASendTo,    sunxi PPT中有详解

 

用主机名获得ip地址:gethostbyname   <->   gethostbyaddr

HOSTENT  * pHost;

pHost = gethostbyname(edit_name);

addrto.sin_addr.S_un.S_addr = *((DWORD*)pHost->h_addr_list[0]);

 

Class 17.进程间通信

剪贴板

OpenClipboard   EmptyClipboard   SetClipboardData

CloseClipboard      

匿名管道

 

 

命名管道

 

 

邮槽

 

 

Class 18. ActiveX

属性、事件、方法。

 

增加activex控件到工程会自动添加一个该控件的类。Project -> Add To Project ->Comgeonents and Contrls

 

Class 19.动态链接库

_declspec(dllexport) 导出函数需要在前面增加该语句。声明时应该使用_declspec(dllimport)该语句而不使用extern,这样效率更高。

GetForegroundWindow()获取当前用户窗口

extern  C采用c语言编译方式到处库函数。(而不采用c++名字改编),不能导出类的成员函数,只能导出全局函数  

模块定义文件。。。。。。。。。即使是_stdcall也不会采用c++的名字改编

 

动态加载一个动态链接库:LoadLibrary     GetProcAddress  只加载需要的函数,节省内存空间,提高性能   FreeLibrary

 

DllMain

 

原文地址:https://www.cnblogs.com/songcf/p/3042346.html