Windows编程教案讲解.docx
《Windows编程教案讲解.docx》由会员分享,可在线阅读,更多相关《Windows编程教案讲解.docx(36页珍藏版)》请在冰豆网上搜索。
Windows编程教案讲解
Windows编程教案
第一课最简单的Windows程序(2学时)
Windows编程是一个很大的主题,涉及的方面也非常的多。
Windows始于90年代,至今Windows编程的发展已经非常成熟了,而单独直接使用API的开发也是越来越少了。
因此,市面上很少有泛泛的简单入门级的Windows程序设计了。
一个是系统级的Windows编程介绍,如Windows核心编程。
一个是方向级的Windows编程介绍如Windows图形编程,Windows网络编程等等。
我们这次课的主要参考用书是Windows核心编程,同时也参考了一些其他内容。
鉴于教材的价格较贵,同时也需要考虑我们自身的学习内容不一定很多以及学时的原因,就没有定教材。
看我的教案吧。
(1)Win32API
API:
ApplicationProgramInterface。
应用程序接口。
API就是在进行Windows编程时使用的函数库。
本课就是
Windows编程=API+C语言(或者C++语言)
(2)开发环境
我校机器上安装了VC++6.0。
相信这是大家一直以来学习C,C++使用的开发环境。
但VC60离我们实在太远了,它是一款90年代的产品,已经近20年的历史了。
我们机器里还有VS2005或VS2008,那里面的C环境要比VC60强太多了,强烈建议大家使用更高级的平台。
本次授课的开发环境有两个。
一个是轻量级的DEVC++,一个是重量级的VS2010.简单程序我们都将用DEVC++来实现。
DEVC++是一个非常小的C环境,但性能要优于VC60,调试环境不如VC60。
这个环境在我们的共享资源里有,大家可以下载安装。
安装过程非常简单,一直下一步即可。
这是其主界面。
(3)最简单的Windows程序
提到最简单的程序,几乎所有的人都会想起经典的HelloWorld。
这不是Windows程序,如果在以前这叫DOS程序,现在叫Windows控制台应用程序。
它不算Windows程序,但它很简单的就把Helloword显示到屏幕上了。
而Windows程序要想把HelloWorld显示在屏幕上就确实不容易了。
3.1访问Helloworld网站,因为把Helloworld显示在屏幕上并不容易,我们可以一点一点来,先让Helloworld以文字形式出现在其他地方,这里我们通过访问网站。
把helloworld展现在网页浏览器的地址栏上。
真有这个网站吗?
唉,貌似还真有。
运行程序,打开浏览器并访问网站。
这是Windows程序。
Windows程序和我们以前的程序有什么不同呢?
●Windows程序不能使用scanf,printf,cin,cout。
所以输出helloworld变得没有以前容易了。
●windows程序一定要#include
●windows程序的主函数不是main,是WinMain。
注意区分大小写。
●主函数的参数不一样了
intmain(intargc,char[]*argv)
intWinMain(HINSTANCEhInstance,HINSTANCE,LPSTRlpStr,intnShow)
绝大多数的人,初次接触Windows编程都会被其冗长的名字所折服,啊,没办法,这就是Windows的命名规格,叫匈牙利命令法,是微软的一个匈牙利籍的程序员发明的,它的作用的能够让变量,类型名能够真实的反应其代表的意义,这对英语人士自然很好。
对英语不好的接受起来就有点难了。
详细解释一下
WinMain是Windows编程的主函数。
一定注意大小写啊。
HINSTANCE,用Windows的说法叫句柄数据类型。
但它并不是一个新的数据类型,它是通过#define定义出来的。
#defineDECLARE_HANDLE(name)structname##__{intunused;};typedefstructname##__*name
DECLARE_HANDLE(HINSTANCE);
上面两行是windef.h中对HINSTANCE的定义。
说到底HINSTANCE就是一个指针类型。
LPSTR是typedefchar*LPSTR。
Windows编程里有大量通过#define和typedef定义出来的数据类型名。
本质上它们都不是新的东西,都是以前我们在C语言学过的哪些数据类型另起了一个名字。
为什么要这么做呢?
一般Windows程序比较大,好的命名利于维护和避免错误。
总之,说到底,旧壶装新酒,貌似多了很多数据类型,不要被它们吓到,它们就是比C语言你们学过的东西多穿了件马甲。
第二课在窗口中显示HelloWorld中(4学时)
一、第一课的HelloWorld出现在网页上。
这不是我们的目的,我们要生成正常一点的HelloWorld。
Windows程序中要显示HelloWorld看来还不是太容易。
(1)将HelloWorld绘制到桌面
补充说明
如果要让这个程序顺利执行,需要
写的内容是lgdi32
运行的效果,helloworld显示在桌面上了
看到HelloWorld了吗。
说明
●WinMain是Window的主函数
●HDC是个什么呢,本质上是个指针,但是我们不需要了解它指向了什么,因此,简而化之HDC是一个32位的无符号整数。
HDC叫设备上下文句柄。
设备上下文指显示器屏幕或打印机什么的。
句柄有点类似文件句柄的意思,有了它才能操作设备。
在这里有了它才能向设备上绘制。
所有涉及绘图的地方都涉及HDC。
GetDC(窗口句柄)。
如果使用GetDC(NULL)得到桌面的设备上下文。
否则可以得到一个窗口的设备上下文,我们可以在窗口上进行绘制。
(2)LPTSTR是TCHAR*的另一个写法
(3)TextOut是WindowsAPI的一个函数,功能是将文本写到设备上下文上。
TextOut(HDC,横坐标,纵坐标,字符串,字符串长度)
(4)ReleaseDC(窗口句柄,HDC)释放设备上下文
GetDC的得到的HDC一定要用ReleaseDC释放,否则机器容易资源耗尽。
二、在一个独立窗口中显示HelloWorld,这是重点了,涉及一些Windows编程重要的内容
分如下几个步骤
(1)定义一个全局函数
(2)定义WinMain函数
(3)在WinMain函数内注册窗口类
lpszClassName:
自己取个名字,字母
lpfnWndProc:
函数指针,为我们在第一步定义的函数名。
用强制类型转换
在Windows中显示一个窗口,一定要先注册窗口类。
函数式RegisterClassEx(&wc)
(4)创建并显示窗口
(5)建立消息循环
(6)补充处理WM_PAINT,补充WndProc函数
总结:
创建窗口的模式是基本是固定的,本课的代码很大一部分就是这么写。
主要在WndProc内存在不同。
涉及的API函数
RegisterClassEx(&WNDCLASSEX)
WinMain(HINSTACNE,HINSTANCE,LPSTR,intnShow)
DefWindowProc(HWND,UINT,WPARAM,LPARAM)
GetMessage(LPMSGlpMsg,HWNDhWnd,UINTwMsgFilterMin,UINTwMsgFilterMax).如果得到WM_QUIT返回0
TranslateMessage(&MSG)
DispathMessage(&MSG)
BeginPaint(&PAINTSTRUCT)
TextOut(HDC,INT,INT,LPSTR,INT)
EndPaint(HWND,&PAINTSTRUCT)
作业:
自己建立应用,在窗口100,100位置显示HelloWorld
第三课坐标位置及大小(4学时)
在我们写控制台应用的时候,不能自由的控制输出显示的位置。
因此,没有学习过这方面的内容,现在我们创建了窗口,并且在窗口上显示了HelloWorld。
这个过程涉及到很多涉及位置和大小的因素,如窗口的大小,显示的位置,文字显示的位置。
说到位置,就涉及定位,说到定位就要说坐标系。
在屏幕上显示内容涉及到坐标空间的知识。
在Windows应用中坐标空间分如下几部分内容
1、物理坐标空间
物理坐标空间,指的是物理设备上对应的坐标系。
如显示器
坐标原点在左上角。
如下是一个1024*768的屏幕物理坐标
(0,0)(1024,0)
(0,768)
2、设备坐标空间
基于设备上下文指定的坐标空间。
如窗口内显示的文本,使用的坐标就是基于窗口内上下文的坐标。
可以看到设备空间是物理空间体系的一个子空间。
设备空间可以依赖于一个窗口。
换句话可以把设备空间理解为在物理空间上显示的一个对象,其子空间。
下面我们通过一个小例子理解物理空间和设备空间
在窗口的标题条,以设备坐标,和物理坐标的形式显示鼠标在窗口内的位置
WndProc处理消息循环
WM_MOUSEMOVE,鼠标移动时消息标识,是个整数。
其参数lParam,的第16位代表设备坐标中的X,高16位代表设备坐标的Y。
POINT是结构体。
只有x,y两个成员
ClientToScreen,将设备坐标转换为屏幕坐标(物理坐标)
sprintf:
格式化字符串
SetWindowText:
设Window标题
3、页面坐标空间(逻辑坐标空间的一种)
作用,可以任意指定坐标原点,坐标轴方向,比例尺等信息。
可以用来与设备无关的大小如厘米,毫米等。
页面坐标叫窗口,其表示有原点(X,Y),宽度,高度组成(WIDTH,HEIGHT)
设备坐标叫视口,其表示有原点(x,y),宽度,高度组成(width,height)
页面坐标和设备坐标的变换关系,大写为设备坐标,小写为页面坐标
PX=X+(px-x)*WIDTH/width
PY=Y+(py-y)*HEIGHT/height
px=x+(PX-X)*width/WIDTH
py=y+(PY-Y)*heigh/HEIGHT
GDI函数使用页面坐标,显示出来时是设备坐标
通过对窗口,是否对应的四个参数的设置,可以实现特殊的变换。
页面坐标是逻辑坐标的一种。
在这个例子中我们一直使用
MoveToEx(ps.hdc,0,0,NULL);
LineTo(ps.hdc,30,30);
划线,MoveToEx是把画笔移动到指定位置(页面坐标),LineTo是从画笔所在位置到目标位置画一条线。
在这个例子中,每次划线前通过设置视口,窗口结果使划线的结果不同。
这种形式的坐标转换无法实现旋转
4、世界坐标空间(逻辑坐标空间的另一种)
功能:
比页面坐标空间方便,可以实现旋转
结构体
XFORM{
FLOATeM11,
FLOATeM12,
FLOATeM21,
FLOATeM21,
FLOATeDx,
FLOATeDy,
}
世界坐标到设备坐标的变换。
小写到大写。
PX=eM11*px+eM21*py+eDx;
PY=eM12*px+eM22*py+eDy;
默认为{1,0,0,1,0,0}和设备坐标相同
{1001dxdy}
{mx00my00}缩放
{-100-100}映像
旋转{cos(a),sin(a),-sin(a),cos(a),0,0}顺时针旋转a度
{cos(a),-sin(a),sin(a),cos(a),0,0}逆时针旋转a度
我们下面的例子通过Rectangle(ps.hdc,0,0,50,50);绘制50*50的矩形,用循环配合世界坐标变换绘制特殊的图形
循环20次,每次旋转坐标轴的方向,绘制正方形。
总结:
物理坐标指的是屏幕坐标,不能改变坐标轴
设备坐标指的是窗口坐标,不能改变坐标轴
页面坐标和世界坐标均是逻辑坐标,可以改变坐标轴,世界坐标功能更强,可以旋转。
理解这些概念的绘图是很重要的。
相关函数
BOOLClientToScreen(HWNDhWnd,LPPOINTlpPoint);
设备坐标转屏幕坐标
BOOLScreenToClient(HWNDhWnd,LPPOINTlpPoint);
屏幕坐标转设备坐标
intMapWindowPoints(HWNDhWndFrom,HWNDhWndTo,LPPOINTlpPoints,UINTcPoints);
各个窗口设备坐标之间的转换
BOOLSetWindowOrgEx(HDChdc,intX,intY,LPPOINTlpPoint);
设置窗口的原点
SetViewportOrgEx(HDChdc,intX,intY,LPPOINTlpPoint);
设置视口的原点
BOOLSetViewportExtEx(HDChdc,intnXExtent,intnYExtent,LPSIZElpSize);
设置视口的width,height
BOOLSetWindowExtEx(HDChdc,intnXExtent,intnYExtent,LPSIZElpSize);
设置窗口的width,height
SetMapMode设置页面坐标的映射模式
SetGraphicsMode设置世界坐标的映射模式
Rectangle绘制矩形,并填充内部
SetWorldTransform设置世界坐标变换
LineTo:
换线
MoveToEx:
移动画笔
SetWindowText设置窗口标题
LPtoDP(hdc,LPPOINT,int)把逻辑坐标点转换为设备坐标点
作业:
使用movetoex,lineto,LPtoDP及世界坐标变换,绘制正六边形
提示:
画一条水平线后,将坐标原点移动到线的末尾,并将坐标轴旋转60度*n,重复上步
要将坐标移动到线尾需要使用LPtoDP
第四课色彩及绘制(6学时)
(1)画点
像素:
计算机屏幕上的一个点。
是计算机屏幕显示的最小单位。
点的个数取决于计算机的分辨率。
如1024*768,则屏幕由1024*768个点组成。
每个点都可以独立的显示一个颜色。
计算机能够表示的颜色有256*256*256=16777216种。
颜色的表示COLORREF。
定义颜色RGB
COLORREFcolor=RGB(红,绿,蓝)
随机绘制颜色点
需要#include
srand:
随机种子函数,传递的参数不同,可以生成不同的随机数序列
GetTickCount():
API函数,得到系统开机后到现在的滴答数,特点就是每次返回的结果不重复。
两者的配合得到不重复的随机数序列
rand得到函数
SetPixel设置某点的颜色
(2)画线
在以前的例子里我们一直用1个像素宽的黑色实现来画线。
现在我们学习创建画笔,用画笔来画线。
步骤1、创建画笔CreatePen(画笔类型,宽度,颜色)
2、将画笔选入设备上下文SelectObject
3、用画笔绘制
4、将画笔选出设备
5、删除创建的画笔对象
SelectObject是将GDI对象画笔选入设备上下文,并将当前的选出返回。
因此我们两次使用SelectObject,最后一个将以前的画笔选入,返回我们创建的,并在下一步删除画笔。
虚线只能支持宽度1.
画线函数
Polygon(HDC,LPPOINT,INT).连接指定点,画多边形,封闭。
如果画4边形则确认3个点即可。
Polyline(HDC,LPPOINT,INT).连接指定点,画多边,不封闭
MoveToEx:
移动画笔
LineTo:
用当前的画笔划线
Arc:
画圆弧BOOLArc(HDChdc,intnLeftRect,intnTopRect,intnRightRect,intnBottomRect,intnXStartArc,intnYStartArc,intnXEndArc,intnYEndArc
);
前4个是画圆弧的矩形,后四个指定了弧开始和结束的位置
作业:
画一条正弦曲线
使用SexPixel,LineTo,MoveToEx实现
(3)画面
画面就是用画刷来填充
步骤
1、创建画刷CreateSolidBrush(颜色)
2、将画刷选入设备上下文SelectObject
3、用画刷填充
4、将画刷选出设备
5、删除创建的画刷对象
用蓝色画刷填充矩形,矩形的边框是黑色。
CreateSolidBrush:
创建颜色画刷
Rectangle:
绘制矩形,用当前的Pen绘制边框,用当前的Brush来填充矩形内部
FillRect:
画刷填充矩形。
FillRect(hdc,&RECT,HBRUSH)
使用FillRect不绘制边框,因为参数中有画笔,也不用SelectObject了。
Ellipse:
椭圆,圆。
画边框,填充
Pie:
圆饼
(4)位图
将文件系统中的位图显示到窗口中。
绘制位图步骤
1、根据现有的设备上下文创建兼容的设备上下文
2、加载位图
3、绘制图像
4、删除加载的位图
5、删除兼容的设备上下文
BitBlt是在设备上下文之间拷贝图像的函数,非常常用
在上一个列子的基础上,得到位图的大小并绘制实际大小的位图
作业:
在一个窗口上显示一副位图文件(*.bmp)。
(5)字体和文本
创建逻辑字体并显示文本
步骤
1、创建逻辑字体
2、选入字体
3、输出文本
4、选出字体
5、删除字体
另一个与文本绘制有关的功能更强的函数是DrawText
总结:
本课介绍了一些基本的绘图操作,其中涉及了较多的函数,这里只是介绍了基本的使用方式和原理。
函数
srand
rand
GetClientRect
SetPixel
LineTo
MoveToEx
CreatePen
CreateSolidBrush
CreateFontIndirect
BitBlt
SelectObject
DeleteObject
CreateCompatibleDC
LoadImage
Rectangle
FillRect
DeleteDC
等等。
第五课常用控件的使用(6学时)
在上面的几节课程中我们学习了如何建立Windows应用,并在图形环境下绘制图形。
这些操作都是控制台应用中没有的。
本章我们介绍如何在窗口中加入按钮等常规控件,并且处理它们。
一般控件种类,按钮,列表组合,编辑,列表,滚动条,静态文本。
控件是一种特殊的窗口。
这些特殊窗口的类已经由Windows系统注册了,不需要我们注册。
这些类的名字分别为。
BUTTON,COMBOBOX,EDIT,LISTBOX,SCROLLBAR,STATIC
(1)创建
任何时候均可,但通常在WM_CREATE事件中处理
WM_CREATE是在窗口创建时触发
WM_DESTORY是在窗口销毁时触发
控件用CreateWindow创建,返回控件窗体的句柄,窗体的类型一定为WS_CHILDWINDOW。
附加的类型以或关系叠加。
具体要参见MSDN
(2)操控
控制这些控件是通过向这些控件的窗体句柄发送特点消息来实现的
如SendMessage(控件句柄,消息指,参数1,参数2)具体设置参见MSDN
在上面的例子,我们处理下拉列表的时候使用了SendMessage发送消息
(3)反馈
我们操作控件会触发控件的事件得到一些反馈,下面介绍如何得到这些反馈。
总体上,我们把这些反馈过程叫通知。
通知的过程是将反馈发送给父窗体,一般父窗体有两个事件接收控件的反馈
WM_NOTIFY,WM_COMMAND。
WM_COMMAND
HIWORD(wParam)通知消息号
LOWORD(wParam)控件标识
WM_NOTIFY
wParam:
控件标识
lParam:
NHMDR的指针
比如按钮的单机对应的事件是BN_CLICKED。
该事件通过WM_COMMAND通知。
我们把上个例子补充完整,并且为每个控件指定ID,指定的方式是在(HMENU)的后面写个整数,原则上应该不同。
HIWORD,得到一个字的高字节。
LOWORD得到一个字的低字节。
(4)通用控件
我们上面介绍的是基本的控件,除了这些基本控件外还有一些通用控件。
这些控件的使用和处理和基本的控件差不多,但功能更强大。
ANIMATE_CLASS:
动画控件,播放AVI动画
DATETIMEPICK_CLASS:
日期时间下拉控件
HOTKEY_CLASS:
定义热键的控件
MONTHCAL_CLASS:
月份选择控件
PROGRESS_CLASS:
进度条控件
REBARCLASSNAME:
rebar控件
STATUSCLASSNAME:
状态条控件
TOOLBARCLASSNAME:
工具条
TOOLTIPS_CLASS:
提示控件
TRACKBAR_CLASS:
轨迹条
UPDOWN_CLASS:
上下箭头
WC_COMBOBOXEX:
组合框扩展
WC_HEADER:
头控件
WC_IPADDRESS:
IP地址控件
WC_LISTVIEW:
listview控件
WC_PAGESCROLLER:
页滚动控件
WC_TABCONTROL:
tabControl控件
WC_TREEVIEW:
树视图控件
通用控件在使用前使用InitCommonControlsEx初始化。
使用这些通用控件要include
同时在连接时要连接comctl32.dll
头部
这些控件和IE有关系,根据IE版本不同,控件的外观和功能有区别。
(5)创建菜单
CreateMenu:
创建一个菜单
CreatePopupMenu:
创建一个子菜单
AppendMenu:
向菜单增加项目
SetMenu:
将菜单联系到窗口
第六课进程及线程(2学时)
●进程:
是一个正在运行的程序的实例。
由两个部分组成
1、一个是操作系统用来管理进行的内核对象。
内核对象是系统用来存放关于进程信息的地方。
2、地址空间,每个进行都有自己的地址空间
进程本身不执行代码,进程要至少拥有一个线程,由线程来执行代码。
每个线程都拥有自己的CPU寄存器和堆栈。
当创建一个进程时系统会自动创建一个主线程。
CreateProcess创建进程
内部执行细节:
1创建一个小的结构存放进程信息
2分配地址空间
3创建一个小的结构存放线程信息
4执行C/C++启动代码,最终会调用WinMain或main。
结束一个进程TerminateProcess
TerminateProcess
1使用ToolHelp遍历系统进程
列举系统全部的进程
需要
#include
#include
usingnamespacestd;
●线程
线程由两个部分组成
1内核对象
2线程堆栈,用于维护执行代码时所有的函数参数和局部变量
进程是活波的,进程不执行任何东西,它是线程的容器。
线程在进程