Windows学习笔记第二课---第一个windows程序Hello Windows!

一、自己的窗口

        在前面,我们使用了同一个函数MessageBox来向使用者输出文字。MessageBox函数会建立一个「窗口」。但这只是一个功能有限的特殊窗口。消息窗口有一个带关闭按钮的标题列、一个选项图标、一行或多行文字,以及最多四个按钮。当然,必须选择Windows提供给您的图标与按钮。

在Windows中,「窗口」一词有确切的含义。一个窗口就是屏幕上的一个矩形区域,它接收使用者的输入并以文字或图形的格式显示输出内容。

  

我们不能在消息框中显示图形,而且也不能在消息框中添加菜单。要添加这些对象,就需要建立自己的窗口,现在就开始。

建立窗口很简单,只需呼叫CreateWindow函数即可。


桌面上常见的窗口:
应用程序窗口:
显示程序名称的标题列、菜单甚至可能还有工具列和滚动条。
对话框:它可以有标题列也可以没有标题列。装饰对话框表面的还有各式各样的按键、单选按钮、复选框、清单方块、滚动条和文字输入区域。其中每一个小的视觉对象都是一个窗口。更确切地说,这些都称为「子窗口」或「控件窗口」或「子窗口控件」。

所谓「Windows给程序发送消息」,是指Windows呼叫程序中的一个函数,该函数的参数描述了这个特定消息。这种位于Windows程序中的函数称为「窗口消息处理程序」。

窗口通常是在「窗口类别」的基础上建立的。窗口类别标识了处理窗口消息的窗口消息处理程序。使用窗口类别使多个窗口能够属于同一个窗口类别,并使用同一个窗口消息处理程序。

程序建立的每一个窗口都有相关的窗口消息处理程序。这个窗口消息处理程序是一个函数,既可以在程序中,也可以在动态链接库中。

对象是程序与数据的组合。窗口是一种对象,其程序是窗口消息处理程序。数据是窗口消息处理程序保存的信息和Windows为每个窗口以及系统中那个窗口类别保存的信息。

Windows程序开始执行后,Windows为该程序建立一个「消息队列」。这个消息队列用来存放该程序可能建立的各种不同窗口的消息。程序中有一小段程序代码,叫做「消息循环」,用来从队列中取出消息,并且将它们发送给相应的窗口消息处理程序。有些消息直接发送给窗口消息处理程序,不用放入消息队列中。

建立一个窗口首先需要注册一个窗口类别,那需要一个窗口消息处理程序来处理窗口消息。处理窗口消息对每个Windows程序都带来了些负担。


代码及其详细注释如下:

/*------------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//窗口消息处理程序声明:
                                                       //LRERULT为函数返回值类型,宏定义为LONG;
                                                       //CALLBACK说明的是函数参数的进栈顺序(从左到右)
                                                       //WndProc为函数名,可任意改
                                                       //4个函数参数为message结构体中的前4个参数,

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)       //主函数,Windows程序进入点;其中,int为函数返回值类型,WINAPI说明的是函数的进栈顺序。
					                                    //第一个参数为执行实体(程序自身)句柄,唯一的标识该程序;第二个参数在32位的Windows中已失去了意义,总是NULL;
														//第三个参数是用于执行程序的命令列;第四个参数指出窗口最初的显示方式,最小化、最大化、还是正常显示。
{
	static TCHAR szAppName[] = TEXT ("HelloWin") ;      //定义一个字符串数组,并赋以初值“HelloWin”,这个“HelloWin”是程序的名字
	                                                    //是要进操作系统的注册表的!是告诉操作系统你这个程序的名字是什么!
	HWND         hwnd ;                                 //定义窗口句柄
	MSG          msg ;                                  //结构体类型MSG的变量申明,该结构体中有六个成员变量,储存有关消息的信息
	WNDCLASS     wndclass ;                             //结构体类型WNDCLASS的变量申明,以下为该变量成员的初始化
	
	wndclass.style         = CS_HREDRAW | CS_VREDRAW ;  //CS_HREDRAW表示水平重画,即水平拖动窗口时,会调用WM_PAINT消息重画窗口,调整窗口尺寸
	                                                    //CS_VREDRAW表示垂直重画,即垂直拖动窗口时,会调用WM_PAINT消息重画窗口,调整窗口尺寸
	wndclass.lpfnWndProc   = WndProc ;                  //该字段是依据这个窗口类别来建立的所有窗口的消息处理程序的地址
	wndclass.cbClsExtra    = 0 ;                        //预留空间的附加值,此程序没用到这个域!
	wndclass.cbWndExtra    = 0 ;                        //预留空间的附加值,此程序没用到这个域!
	wndclass.hInstance     = hInstance ;                //该字段为执行实体句柄,初始化为WinMain中的第一个参数
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;                //装载图标函数。当装载自己的图标时,第一个参数设为hInstance
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;                    //装载光标函数。也可装载自己的光标
	wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;           //该字段为依据该类别建立的窗口背景颜色。此程序中设为黑色背景,可根据需要设置颜色
	wndclass.lpszMenuName  = NULL ;                                            //该字段指定窗口类别菜单。该程序中没有设置菜单
	wndclass.lpszClassName = szAppName ;                                       //类别名称,该类别名称与程序名相同
	
	if (!RegisterClass (&wndclass))                                          //向操作系统注册窗口类,即向操作系统申请内存
	{
		MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
			szAppName, MB_ICONERROR) ;                                        //消息对话框,用于异常处理
		return 0 ;
	}
// 创建窗口函数。在CreatWindow调用返回之后,Windows内部已经建立了这个窗口,即已经分配了内存	
	hwnd = CreateWindow (szAppName,                  // window class name  应用程序在操作系统注册表中的名称   
						 TEXT ("The Hello Program"), // window caption     应用程序标题栏名称
						 WS_OVERLAPPEDWINDOW,        // window style       窗口样式
						 CW_USEDEFAULT,              // initial x position 窗口显示时距屏幕左上角的x坐标
						 CW_USEDEFAULT,              // initial y position 窗口显示时距屏幕左上角的y坐标
						 CW_USEDEFAULT,              // initial x size     窗口宽度
						 CW_USEDEFAULT,              // initial y size     窗口高度
						 NULL,                       // parent window handle 父窗口句柄,此程序没有
						 NULL,                       // window menu handle   菜单句柄
						 hInstance,                  // program instance handle 程序实例句柄
						 NULL) ;                     // creation parameters 创建参数指针
	
	ShowWindow (hwnd, iCmdShow) ;   //该函数在显示器上显示函数
	                                //第一次调用窗口回调函数Wndproc,注意Wndproc函数不是ShowWindow函数来调用,而是
                                    //ShowWindow函数向操作系统发送消息,是操作系统根据发送的消息来调用Wndproc函数!
                                    //操作系统调用Wndproc函数后并响应WM_CREATE消息!
	UpdateWindow (hwnd) ;           //刷新窗口函数,操作系统调用WndProc函数并响应WM_PAINT消息      
	
	while (GetMessage (&msg, NULL, 0, 0))   // 这是所有WINDOWS程序的核心,消息循环处理过程!这里是接受消息和发送消息的地方!
		                                    //这一呼叫传给Windows一个指标,指向名为msg的MSG结构。
		                                    //第二、第三和第四个参数设定为NULL或者0,表示程序接收它自己建立的所有窗口的所有消息。
											//Windows用从消息队列中取出的下一个消息来填充消息结构的各个字段。
											//GetMessage 函数从操作系统的消息队列中获得消息,一个一个的处理,来一个处理一个,
                                            //直到获得退出消息,也就是点击应用程序右上角的叉子!退出消息循环,并响应WM_QUIT消息
	{
		TranslateMessage (&msg) ;           //将msg结构传给Windows,进行一些键盘转换
		DispatchMessage (&msg) ;            //又把msg发送给窗口过程,由操作系统调用消息处理程序WndProc
	}
	return msg.wParam ;
}   //主函数结束

//窗口回调函数,此函数由操作系统调用,因此只有声明和定义!
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC         hdc ;    //设备描述表句柄
	PAINTSTRUCT ps ;     //绘图结构体变量
	RECT        rect ;   //矩形结构体变量
	
	switch (message)     //message消息类型!分别处理不同的消息!
	{
	case WM_CREATE:     //此消息是一个应用程序发送的第一个消息,也是唯一的一次!在窗口显示之前该消息就已经执行了
		PlaySound (TEXT ("HelloWin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;//播放声音文件
		return 0 ;
		
	case WM_PAINT:     //这个消息在Windows程序设计中是很重要的。
		               //当窗口显示区域的一部分显示内容或者全部变为「无效」,以致于必须「更新画面」时,将由这个消息通知程序。

		hdc = BeginPaint (hwnd, &ps) ;           //开始窗口绘制   
		
		GetClientRect (hwnd, &rect) ;            //获得窗口客户区的尺寸
		
		DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
			DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;     //显示文本串
		
		EndPaint (hwnd, &ps) ;                   //结束窗口绘制
		return 0 ;
		
	case WM_DESTROY:   //处理退出消息
		PostQuitMessage (0) ;                    //在消息队列中插入一条“退出”消息
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;  //执行默认的消息处理,处理一些闲杂以及一些不可预料的消息!去掉该句可能造成死机
}

注意事项:如果使用Microsoft Visual C++ 为此程序建立新项目,那么得加上连结程序所需的链接库文件。从Project菜单选择 Setting选项,然后选取Link页面标签。从 Category清单方块中选择General,然后在 Object/Library Modules文字方块添加WINMM.LIB(Windows multimedia-Windows多媒体)。您这样做是因为HELLOWIN将使用多媒体功能呼叫,而内定的项目中又不包括多媒体链接库文件。不然连结程序报告了错误信息,表明PlaySound函数不可用。(或者在函数预编译命令时加上:#pragma comment(lib,"Winmm.lib"),就是告诉编译器在链接DLL时候连接了此函数)

如下图:

Windows学习笔记第二课---第一个windows程序Hello Windows!_第1张图片

关于此函数的详细说明,请移步:http://blog.sina.com.cn/s/blog_af169d640101nwcs.html OR http://blog.csdn.net/clearver/article/details/5209244

另外声音文件必须在您的工程目录下。。

工程文件以及源代码:http://download.csdn.net/detail/hu1020935219/6391647

执行情况如下:

Windows学习笔记第二课---第一个windows程序Hello Windows!_第2张图片

未完待续.......












你可能感兴趣的:(Windows学习笔记第二课---第一个windows程序Hello Windows!)