视频下载地址:链接: http://pan.baidu.com/s/1qYj9BMs 密码: fn8u
《c语言开发窗口应用程序》前言
本教程适合什么样的人学习
适合已经掌握基本的c语言语法,想进一步提高c语言,不想总是玩控制台和做数学计算题的朋友。
通过本教程能学到什么?
1.学会制作带窗口界面的程序。
2.学会软件开发中常用的各种技术,如网络编程,多线程编程,数据库编程。
3.项目实战,让您知道软件是怎么一步一步制作的。可以学会c语言的模块化编程以及一些编程习惯和思路。
教学模式
从需求出发,通过项目实战教学,期间遇到的知识点再详细讲解,最终项目学会了,知识也学会了,并且比零散的知识更加容易记住,做到真正的学以致用。
第一阶段:windows图形编程
第一节:我的第一个窗口
窗口是什么?
程序的窗口到底是什么?其实窗口,可以理解为电脑屏幕上的一个图片或者是像素点,底层的原理都是操作让显示屏显示特定的图形。只是这一切都不需要我们去编写代码来控制屏幕显示。是由操作系统来完成,然后编写操作系统的人编写出来一些函数,提供给程序员去使用,从而达到创建窗口的目的。
Windows系统下如何编写带窗口的程序?
c语言通过调用windows系统提供给的API来创建窗口。
API是什么?
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
你也可以自己编写API提供特定的功能,然后给其他程序员去使用,这就是你的API。我们这里说的API特指windows系统提供的api,他是由编写windows操作系统的程序员编写的,然后提供给需要的程序员使用,比如创建窗口。
简而言之,windows API其实就是开发windows系统的程序员编写来提供给我们程序员用的函数。
为何其他的语言直接鼠标拖拉一下就能有界面?
很多语言都可以调用这些API,比如c、c++、java、vb、c#等等,调用的都是同样的函数,用法也是一样,只是不同语言调用方式上有点区别而已。
像vb、Delphi、易语言之类的,鼠标拖拉一下就有界面。其实只是对我们程序员隐藏了底层的东西,其本质还是一样调用了windows提供给他的API函数来实现。
大家可能会想,既然拖拉一下都可以做出界面,那我们还有必要学习直接用API创建窗口这么麻烦吗?当然是有必要的,理解原理以后,我们就不会被表面的东西遮住眼睛,能够一眼洞穿他的本质,撕去他的伪装。以后大家还会接触到很多的界面库(如:Duilib),有的是开放源码的,当大家去读这些代码的时候,就必须要具备这些基础的理论知识。
动手编写第一个带窗口的程序?
窗口程序的主函数名称 跟控制台程序的主函数名称不一样。
在控制台程序中,基本框架是:
int main(void)
{
return 0;
}
Win32窗口程序,基本框架是:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow)
{
return 0;
}
看起来比较复杂,是因为有很多数据类型没有见过。
下面来一一解释一下:
int :代表返回值是整形 这个跟控制台程序一样。
WINAPI :
这个是调用约定,实质上是它是宏 #define WINAPI __stdcall 说明是stdcall的调用约定,想了解更多关于调用约定的,可以直接谷歌搜索 调用约定。Ps:谷歌被墙,可以通过这个地址使用谷歌搜索服务(g.zixue7.cn或go.zixue7.cn)
WinMain :
这个是函数名 就像控制台程序中的 main
HINSTANCE :
这个是一个自定义类型, 是句柄型数据类型,相当于装入了内存的资源的ID,比如我们的程序被加载到内存中,就是一个资源,就有一个编号,WinMain函数的第一个参数就是表示我们当前运行这个程序本身的资源id。
hInstance:
应用程序当前实例的句柄。 这个值其实就是程序加载到内存空间后的首地址。
hPrevlnstance:
应用程序的先前实例的句柄。对于同一个程序打开两次,出现两个窗口第一次打开的窗口就是先前实例的窗口。
PSTR szCmdLine:
在WINNT.H中有如下定义
typedef char CHAR;
typedef CHAR *LPSTR, *PSTR;
这就说明 PSTR 其实就是个char类型的指针而已。
这个参数的作用就是接受命令行参数。比如在启动程序的时候用如下命令:
zixue7.exe admin password
那么这个szCmdLine 中保存的就是 admin password这个字符串
这个参数的值,可以直接使用,也可以通过 GetCommandLine() 函数获取到。
int iCmdShow :这个是控制窗口的显示状态,比如最大化,最小化,隐藏。
上面这些参数解释,一开始看不懂,没有关系,完全不影响我们下面的学习,可以等到以后知识积累足够了,再回头好好理解。
对主函数了解差不多之后,我们来编写第一个窗口程序,代码如下:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow)
{
MessageBox(NULL, TEXT("窗口内容"), TEXT("窗口标题"), MB_OK);
return 0;
}
其实这还不算真正的窗口程序,只是一个对话框窗口。
接下来,我们先来配置好本次课程用的开发环境。
开发环境搭建
本套教程采用的开发工具是VS2013,下载地址:http://www.zixue7.com/thread-36148-1-1.html
安装过程 略微有点漫长。。
安装的时候遇到这个问题 要么装一下ie10 要么不管他 点继续。
如何创建项目,具体看视频演示,也可以自己摸索一下。
下面看第一个窗口的代码:
#include <windows.h>
//窗口过程函数
LRESULT CALLBACK WndProc(HWND,UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
//定义窗口类结构体变量
WNDCLASS wc;
//窗口类名称
static TCHAR* szAppName =TEXT("zixue7");
//窗口句柄
HWND hwnd = NULL;
//消息结构
MSG msg;
/**
下面的代码填充窗口类信息,如图标,鼠标样式,背景,过程函数等
*/
wc.style = CS_HREDRAW | CS_VREDRAW; //窗口样式
wc.lpfnWndProc = WndProc; //过程函数
wc.cbClsExtra = 0; //扩展字段
wc.cbWndExtra = 0; //扩展字段
wc.hInstance = hInstance; //当前实例句柄
wc.hIcon = LoadIcon(hInstance,IDI_APPLICATION); //设置程序图标
wc.hCursor = LoadCursor(NULL,IDC_ARROW); //设置鼠标
//用白色画刷填充背景
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
//菜单
wc.lpszMenuName = NULL;
//类名
wc.lpszClassName = szAppName;
//像操作系统注册窗口类
if (!RegisterClass(&wc))
{
MessageBox(NULL,TEXT("程序只能在windowsNT下运行"),
szAppName, MB_ICONERROR);
return 0;
}
//创建窗口
hwnd = CreateWindow(szAppName, //要注册的窗口类名
TEXT("c语言编写的第一个窗口程序-www.zixue7.com"),//窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //窗口距离屏幕左上角都横坐标
CW_USEDEFAULT, //窗口距离屏幕左上角都纵坐标
400, //窗口宽度
300, //窗口高度
NULL, //父窗口句柄
NULL, //菜单句柄
hInstance, //当前实例句柄
NULL); //指向一个值的指针,该值传递给窗口 WM_CREATE消息。一般为NULL
//显示窗口
ShowWindow(hwnd, iCmdShow);
//更新窗口
UpdateWindow(hwnd);
//消息循环,一直停在这里,退出消息循环就表示程序结束了。
while (GetMessage(&msg,NULL, 0, 0))
{
//翻译消息
TranslateMessage(&msg);
//分发消息
DispatchMessage(&msg);
}
return msg.wParam;
}
/**
消息处理函数
*/
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
//发送结束请求,里面的参数为退出码
PostQuitMessage(0);
break;
}
//调用默认的过程函数
return DefWindowProc(hwnd,message, wParam, lParam);
}
运行效果:
我们已经用纯代码生成了第一个窗口,这是一个好的开始,虽然只有短短的几十行代码,但是其中的信息量是非常大的,今后所有的窗口程序,我们都是基于上面的一个基本框架代码。
我们先来看看在windows下创建一个窗口的整个过程:
1.告诉系统,我们要创建一个怎么样的窗口。
如何告诉?通过WNDCLASS这个结构来告诉他,我们设置这个结构的不同字段。
设置好字段之后,调用RegisterClass函数来告诉系统,我们要注册一个这样的窗口类型。
2.创建窗口。
上一步创建了一个窗口类型,其实这个窗口类型可以理解为一个模板,接下来我们就告 操作系统,我们要以xx模板创建一个窗口。怎么告诉他呢?就是调用函数CreateWindow,这个函数参数十分的多,也不需要去死记硬背,书写多了自然就记住 了,写的时候不知道有哪些参数就百度搜下函数名称就好了。
3.显示窗口
创建好窗口之后,默认是没显示的,我们还需要让他显示出来,同样是调用函数
ShowWindow来显示, 调用这个函数来更新窗口UpdateWindow
4.消息循环
创建好窗口之后,不是要等待用户的操作吗?比如鼠标单击,键盘按键等等。
这些东西在windows系统中都是一种消息。
上面的 WndProc 这个函数就是专门处理这些消息,我们可以在这个函数中处理我们感
兴趣的消息。
重点:消息机制(也就是消息循环具体是怎么循环的,消息从哪里来,要到哪里去)
一个消息的产生到结束是怎样一个过程,就以用户点击鼠标为例。
1.用户在应用程序A上面单击了左键
2.操作系统捕捉到了这个单击左键的消息,就把它放到由操作系统管理的消息队列中。
3.我们的程序创建好之后就通过GetMessage函数一直不停的去检测消息队列中是否有自己关心的消息(至于如何判断哪些消息是我们窗口所关心的,这个由操作系统去管,此处不必深究。)
4.获取到消息之后,操作系统(可以看到我们并没有在我们代码中直接调用)就调用窗口过程函数来处理,窗口过程函数就是上面代码中的WndProc。 他怎么知道要调用这个函数来处理呢?是因为在我们注册窗口类的时候通过这段代码告诉他的wc.lpfnWndProc = WndProc; 程序又不是神