一 MFC的发展

VC 1.0->VC 5.0->VC 6.0->VC2008 SP1)->VS2010

二 MFC基础

1 MFC 微软基础类库

采用类的方式,将Win32 API等进行封装,形成的库.

2 MFC相关的头文件

afx.h   (application framework, X)

afxwin.h  (类似于windows.h)

afxext.h  (MFC扩展头文件)

...

三 MFC应用程序

MFC应用程序主要分为以下三类,对比通常的应用程序,变化的地方如下:

1 MFC的控制台程序

1.1 包含afx系列的头文件

1.2 CWinApp theApp - MFC的应用程序类,封装了应用程序的启动过程.

1.3 AfxWinInit MFC初始化函数,将应用程序的信息初始化.

2 MFC的动态库和静态库

2.1 静态库

2.1.1 增加了MFC的支持

2.2 动态库

动态库分类如下:

2.2.1 MFC规则DLL分为如下两类:

使用MFC静态库的规则DLL

使用MFC动态库的规则DLL

2.2.2 MFC扩展DLL

动态库与C++动态库的不同点如下:

1 增加了MFC相关的afx头文件

2 包含一个继承CWinApp类, 并且声明了该类的全局变量.

3 MFC应用程序

3.1 单文档视图应用程序

3.1.1 包含一个继承CWinApp类

3.1.2 CMainFrame类

3.1.3 CView的一个子类

3.1.4 CDocument的一个子类

3.2 多文档视图应用程序

3.2.1 包含一个继承CWinApp类

3.2.2 CMainFrame类

3.2.3 CView的一个子类

3.2.4 CDocument的一个子类

3.2.5 CChildFrame 子框架窗口

3.3 对话框应用程序

3.3.1 包含一个继承CWinApp类

3.3.2 对话框类

四 MFC中的类

在MSDN中搜索“Hierarchy chart”就可以看到整个MFC类继承图的关系

常用的类分类如下:

1 CObject类

MFC类的基础,大部分MFC类都是它的子类。

CObject封装了MFC的基础的机制,比如:

1.1 new和Delete

1.2 Assert

1.3 运行式信息

1.4 动态创建

1.5 序列化

2 应用程序框架类

封装了应用程序启动相关信息,以及MFC消息映射机制。

3 窗口支持类

封装了窗口操作的API,各种控件及窗口的框架.

4 绘图类

提供了绘图API的封装,以及相关的GDI设备封装.

5 MFC的集合类

提供了数组、链表、映射的数据结构的操作.

6 数据库支持类

ODBC支持类和DAO的支持类。DAO的类已作废.

7 同步类

临界区/事件/互斥/信号量的封装

8 Socket类

封装了socket的编程.

9 常用数据结构

CString CRect CPoint等.

五第一个MFC程序

不使用向导,自己创建一个MFC应用程序。

1.新建一个Win32 Application项目“WinMFC”

2.选择一个简单的Win32应用程序

3.修改环境为MFC应用程序的环境

3.1修改stdafx.h头文件,将#include <Windows.h> 改成#include <afxwin.h>

3.2删掉WinMFC.cpp文件中的WinMain()函数

3.3进入项目的属性设置

4.增加应用程序类CWinApp

4.1在WinMFC.cpp文件中编写继承自CWinApp类的类CMyApp类

4.2在CMyApp类中添加InitInstance函数

InitInstance函数是在程序启动过程中,会被调用,我们可以在这个函数中,创建窗口或者各种初始化操作.

4.3添加CMyApp的全局变量

//应用程序类

class CMyApp : public CWinApp

{

public:

virtual BOOL InitInstance( );

};

//定义CMyApp的全局变量

CMyApp theApp;

//初始化函数

BOOL CMyApp::InitInstance( )

{

AfxMessageBox("Hello App");

return TRUE;

}

这样,一个基本的MFC应用程序就创建好了。编译运行,会看到如下结果:

这个MFC是怎么执行起来的呢??先别急

程序可以启动了,下面开始创建窗口

1.在WinMFC.cpp文件中编写继承自CFrameWnd类的类CMyFrameWnd类

2.在App的InitInstance函数定义窗口对象

3.创建窗口(Create)并显示(ShowWindow)

4.将窗口设置成App的主窗口m_pMainWnd = pWnd;

5.在CMyFrameWnd中添加窗口处理函数WindowProc,在WindowProc中处理消息

WinMFC.cpp完整代码

// WinMFC.cpp : Defines the entry point for the application.

//

#include "stdafx.h"

//框架窗口类

class CMyFrameWnd : public CFrameWnd

{

public:

//窗口处理函数

virtual LRESULT WindowProc( UINT message,

WPARAM wParam, LPARAM lParam );

};

//窗口处理函数

LRESULT CMyFrameWnd::WindowProc( UINT message,

WPARAM wParam, LPARAM lParam )

{

switch( message )

{

case WM_CREATE:

AfxMessageBox( "WM_CREATE" );

break;

case WM_PAINT:

{

PAINTSTRUCT ps = { 0 };

HDC hDC = ::BeginPaint( m_hWnd,  &ps );

CHAR szText[] = "Hello world!";

TextOut( hDC, 100, 100,

szText, strlen( szText ) );

::EndPaint( m_hWnd, &ps );

}

break;

}

return CFrameWnd::WindowProc( message,

wParam, lParam );

}

//应用程序类

class CMyApp : public CWinApp

{

public:

virtual BOOL InitInstance( );

};

//定义CMyApp的全局变量

CMyApp theApp;

//初始化函数

BOOL CMyApp::InitInstance( )

{

//定义窗口对象

CMyFrameWnd * pWnd = new CMyFrameWnd();

//创建窗口

pWnd->Create( NULL, "MyApp" );

//显示窗口

pWnd->ShowWindow( SW_SHOW );

//设置主窗口

m_pMainWnd = pWnd;

return TRUE;

}

六 MFC应用程序的启动

MFC应用程序与Win32程序一样,都需要程序的入口函数.

1 CWinApp

应用程序类,封装了应用程序的相关信息,可以提供初始化 消息循环等处理.

CWinApp的构造函数中执行了什么:

1 将this指针保存到ThreadState中.this指针就是CMyApp对象----theApp

pThreadState->m_pCurrentWinThread = this

2 将this指针保存到ModuleState中

pModuleState->m_pCurrentWinApp = this

3 各种的成员变量的初始化

2 程序的入口函数

在CMyApp::InitInstance()函数中加一个断点,然后运行,程序在断点处停下来。

这时候打开“Call Stack”窗口,观察程序的调用过程。

PS:双击调用栈里面的函数,就会跳过去~~

根据跟踪调用过程,得到如下结论:

1 MFC也拥有WinMain函数,与Win32程序一致.

2 在WinMain函数中,调用了AfxWinMain函数.

AfxWinMain函数中执行了什么:

1 调用AfxWinInit初始化应用程序

2 调用CWinApp的InitApplication初始MFC内部数据

3 调用CWinThread的InitInstance函数做初始化操作

4 调用CWinThread的Run函数进行消息循环

5 调用AfxWinTerm函数做退出处理.

3 现在,再来总结一下程序的启动过程:

1 CWinApp在构造过程中, 将自己的this指针分别保存到全局变量中.

2 在AfxWinMain执行中,首先从全局变量中将保存CWinApp的地址获取到.

3 调用CWinApp的InitInstance函数,进行初始化.我们在InitInstance函数中,创建窗口等初始化操作.

4 调用Run函数,进行消息循环.

七窗口创建及窗口处理函数

1 窗口创建过程

1 窗口的参数初始化,包括窗口类,窗口风格,窗口处理函数等信息.

注意:将DefWindowProc注册成窗口处理函数.

2 设置 "创建HOOK" (钩子)

当窗口创建的时候,调用这个HOOK函数.

Wnd -> HOOK -> WndProc

3 创建窗口

CreateWindowEx

4 卸载 "创建HOOK"

将HOOK程序从当前程序中移除

2 HOOK(钩子)程序

上面说的"创建HOOK"到底做了什么:

1 使用AfxGetAfxWndProc函数获取了一个WNDPROC函数指针, 也就是AfxWndProc(AfxWndProcBase)函数地址.

2 将这个WNDPROC函数设置成当前窗口的处理函数

3 将窗口句柄和窗口类的指针保存到MFC的映射数据中(afxMapHWND函数)。这样就可以通过窗口句柄获取对应的窗口对象指针了。

总得来说,就是在窗口创建时,将AfxWndProc函数设置为当前窗口的窗口过程函数。

3 AfxWndProc(Base)窗口处理函数

AfxGetAfxWndProc函数到底做了什么:

1 根据窗口句柄获取了相对应的窗口的CWnd *类型的指针,从映射数据中根据窗口句柄查找CWnd *指针.(afxMapHWND函数)

2 调用AfxCallWndProc函数

3 在AfxCallWndProc函数中,调用CWnd的WindowProc函数

注意: 在MFC程序当中,所有窗口处理都是使用一个函数(AfxWndProc函数).

4 窗口的创建及处理过程

经过上面的分析,总结窗口的创建及处理过程如下:

1 将DefWindowProc函数注册成当前窗口的处理函数

2 设置钩子函数

3 创建窗口,并执行钩子函数

4 在钩子函数中将窗口类指针和窗口句柄的对应关系保存.

5 在钩子函数中将AfxWndProc(Base)函数设置当前窗口的窗口处理函数

6 在AfxWndProc(Base)收到窗口消息,从窗口对应关系中,查询相应的窗口类指针.

7 调用窗口类WindowProc函数处理消息

八消息映射

为了简化Win32的API编程中复杂的switch...case...,MFC重新封装了消息的传递方式。

下面,新建一个Win32应用程序,通过修改它实现MFC的消息映射,来观察一下。(PS:其实创建过程跟上面的过程差不多,多写几遍,写到吐为止)

1.修改stdafx.h头文件,将#include <Windows.h> 改成#include <afxwin.h>

2.

3.删掉MFCMsg.cpp文件中的WinMain()函数

4.

MFCMsg.cpp中定义CMsgFrame、CMsgApp和theApp

class CMsgFrame : public CFrameWnd

{

public:

virtual LRESULT WindowProc( UINT nMsg,

WPARAM wParam, LPARAM lParam);

};

LRESULT CMsgFrame::WindowProc( UINT nMsg,

WPARAM wParam, LPARAM lParam)

{

//以前这里就是很多switch来处理,现在没了

//被后面的BEGIN_MESSAGE_MAP()到END_MESSAGE_MAP中间的内容取代了

return CFrameWnd::WindowProc( nMsg,

wParam, lParam );

}

class CMsgApp : public CWinApp

{

public:

virtual BOOL InitInstance( );

};

CMsgApp theApp;

BOOL CMsgApp::InitInstance( )

{

CMsgFrame * pWnd = new CMsgFrame( );

pWnd->Create( NULL, "MsgApp" );

m_pMainWnd = pWnd;

m_pMainWnd->ShowWindow( SW_SHOW );

m_pMainWnd->UpdateWindow( );

return TRUE;

}

5.下面是跟前面不同的地方了。

在CMsgFrame中增加消息映射的宏

class CMsgFrame : public CFrameWnd

{

public:

virtual LRESULT WindowProc( UINT nMsg,

WPARAM wParam, LPARAM lParam);

public:

//消息映射宏定义

DECLARE_MESSAGE_MAP( )

};

//消息映射的宏实现

BEGIN_MESSAGE_MAP( CMsgFrame, CFrameWnd )

END_MESSAGE_MAP( )

6.增加一个OnPaint函数作为WM_PAINT消息的响应函数,并在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间添加消息映射

class CMsgFrame : public CFrameWnd

{

public:

virtual LRESULT WindowProc( UINT nMsg, WPARAM wParam, LPARAM lParam);

public:

//消息映射宏定义

DECLARE_MESSAGE_MAP( )

public:

//消息函数

afx_msg LRESULT OnPaint( WPARAM wParam,LPARAM lParam );

};

//消息映射的宏实现

BEGIN_MESSAGE_MAP( CMsgFrame, CFrameWnd )

//消息和消息处理函数的对应

ON_MESSAGE( WM_PAINT, OnPaint )

END_MESSAGE_MAP( )

LRESULT CMsgFrame::OnPaint( WPARAM wParam, LPARAM lParam )

{

PAINTSTRUCT ps = { 0 };

HDC hDC = ::BeginPaint( m_hWnd, &ps );

TextOut( hDC, 100, 100, "Msg", 3 );

::EndPaint( m_hWnd, &ps );

return 0;

}

此时的运行结果:

7.同理,添加一个WM_CREATE消息:

class CMsgFrame : public CFrameWnd

{

public:

virtual LRESULT WindowProc( UINT nMsg, WPARAM wParam, LPARAM lParam);

public:

//消息映射宏定义

DECLARE_MESSAGE_MAP( )

public:

//消息函数

afx_msg LRESULT OnPaint( WPARAM wParam, LPARAM lParam );

afx_msg LRESULT OnCreate( WPARAM wParam, LPARAM lParam );

};

//消息映射的宏实现

BEGIN_MESSAGE_MAP( CMsgFrame, CFrameWnd )

//消息和消息处理函数的对应

ON_MESSAGE( WM_PAINT, OnPaint )

ON_MESSAGE( WM_CREATE, OnCreate )

END_MESSAGE_MAP( )

LRESULT CMsgFrame::OnCreate( WPARAM wParam,

LPARAM lParam )

{

AfxMessageBox("OnCreate");

return 0;

}

LRESULT CMsgFrame::OnPaint( WPARAM wParam,

LPARAM lParam )

{

PAINTSTRUCT ps = { 0 };

HDC hDC = ::BeginPaint( m_hWnd, &ps );

TextOut( hDC, 100, 100, "Msg", 3 );

::EndPaint( m_hWnd, &ps );

return 0;

}

经过以上的分析,总结消息映射如下:

1 消息映射添加步骤

1 在FrameWnd添加消息宏定义

DECLARE_MESSAGE_MAP

2 添加消息宏实现

3 添加消息处理函数

4 添加消息和处理函数的对应

2 消息宏的实现

DECLARE_MESSAGE_MAP等到底是什么呢?将这些宏展开如下:

//消息映射宏DECLARE_MESSAGE_MAP展开

private:

static const AFX_MSGMAP_ENTRY _messageEntries[];

protected:

static AFX_DATA const AFX_MSGMAP messageMap;

static const AFX_MSGMAP* PASCAL _GetBaseMessageMap();

virtual const AFX_MSGMAP* GetMessageMap() const;

//BEGIN_MESSAGE_MAP( CMsgFrame, CFrameWnd )展开

const AFX_MSGMAP* PASCAL CMsgFrame::_GetBaseMessageMap()

{

return &CFrameWnd::messageMap;

}

const AFX_MSGMAP* CMsgFrame::GetMessageMap() const

{

return &CMsgFrame::messageMap;

}

AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMsgFrame::messageMap =

{

&CMsgFrame::_GetBaseMessageMap,

&CMsgFrame::_messageEntries[0]

};

AFX_COMDAT const AFX_MSGMAP_ENTRY CMsgFrame::_messageEntries[] =

{

//ON_MESSAGE( WM_PAINT, OnPaint )展开

{ WM_PAINT, 0, 0, 0, AfxSig_lwl,(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&OnPaint },

//END_MESSAGE_MAP()展开

{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }

};

先不要晕,将展开的代码多看几遍,分析一下就清楚了。

其中有些数据类型需要解释一下:

1 AFX_MSGMAP_ENTRY 是用于保存消息ID与对应函数指针,及相关的信息

struct AFX_MSGMAP_ENTRY{

UINT nMessage; //消息ID

UINT nCode;//通知代码

UINT nID; //控件的ID

UINT nLastID;//控件的ID范围的最后

UINT nSig;//操作类型或pfn函数类型

AFX_PMSG pfn;//消息处理函数的函数指针

};

2 AFX_MSGMAP 用于保存GetBaseMap的函数地址及AFX_MSGMAP_ENTRY数组的地址.

struct AFX_MSGMAP{

//函数指针

const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();

//AFX_MSGMAP_ENTRY类型指针

const AFX_MSGMAP_ENTRY* lpEntries;

};

下面对上面的宏代码做一些说明

1 _messageEntries[], 静态成员,类型为 AFX_MSGMAP_ENTRY。

保存CMsgFrame中消息ID和对应的消息处理函数的数组。

2 messageMap, 静态成员,类型为 AFX_MSGMAP。

保存了CMsgFrame中的_GetBaseMessageMap函数指针以及_messageEntries数组地址

3 _GetBaseMessageMap, 静态成员

获取父类的messageMap的地址

4 GetMessageMap,虚函数

获取自己的messageMap地址

下面通过“->”来捋一下几个成员直接的关系:

CMsgFrame::GetMessageMap -〉&messageMap{

&_messageEntries[0] -> {

ID<->Func,

ID<->Func,

....

}

_GetBaseMessageMap -> &parent::messageMap

{

&_messageEntries[0],

_GetBaseMessageMap->&parent::messageMap

}

}

3 消息映射过程

1 消息处理函数WindowProc收到消息后,调用OnWndMsg处理消息,OnWndMsg如果不处理消息,那么WindowProc将调用DefWindowProc默认处理消息并返回.

2 OnWndMsg处理消息

1 使用GetMessageMap函数获取该窗口类的messageMap变量的地址.

const AFX_MSGMAP* pMessageMap;

pMessageMap = GetMessageMap();

2 在messageMap中的lpEntries数组中,查找消息ID所对应的数组元素.

3 如果未找到,获取父类的messageMap指针,返回3.2.2,从父类的lpEntries数组继续查找.

4 如果找到,获取找到的数组元素的地址lpEntry,退出查找过程,执行下一步.

const AFX_MSGMAP_ENTRY* lpEntry = NULL;

for ( ;  pMessageMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)())

{

lpEntry = AfxFindMessageEntry(

pMessageMap->lpEntries,

message, 0, 0))

if( lpEntry != NULL )

{

goto LDispatch;

}

}

5 根据找到的lpEntry的nSig标识,调用lpEntry当中的pfn函数指针,处理消息.

LDispatch:

union MessageMapFunctions mmf;

mmf.pfn = lpEntry->pfn;

int nSig;

nSig = lpEntry->nSig;

switch (nSig)

{

case AfxSig_lwl:

lResult = (this->*mmf.pfn_lwl)(wParam, lParam);

break;

}

九MFC的消息分类

MFC的消息分类按照处理方式来分。主要分为4类:

1 窗口消息

例如WM_CREATE、WM_PAINT、鼠标、键盘等消息,这些消息的处理方式是直接调用消息处理函数.

这类消息使用的宏:

ON_MESSAGE(  )

ON_WM_XXXXX( ): ON_WM_CREATE()

消息处理时,采用上面的处理方式.

前面的WM_CREATE消息就不用写成ON_MESSAGE( WM_CREATE, OnCreate ),而直接写成ON_WM_CREATE即可。

函数的定义和声明也要相应地修改为:

afx_msg LRESULT OnCreate( WPARAM wParam, LPARAM lParam );

afx_msg int OnCreate();

LRESULT CMsgFrame::OnCreate( WPARAM wParam,

LPARAM lParam )

{

AfxMessageBox("OnCreate");

return 0;

}

int CMsgFrame::OnCreate()

{

AfxMessageBox("OnCreate");

return 0;

}

2 命令消息 WM_COMMAND

菜单、工具栏、按钮等点击时的命令. 消息首先发送到主窗口,由主窗口逐层向子窗口派发。

这类的消息使用的宏:

ON_COMMAND( )

ON_COMMAND_RANGE( )

消息处理时,在OnWndMsg中调用OnCommand处理函数进行消息处理.

3 通知消息 WM_NOTIFY

子窗口对父窗口的通知消息。

控件消息宏,例如: EDIT控件 ON_EN_CHANGE、ON_NOTIFY/ON_NOTIFY_RANGE消息处理时,在OnWndMsg中调用OnNotify(OnCommand)处理函数进行消息处理。

4 自注册消息

用户自注册消息的处理。

用户需调用RegisterWindowMessage函数注册消息,然后在消息映射中使用.

UINT RegisterWindowMessage(

LPCTSTR lpString //消息名字符串

);

返回注册成功的消息ID(0xC000-0xFFFF)

消息映射宏: ON_REGISTERED_MESSAGE

消息处理时, 与窗口消息处理类似,但是在查找消息处理函数和执行消息处理函数时不同.

自注册消息使用举例:

// RegisterMsg.cpp : Defines the entry point for the application.

//

#include "stdafx.h"

//注册消息ID

UINT g_nRegMsg = RegisterWindowMessage( "MYREGMSG" );

class CRegsiterFrame : public CFrameWnd

{

DECLARE_MESSAGE_MAP( )

public:

afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );

afx_msg void OnTest( );

//消息处理函数

afx_msg LRESULT OnRegMsg( WPARAM wParam,LPARAM lParam );

};

BEGIN_MESSAGE_MAP( CRegsiterFrame, CFrameWnd )

ON_WM_CREATE( )

ON_COMMAND( 1001, OnTest )

//消息宏映射

ON_REGISTERED_MESSAGE( g_nRegMsg, OnRegMsg )

END_MESSAGE_MAP( )

int CRegsiterFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )

{        //父类的OnCreate处理

/*if(!CFrameWnd::OnCreate( lpCreateStruct ) )

{

return 0;

}*/

//创建按钮

CreateWindow( "BUTTON", "Test",

WS_CHILD|WS_VISIBLE,

50, 50, 200, 30, m_hWnd, (HMENU)1001,

AfxGetApp()->m_hInstance, NULL );

return 1;

}

void CRegsiterFrame::OnTest( )

{        //发送消息

SendMessage( g_nRegMsg );

}

LRESULT CRegsiterFrame::OnRegMsg( WPARAM wParam,LPARAM lParam )

{

AfxMessageBox( "OnRegMsg" );

return 0;

}

class CRegisterApp : public CWinApp

{

public:

virtual BOOL InitInstance( );

};

CRegisterApp theApp;

BOOL CRegisterApp::InitInstance( )

{

CRegsiterFrame * pWnd = new CRegsiterFrame( );

pWnd->Create( NULL, "Register Msg" );

m_pMainWnd = pWnd;

m_pMainWnd->ShowWindow( SW_SHOW );

m_pMainWnd->UpdateWindow( );

return TRUE;

}

 

