您的位置:首页 > 编程语言 > C语言/C++

《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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: