Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2014506
  • 博文数量: 960
  • 博客积分: 52560
  • 博客等级: 大将
  • 技术积分: 13131
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-31 14:15
文章分类

全部博文(960)

文章存档

2011年(1)

2008年(959)

我的朋友

分类: C/C++

2008-08-01 16:53:49

下载本文示例代码
预设目录:

第一部分:WinSDK

第二部分:MFC类基础,C 程序编写规范介绍

第三部分:MFC基于对话框程序

第四部分:Dll动态链接库

第五部分:COM组件基础

第六部分:COM组件几个常用技术:IDispatch,可连接对象.

第七部分:COM组件的应用,以及MFC的COM编写

第一部分:WinSDK

学习VC已近一年了,回顾我的学习历史真是相当的艰苦。既没有老师教,图书馆里也没有好书可看。为了买到好书,身上的银子几近花光,不得不过节衣缩食的生活。近些日来动起自己写写什么的打算,一来可以对自己的学习状况进行总结。二来,请教高手,可以帮忙指出错漏之处。三来,说不定会对初学者们有所帮助, 最起码也可以练练文笔。

OK。谈正事喽。首先MFC(Microsoft Foundation Class)是一种用来构建Win32程序的类库,但究其根本的话,是基于Windows老祖宗—Windows SDK,其历史可以追溯到Window 3.x时代。它整个构架是由C来编写的。更重要的是它的程序结构至今还是Win32程序的根本。因此,在学习VC的过程中,理解其程序结构是编写Win32程序的根本。

下面,就是一个WinSDK程序的示例(摘自侯先生的《深入浅出MFC》,在侯捷站点上有其此书的繁体电子版)

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)

{

	MSG msg;

	if (!hPrevInstance)

	if (!InitApplication(hInstance))

		return (FALSE)



	if (!InitInstance(hInstance, nCmdShow))

		return (FALSE);



	while (GetMessage(&msg, NULL, 0, 0)) 

	{

		TranslateMessage(&msg);

		DispatchMessage (&msg);

	}

	return (msg.wParam); 

}



BOOL InitApplication(HINSTANCE hInstance)

{

	wc.style = CS_HREDRAW | CS_VREDRAW;

	wc.lpfnWndProc = (WNDPROC)WndProc; 

	wc.cbClsExtra = 0;

	wc.cbWndExtra = 0;

	wc.hInstance = hInstance;

	wc.hIcon = LoadIcon(hInstance, "jjhouricon");

	wc.hCursor = LoadCursor(NULL, IDC_ARROW);

	wc.hbrBackground = GetStockObject(WHITE_BRUSH); 

	wc.lpszMenuName = "GenericMenu";

	wc.lpszClassName = "MyWindow";

	return (RegisterClass(&wc));

}



BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

	hWnd = CreateWindow("MyWindow","This is Windows SDK",

	WS_OVERLAPPEDWINDOW,

	CW_USEDEFAULT,

	CW_USEDEFAULT,

	CW_USEDEFAULT,

	CW_USEDEFAULT,

	NULL,

	NULL,

	hInstance,

	NULL);

	if (hWnd == NULL)

		return (FALSE);

	ShowWindow(hWnd, nCmdShow); 

	UpdateWindow(hWnd);

	return (TRUE);

}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

	switch (message)

	{

        case WM_DESTROY:

            PostQuitMessage(0);

            break;

        default:

            return DefWindowPro(hWnd, message, wParam, lParam);

}

    return 0;

}
首先,在C语言中的入口函数是main函数,在Win32程序中则是WinMain。其原型是
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int CmdShow)
第一个参数是hInstance,是所传进来的值是此程序的当前程序实例句柄。什么叫实例呢?当你运行两次同一个Windows程序时,屏幕上会出现两个一模一样的窗口;这时我们就说这个程序就被生成了两个实例。再举一个例子,在你眼前搁仨苹果,其时这个仨苹果就是苹果这一大类的三个实例。按照这个思路说实例就是一个抽象概念中的实体存在。那么严格来说其时我们所编写的并不是这个程序,而是这个程序的逻辑。而程序实例则是按照这个我们编写的逻辑所生成的实体结果。而句柄就是用来代表实例的,它是一个32位的值。每一个实例都对就着一个32位的值,而这个值就被称为句柄。不知道我说明白没有。这里的Instance就是当前程序被实例化后的句柄。而且属于同一个实例中的资源是共享的。第二个参数hPreInstance则代表上一个(前一个)程序实例句柄,在Win32程序中这个值总为空(为零),第三个参数是lpCmdLine,这是一个字符串,记录着启动程序时的命令行,起着C中main函数的(argc,argv)的作用.最后nCmdShow则表示这个程序的窗口是否被显示出来。

