《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制
2012-08-20 19:02
176 查看
1.API和SDK
2.窗口:通过窗口句柄来标识。
3.句柄(HANDLE):各种资源的标识号。 窗口句柄(HWND) 图标句柄(HICON)光标句柄(HCURSOR) 画刷句柄(HBRUSH) 实例句柄(HINSTANCE)。
4.Windows程序设计,是事件驱动的,主要是基于消息的。
消息:MSG结构体
Typedef struct tagMSG{
HWND hwnd; //表示消息所属的窗口
UINT message; //消息的标识符,WM_XXX宏(eg:WM_CHAR)
WPARAM wParam;//消息的附加信息 (eg:WM_CHAR用户输入的具体字符)
LPARAM lParam;//附加信息 (WPARAM:unsigned int; LPARAM:long)
DWORD time; //消息投递时的时间
POINT pt; //鼠标的当前位置
}MSG;
消息队列:系统为应用程序创建一个消息队列,并将该程序的消息放入消息队列,应用程序通过一个消息循环依次从队列中取出消息并响应。这种消息机制,就是Windows程序的运行机制。(进队消息和不进队消息(直接发给应用程序))
窗口过程函数:(回调函数)处理消息
5.WinMain函数:Windows程序的入口点函数。
函数原型:int WINAPI WinMain(
HINSTANCE hInstance,//程序当前运行的实例句柄(标识实例)
HINSTANCE hprevInstance,//当前实例的前一实例的句柄(NULL)
LPSTR lpCmdLine,//命令行参数
int nCmdShow//指定程序的窗口如何显示
)//这四个参数都是系统调用WinMain函数时传递给应用程序的(实例句柄由操作系统分配)
6.窗口的创建
(1)设计一个窗口类
typedef struct _WNDCLASS{
UINT style; //窗口样式(eg:CS_HREDRAW 水平重绘)位标志标识符
WNDPROC lpfnWndProc;//函数指针,指向窗口过程函数(回调函数)
int cbClsExtra;//WNDCLASS类附加内存(0)
int cbWndExtra;//窗口附加内存(0)
HANDLE hInstance;//包含窗口过程的程序的实例句柄
HICON hIcon; //图标句柄(NULL为默认图标;LoadIcon()加载图标)
HCURSOR hCursor;//光标句柄(LoadCursor()加载光标)
HBRUSH hbrBackground; //背景画刷句柄(GetStockObject()得到画刷)
LPCTSTR lpszMenuName; //指定菜单资源的名字(NULL,没有默认菜单)
LPCTSTR lpszClassName;//指定该窗口类的名字
} WNDCLASS;
HICON LoadIcon(HINSTANCE hInstance;LPCTSTR lpIconName);//加载图标资源
HCURSOR LoadCursor (HINSTANCE hInstance;LPCTSTR lpIconName);//加载光标
HGDIOBJ GetStockObject(int fnObject);//得到系统的标准画刷
(2)注册窗口
ATOM RegisterClass(CONST WNDCLASS *lpWndClass);// lpWndClass:窗口类对象的指针.(注册成功后才可以创建该类型的窗口)
(3)创建窗口
HWND CreatWindow(
LPCTSTR lpClassName,//指定窗口类的名称即WNDCLASS. lpszClassName
LPCTSTR lpWindowName,//指定窗口的名称(显示在标题栏)
DWORD dwStyle,//指定创建的窗口的样式(eg:WS_OVERLAPPEDWINDOW位标志标识符)Todo: WNDCLASS的style是指定窗口类的样式,所有基于该窗口类创建的窗口都具有这些样式,而dwStyle是指定具体某个具体窗口的样式。
int x,//窗口左上角x坐标(CW_USEDEFAULT 默认位置,y被忽略)
int y,//窗口左上角y坐标
int nWidth,//窗口宽度(CW_USEDEFAULT 默认大小,nHeight忽略)
int nHeight,//窗口的高度
HWND hWndParent,//指定该窗口的父窗口的句柄
HMENU hMenu,//指定窗口菜单的句柄
HANDLE hInstance,//指定窗口所属的应用程序实例的句柄
LPVOID lpParam//WM_CREATE附加参数lParam传入的数据指针(NULL)
);
(4)显示窗口
BOOL ShowWindow(
HWND hWnd, //窗口句柄
Int nCmdShow //指定窗口显示的状态
);
(5)更新窗口
BOOL UpdateWindow(HWND hWnd); //发送一个WM_PAINT消息来刷新窗口(直接发给窗口过程函数处理,不进入消息队列!)
7.消息循环
(1)取出消息
BOOL GetMessage(
LPMSG lpMsg,//指向一个消息结构体(保存从消息队列中得到的消息)
HWND hWnd,//指定接受哪一个窗口的消息(NULL,所有窗口)
UINT wMsgFilterMin;//指定要获取的消息的最小值(0)
UINT wMsgFilterMax//指定要获取的消息的最大值(0,所有消息)
);//接收到WM_QUIT消息时返回0值,其余非零,错误返回-1
(2)转换消息
TranslateMessage(LPMSG lpMsg);//将虚拟键消息转换为字符消息。
(3)传递消息
DispatchMessage(LPMSG lpMsg);//分派一个消息到窗口过程(实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理)
Todo:从消息队列中获取消息还可以使用PeekMessage()函数;发送消息可以使用SendMessage()和PostMessage()函数。其中,SendMessage()发送的是不进队消息,目标窗口将消息处理完毕后该函数才返回。还有PostThreadMessage()用于向线程发消息。
8.窗口过程函数
LRESULT CALLBACK WindowProc(
HWND hWnd,//窗口句柄
UINT uMsg,//消息代码
WPARAM wParam,//附加参数
LPARAM lParam//附加参数
);
实例:第一个Windows窗口程序
#include<windows.h>
#include<stdio.h>
#include<string>
using namespace std;
LRESULT CALLBACK WindowProc(
HWND hWnd, //窗口句柄
UINT uMsg, //消息代码
WPARAM wParam,//附加参数
LPARAM lParam //附加参数
);//回调函数申明
int WINAPI WinMain(
HINSTANCE hInstance, //程序当前运行的实例句柄(标识实例)
HINSTANCE hprevInstance,//当前实例的前一实例的句柄(NULL)
LPSTR lpCmdLine, //命令行参数
int nCmdShow //指定程序的窗口如何显示
)
{
//1.设计一个窗口类
WNDCLASS wndClass;
wndClass.cbClsExtra=0;//WNDCLASS类附加内存
wndClass.cbWndExtra=0;//窗口附加内存
wndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//背景画刷句柄
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);//光标句柄
wndClass.hIcon=LoadIcon(NULL,IDI_INFORMATION);//图标句柄
wndClass.hInstance=hInstance; //应用程序实例句柄由WinMain函数传进来
wndClass.lpfnWndProc=WindowProc;//函数指针,指向窗口过程函数(回调函数)
wndClass.lpszClassName="FirstWin";//指定该窗口类的名字
wndClass.lpszMenuName=NULL;//指定菜单资源的名字(NULL,没有默认菜单)
wndClass.style=CS_HREDRAW|CS_VREDRAW;//窗口样式
//2.注册窗口
RegisterClass(&wndClass);
//3.创建窗口
HWND hwnd; //定义一个变量用来保存成功创建窗口后返回的句柄
hwnd=CreateWindow("FirstWin","MyFirstWin",WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL);
//4.显示窗口
ShowWindow(hwnd,SW_SHOWNORMAL);
//5.更新窗口
UpdateWindow(hwnd);
//6.定义消息结构体,开始消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)//窗口过程定义
{
switch(uMsg)
{
case WM_CHAR: //用户按下字符键,程序将得到一个WM_CHAR消息,在其wParam中含有字符的ASCLL码值
char szChar[20];
sprintf(szChar,"char code is %c",wParam);
MessageBox(hwnd,szChar,"char",0);
/*函数原型:int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);*/
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse click!","message",0);
HDC hdc;
hdc=GetDC(hwnd); //获取DC句柄(Device Context)
TextOut(hdc,0,50,"My Process!",strlen("My Process!"));
/*函数原型:BOOL TextOut(
HDC hdc, // handle to device context
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString // number of characters in string
);*/
ReleaseDC(hwnd,hdc);//用完后释放DC所占的资源,以免内存泄漏
break;
case WM_PAINT:
HDC hDC; //如果这里定义HDC hdc将和上一个case中定义重复,所以每个case中的变量不是仅在那个case中可见
PAINTSTRUCT ps;//该结构体对象用于接受绘制的信息
hDC=BeginPaint(hwnd,&ps);//调用BeginPaint函数得到DC句柄(在响应WM_PAINT消息时,要得到窗口的DC必须用BeginPaint函数
//该函数也只能在响应WM_PAINT消息的代码中使用,在其他地方只能用GetDC来得到DC的句柄)
TextOut(hDC,0,0,"My First Process!",strlen("My First Process!"));
EndPaint(hwnd,&ps);//用BeginPaint函数得到的DC,必须用EndPaint函数释放
break;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"是否真的结束?","message",MB_YESNO))
{
DestroyWindow(hwnd);//DestroyWindow函数在销毁窗口后会向窗口过程发送WM_DESTROY消息,此时窗口已经销毁但程序还未退出
}
break;
case WM_DESTROY:
PostQuitMessage(0); //该函数向应用程序的消息队列中投递一条WM_QUIT消息并返回;GetMessage函数只有收到WM_QUIT消息才返回0,退出循环
break;
default: return DefWindowProc(hwnd,uMsg,wParam,lParam);//缺省的窗口过程
}
return 0;
}
2.窗口:通过窗口句柄来标识。
3.句柄(HANDLE):各种资源的标识号。 窗口句柄(HWND) 图标句柄(HICON)光标句柄(HCURSOR) 画刷句柄(HBRUSH) 实例句柄(HINSTANCE)。
4.Windows程序设计,是事件驱动的,主要是基于消息的。
消息:MSG结构体
Typedef struct tagMSG{
HWND hwnd; //表示消息所属的窗口
UINT message; //消息的标识符,WM_XXX宏(eg:WM_CHAR)
WPARAM wParam;//消息的附加信息 (eg:WM_CHAR用户输入的具体字符)
LPARAM lParam;//附加信息 (WPARAM:unsigned int; LPARAM:long)
DWORD time; //消息投递时的时间
POINT pt; //鼠标的当前位置
}MSG;
消息队列:系统为应用程序创建一个消息队列,并将该程序的消息放入消息队列,应用程序通过一个消息循环依次从队列中取出消息并响应。这种消息机制,就是Windows程序的运行机制。(进队消息和不进队消息(直接发给应用程序))
窗口过程函数:(回调函数)处理消息
5.WinMain函数:Windows程序的入口点函数。
函数原型:int WINAPI WinMain(
HINSTANCE hInstance,//程序当前运行的实例句柄(标识实例)
HINSTANCE hprevInstance,//当前实例的前一实例的句柄(NULL)
LPSTR lpCmdLine,//命令行参数
int nCmdShow//指定程序的窗口如何显示
)//这四个参数都是系统调用WinMain函数时传递给应用程序的(实例句柄由操作系统分配)
6.窗口的创建
(1)设计一个窗口类
typedef struct _WNDCLASS{
UINT style; //窗口样式(eg:CS_HREDRAW 水平重绘)位标志标识符
WNDPROC lpfnWndProc;//函数指针,指向窗口过程函数(回调函数)
int cbClsExtra;//WNDCLASS类附加内存(0)
int cbWndExtra;//窗口附加内存(0)
HANDLE hInstance;//包含窗口过程的程序的实例句柄
HICON hIcon; //图标句柄(NULL为默认图标;LoadIcon()加载图标)
HCURSOR hCursor;//光标句柄(LoadCursor()加载光标)
HBRUSH hbrBackground; //背景画刷句柄(GetStockObject()得到画刷)
LPCTSTR lpszMenuName; //指定菜单资源的名字(NULL,没有默认菜单)
LPCTSTR lpszClassName;//指定该窗口类的名字
} WNDCLASS;
HICON LoadIcon(HINSTANCE hInstance;LPCTSTR lpIconName);//加载图标资源
HCURSOR LoadCursor (HINSTANCE hInstance;LPCTSTR lpIconName);//加载光标
HGDIOBJ GetStockObject(int fnObject);//得到系统的标准画刷
(2)注册窗口
ATOM RegisterClass(CONST WNDCLASS *lpWndClass);// lpWndClass:窗口类对象的指针.(注册成功后才可以创建该类型的窗口)
(3)创建窗口
HWND CreatWindow(
LPCTSTR lpClassName,//指定窗口类的名称即WNDCLASS. lpszClassName
LPCTSTR lpWindowName,//指定窗口的名称(显示在标题栏)
DWORD dwStyle,//指定创建的窗口的样式(eg:WS_OVERLAPPEDWINDOW位标志标识符)Todo: WNDCLASS的style是指定窗口类的样式,所有基于该窗口类创建的窗口都具有这些样式,而dwStyle是指定具体某个具体窗口的样式。
int x,//窗口左上角x坐标(CW_USEDEFAULT 默认位置,y被忽略)
int y,//窗口左上角y坐标
int nWidth,//窗口宽度(CW_USEDEFAULT 默认大小,nHeight忽略)
int nHeight,//窗口的高度
HWND hWndParent,//指定该窗口的父窗口的句柄
HMENU hMenu,//指定窗口菜单的句柄
HANDLE hInstance,//指定窗口所属的应用程序实例的句柄
LPVOID lpParam//WM_CREATE附加参数lParam传入的数据指针(NULL)
);
(4)显示窗口
BOOL ShowWindow(
HWND hWnd, //窗口句柄
Int nCmdShow //指定窗口显示的状态
);
(5)更新窗口
BOOL UpdateWindow(HWND hWnd); //发送一个WM_PAINT消息来刷新窗口(直接发给窗口过程函数处理,不进入消息队列!)
7.消息循环
(1)取出消息
BOOL GetMessage(
LPMSG lpMsg,//指向一个消息结构体(保存从消息队列中得到的消息)
HWND hWnd,//指定接受哪一个窗口的消息(NULL,所有窗口)
UINT wMsgFilterMin;//指定要获取的消息的最小值(0)
UINT wMsgFilterMax//指定要获取的消息的最大值(0,所有消息)
);//接收到WM_QUIT消息时返回0值,其余非零,错误返回-1
(2)转换消息
TranslateMessage(LPMSG lpMsg);//将虚拟键消息转换为字符消息。
(3)传递消息
DispatchMessage(LPMSG lpMsg);//分派一个消息到窗口过程(实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理)
Todo:从消息队列中获取消息还可以使用PeekMessage()函数;发送消息可以使用SendMessage()和PostMessage()函数。其中,SendMessage()发送的是不进队消息,目标窗口将消息处理完毕后该函数才返回。还有PostThreadMessage()用于向线程发消息。
8.窗口过程函数
LRESULT CALLBACK WindowProc(
HWND hWnd,//窗口句柄
UINT uMsg,//消息代码
WPARAM wParam,//附加参数
LPARAM lParam//附加参数
);
实例:第一个Windows窗口程序
#include<windows.h>
#include<stdio.h>
#include<string>
using namespace std;
LRESULT CALLBACK WindowProc(
HWND hWnd, //窗口句柄
UINT uMsg, //消息代码
WPARAM wParam,//附加参数
LPARAM lParam //附加参数
);//回调函数申明
int WINAPI WinMain(
HINSTANCE hInstance, //程序当前运行的实例句柄(标识实例)
HINSTANCE hprevInstance,//当前实例的前一实例的句柄(NULL)
LPSTR lpCmdLine, //命令行参数
int nCmdShow //指定程序的窗口如何显示
)
{
//1.设计一个窗口类
WNDCLASS wndClass;
wndClass.cbClsExtra=0;//WNDCLASS类附加内存
wndClass.cbWndExtra=0;//窗口附加内存
wndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//背景画刷句柄
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);//光标句柄
wndClass.hIcon=LoadIcon(NULL,IDI_INFORMATION);//图标句柄
wndClass.hInstance=hInstance; //应用程序实例句柄由WinMain函数传进来
wndClass.lpfnWndProc=WindowProc;//函数指针,指向窗口过程函数(回调函数)
wndClass.lpszClassName="FirstWin";//指定该窗口类的名字
wndClass.lpszMenuName=NULL;//指定菜单资源的名字(NULL,没有默认菜单)
wndClass.style=CS_HREDRAW|CS_VREDRAW;//窗口样式
//2.注册窗口
RegisterClass(&wndClass);
//3.创建窗口
HWND hwnd; //定义一个变量用来保存成功创建窗口后返回的句柄
hwnd=CreateWindow("FirstWin","MyFirstWin",WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL);
//4.显示窗口
ShowWindow(hwnd,SW_SHOWNORMAL);
//5.更新窗口
UpdateWindow(hwnd);
//6.定义消息结构体,开始消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)//窗口过程定义
{
switch(uMsg)
{
case WM_CHAR: //用户按下字符键,程序将得到一个WM_CHAR消息,在其wParam中含有字符的ASCLL码值
char szChar[20];
sprintf(szChar,"char code is %c",wParam);
MessageBox(hwnd,szChar,"char",0);
/*函数原型:int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);*/
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse click!","message",0);
HDC hdc;
hdc=GetDC(hwnd); //获取DC句柄(Device Context)
TextOut(hdc,0,50,"My Process!",strlen("My Process!"));
/*函数原型:BOOL TextOut(
HDC hdc, // handle to device context
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString // number of characters in string
);*/
ReleaseDC(hwnd,hdc);//用完后释放DC所占的资源,以免内存泄漏
break;
case WM_PAINT:
HDC hDC; //如果这里定义HDC hdc将和上一个case中定义重复,所以每个case中的变量不是仅在那个case中可见
PAINTSTRUCT ps;//该结构体对象用于接受绘制的信息
hDC=BeginPaint(hwnd,&ps);//调用BeginPaint函数得到DC句柄(在响应WM_PAINT消息时,要得到窗口的DC必须用BeginPaint函数
//该函数也只能在响应WM_PAINT消息的代码中使用,在其他地方只能用GetDC来得到DC的句柄)
TextOut(hDC,0,0,"My First Process!",strlen("My First Process!"));
EndPaint(hwnd,&ps);//用BeginPaint函数得到的DC,必须用EndPaint函数释放
break;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"是否真的结束?","message",MB_YESNO))
{
DestroyWindow(hwnd);//DestroyWindow函数在销毁窗口后会向窗口过程发送WM_DESTROY消息,此时窗口已经销毁但程序还未退出
}
break;
case WM_DESTROY:
PostQuitMessage(0); //该函数向应用程序的消息队列中投递一条WM_QUIT消息并返回;GetMessage函数只有收到WM_QUIT消息才返回0,退出循环
break;
default: return DefWindowProc(hwnd,uMsg,wParam,lParam);//缺省的窗口过程
}
return 0;
}
相关文章推荐
- VC++深入详解(孙鑫)(第一章 Windows 程序内部运行机制)学习笔记
- 《VC++深入详解》读书笔记 第一章:Windows程序内部运行机制
- 孙鑫老师VC++lesson1(Windows程序内部运行机制)学习笔记
- 孙鑫《vc ++深入详解》第一章windows程序内部运行机制
- [VC++深入详解] 1. Windows程序内部运行机制
- 第一章,Windows程序内部运行机制
- 第一章:Windows程序内部运行机制
- 【转】第一章 Windows程序内部运行机制
- 孙鑫VC++深入详解(1):windows程序内部运行机制
- 《VC++深入详解》学习笔记[1]——第1章 Windows程序内部运行机制
- 《VC++深入详解》读书笔记——1.Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制实例详解
- 从WinMain函数看Windows程序内部运行机制
- 孙鑫VC++讲座笔记-(1)Windows程序内部运行机制
- Windows程序内部运行机制笔记
- Windows程序内部运行机制
- Windows程序内部运行机制
- 一. Windows程序内部运行机制--Windows编程课程学习笔记
- (1)Windows程序内部运行机制