文档详情

WIN98特殊窗口的动态拖动

飞***
实名认证
店铺
DOCX
28.85KB
约8页
文档ID:4690357
WIN98特殊窗口的动态拖动_第1页
1/8

WIN98 特殊窗口的动态拖动 一、命令检测与光标动态提示这种窗口拖动一般分为两种:特定客户命令区域和非特定客户命令区域特定客户命令区域是指利用"RECT"定义的特定子矩形区域;非特定客户命令区域是指没有明确定义的窗口客户区域部分,即所有特定客户命令区域之外的部分实现该功能的首要问题是如何检测和处理特定客户命令区域和非特定客户命令区域内的鼠标命令,以及如何利用鼠标光标来动态提示用户何时可以进行窗口的拖动操作1、特定客户命令区域检测鼠标命令要在窗口中设置实现拖动功能的图标命令按钮,就必须在资源文件中定义命令按钮的特定客户区域,该区域一般也就是命令按钮图标的矩形区域,这个区域的定义方法为"RECT DragRT",其中 DragRT 为定义的检测鼠标命令的矩形区域,它用 DragRT.LEFT、DragRT.TOP、DragRT.RIGHT 和 DragRT.BOTTOM 四个参数来描述矩形区域相对于窗口客户区域左上角的相对坐标值也可用"SETRECT"函数填充窗口函数在处理鼠标消息 WM_LBUTTONDOWN 时,当收到系统传递的鼠标位置参数 lParam 后,通过 MAKEPOINT()函数将其转换为窗口坐标值,然后利用判断某坐标点是否位于特定矩形区域内的函数 PtInRect(),判断出鼠标指针是否点击在拖动命令按钮之内。

2、非特定客户命令区域检测鼠标命令当窗口应用程序中采取了非特定客户命令区域拖动方法时,必须在资源文件中事先确定各个特定客户命令区域的矩形坐标,这时非特定客户命令区域是不规则的区域,它需要根据实际的应用程序窗口及各个命令按钮矩形区域来确定,也就是各个命令按钮矩形区域相对于窗口矩形区域的“非”子集窗口函数在处理鼠标消息 WM_LBUTTONDOWN 时,首先利用函数 PtInRect()判断当前鼠标指针是否点击在各个命令按钮矩形区域内,如果未点击在任何命令按钮区域内,则可确定鼠标点击在非特定客户命令区域内,从而启动窗口拖动功能  3、窗口拖动功能的光标动态提示实现鼠标光标动态提示功能前需要定制鼠标光标形状,窗口拖动功能的动态提示光标形状一般为四箭头图案,这可以利用微软公司的 SDK、FPT3.0 和VC++4.1 等高级开发软件中的资源编辑器"IMAGE EDIT"等来实现光标资源文件一般为 32X32 的 2 色或 16 色.CUR 图形文件建立起自己的鼠标光标资源文件后,首先需要在应用程序的资源文件中定义鼠标光标,然后在应用程序中利用 LoadCursor()调入,并在类中进行设置:wc.hCursor=hCurm。

当鼠标光标需要在窗口的特定客户命令按钮区域内或非特定客户命令区域内进行动态提示时,不能使用上述定义方法,而需要在窗口函数处理WM_MOUSEMOVE 消息时进行特殊处理:首先判断鼠标光标指针的当前位置是否在拖动命令按钮或非特定客户命令区域内,如果鼠标指针位置满足拖动窗口功能区域的要求,则利用 API 函数 SETCURSOR()改变鼠标光标图案,提示用户此时可以进行窗口拖动操作,并将鼠标输入控制权交给当前窗口,同时设置改变后的鼠标光标标志;当鼠标指针移出拖动窗口命令启动区域时,恢复原来鼠标光标图案同时释放鼠标输入焦点控制权,并清除鼠标光标动态提示标志单元二、动态拖动框的定制窗口拖动前的关键问题是鼠标拖动窗口过程中的拖动框显示与擦除功能实现窗口拖动虚框就是在 WINDOWS 整个屏幕区域内显示被拖动窗口大小的线框,它的大小需要根据被拖动窗口的矩形区域大小和实际需要来具体确定,一般为被拖动窗口的矩形区域大小WINDOWS 系统中的绘图方法是通过显示设备描述表实现的,绘图操作需要占用一定的 GDI 资源WINDOWS 95 中的 GDI 资源要比 WINDOWS3.X 中的 GDI资源大得多,所以系统可以为窗口、菜单、对话框、字体和各种绘图函数分配足够的 GDI 资源。

WINDOWS 中有两种使用显示设备描述符表的方法:更新窗口显示客户区域和直接操作窗口显示客户区域更新窗口显示客户区域是直接针对应用程序窗口矩形区域而言的,在窗口函数响应 WM_PAINT 消息时利用图形操作命令进行窗口更新处理:InvalidateRect(hWnd,&WinRECT,TRUE);//WinRECT 为要更新区域UpdateWindow(hWnd);窗口初始建立时默认为更新窗口的全部区域,当要更新的矩形区域为 NULL时表示更新窗口所有矩形区域函数 UpdateWindow()通知系统向要更新矩形区域的窗口发送 WM_PAINT 消息,窗口函数接收到 WM_PAINT 消息后首先利用BeginPaint()函数取得设备描述符表,然后利用图形命令直接对显示设备进行更新操作,最后利用 EndPaint()函数通知系统更新操作结束更新窗口矩形区域直接使用窗口类中定义的屏幕画刷,即使利用SelectObject()函数选择相应屏幕画刷也无效,而且更新矩形区域范围是通过InvalidateRect()函数累加的,由 UpdateWindow()函数通知系统开始进行窗口更新操作整个过程是由系统来调度的,因此使用这种方法无法实现窗口的拖动虚框绘制和实时操作。

直接操作窗口客户区域的方法是利用 GetDC()函数直接取得显示设备句柄,利用各种图形操作命令直接对显示设备进行绘图它使用屏幕当前设置的画笔和画刷来实现各种图形绘制操作,无须向系统传递任何消息应用程序就可以实时地对屏幕窗口进行更新和绘图操作其操作过程是首先取得显示设备描述符句柄 hDC=GetDC(hWnd),当 hWnd 参数为 NULL 时取得的是整个屏幕的设备描述符表句柄,然后利用 SelectObject()函数设置当前屏幕的画笔和画刷,利用各种画图函数完成屏幕的绘图操作,最后利用 ReleaseDC()函数释放获取的设备描述表如果利用画矩形函数 Rectangle()实现虚框,那么在设置当前屏幕画笔的同时必须使用 SelectObject(hDC,GetStockObject(NULL_BRUSH))屏蔽掉任何屏幕画刷,否则 WINDOWS 程序会很快吞筮掉所有 GDI 资源,相当于在屏幕设备资源中增加了无数矩形区域对于窗口拖动框的擦除操作,只需在拖动框绘制函数中将屏幕的图形画笔操作方式设置为 R2_XORPEN 异或方式,即 SetROP2(hDC2,R2_XORPEN)在拖动框绘制结束时注意恢复,在窗口拖动框移动到下一个位置前,在原屏幕位置重新调用绘制函数一次将原来拖动框擦除(见程序 1)。

//利用画矩形函数实现拖动实框(由于篇幅画线、画点函数省略)void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy){ HDC hDC;int oldrop2,m,k;hDC = GetDC(NULL); //取得全屏幕设备描述句柄oldrop2= GetROP2(hDC); //取得原来屏幕画图方式SetROP2(hDC,R2_XORPEN); //设置异或屏幕画图方式SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽画刷SelectObject(hDC2,GetStockObject(WHITE_PEN));//选择画笔   for (k=0;k    xx1-=1;xx2+=1;yy1-=1;yy2+=1;Rectangle(hDC2,xx1,yy1,xx2,yy2);}SetROP2(hDC2,oldrop2); //恢复原来作图方式ReleaseDC(NULL,hDC2); //释放设备描述符表}(程序 1)三、动态拖动窗口“三步曲”完成了对 WINDOWS 高级窗口的客户区域拖动命令判断、拖动功能的鼠标光标动态提示和定制窗口拖动框函数之后,就需要实现整个拖动方案中的拖动过程启动、窗口拖动框移动和拖动结束处理的三步曲过程。