在主函数中,第一个要执行的函数就是InitApplication(),语句如下:

if (!InitApplication(hInstance))

return (FALSE);
这个函数所起的作用是注册窗口类。注册窗口类的意思就是告诉系统将我们的提供的图标,菜单,消息处理函数,光标联系起来成为一个窗口类,为后面的显示窗口作准备。在InitApplication()函数中使用RegisterClass()来注册窗口。如果成功则返回true,否则返回false。其唯一的参数是一个WNDCLASS结构。其中各字段功能如下:(关于具体值请查看MSDN)
style 指定窗口风格,譬如例子所举的CS_HREDRAW表示当水平长度发生改变时,重画整个窗口。 LpfnWndProc 指定窗口的消息处理函数,其函数的原型必须是
LRESULT CALLBACK WndProcName(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
WndProcName这一名字是随便起的.
hInstance 标识该窗口属于哪个程序实例.
hIcon 标识该窗口图标的图标句柄
hCurosr 标识该窗口光标的光标句柄
hbrBackground 标识该窗口的背景画笔.
lpszClassName 为这个窗口类所起的名字,为后来建立窗口引用窗口类所用。

当注册窗口类成功后就可以建立窗口了。主函数调用InitInstance()来建立窗口.在InitInstance()函数中使用CreateWindow();来建立窗口,其中第一个参数就是窗口类的名称,则注册窗口类时lpszClassName字段中的内容。如果成功则返回句柄,句柄代表刚刚建立好的窗口(实例)。否则的话返回的句柄为空。当建立好窗口的并不立即显示,还需用ShowWindow来使系统显示窗口,其参数就是一个窗口句柄(HWND)。看吧,在WinSDK中都是句柄来标识任何东西的(程序,窗口,图标,光标,文件等等)。然后再使用UpdateWindow()让窗口在屏幕上重绘一遍,使其真正显示出来。最后返回true.
接着就是WinSDK中重要一节消息循环:
while (GetMessage(&msg, NULL, 0, 0)) 

{

	TranslateMessage(&msg);

	DispatchMessage (&msg);

}
在每个程序实例中系统都会给配置了一个消息队列,当消息产生后(譬如:刷新WM_PAINT,鼠标移动WM_MOSEMVOE,键盘某个键被按下WM_KEYDOWN等等),就会将其放入队列尾部。程序这里用了一个while循环,这就是著名的消息循环了。GetMessage()在队列头部取出一条消息放入第一参数msg中,如果不是WM_QUIT (退出程序消息)消息则返回true,如果是WM_QUIT则返回false,结束循环。循环中第一个函数TranslateMessage()是键盘转换函数,其功能是将虚拟键消息转换成字符消息:

*WM_KEYDOWN/WM_KEYUP组合成一个WM_CHAR或WM_DEADCHAR消息
*WM_SYSKEYDOWN/WM_SYSKEYUP组合成一个WM_SYSCHAR或WM_SYSDEADCHAR消息。
并将组合成的消息放到队列当中去,等以后处理。

DispatchMessage()函数是将消息传送给相应的窗口消息处理函数中去。在MSG结构中有一个HWND字段它记录着产生消息的窗口,DispatchMessage会查找这个HWND句柄属于哪个窗口类,并将消息传入这个窗口类所联系的消息处理函数(在WNDCLASS结构中LpfnWndProc字段所指向的函数)中去。这样它就完成了它的消息分配工作。在上面示例程序中,只注册了一个窗口类。所以所有消息都是由这个窗口类的窗口实例所产生的,因此所有的消息都会被传入WinProc中去了。

在消息处理函数的入口参数中,是标识一条消息的主要信息,hWnd发生消息的源窗口,message消息的类型表示发生了什么消息,wParam,lParam与消息捆绑来的信息。因为在C\C 中类型是可以自由转换的,所以根据不同消息,其里面的内容是不一致。在消息处理函数中一般上是用switch/case语句来实现不同消息不同处理的。相信大家一看就明白怎么回事了。

关于message中的信息在VC98\Include\WinUSER.h(参考行数1292)中有详细的定义,各个消息的涵义可在MSDN中查到。

以上,就是我所知道的WinSDK所有东西。如果有什么错误和遗漏之处,请写信给我:Blue_Atlantis400@Hotmail.com;QQ:63068279。

(第一部分完)

下载本文示例代码
阅读(471) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~