1.MSG
typedef struct tagMSG{
HWND hwnd; //表示消息所属窗口
UINT message; //指定消息的标志符
WPARAM wParam;
LPARAM lParam; //wParam、lParam指定消息的附加消息
DWORD time; //消息送到消息队列的时间
POINT pt; //鼠标的当前位置
}MSG;
2.消息队列
3.进对消息和不进对消息
不进对消息在系统调用窗口过程时直接发送给窗口。最终都由系统调用窗口过程函数对消息处理。
4.WinMain函数实际是由插入到可执行文件中的启动代码调用的。
5.WinMain函数
int WINAPI WinMain(
HINSTANCE hInstance; //程序当前运行的实例句柄(只有运行中的程序才有程序实例,才有实例句柄,一个程序可以运行多个实例)
HINSTANCE hPrevInstance; //当前实例的前一个实例句柄。在WIN32中已不起作用,为NULL)
LPSTR lpCmdLine; //传递给应用程序的命令行参数。
int nCmdShow; //指定窗口该如何显示
);
6.WINAPI其实就是_stdcall
7.窗口的创建:设计一个窗口类、注册窗口类、创建窗口、显示及更新窗口
8.窗口类
typedef struct _WNDCLASS{
UINT style; //指定窗口的样式
WNDPROC lpfnWndProc; //指向窗口过程函数的函数指针
int cbClsExtra; //类附加内存空间
int cbWndExtra;
HANDLE hInstance; //指定包含窗口过程的程序的实例句柄
HICON hIcon; //指定窗口类的图标句柄
HCURSOR hCursor; //指定窗口类的光标句柄
HBRUSH hbrBackground; //GetStockObject可以获取画刷、画笔、字体、调色板的句柄,它的返回值的类型为HGDIOBJ
LPCTSTR lpszMenuName; //一个以空终止的字符串,指定菜单资源的名字。
LPCTSTR lpszClassName; //一个以空终止的字符串,指定窗口类的名字。
}WNDCLASS;
回调函数实现的机制:
(1)定义一个回调函数。
(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者。
(3)当特定的事件或条件发生时,调用者使用函数指针调用回调函数对事件进行处理。
9._stdcall和_cdecl
10.LPCTSTR 实际就是 const char *指向字符常量的指针,MAKEINTRESOURCE宏把资源ID标志符转换为我们需要的LPCTSTR类型。
11.同一个ID可以标识多个不同的资源,ID是一个整数,在resource.h中被定义为一个宏。
12.ATOM RegisterClass(CONST WNDCLASS *lpWndClass)
13.创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //pointer to registered class name
LPCTSTR lpWindowName, //pointer to window name
DWORD dwStyle, //window style
int x, //horizontal position of window
int y, //vertical position of window
int nWidth, //window width
int nHeight, //window height
HWND hWndParent, //handle to parent or owner window
HMENU hMenu, //handle to menu or child-window identifier
HANDLE hInstance, //handle to application instance
LPVOID lpParam //pointer to window-creation data
);
14.#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | //产生一个层叠的窗口,有一个标题栏和一个边框
WS_CAPTION | //创建一个有标题栏的窗口
WS_SYSMENU | //创建一个在标题栏上带有系统菜单的窗口,和WS_CAPTION一起使用
WS_MINIMIZEBOX | //必须设定WS_SYSMENU
WS_MAXIMIZEBOX) //必须设定WS_SYSMENU
15.如果参数x被设为CW_USEDEFAULT,那么系统为窗口选择默认的左上角坐标而忽略y,nWidth也是如此。
16.hWndParent:子窗口必须具有WS_CHILD样式
17.lpParam作为WM_CREATE消息的附加参数lpParam传入的数据指针。在创建多文档界面的客户窗口时,lpParam必须指向CLIENTCREATESTRUCT结构体。
18.BOOL ShowWindow(HWND hwnd,int nCmdShow)
hwnd是CreateWindow返回的,nCmdShow:SW_HIDE,SW_SHOW,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_SHOWNORMAL
19.UpdateWindow(hwnd)发送WM_PAINT消息
20.BOOL GetMessage(
LPMSG lpMsg, //address of structure with message
HWND hWnd, //handle of window
UINT wMsgFilterMin, //first message
UINT wMsgFilterMax, //last message
);
hWnd设置为NULL,用于接收属于调用线程的所有窗口的消息。
后两者都设置为0,则接收所有消息。
21.GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT,返回零,出现错误返回-1。
22.TranslateMessage(&msg)用于将虚拟键消息转换为字符消息。敲击键盘时,系统会产生WM_KEYDOWN和WM_KEYUP消息,
这两个消息的附加参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息。它将这两个消息的组合转换为一条WM_CHAR消息
(该消息的附加参数wParam包含了字符的ASCII码。
23.DispatchMessage函数分派一个消息到窗口过程,由窗口过程函数处理消息。
实际上是将消息回传给操作系统,由系统调用窗口过程对消息进行处理。
24.windows应用程序的消息处理机制
25.从消息队列中获取消息还可以用PeekMessage函数。
BOOL PeekMessage(
LPMSG lpMsg,
HWND hwnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
wRemoveMsg指定消息获取的方式,有PM_NOREMOVE,PM_REMOVE.
26.发送消息可以使用SendMessage和PostMessage.前者将消息直接发送给窗口,
并调用窗口的窗口过程进行处理。处理完后才返回,它发送的消息为不进队消息。
27.PostMessage将消息放入创建窗口的线程的消息队列中立即返回。
PostThreadMessage用于向线程发送消息。
对于线程消息,MSG结构体中的hwnd成员为NULL。
28.窗口过程函数的形式:
LRESULT CALLBACK WindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
系统通过窗口过程函数的地址来调用窗口过程函数。
29.窗口大小发生变化时是否发生重绘,取决于WNDCLASS结构体中的style中是否设置了CS_HREDRAW和CS_VREDRAW.
30.系统为什么不直接保存窗口中的图形数据,而要由应用程序不断进行重绘?
(C++)
31.struct和class区别:
结构体是使用struct声明的类。在默认情况下,它的成员的公有的(public),而类的成员是私有的(private)。
32.如果一个类中没有定义构造函数,那么编译器只有在以下三种情况,才会提供默认的构造函数:
a.如果类中有虚拟成员函数或虚拟继承父类(即有虚拟基类)时;
b.如果类的基类有构造函数(可以使用户定义的构造函数或编译器提供的默认构造函数);
c.在类中的所有非静态的对象数据成员,他们所属的类中有构造函数(可以使用户定义的构造函数或编译器提供的默认构造函数);
32.析构函数不允许有返回值,不允许带参数,并且一个类中只能有一个析构函数。
当一个类的对象超出它的使用范围时,对象所在的内存空间被系统回收,或者在程序中用delete删除对象时,析构函数将自动调用。
33.在类中定义成员变量时,不能直接给成员变量赋初值。
34.多重继承
35.匈牙利表示法:变量命名约定,变量名以一个或多个小写字母开始,这些字母表示变量的数据类型。
一般有:a,b,by,c,cb,rgb,cx,cy,dw,fn,h,i,m_,n,np,p,l,lp,s,sz,tm,w,x,y
36.public、protected、private继承方式,基类的成员在派生类中的访问权限。基类中的private成员不能被派生类访问,所以private成员不能被派生类继承。
37.在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时会根据对象的实际类型来调用相应的函数,即对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
38.纯虚函数是被指明不具体实现的虚成员函数。纯虚函数也可以有函数体。它在派生类中具体定义。具有纯虚函数的类叫抽象类,它不能声明对象。
C++的多态性是由虚函数实现的,而不是纯虚函数。如果子类有对基类虚函数的覆盖定义,无论该覆盖定义前是否有virtual,都是虚函数。
39.构成函数覆盖的条件
a 基类函数必须是虚函数(使用virtual关键字进行声明)。
b 发生覆盖的两个函数要分别位于派生类和基类中。
c 函数名称与参数列表必须完全相同。
40.函数重载、覆盖、隐藏
41.两种函数隐藏的情况:
(1)派生类的函数与基类的函数完全相同(函数名和参数列表都相同),只是基类的函数没有使用virtual关键字。此时基类的函数将被隐藏,而不是覆盖。
(2)派生类的函数与基类的函数同名,但参数列表不同,在这种情况下,不管基类的函数声明是否有virtual关键字,基类的函数都将被隐藏。注意这种情况与函数重载的区别,重载发生在同一个类中。
42.引用必须在声明时进行初始化。