于是必须在窗口函数中直接处理 WM_LBUTTONDOWN、WM_MOUSEMOVE 和WM_LBUTTONUP消息下面来具体处理上述三个步骤中的细节问题第一步,在窗口函数中对鼠标点击消息 WM_LBUTTONDOWN 进行判断,以处理用户通过鼠标光标动态提示功能获取满足窗口拖动条件时,按下鼠标左键产生的启动拖动过程消息其功能性代码如下:case WM_LBUTTONDOWN:pt = MAKEPOINT(lParam);if(PtInRect(&DragRT,pt)){DragBegin((LPRECT)&WinRT,lParam,hWnd,2);//启动过程} else {//进行其它处理;}上述 DragBegin()函数为笔者开发的窗口拖动启动函数由于一个高级窗口应用程序中往往存在很多窗口,所以将其作为一个单独函数处理其中 WinRT 为高级窗口矩形区域,这里作为拖动框矩形区域参数来传递,lParam 为鼠标光标指针长整数,hWnd 为当前被拖动窗口的句柄,2 为拖动框宽度这时,需要同时将鼠标控制权交给当前被拖动窗口、设置拖动窗口标志单元、保存当前鼠标在屏幕上的位置并显示被拖动窗口的拖动框。

拖动功能启动函数的源代码如下:void DragBegin(LPRECT WinRect, //拖动框的矩形区域LPARAM lParam, //鼠标光标当前指针HWND hwnd, //当前窗口句柄unsigned int kk) //拖动框显示的宽度{SetCapture(hwnd); //拖动时窗口必须具有鼠标输入权MoveFlag=TRUE; //设置拖动标志oldmx=LOWORD(lParam);//记录当前鼠标屏幕坐标 Xoldmy=HIWORD(lParam);//记录当前鼠标屏幕坐标 YDrawMoveRect(WinRect->left,WinRect->top,//显示拖动框WinRect->right,WinRect->bottom,kk);}第二步,需要处理鼠标拖动窗口时的拖动框移动过程,这需要在窗口函数中进行 WM_MOUSEMOVE 消息处理拖动框的移动包括上次显示拖动框的清除和本次拖动框的显示两步由于拖动框绘制函数中对当前的绘制方式进行了重新设置,异或方式使得只要重新在原屏幕坐标位置处调用一次该函数即可清除拖动框,因此,在鼠标拖动窗口移动过程中显示和清除拖动框只需要调用两次拖动框绘制函数即可。

另外,拖动框在屏幕上位置的计算方法也非常简单,就是将当前取得的屏幕位置坐标值减去保存的前次屏幕位置坐标值所得鼠标移动偏移量,再用原来窗口屏幕左上角坐标值加上这个偏移量,就可以确定被拖动窗口和拖动框新的屏幕位置坐标值  case WM_MOUSEMOVE:if(MoveFlag==TRUE){DragMove((LPRECT)&WinRT,WinWT,WinHi,lParam,2);} else {//进行其它处理;}鉴于高级窗口应用程序一般为多个子窗口,所以将拖动框移动处理过程单独编制成函数,并且对鼠标拖动窗口过程中窗口不能完全位于屏幕可见区域内进行了特殊处理开发者可根据需要自行调整其位置,以便被拖动的窗口能够完全被显示于屏幕可视区域内其拖动过程函数源代码部分如下:void DragMove(LPRECT rcwin, //拖动框矩形区域unsigned int wi, //被拖动窗口宽度unsigned int hi, //被拖动窗口高度LPARAM lParam, //鼠标位置指针unsigned int kk) //拖动框边框宽度{ DrawMoveRect(rcwin->left,rcwin->top,rcwin->right,rcwin->bottom,kk);//清除上次画拖动框rcwin->left+=LOWORD(lParam)-sImeG.oldmx;//计算窗口rcwin->t。

下载提示
相似文档
正为您匹配相似的精品文档