版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
可视化程序设计第一部分API编程(第3章~第7章)第二部分MFC编程(第8章~第14章)VisualC++面向对象与可视化程序设计习题解析与编程实例(第2版)第3章Windows应用程序3.1Windows编程基础知识3.2Windows应用程序常用消息3.3Windows中的事件驱动程序设计3.4Windows应用程序的基本结构可视化集成开发环境(IDE)可视化集成开发环境VisualC++VisualBasicVisualJavaC++BuilderDelphiJBuilder√集成IDE源程序编辑器和编译器Debug系统函数库和系统函数开发工具资源管理器和资源编辑器可供选择的例程库(MFCAppWizard)联机帮助(MSDNLibrary)应用程序发布和安装工具Windows程序面向对象的程序=对象1+对象2+…Windows程序的规范部件(窗口、菜单、对话框、按钮、程序模块等)是对象,编程时相当一部份工作是创建对象和为对象属性赋值.对象之间通过消息互相通信VisualC++编程方法传统方法(API)Windows系统是一个很大的服务中心,调用它的各种服务(上千个API函数),可以帮助应用程序达到管理窗口、描绘图形、使用周边设备等目的.由于这些服务针对的对象是应用程序,所以称之为应用编程接口(API).交互式方法(MFC)MFC类库将API函数封装成一百多个类,程序员利用已定义好的类或自定义的类,来创建各类对象并确定对象的属性,从而搭建起应用程序的“框架”.进一步编写必要的细节代码,最后构成完整的应用程序.Windows编程的重要概念窗口事件驱动句柄消息窗口(Window)窗口是Windows应用程序的基本操作单元,是应用程序与用户交互的接口环境,也是系统管理应用程序的基本单位.编写Windows应用程序首先应创建一个或多个窗口.程序的运行过程也就是在窗口内部、窗口与窗口之间、窗口与系统之间进行数据处理与数据交换的过程.客户区事件驱动(EventDriven)传统的面向过程程序的流程遵从于程序员预先规定的路径,而Windows应用程序的执行顺序取决于事件的发生顺序(事件驱动)事件:对象可以识别的一个动作.例如,按下鼠标,按下/释放键盘键等.当一个事件发生时,系统会产生一条特定的消息,以标识该事件的发生.消息:传递信息或请求的数据包.例如,在窗口客户区按下鼠标左键时,将产生一条WM_LBUTTONDOWN消息.该消息包含虚键是否按下、光标坐标等信息.并非所有的消息都是由事件产生.有些消息是由系统发出的,有些消息是由函数调用产生的.WM_PAINT消息是由系统发出的.调用PostQuitMessage()会产生一条WM_QUIT消息.Windows程序的设计重点是编写消息处理代码.句柄(Handle)Avariablethatidentifiesanobject;anindirectreferencetoanoperatingsystemresource.句柄是一个用于标识对象的变量,具有4个字节的长度,用于标识应用程序中不同的对象或同类对象中不同的实例.应用程序通过句柄来访问它所标识的对象,并进行相应的操作.窗口按钮图标滚动条输出设备控制文件表3-1常用句柄类型及其说明句柄类型说明句柄类型说明HWND窗口句柄HDC设备环境句柄HINSTANCE应用实例句柄HBITMAP位图句柄HCURSOR光标句柄HICON图标句柄HFONT字体句柄HMENU菜单句柄HPEN画笔句柄HFILE文件句柄HBRUSH画刷句柄HGDIOBJGDI对象Win32API共有39种句柄类型.例3-1代码片断:HWNDhwnd;…;hwnd=CreateWindow(…);消息(Message)传递信息或请求的数据包.Messagescanbepassedbetweentheoperatingsystemandanapplication,differentapplications,threadswithinanapplication,andwindowswithinanapplication.消息队列(MessageQueue)队列是一种先进先出(FirstInFirstOut)的线性表,它允许在表的一端进行插入,而在另一端删除元素.消息队列:Anoperatingsystem-definedmemoryobjectthatholdsanorderedlistofmessagesawaitingprocessing.Thesystemmessagequeueholdsmouseandkeyboardinputwaitingtobepassedtoathread'smessagequeue.Athread'smessagequeueholdsmessageswaitingtoberetrievedbyathread'smessageloop.消息结构MSGtypedefstructtagMSG{
HWNDhwnd;//接收消息的窗口句柄
UINTmessage;//消息号,unsigned
int,每种消息都有相应的消息号
WPARAMwParam;//32位附加信息,取决于消息号
LPARAMlParam;//32位附加信息,取决于消息号
DWORDtime;//消息发送时间,32位unsigned
POINT
pt;//消息发送时光标的屏幕位置}MSG;typedefstructtagPOINT{
LONGx;
LONGy;
}POINT;例3-1代码片断:MSGMsg;…;while(…){…};消息的分类system-definedmessages每一个系统消息都有一个唯一的标识(消息号),不同类别的系统消息带有不同的前缀.WM消息涉及各种信息和请求,包括鼠标输入、键盘输入,菜单、对话框输入,窗口的创建和管理,动态数据交换(DDE).application-definedmessages如果一个应用定义了自己的消息,则接收窗口的消息处理过程必须对消息进行解释并提供适当的处理.前缀类别前缀类别BM按钮控件CB组合框控件DM下压式按钮控件EM编辑控件LB列表框控件SBM滚动条控件WM窗口共23类第3章Windows应用程序3.1Windows编程基础知识3.2Windows应用程序常用消息3.3Windows中的事件驱动程序设计3.4Windows应用程序的基本结构关闭窗口时发生了什么?按关闭按钮1.产生WM_CLOSE消息2.产生WM_DESTROY消息3.产生WM_QUIT消息调用PostQuitMessage函数4.终止应用第3章Windows应用程序3.1Windows编程基础知识3.2Windows应用程序常用消息3.3Windows中的事件驱动程序设计
过程驱动(图3-2)&事件驱动(图3-3)3.4Windows应用程序的基本结构Windows应用程序的基本结构Windows程序入口函数WinMain窗口处理函数(过程)WndProc完成一系列定义和初始化工作,并产生消息循环定义应用程序接收消息后如何进行响应函数调用时参数传递次序问题#include<iostream.h>voidf(intx,inty){ cout<<x<<'\t'<<y<<endl;//2 1}voidmain(){ inti=0; f(++i,++i);}表明VisualC++默认参数传递次序为右至左.①定义并注册“窗口类”typedefstruct_WNDCLASS{UINTstyle;//窗口类样式WNDPROClpfnWndProc;//指向窗口处理函数的指针
intcbClsExtra;//指定系统为窗口类结构分配和追加的附加内存intcbWndExtra;//指定系统为窗口实例分配和追加的附加内存HANDLEhInstance;//包含窗口处理过程的实例句柄HICONhIcon;//图标句柄HCURSORhCursor;//光标句柄HBRUSHhbrBackground;//背景画刷句柄(指定窗口客户区的背景)LPCTSTRlpszMenuName;
//字符指针,指向菜单资源名LPCTSTRlpszClassName;//字符指针,指向窗口类名}WNDCLASS;创建窗口前必须对窗口进行设计,指定窗口的特征.例3-1代码片断:
WNDCLASSwndclass;
对wndclass各成员赋值;光标HCURSORLoadCursor(HINSTANCEhInstance,//应用实例句柄(指定光标资源的来源)
//NULL表示使用系统预定义光标LPCTSTRlpCursorName//字符指针,指向
//光标名或光标资源(前缀为IDC_)标识);lpCursorName值说明IDC_APPSTARTING箭头+沙漏IDC_ARROW箭头IDC_CROSS十字IDC_HELP箭头+问号IDC_IBEAMI型IDC_NO带斜线的圆IDC_SIZEALL4方向的箭头……上机时修改光标共16种画刷(指定区域的背景颜色)HGDIOBJGetStockObject(intfnObject//GDI对象类型);返回一个“库存的”GDI对象(画笔、画刷、字体、调色板)句柄fnObject值说明BLACK_BRUSH黑刷DKGRAY_BRUSH黑灰刷GRAY_BRUSH灰刷HOLLOW_BRUSH,NULL_BRUSH空背景刷(透明)LTGRAY_BRUSH灰白刷WHITE_BRUSH白刷以下为画笔、字体、调色板的fnObject值例3-1代码片断:
wndclass.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH);上机时修改窗口客户区背景①定义并注册“窗口类”ATOMRegisterClass(CONSTWNDCLASS*lpWndClass//常量指针,指向要注册的窗口类(结构体变量)
//常量指针限制了指针的间接操作);若函数调用成功,返回非零值来唯一地标识已被注册成功的窗口类,否则返回0.ATOM:unsignedshort例3-1代码片断:
if(!RegisterClass(&wndclass))
{
MessageBeep(0);//注册失败时发出警告声音
returnFALSE;
}②创建并显示窗口HWNDCreateWindow(LPCTSTRlpClassName,//字符指针,指向已注册的窗口类名LPCTSTRlpWindowName,//字符指针,指向窗口标题名,有时用命令行参数DWORDdwStyle,//unsignedint,窗口样式(表3-5),不同于窗口类样式
//组合样式则按位或运算intx,//窗口左上角X坐标inty,//窗口左上角Y坐标intnWidth,//窗口宽度intnHeight,//窗口高度HWNDhWndParent,//父窗口句柄HMENUhMenu,//菜单句柄或子窗口标识HANDLEhInstance,//应用实例句柄LPVOIDlpParam//any类型指针,指向窗口创建的数据);若函数调用成功,返回一个新窗口句柄.调用该函数将发送一个WM_CREATE消息,WM_CREATE消息是不入队的.窗口样式(表3-5)窗口样式(表3-5续)例3-1创建窗口代码片断HWNDhwnd;WNDCLASSwndclass;
hwnd=CreateWindow(lpszClassName,//已注册的窗口类名lpszTitle,//窗口标题名My_Windows//有时用命令行参数lpCmdLineWS_OVERLAPPEDWINDOW,//窗口样式CW_USEDEFAULT,//左上角坐标CW_USEDEFAULT,//左上角坐标CW_USEDEFAULT,//高度CW_USEDEFAULT,//宽度NULL,//无父窗口NULL,//无菜单hInstance,//应用实例句柄NULL//无其他参数);上机时修改窗口样式②创建并显示窗口显示窗口
BOOLShowWindow(
HWNDhWnd,//窗口句柄
int
nCmdShow
//窗口的显示状态(表3-6)
);
第2个参数既可以是系统分配的值(P77),也可以是表3-6中的值.发送WM_PAINT消息刷新窗口客户区,WM_PAINT消息是不入队消息.
BOOLUpdateWindow(
HWNDhWnd
//窗口句柄
);窗口的显示状态(表3-6)上机时修改窗口的显示状态③产生消息循环建立消息循环的目的是要不断地从消息队列中取回消息,并将消息传递给窗口处理函数.消息循环的一般格式:
MSGMsg;
while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}GetMessage函数从消息队列中取回一条消息,并将该消息的相关信息保存在lpMsg指向的MSG结构中.wMsgFilterMin、wMsgFilterMax都取0时,表示不过滤消息.仅当收到WM_QUIT消息(调用PostQuitMessage函数将产生),函数才返回0,此时消息循环的条件才为假.在收到WM_QUIT消息前,消息循环不会退出,程序始终处于运行状态.BOOLGetMessage(
LPMSGlpMsg, //指向MSG结构体变量
//取回的消息信息保存在结构体变量中
HWNDhWnd, //窗口句柄,指定接收属于哪个窗口的消息 //NULL表示接收调用线程所有窗口消息
UINTwMsgFilterMin,//用于消息过滤的最小消息号
UINTwMsgFilterMax//用于消息过滤的最大消息号
);TranslateMessage函数将按键消息转换成字符消息.字符消息将再次投递到消息队列中.尽管按键消息提供了许多有关键的基本信息,但不提供字符键的字符码.如果想要得到字符码,应用程序必须在线程循环中包含TranslateMessage函数.怎么才能得到字符键的字符码?BOOLTranslateMessage(CONSTMSG*lpMsg//指向MSG结构体变量);按键消息Msg字符消息①GetMessage()③GetMessage()②TranslateMessage()DispatchMessage函数分派一个消息到窗口处理函数(过程),以便对消息作出适当的响应.实际上DispatchMessage函数是将消息回传给操作系统,操作系统再调用窗口处理函数对消息进行处理.LONGDispatchMessage(CONSTMSG*lpmsg//指向MSG结构变量);操作系统消息队列应用程序窗口处理①消息入队②GetMessage()③DispatchMessage()④
调用对消息循环的理解MSGMsg; //定义结构体变量存放消息信息while(GetMessage(&Msg,NULL,0,0)){
TranslateMessage(&Msg);
DispatchMessage(&Msg);}取回的消息信息存放于Msg中按键消息转换成字符消息字符消息重新入队发送至窗口处理函数窗口处理函数WndProc LRESULTCALLBACKWndProc(
HWNDhwnd,//窗口句柄,指定对哪个窗口的消息做处理
UINTuMsg,//待处理的消息号
WPARAMwParam,//待处理消息的第1个附加信息参数
LPARAMlParam//待处理消息的第2个附加信息参数
)
{
多分支选择结构;
}函数的返回类型LRESULT即long.窗口处理函数是CALLBACK函数,它不是由WinMain函数调用的,而是由系统调用.函数名可以随意取,但要注意前后一致.指定函数调用规则窗口处理函数调用示意LRESULTCALLBACKWndProc( HWNDhwnd, UINTuMsg, WPARAMwParam, LPARAMlParam){……}DispatchMessage(&Msg)typedefstructtagMSG{
HWNDhwnd;UINTmessage;
WPARAMwParam;
LPARAMlParam;
DWORDtime;
POINTpt;
}MSG;Msg系统窗口处理函数体的一般格式LRESULTCALLBACKWindowProc(HWNDhwnd,
UINTuMsg,WPARAMwParam,LPARAMlParam)
{
switch(uMsg)//uMsg为待处理的消息号(unsignedint){case消息1:处理代码;
case消息2:处理代码;
caseWM_DESTROY://Thismessageissentwhen //awindowisbeingdestroyed
PostQuitMessage(0);//产生WM_QUIT消息 //GetMessage函数返回0
//退出消息循环,应用终止
default://对未定义处理的其他消息提供默认处理
//保证所有分派过来的消息均得到处理
returnDefWindowProc(hwnd,uMsg,wParam,lParam);}上机时修改例3-1的窗口处理函数,实现在窗口客户区按下鼠标左键时终止程序.例3-1基本结构今后主要的修改位置#include<windows.h>//数据类型、数据结构、API函数的定义LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);//函数声明intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance, LPSTRlpCmdLine,intnCmdShow){①定义并注册窗口类;②创建并显示窗口;③产生消息循环;returnMsg.wParam;//只要返回1个整数就可以}LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage, WPARAMwParam,LPARAMlParam){switch(message){//case其他消息:…;break;caseWM_DESTROY: PostQuitMessage(0);default: returnDefWindowProc(hwnd,message,wParam,lParam);}return(0);}第4章Windows的图形设备接口及Windows绘图4.1图形设备接口4.2绘图工具与颜色4.3常用绘图函数4.4应用实例4.5小结图形设备接口(GDI)对于涉及图形输出的Windows应用,如果让应用程序直接与硬件设备打交道,则程序员必须了解各种输出设备的细节.GDI是应用程序与输出设备之间的中介一方面,GDI向应用程序提供了一个与设备无关的编程环境.另一方面,GDI通过设备驱动程序实现图形输出.应用程序GDI屏蔽了硬件设备的差异性,使应用程序与设备无关驱动程序绘图操作过程应用程序×Windows系统不允许应用程序直接访问外部设备应用程序DCGDI驱动程序外设Windows系统提供了一个统一的设备环境,通过它使应用程序与外设相连DC应用程序的每一次图形操作均参照DC的属性执行,并可通过HDC更改它的属性设备描述表(DeviceContext)设备描述表(设备环境,设备上下文,DC)是一组属性的集合(结构体类型),属性集包括:一组图形对象各图形对象的相关属性影响输出的图形模式物理输出设备的信息(设备名、驱动程序等)图形输出的主要任务是创建和维护一个设备描述表.图形对象及其属性图形对象属性位图字节数、尺寸(像素)、颜色格式、压缩方案等画刷样式、颜色、填充图案、起始点调色板颜色、颜色号字体字体名、宽度、高度、磅值、字符集等画笔样式、宽度、颜色区域位置、尺寸Whenanapplicationcreatesadevicecontext,thesystemautomaticallystoresasetofdefaultobjectsinit.AnapplicationcanexaminetheattributesofthedefaultobjectsbycallingtheGetCurrentObject
andGetObjectfunctions.Theapplicationcanchangethesedefaultsbycreatinganewobjectandselectingitintothedevicecontext.AnobjectisselectedintoadevicecontextbycallingtheSelectObjectfunction.图形模式表4-2中能否发现上述5种图形模式?设备描述表类型窗口管理在窗口中绘画、绘图、写文本是Windows应用常见的数据输出方式.多任务操作系统意味着可能有多个应用同时在运行,导致屏幕中出现多个窗口.为了确保程序的平滑运行以及应用之间的相互协调,系统要对屏幕中的各种输出统一管理.窗口是应用程序(对显示类型而言)的主要输出设备.对每一个窗口,系统都提供一个唯一的DC.利用DC,应用程序将它的输出引导至相应的窗口中.窗口DC窗口刷新下列情况要对窗口进行刷新:首次创建窗口改变窗口大小移动窗口将窗口从下层移至顶层对象穿越窗口最小化窗口最大化窗口显示文件中的数据滚动数据改变数据选中数据如果不刷新需要恢复的区域底层窗口被顶层窗口覆盖当底层窗口置于顶层时,需要恢复被覆盖区域的颜色和形状刷新请求下列事件发生时,窗口客户区内容需要被刷新窗口移动:窗口移动或显示,改变窗口大小,滚动窗口.去除覆盖:关闭下拉式菜单,消除对话框或消息框等对象.对象穿越:光标穿过用户区,图标拖过用户区.针对刷新请求,如果线程消息队列为空,系统直接发送WM_PAINT消息至窗口处理过程,以通知窗口函数执行刷新处理.刷新请求的优先级别低.WM_PAINT消息是不入队消息(不进入线程消息队列).教材P84第3段叙述有错误.注意:WM_PAINT消息是由系统产生,要等应用程序的消息队列(线程消息队列)为空时才发送WM_PAINT消息.系统对刷新请求的响应窗口移动后的刷新被覆盖区域的刷新对象穿越后的刷新(系统自动完成)标记待刷新的区域当消息队列为空时,系统直接发送WM_PAINT消息至窗口处理过程执行刷新(默认处理)DefWindowProc()有些刷新要由应用自己维护有些刷新是由应用程序自已管理的.例如,显示文件、选择数据等,对这些刷新请求有2种处理方式:标记待刷新的区域发送WM_PAINT消息至窗口处理过程处理WM_PAINT消息发送其他消息入列从队列中取回消息并发送至窗口处理过程处理消息只有在队列中没有其他消息的情况下,系统才会发送WM_PAINT消息,导致第1种方式可能会存在一些延时,此时可考虑第2种方式.如果想在窗口中绘图,最好采用第1种方式.12例4-1例4-1对WM_PAINT消息的处理
caseWM_PAINT:
hDC=BeginPaint(hWnd,&PtStr);//获得DC句柄
SetMapMode(hDC,MM_ANISOTROPIC);//设置各向异性映射模式
hPen=(HPEN)GetStockObject(BLACK_PEN);//画笔,多余!
hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH);//画刷
SelectObject(hDC,hBrush);//选择画刷
SelectObject(hDC,hPen);//选择画笔,多余!
RoundRect(hDC,50,120,100,200,15,15);//圆角矩形
hBrush=(HBRUSH)GetStockObject(LTGRAY_BRUSH);//画刷
SelectObject(hDC,hBrush);//选择画刷
Ellipse(hDC,150,50,200,150);//椭圆
hBrush=(HBRUSH)GetStockObject(HOLLOW_BRUSH);//画刷
SelectObject(hDC,hBrush);//选择画刷
Pie(hDC,259,50,300,100,250,50,300,50);//饼形
EndPaint(hWnd,&PtStr);//释放DC
return0;例4-1中的WM_PAINT消息新建窗口后更新窗口客户区,系统会发送WM_PAINT消息.
hWnd=CreateWindow(...);
if(!hWnd)
returnFALSE;
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);当窗口内容发生改变时,系统也会发送WM_PAINT消息.修改后的例4-1不处理WM_PAINT消息对WM_LBUTTONDOWN消息的处理代码如下:
caseWM_LBUTTONDOWN:
hDC=GetDC(hWnd);
SetMapMode(hDC,MM_ANISOTROPIC);
hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH);
SelectObject(hDC,hBrush);
RoundRect(hDC,50,120,100,200,15,15);
hBrush=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
SelectObject(hDC,hBrush);
Ellipse(hDC,150,50,200,150);
hBrush=(HBRUSH)GetStockObject(HOLLOW_BRUSH);
SelectObject(hDC,hBrush);
Pie(hDC,259,50,300,100,250,50,300,50);
ReleaseDC(hWnd,hDC);
return0;修改后的例4-1运行情况程序运行后并没有立即绘图鼠标左击时绘图,但图形不能自动刷新刷新常用的方法保存副本刷新时将副本拷贝到相应的窗口中,适合于刷新复杂图形.记录事件刷新时重新执行这个事件.重新绘制如果绘制的图形比较简单,可以将绘图代码放在WM_PAINT消息的响应模块中,一旦需要刷新,系统将发送WM_PAINT消息.用最小矩形标记待刷新区域交集用最小矩形标记待刷新区域用最小矩形标记待刷新区域最小矩形获取设备环境的三种方法调用BeginPaint函数调用GetDC函数调用GetDCEx函数BeginPaint函数HDCBeginPaint(HWNDhwnd,//窗口句柄LPPAINTSTRUCTlpPaint//PAINTSTRUCT类型指针);通知指定的窗口准备进行绘画,并填写一个带有裁剪区(最小矩形)信息的PAINTSTRUCT结构.函数调用成功,返回一个显示型DC句柄;函数调用失败,返回NULL,表示无可用的DC.该函数只能出现在WM_PAINT消息的处理模块中.绘图完成后,需要调用EndPaint函数释放获取的设备环境.
BOOLEndPaint(HWNDhWnd,PAINTSTRUCT*lpPaint);
设备环境窗口PAINTSTRUCT结构PAINTSTRUCT结构矩形结构(P75)
typedef
struct_RECT{
LONGleft;//左上角x坐标
LONGtop;//左上角y坐标
LONGright;//右下角x坐标
LONGbottom;//右下角y坐标
}RECT;PAINTSTRUCT结构
typedef
struct
tagPAINTSTRUCT{
HDChdc;//显示型DC句柄
BOOLfErase;//是否擦除背景,真表示擦除
RECT
rcPaint;//裁剪区域(限制输出只能在裁剪区内)
BOOLfRestore;//系统保留
BOOLfIncUpdate;//系统保留
BYTErgbReserved[32];//系统保留
}PAINTSTRUCT;GetDC/GetDCEx函数HDCGetDC(HWNDhWnd//窗口句柄);没有限定函数调用位置,可以在非WM_PAINT消息的响应模块中使用.释放DCint
ReleaseDC(HWND
hWnd,HDChDC);HDCGetDCEx(HWNDhWnd,//窗口句柄HRGNhrgnClip,//裁剪区句柄DWORDflags//unsignedint,指定DC创建方式);缩放平移旋转切变反射映射模式(Mappingmode)程序员绘图是在一个统一的逻辑坐标系中进行的,而实际图形输出依赖于设备坐标系,两者间存在坐标系的转换问题.映射模式定义了基于逻辑坐标系的图形与实际输出效果之间的关系.映射模式(续)窗口:对应逻辑坐标系上程序员设定的区域.视口:对应实际输出设备上程序员设定的区域.窗口、视口可以调用相关函数进行设置.窗口、视口只有在MM_ANISOTROPIC(各向异性)映射模式和MM_ISOTROPIC(各向同性)映射模式下才有意义.MM_ANISOTROPIC不改变视口尺寸,导致窗口中画的图形在视口中发生了变化MM_ISOTROPIC强制改变视口尺寸,从而窗口中画的图形在视口中进行了等比例的缩放窗口视口程序员设定的视口实际视口与映射模式有关的函数设置映射模式
int
SetMapMode(
HDChdc,//DC句柄
int
fnMapMode
//映射模式(表4-4)
);
函数调用成功,返回前一次的映射模式;否则返回0.获取当前的映射模式
int
GetMapMode(
HDChdc
//DC句柄
);设置窗口、视口区域设置窗口区域
BOOLSetWindowExtEx(
HDChdc,//DC句柄
int
nXExtent,//窗口宽度
int
nYExtent,//窗口高度
LPSIZElpSize
//原窗口尺寸(SIZE类型指针)
);设置视口区域
BOOLSetViewportExtEx(
HDChdc,
int
nXExtent,
int
nYExtent,
LPSIZElpSize
);typedefstructtagSIZE{LONGcx;LONGcy;}SIZE;设置窗口、视口原点设置窗口原点
BOOLSetWindowOrgEx(
HDChdc,
intX,//新原点x坐标
intY,//新原点y坐标
LPPOINTlpPoint
//Point类型指针,保存原原点坐标
);设置视口原点
BOOLSetViewportOrgEx(
HDChdc,
intX,
intY,
LPPOINTlpPoint
);typedefstructtagPOINT{
LONGx;
LONGy;
}POINT;第4章Windows的图形设备接口及Windows绘图4.1图形设备接口4.2绘图工具与颜色4.3常用绘图函数4.4应用实例4.5小结画笔获取系统提供的画笔
HPENhP;//画笔句柄
hP=(HPEN)GetStockObject(BLACK_PEN);创建自定义画笔
HPENhP;
hP=CreatePen(...);将画笔选入DC
HGDIOBJSelectObject(
HDChdc,
HGDIOBJhgdiobj
//已创建的对象句柄
);删除画笔
BOOLDeleteObject(
HGDIOBJhObject
//图形对象句柄
);WHITE_PENDC_PENHPENCreatePen(
intfnPenStyle,//样式(表4-5)
intnWidth,//线型
COLORREFcrColor//颜色
);画刷获取系统提供的画刷
HBRUSHhBr;
hBr=(HBRUSH)GetStockObject(BLACK_BRUSH);创建自定义画刷
HBRUSHhBr;
hBr=CreateSolidBrush(...);//单色画刷
hBr=CreateHatchBrush(...);//带阴影图案画刷表4-6HBRUSHCreateSolidBrush(
COLORREFcrColor//画刷颜色
);HBRUSHCreateHatchBrush(
intfnStyle,//阴影样式(表4-7)
COLORREFclrref//画刷颜色
);将画刷选入DC删除画刷颜色Windows用32位无符号整数值表示一种颜色.Windows使用宏RGB定义颜色.
COLORREFRGB(
BYTEbRed,//红色值
BYTEbGreen,//绿色值
BYTEbBlue
//蓝色值
);
返回一种用32位表示的颜色.00~2550~2550~25532位第4章Windows的图形设备接口及Windows绘图4.1图形设备接口4.2绘图工具与颜色4.3常用绘图函数4.4应用实例4.5小结设置画笔当前位置BOOLMoveToEx(
HDChdc,//DC句柄
intX,//新位置x坐标
intY,//新位置y坐标
LPPOINTlpPoint//Point类型指针,用于保存前一次的位置
);直线从当前位置到目标位置的直线
BOOLLineTo(//教材P91函数名有错误
HDChdc,//DC句柄
int
nXEnd,//目标点x坐标
int
nYEnd
//目标点y坐标
);依次连接POINT数组中的各点(画一组直线)
BOOLPolyline(
HDChdc,//DC句柄
CONSTPOINT*lppt,//POINT指针,指向POINT数组
//每个数组元素表示一个点
int
cPoints
//数组中的点数(>=2)
);五角星示例longWINAPIWndProc(...){PAINTSTRUCTps;HDChdc;POINTaptStar[6]={{50,2},{2,98},{98,33},{2,33},{98,98},{50,2}};switch(iMessage){caseWM_PAINT:hdc=BeginPaint(hWnd,&ps);
Polyline(hdc,aptStar,6);EndPaint(hWnd,&ps);return0;caseWM_DESTROY:PostQuitMessage(0);return0;default:return(DefWindowProc(hWnd,iMessage,wParam,lParam));}}椭圆弧BOOLArc(
HDChdc,//DC句柄
intx1,inty1,//左上角坐标
intx2,inty2,//右下角坐标
intx3,inty3,//用于确定弧的起始点
intx4,inty4//用于确定弧的终止点
);(x1,y1)(x2,y2)(x3,y3)(x4,y4)饼图(椭圆扇面,被填充)BOOLPie(
HDChdc,//DC句柄
intx1,inty1,//左上角坐标
intx2,inty2,//右下角坐标
intx3,inty3,//用于确定弧的起始点
intx4,inty4//用于确定弧的终止点
);(x1,y1)(x2,y2)(x3,y3)(x4,y4)矩形、圆角矩形(被填充)BOOLRectangle(
HDChdc,
intx1,inty1,//左上角坐标
intx2,inty2//右下角坐标
);BOOLRoundRect(
HDChdc,
intx1,inty1,//左上角坐标
intx2,inty2,//右下角坐标
int
nWidth,//圆角宽度
int
nHeight
//圆角高度
);椭圆(被填充)BOOLEllipse(
HDChdc,
intx1,inty1,
intx2,inty2
);多边形(被填充)BOOLPolygon(
HDChdc,
CONSTPOINT*lpPoints,//指向顶点数组
intnCount//顶点数,>=2
);第4章Windows的图形设备接口及Windows绘图4.1图形设备接口4.2绘图工具与颜色4.3常用绘图函数4.4应用实例例4-1、例4-3程序结构相同,均是响应WM_PAINT消息例4-2除了响应WM_PAINT消息外,还用到了鼠标左击与右击4.5小结例4-2初始映射模式为MM_TEXT,鼠标左击更改为MM_ISOTROPIC,同时刷新用户区;鼠标右击为MM_ANSIOTROPIC,同时刷新用户区.指定刷新区域
BOOLInvalidateRect(
HWNDhWnd,//窗口句柄
CONSTRECT*lpRect,//RECT结构指针,指定哪块区域
//要被刷新,NULL为整个客户区
BOOLbErase
//TRUE表示刷新时擦除背景
);调用BeginPaint函数时,系统填写一个带有裁剪区信息的PAINTSTRUCT结构.调用InvalidateRect函数又指定了一块刷新区域,这些区域将合并成新的刷新区域.调用InvalidateRect函数后将触发WM_PAINT消息.例4-2intnMode=MM_TEXT;//全局变量存放映射模式LRESULTCALLBACKWndProc(...){HDChdc;PAINTSTRUCTps;HBRUSHhB1,hB2;switch(message){caseWM_LBUTTONDOWN:
nMode=MM_ISOTROPIC;InvalidateRect(hwnd,NULL,1);break;caseWM_RBUTTONDOWN:
nMode=MM_ANISOTROPIC;InvalidateRect(hwnd,NULL,1);break;caseWM_PAINT:hdc=BeginPaint(hwnd,&ps);
SetMapMode(hdc,nMode);
break;...}}例4-2运行情况MM_TEXT模式MM_ISOTROPIC模式MM_ANSIOTROPIC模式习题4-9在窗口中使用定时器,每隔1秒,交替地用红色、绿色和蓝色的画刷来填充整个窗口客户区.设置定时器(定时触发WM_TIMER消息)
UINTSetTimer(
HWNDhWnd,//窗口句柄,指定定时器与窗口关联
UINTnIDEvent,//定时器标识,非0整数
UINTuElapse,//时间间隔,单位毫秒
TIMERPROClpTimerFunc
//指向WM_TIMER消息处理过程
//若为NULL,则消息入队
);
函数调用成功,返回定时器标识,否则返回0.释放定时器
BOOLKillTimer(
HWNDhWnd,//与定时器相关联的窗口句柄
UINTuIDEvent
//定时器标识,指明释放哪个定时器
);源代码如何显示动画效果?SetTimer()WM_TIMER消息WM_PAINT消息InvalidateRect()画图①②③④⑤例:正方形沿客户区边框顺时针方向移动左击时移动,右击时停止源代码staticUINTTimerID;HDChdc;PAINTSTRUCTps;staticRECTrc;staticLONGx1,x2,y1,y2,step;switch(message){caseWM_CREATE: GetClientRect(hWnd,&rc); x1=0;y1=0;x2=40;y2=40; step=(rc.right-rc.left)/200;break;caseWM_LBUTTONDOWN: TimerID=SetTimer(hWnd,1,5,NULL);break;caseWM_RBUTTONDOWN: KillTimer(hWnd,TimerID);break;caseWM_TIMER: InvalidateRect(hWnd,NULL,true);break;caseWM_PAINT: hdc=BeginPaint(hWnd,&ps); Rectangle(hdc,x1,y1,x2,y2); if(x2<rc.right&&y2<=40)//上边界
{x1=x1+step;x2=x2+step;} if(x2>=rc.right&&y2<rc.bottom)//右边界
{y1=y1+step;y2=y2+step;} if(y2>=rc.bottom)//下边界
{x1=x1-step;x2=x2-step;} if(x1<=rc.left)//左边界
{y1=y1-step;y2=y2-step;} EndPaint(hWnd,&ps);break;
……第5章文本的输出方法与字体的设置5.1设置文本的设备环境5.2文本的输出过程5.3文本操作实例5.4小结文本输出文本与图形没有明显的界限,某种意义上任何内容都可看成是图形实体.因此,可以使用GDI进行文本输出.文本输出的关键问题字体的选择(系统提供的字体或用户自定义的字体)格式化文本将文本在窗口客户区画出来字体字体:字符、符号构成的集合.字体是一种图形对象.同一种字体具有相同的设计风格.不同的字体在大小、形态上有所不同.字体字体36号黑体36号楷体获取字体定义字体句柄
HFONThF;获得字体句柄
hF=(HFONT)GetStockObject(字体);字体说明ANSI_FIXED_FONTANSI等宽字体ANSI_VAR_FONTANSI变宽字体DEVICE_DEFAULT_FONT与设备相关的字体DEFAULT_GUI_FONT默认GUI字体OEM_FIXED_FONTOEM(原始设备制造商)提供的等宽字体SYSTEM_FONT系统字体,DC的默认值SYSTEM_FIXED_FONT系统等宽字体除了系统提供的字体外,用户还能创建自定义字体.
hF=CreateFont(...);创建逻辑字体HFONTCreateFont(
intnHeight,//字体高度
intnWidth,//平均字符宽度
intnEscapement,//行角度
intnOrientation,//字符角度
intfnWeight,//字体粗细
DWORDfdwItalic,//是否倾斜
DWORDfdwUnderline,//下划线标志
DWORDfdwStrikeOut,//删除线标志
DWORDfdwCharSet,//字符集
DWORDfdwOutputPrecision,//输出精度
DWORDfdwClipPrecision,//裁剪精度
DWORDfdwQuality,//输出质量
DWORDfdwPitchAndFamily,//间距与字体系列
LPCTSTRlpszFace//指向字体名);将字体选入设备环境 HDChdc;
...
SelectObject(hdc,hF);系统提供的DC具有默认的SYSTEM_FONT,只有更改为其他字体或用户自定义的字体后,才应该将这种字体选入DC.文本输出完成后,应该删除字体.
DeleteObject(hF);文本颜色、背景颜色设置文本颜色
COLORREFSetTextColor(
HDChdc,
COLORREFcrColor
//文本颜色
);设置背景颜色
COLORREFSetBkColor(
HDChdc,
COLORREFcrColor
//背景颜色
);格式化文本第5章文本的输出方法与字体的设置5.1设置文本的设备环境5.2文本的输出过程5.3文本操作实例5.4小结获取字体信息正式输出文本之前,程序员可以获取当前正在使用的字体的信息,为后续工作做准备.系统定义了一个TEXTMETRIC(文本度量,简称TM)结构,用于保存字体的基本信息.
typedef
struct
tagTEXTMETRIC{//P106
...
}TEXTMETRIC;获取字体信息
BOOLGetTextMetrics(
HDChdc,//DC句柄
LPTEXTMETRIClptm
//TEXTMETRIC类型指针
);
将DC中的字体对象的信息填充到TEXTMETRIC中TEXTMETRIC结构typedefstructtagTEXTMETRIC{LONGtmHeight; //字符高度LONGtmAscent;LONGtmDescent;LONGtmInternalLeading;LONGtmExternalLeading;//行距LONGtmAveCharWidth;//平均字符宽度LONGtmMaxCharWidth;LONGtmWeight;LONGtmOverhang;LONGtmDigitizedAspectX;LONGtmDigitizedAspectY;BCHARtmFirstChar;BCHARtmLastChar;BCHARtmDefaultChar;BCHARtmBreakChar;BYTEtmItalic;BYTEtmUnderlined;BYTEtmStruckOut;BYTEtmPitchAndFamily;BYTEtmCharSet;}TEXTMETRIC;格式化文本格式化文本包括对齐方式、字符间距、行距、字体颜色、背景颜色等.进行文本输出时,程序员还需考虑待输出字符串的起始位置.而起始位置的计算可能与当前正在使用的字体信息以及与前次输出的字符串宽度、高度有关.计算字符串的宽度和高度
BOOLGetTextExtentPoint32(
HDChdc,
LPCTSTRlpString,//字符指针,指向字符串
int
cbString,//选定的字符数
LPSIZElpSize
//SIZE类型指针,计算的字符串宽度 //和高度存放在一个SIZE结构中
);typedefstructtagSIZE{
LONGcx;
LONGcy;
}SIZE;文本输出在指定位置输出字符串
BOOLTextOut(
HDChdc,
int
nXStart,//起始x坐标
int
nYStart,//起始y坐标
LPCTSTRlpString,//字符指针,指向待输出的字符串
int
cbString
//指定输出字符数
//输出整个串:lstrlen(lpString)
);例HDChdc;PAINTSTRUCTps;char*str1="这是我的第一个字符串";char*str2="第二个字符串";char*str3="这是我的第三个字符串";intx=0,y=0;TEXTMETRICtm;//存放字体信息SIZEsize;//存放字符串的宽度与高度switch(message){caseWM_PAINT:hdc=BeginPaint(hwnd,&ps);TextOut(hdc,x,y,str1,strlen(str1));//输出第一个字符串
GetTextMetrics(hdc,&tm);//获取当前字体信息
y=y+tm.tmHeight+tm.tmExternalLeading;//字符高度+行距
TextOut(hdc,x,y,str2,strlen(str2));//输出第二个字符串
//计算第二个串的宽度与高度
GetTextExtentPoint32(hdc,str2,strlen(str2),&size);x=x+size.cx+tm.tmAveCharWidth;TextOut(hdc,x,y,str3,strlen(str3));//输出第三个字符串
EndPaint(hwnd,&ps);break;...第5章文本的输出方法与字体的设置5.1设置文本的设备环境5.2文本的输出过程5.3文本操作实例5.4小结例5-1字符高度+行距平均字符宽度TEXTMETRIC例5-1源代码staticlongnXChar,nYChar;
HDChDC;shortx;
TEXTMETRICtm;//存放字体信息shortLnCount=6;PAINTSTRUCTPtStr;staticchar*textbuf[]={...};switch(message){caseWM_CREATE:hDC=GetDC(hWnd);GetTextMetrics(hDC,&tm);nXChar=tm.tmAveCharWidth;nYChar=tm.tmHeight+tm.tmExternalLeading;ReleaseDC(hWnd,hDC);break;caseWM_PAINT:hDC=BeginPaint(hWnd,&PtStr);for(x=0;x<LnCount;x++)TextOut(hDC,nXChar,nYChar*(1+x),textbuf[x],lstrlen(textbuf[x]));EndPaint(hWnd,&PtStr);break;...}第6章Windows应用程序对键盘与鼠标的响应6.1键盘在应用程序中的应用6.2键盘操作应用举例6.3鼠标在应用程序中的应用4.4鼠标应用程序实例6.5小结扫描码&虚拟码键盘上每一个键都对应着一个唯一值,这个值称之为扫描码.扫描码是设备相关的,用户按下(或释放)键时由键盘硬件产生,用来标识不同的键.为了实现应用程序与设备的无关性,应用程序往往使用的是与设备无关的虚拟码(Virtual-KeyCodes).虚拟码是由系统定义的并与设备无关的键标识(表6-1).扫描码、虚拟码之间存在着一种映射关系,键盘驱动程序负责解释扫描码并把它转换成相应的虚拟码.扫描码虚拟码某个键驱动程序键盘输入模型扫描码、虚拟码和其他按键信息键盘设备被所有的应用、所有的窗口共享.因此,需要解决按键消息(按下或释放键时产生)投往哪个线程消息队列的问题.每个窗口都有一个标明它是否被键盘聚焦的属性,按键消息将投递到获得了键盘焦点的窗口所对应的应用消息队列中.被键盘聚焦的窗口与活动窗口有一定关系.活动窗口是(最上层的)用户正在操作的窗口.键盘聚焦的窗口或者是活动窗口,或者是活动窗口的子窗口.为了帮助辨别活动窗口,系统高亮它的标题栏及边框.一旦窗口获得了键盘焦点,它将收到WM_SETFOCUS消息.一旦窗口失去了键盘焦点,它将收到WM_KILLFOCUS消息.App1App2键盘消息尽管按键消息提供了按键的一些基本信息,但它不提供字符键的字符码.如果想要得到字符码,应用程序必须在线程消息循环中调用TranslateMessage函数.键盘消息①按键消息:按下或释放键时产生②字符消息:按键DOWN消息经TranslateMessage函数转换后产生①按键消息系统按键消息在按下Alt键的同时,按下/释放其他键将产生的消息.系统键主要被系统使用,利用它可以为菜单提供内置键盘接口,或允许用户控制哪一个窗口处于活动状态.一般情况下,用户不必自己处理系统按键消息,而是交给系统自动处理(DefWindowProc函数).非系统按键消息非系统键被应用窗口使用.非系统按键消息由用户自行处理的,除非你忽略它.DefWindowProc函数不会对非系统按键消息做任何处理.KEYUP与KEYDOWN消息通常成对出现.但如果用户按下键后呆足够长时间的话,系统会产生一系列KEYDOWN事件,而用户释放键时只会产生一条KEYUP消息.按键消息系统按键消息非系统按键消息WM_SYSKEYDOWNWM_SYSKEYUPWM_KEYDOWNWM_KEYUP按键消息中的附加信息参数wParam:虚拟键码(编程时会用到)lParam:15~023~162428~25293031重复次数扫描码扩充键标志是否含有附加键系统保留上下文标志Alt是否按下前键状态标志,指明该键原来是down还是up状态转换标志,指明该消息是按下还是释放产生的对非系统按键消息的处理对于非系统按键消息,用户通常只须处理非字符键,这些键主要包括:功能键(F1~F12)、光标移动键(↑、↓、←、→)、Insert、Delete、Home、End等caseWM_KEYDOWN: //非系统键按下产生的消息switch(wParam) //不同的键有不同的虚拟码{caseVK_LEFT:...;break; //←case
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 运维部安全管理制度培训
- 塔吊垂直度检测与安全检查标准培训
- 任务5.1 汽车新媒体运营团队组建工作页
- 中国电梯安全状况与安全管理制度培训
- 2026阿里jvm必问面试题及答案
- 在用锅炉压力容器安全阀校验规范培训
- 生产现场照明管理制度培训
- 机运科电缆与小型电气管理员安全生产责任培训
- 主提升系统安全保护装置及设施试验规范培训
- 工程质量的技术措施
- 渣土外运施工方案(3篇)
- 新型储能项目定额(锂离子电池储能电站分册) 第二册 安装工程
- 插花艺术知到智慧树期末考试答案题库2025年北华大学
- 【MOOC答案】《光纤光学》(华中科技大学)章节作业期末慕课答案
- 马鞍山干熄焦工程施工组织设计
- 中国海军军舰课件
- 销售员安全试题及答案
- GB 4789.3-2025食品安全国家标准食品微生物学检验大肠菌群计数
- 高压电危险及安全防护课件
- 问病荐药流程
- 氢储存运输及加注技术教学课件:4.3液氨储氢技术
评论
0/150
提交评论