01:MFC应用程序编程的更多相关文章

  1. VS2010/MFC编程入门之四(MFC应用程序框架分析)

    VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html   上一讲鸡啄米讲的是VS2010应用 ...

  2. 《Windows编程循序渐进》——建立MFC应用程序

    如何建立MFC应用程序 打开VS2013:

  3. MFC应用程序框架(转)

    对于程序员来说,如果要提高编程效率,一个好用的,功能强大的并且可以得心应手使用的编程工具往往会给我们程序员带来莫大的方便.其实对于现在的编程工具来说,使用哪一种工具都不是问题的关键,重要的是你能够使用 ...

  4. MFC应用程序框架入门(转)

    1 MFC概述 顾名思意,MFC应用程序框架是以MFC作为框架基础的,以此程序框架模式搭建起来的应用程序在程序结构组织上是完全不同于以前的Win32 SDK编程方式的.自20世纪90年代初问世以来,M ...

  5. MFC下DLL编程(图解)

    DLL(Dynamic Link Library,动态链接库)是微软公司为Windows和OS/2操作系统设计一种供应用程序在运行时调用的共享函数库.DLL是应用程序的一种扩展,也是软件共享和重用的传 ...

  6. MFC下DLL编程(图解)

    MFC下DLL编程(图解) DLL(Dynamic Link Library,动态链接库)是微软公司为Windows和OS/2操作系统设计一种供应用程序在运行时调用的共享函数库.DLL是应用程序的一种 ...

  7. 基于MFC的socket编程

    网络编程 1.windows 套接字编程(开放的网络编程接口)添加头文件#include<windows.h> 2.套接字及其分类 socket分为两种:(1)数据报socket:无连接套 ...

  8. MFC控件编程进度条编写

    MFC控件编程进度条编写 一丶进度条编程需要用到的方法 进度条MFC已经帮我们封装好类了. 叫做 CProgressCtrl  进度条编程也很简单. 封装的方法也就那个那几个. GetPos()  获 ...

  9. MFC控件编程之复选框单选框分组框

    MFC控件编程之复选框单选框分组框 一丶分组框 分组框 英文叫做 GroubBox 添加了分组框主要就是分组.好看.不重点介绍 二丶单选框 英文: Raido Button 单选框需要注意的事项 1. ...

随机推荐

  1. mongodb lock 出毛病时解决方法

    错误信息: Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145 解决办法: sudo r ...

  2. 三种迭代Java ArrayList方法及比较

    闲来无事,研究一下Java Collection,首先是ArrayList. 通过三种方式遍历了长度为100000的ArrayList. import java.util.*; public clas ...

  3. 20135220谈愈敏Blog2_操作系统是如何工作的

    操作系统是如何工作的 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计 ...

  4. VS2013简单的单元测试

    安装过程本人在此就不做多余的说明,如果一个程序员连一个软件都无法安装那我也醉了,其次就是希望我们不要为了完成作业而去用VS,下面我具体说一下单元测试. 第一步,文件→新建一个项目,具体操作如下图 打开 ...

  5. 微信小程序input组件抖动及textarea组件光标错位解决方案

    问题一: 使用微信小程序input组件时,在移动端唤起focus或blur事件时,因光标占位导致内容出现叠影及抖动现象. 解决方案: 用<textarea>组件代替了<input/& ...

  6. PAT 1062 最简分数

    https://pintia.cn/problem-sets/994805260223102976/problems/994805268334886912 一个分数一般写成两个整数相除的形式:/,其中 ...

  7. nginx “403 Forbidden” 错误的原因及解决办法

    nginx 的 403 Forbidden errors 表示你在请求一个资源文件但是nginx不允许你查看. 403 Forbidden 只是一个HTTP状态码,像404,200一样不是技术上的错误 ...

  8. 使用 Sixel 图形格式在终端中显示缩略图

    不久前,我们讨论了 Fim,这是一个轻量级的命令行图像查看器应用程序,用于从命令行显示各种类型的图像,如 bmp.gif.jpeg 和 png 等.今天,我偶然发现了一个名为 lsix的类似工具.它类 ...

  9. BZOJ 4173: 数学

    4173: 数学 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 462  Solved: 227[Submit][Status][Discuss] D ...

  10. 【BZOJ2178】圆的面积并(辛普森积分)

    [BZOJ2178]圆的面积并(辛普森积分) 题面 BZOJ 权限题 题解 把\(f(x)\)设为\(x\)和所有圆交的线段的并的和. 然后直接上自适应辛普森积分. 我精度死活一个点过不去,不要在意我 ...