📄 05o024.htm
字号:
<p> iFlag=FALSE; //恢复鼠标光标形状改变标志
<p> }
<p> break;
<p> 二、WINDOWS高级窗口拖动方案中拖动框的客户定制方法
<p> 以上介绍了窗口拖动前鼠标光标位置检测及客户命令区域内拖动功能的鼠标光标动态提示方法,当用户通过鼠标光标动态提示功能取得满足拖动窗口条件时,通过点击鼠标左键来启动拖动方案,这时最关键的技术问题是鼠标拖动窗口移动过程中的拖动框显示与擦除功能实现。窗口拖动虚框就是在WINDOWS 整个屏幕区域内显示描述被拖动窗口大小的线框,它的大小需要根据被拖动窗口的矩形区域大小和实际需要来具体确定,一般情况下为被拖动窗口的矩形区域大小。
<p> WINDOWS 系统中的绘图方法是通过显示设备描述表实现的,绘图操作需要占用一定的GDI 资源,系统为窗口、菜单、对话框、字体和各种绘图函数分配足够的GDI资源,WINDOWS 95中的GDI资源要比WINDOWS3.X中的GDI资源大得多。WINDOWS中有两种使用显示设备描述符表的方法:更新窗口显示客户区域和直接操作窗口显示客户区域。更新窗口显示客户区域是直接针对应用程序窗口矩形区域而言的,在窗口函数响应WM_PAINT消息时利用图形操作命令进行窗口更新处理:
<p> InvalidateRect(hWnd,&WinRECT,TRUE);//WinRECT为要更新区域
<p> UpdateWindow(hWnd);
<p> 窗口初始建立时默认更新窗口的全部区域,当要更新的矩形区域为NULL时表示更新窗口所有矩形区域。函数UpdateWindow()通知系统向要更新矩形区域的窗口发送WM_PAINT消息,窗口函数接收到WM_PAINT消息后首先利用BeginPaint()函数取得设备描述符表,然后利用图形命令直接对显示设备进行更新操作,最后利用EndPaint()函数通知系统更新操作结束。其描述性功能代码如下:
<p> case WM_PAINT:
<p> PAINTSTRUCT ps;
<p> hdc=BeginPaint(hWnd,&ps);//取得设备描述符表
<p> SetBkMode(hdc,OPAQUE); //设备更新方式
<p> SetBkColor(hdc,0x00c0c0c0);
<p> //更新矩形区域内图形操作
<p> EndPaint(hWnd,&ps); //结束更新操作
<p> break;
<p> 更新窗口矩形区域直接使用窗口类中定义的屏幕画刷,即使利用SelectObject()函数选择相应屏幕画刷也无效,而且更新矩形区域范围是通过InvalidateRect()函数累加的,由UpdateWindow()函数通知系统开始进行窗口更新操作,整个过程是由系统来调度的,因此使用这种方法无法实现窗口的拖动虚框绘制和实时操作。
<p> 直接操作窗口客户区域的方法是利用GetDC( )函数直接取得显示设备句柄,利用各种图形操作命令直接对显示设备进行绘图,它使用屏幕当前设置的画笔和画刷来实现各种图形绘制操作,无须系统任何消息应用程序就可以实时地对屏幕窗口进行更新和绘图操作。其操作过程是首先取得显示设备描述符句柄:
<p> HDC hDC;
<p> hDC=GetDC(hWnd);//取得hWnd窗口设备描述符表句柄
<p> 当hWnd参数为NULL时取得的是整个屏幕的设备描述符表句柄,然后利用SelectObject()函数设置当前屏幕的画笔和画刷,就可以利用各种画图函数完成屏幕的绘图操作,最后利用ReleaseDC( )函数释放获取的显示设备描述表。由于这种方法可以直接控制当前屏幕的画笔和画刷,并且无需系统调度就可以直接对屏幕设备进行操作,因此利用这种方法完全可以实现窗口的拖动虚框。窗口的拖动虚框是用来描述要移动窗口大小的虚线框和实线框,当矩形拖动框为虚线时,需要利用画点或画线函数经过一定算法来实现,这就需要设置当前的屏幕画笔;当窗口的拖动框为实线框时,如果利用画线函数只需设置屏幕画笔即可,如果利用画矩形函数Rectangle( )在设置当前屏幕画笔的同时必须使用SelectObject(hDC,GetStockObject(NULL_BRUSH))屏蔽掉任何屏幕画刷,否则WINDOWS程序会很快吞筮掉所有GDI资源,相当于在屏幕设备资源中增加了无数矩形区域。
<p> 对于窗口拖动框的擦除操作,只需在拖动框绘制函数中将屏幕的图形画笔操作方式设置为R2_XORPEN异或方式,即SetROP2(hDC2,R2_XORPEN),在拖动框绘制结束时注意恢复,然后在窗口拖动框移动到下一个位置前,在原屏幕位置重新调用绘制函数一次将原来拖动框擦除。下面给出笔者利用画矩形、画线和画点函数实现的拖动框函数,用户在使用时可选择自己喜欢的实线或虚线拖动框函数。
<p> 函数1为利用画矩形函数实现的拖动实框,其特点是函数的效果高,拖动框作图速度快;函数2为利用画线函数实现的拖动框,其特点是通过设置不同的画线类型可以画虚框也可以画实框;函数3为利用画线函数实现的拖动虚框函数,特点是拖动虚框图案变化灵活,不足是函数效率低作图速度慢。函数通过参数可选择不同的拖动虚框图案或密度。函数3参数XY为1时与WINDOWS 3.X窗口拖动缺省虚框相同为单虚线框,如果XY参数为2 则拖动虚框为矩齿形边框。也可以根据需要选择不同的拖动虚框图案和相应画笔和画刷以达到不同的效果。
<p> //函数1:利用画矩形函数实现拖动实框
<p> void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy)
<p> {
<p> HDC hDC;
<p> int oldrop2,m,k;
<p> hDC = GetDC(NULL); //取得全屏幕设备描述句柄
<p> oldrop2= GetROP2(hDC); //取得原来屏幕画图方式
<p> SetROP2(hDC,R2_XORPEN); //设置异或屏幕画图方式
<p> SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽画刷
<p> SelectObject(hDC2,GetStockObject(WHITE_PEN));//选择画笔
<p> for (k=0;k<xy;k++){ //画实线拖动框
<p> xx1-=1;
<p> xx2+=1;
<p> yy1-=1;
<p> yy2+=1;
<p> Rectangle(hDC2,xx1,yy1,xx2,yy2);
<p> }
<p> SetROP2(hDC2,oldrop2); //恢复原来作图方式
<p> ReleaseDC(NULL,hDC2); //释放设备描述符表
<p> }
<p> //函数2:利用画线函数实现拖动实框或虚框
<p> void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy)
<p> { HDC hDC2;
<p> int oldrop2,m,k;
<p> hDC = GetDC(NULL); //取得全屏幕设备描述句柄
<p> oldrop2= GetROP2(hDC); //取得原来屏幕画图方式
<p> SetROP2(hDC,R2_XORPEN); //设置异或屏幕画图方式
<p> SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽画刷
<p> SelectObject(hDC2,GetStockObject(WHITE_PEN));//选择画笔
<p> for (k=0;k<xy;k++){ //可设置画线类型画实线或虚线拖动框
<p> xx1-=1;
<p> xx2+=1;
<p> yy1-=1;
<p> yy2+=1;
<p> MoveTo(hDC2,xx1,yy1);
<p> LineTo(hDC2,xx2,yy1);
<p> MoveTo(hDC2,xx1,yy1);
<p> LineTo(hDC2,xx2,yy1);
<p> }
<p> SetROP2(hDC2,oldrop2); //恢复原来作图方式
<p> ReleaseDC(NULL,hDC2); //释放设备描述符表
<p> }
<p> //函数3:利用画点函数实现不同图案的拖动虚框
<p> void DrawMoveRect(int xx1,int yy1,int xx2,int yy2,int xy)
<p> { HDC hDC2;
<p> int oldrop2,i,j,x1,x2,y1,y2;
<p> hDC = GetDC(NULL); //取得全屏幕设备描述句柄
<p> oldrop2= GetROP2(hDC); //取得原来屏幕画图方式
<p> SetROP2(hDC,R2_XORPEN); //设置异或屏幕画图方式
<p> SelectObject(hDC,GetStockObject(NULL_BRUSH));//屏蔽画刷
<p> SelectObject(hDC2,GetStockObject(WHITE_PEN));//选择画笔
<p> for (j=0;j<xy;j++){ //利用画点函数绘制窗口拖动虚框图案
<p> x1=xx1-j; //带注释部分为另一图案
<p> x2=xx2+j;
<p> y1=yy1-j;
<p> y2=yy2+j;
<p> for (i=x1;i<x2;i+=2) //用指定颜色在屏幕上画拖动虚框点
<p> SetPixel(hdc,i,y1,RGB(255,0,0));
<p> //if (i<x2-2) SetPixel(hdc,i+1,y1+1,RGB(255,0,0));}
<p> for (i=y1;i<y2;i+=2)
<p> SetPixel(hdc,x2,i,RGB(255,0,0));
<p> //if (i<y2-2) SetPixel(hdc,x2-1,i+1,RGB(255,0,0));}
<p> for (i=x2;i>x1;i-=2)
<p> SetPixel(hdc,i,y2,RGB(255,0,0));
<p> //if (i>x1+2) SetPixel(hdc,i-1,y2-1,RGB(255,0,0));}
<p> for (i=y2;i>y1;i-=2)
<p> SetPixel(hdc,x1,i,RGB(255,0,0));
<p> //if (i>y1+2) SetPixel(hdc,x1+1,i-1,RGB(255,0,0));}
<p> }
<p> SetROP2(hDC2,oldrop2); //恢复原来作图方式
<p> ReleaseDC(NULL,hDC2); //释放设备描述符表
<p> }
<p> 三、WINDOWS高级窗口客户区域拖动技术实现的“三步曲”
<p> WINDOWS
高级窗口的客户区域拖动命令判断、拖动功能的鼠标光标动态提示和定制窗口拖动框函数之后,就需要实现整个拖动方案中的拖动过程启动、窗口拖动框移动和拖动结束处理的三步曲过程。于是必须在窗口函数中直接处理WM_LBUTTONDOWN、WM_MOUSEMOVE和WM_LBUTTONUP消息,来具体处理上述三个步骤中的细节问题。
<p> 第一步,在窗口函数中对鼠标点击消息WM_LBUTTONDOWN进行判断处理,以处理用户通过鼠标光标动态提示功能获取满足窗口拖动条件时,按下鼠标左键产生的启动拖动过程消息,其功能性代码如下:
<p> POINT pt;
<p> BOOL MoveFlag=FALSE;
<p> case WM_LBUTTONDOWN:
<p> pt = MAKEPOINT(lParam); //获取鼠标光标指针
<p> if(PtInRect(&DragRT,pt)){//DragRT为拖动命令区域
<p> DragBegin((LPRECT)&WinRT,lParam,hWnd,2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -