Chinaunix首页 | 论坛 | 博客
  • 博客访问: 129625
  • 博文数量: 37
  • 博客积分: 1490
  • 博客等级: 上尉
  • 技术积分: 326
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-01 16:38
文章分类

全部博文(37)

文章存档

2011年(1)

2010年(23)

2009年(13)

我的朋友

分类: WINDOWS

2010-04-08 15:00:27

第三课∶窗口函数

    一、 关于窗口函数

    在上一堂课里,我们已经提出了"句柄"的概念,并为此进行了较深度的讨论。现在来想,我要补充的是,句柄并非是仅仅是窗口才有的。似乎所有的WINDOWS对象都具有句柄。如,GDI对象中的画笔、刷子等,不久即将要学习的设备场景等也有自己的句柄,等等。但,和一些控件不同,这些对象并不属于窗口。
    什么是窗口呢?有一句非常有趣的话∶如果它位于屏幕,那么它肯定是在一个窗口里;如果它不在于屏幕,它仍然可能在一个窗口里。窗体也是窗口;滚动条、列表框,文本框,甚至是桌面上的快捷图表也是窗口。更有趣的是,就连作为背景的桌面也是窗口。

    很多控件基本上都提供了hWnd属性,但没有提供的也有。对于这些控件可以用SetFocus
方法,将输入焦点设向控件,然后用API函数GetFocus取得当前具有焦点的那个窗口的句柄。当然,这一过程应当写在GoFocus事件中。在我碰到过的问题中有一个有趣的事情是,
VB提供的IE控件的hWnd属性不管用。这个问题我一般都采用上述方法来解决的。
    很多窗口函数都能对系统的任何窗体进行操作。这意味了VB程序可以直接操纵正在运行中的其他窗体。大家知道,如果对VB设计出的程序未做特殊的处理,那么我们可以启动多个该应用程序实例。我们可以利用API窗口函数来判断一个窗体的先例是否在运行当中,从而可以做到如果有先例则停止启动。很多应用程序就是这个样子的。比如四通利方中文平台,在已经启动的情况下再此启动,程序会告诉用户"四通利方已经在运行",并停止启动。

    窗口函数主要可分为四个类型(也许说为"这是为了这次讲课分类出来的"更适合一些)∶
    1、窗口分级函数;
    2、窗口位置与大小函数;
    3、窗口信息函数;
    4、其他窗口函数。
    以下我们就一一讲述。但由于窗口函数比较多,在这里就选择性的进行讨论。关于窗口函数有多少,具体的用法如何,您可以注意"小雁侠"的VB API站点的技术文档,或者本站
程序下载栏目中的WinAPI帮助文。由于帮助文其内容来自"小雁侠"的网站,因此其内容更新比较起来会较晚一些。

    二、窗口分级函数

    系统中运行的窗口是有级别的高低之分的。谁不知道这样?这当然是废话。很多文章都是采用类似的这种废话来做导语,在这里我只不过也是学学而罢。
    一、父子关系。
    每个窗口都可能有自己的父窗口和子窗口。但,系统中运行的窗口是有限的,说明总得有个窗口是没有其父,我们把它叫做顶级窗口。一般把一个应用程序的主窗口就是顶级窗口,VB独立窗体及MDI窗体都是顶级窗口。窗口间的父子关系一般遵循以下规则∶
    1、父窗口显示时,所有包容在其中的可见的子窗口会随着父窗口的显示而显示出来。

    2、父窗口隐藏时,所有包容在其中的子窗口会随着父窗口的隐藏而隐藏。
    3、父窗口被卸载时,哈,您已经知道我想说什么了,当然是∶跟着自动卸载。
    4、父窗口移动时,跟着移动。
    二、兄弟关系及Z序列
    当然,一位父亲有好几个儿女,都是常见的事情。同样,一个父窗口可以拥有多个子窗体。比如,位于一个窗体中的各种控件之间以及MDI窗口的各子窗口之间的关系。父窗口与子窗口的显示、隐藏、卸载及移动,其先后顺序是显而易见的。那么各兄弟窗口之间的情况会是如何呢?

    显然,两个互相重叠的两个子窗体不能都同时显示出它的全貌,自然有个显示的顺序规则。这个顺序规则叫做Z序列。有个解释为,如果把屏幕坐标看层X和Y轴组成的平面(事实上正是如此),那么作为三维坐标系统Z轴可看做是垂直于屏幕的坐标轴。这样,可以认为屏幕上的所有窗口是垂直于这个Z轴的。在Z轴上,谁在前,谁在后,就产生了一个Z序列。很生动!可用WINDOWS API函数和Visual Basic Z序列方法对Z序列进行控制。

    有了以上简单的知识以后,我们就不难应用API窗口分级函数,主要有以下及个∶
窗口分级函数

函数名                                 说   明
FindWindow             按类名或窗口名(Caption)查找一个窗口
FindWindowEx         类似于FindWindow提供了更多的功能
GetLastActivePopup 针对指定的窗口,取回上一个活动的弹出式窗口的句柄
GetParent                获得指定窗口父窗口的句柄
GetTopWindow        获得指定窗口的第一个子窗口的句柄
GetWindow              如给定一个窗口句柄,该函数能取回具有特定关系的另一个窗口                             的句柄。如,第一个子窗口、父窗口或窗口列表内的上一个或下一个窗口。
SetParent                改变任何窗口的父窗口。
    从我个人的经验来看,我最常用的是GetWindow和SetParent函数。

    三、窗口位置与大小函数

     Windows API函数基本上都是(尤其是USER32.DLL动态连接库内的函数)以屏幕像素为度量单位的。这一点很重要,必须牢记。为此,在使用API函数的时候,我们经常把窗体或图片框控件的ScaleMode属性设置为3,即vbPixels(像素)。
     理解窗口位置及大小函数的关键在于分清屏幕坐标、窗口坐标及客户坐标这三个概念。以下图展示了这三个坐标系统之间的关系。


屏目、窗口与客户区坐标系统

     只要对这些坐标有了明确的概念,对使用窗口位置及大小函数就不难了。关于窗口的位置,有些函数返回的是上一堂课学习到的RECT结构。有关窗口位置及大小函数如下表所列∶
窗口位置及大小函数

函数名                                               说  明
BringWindowToTop         使指定的窗口进入可见窗口列表的顶部,如它被部分或全部隐藏,则令其全部可见。同时,该窗口成为当前活动窗口。只有从前台线程调用时,才生效。
ChildWindowFromPoint   在规定的坐标取得某子窗口的句柄(如果有的话),这儿的坐标是指相对于父窗口的客户区坐标。
ChildWindowFromPointEx 与 ChildWindowFromPoint相同,功能更强。
ClientToScreen                判断指定点在窗口客户区内的屏幕坐标。
GetClientRect                  获得对窗口客户区进行表述的一个矩形(RECT)。这是以像素为单位判断客户区大小的一个简便的方法。
GetWindowPlacement    获得指定窗口的一个WINDOWPLACEMENT结构。该结构说明了窗口的状态。
GetWindowRect              用于获得一个矩形(RECT)结构,它描述了窗体在屏幕坐标系统中的位置。
MapWindowPoints          对某窗口客户区坐标内的一个或多个点进行转换,用另一窗口的客户区坐标表示。
MoveWindow                  移动指定窗口的位置,并能改变它的大小。
OpenIcon                        将一个最小化窗口恢复为原始状态。
ScreenToClient                针对屏幕内一个指定的点,用某个特定窗口内的客户区坐标表示它。
SetWindowsPos              更改窗口的位置和大小,并能修改它在内部窗口列表内的位置(这个列表起着控制窗口先是顺序)。
SetWindowPlacement     在一个WINDOWPLACEMENT结构的基础上,设置某窗口的特征。该结构描述了窗口的状态,以及它在最小化、最大化或正常显示时的位置。
WindowFromPoint           根据屏幕上一个指定的点,判断哪个窗口正位于它的下面。
    以上函数的具体用法均可在WinAPI帮助文中找到。在这些函数当中,SetWindowsPos
函数的使用率比较高,现在很多人都是用这个函数来实现"窗口总在前面"的效果,即通过
HWND_TOPMOST常数把窗口置于列表顶部。如果想把From1置于列表顶部,方法如下∶
     SetWindowPos Form1.hWnd, HWND_TOPMOST, Form1.Left / Screen.TwipsPerPixelX, Fo rm1.Top \ Screen.TwipsPerPixelY, Form1.Width \ Screen.TwipsPerPixelX, Form1.Height \ Screen.TwipsPerPixelY, 0

    您可以把这行代码放在Paint事件中。
    另外,GetWindowRect函数、MoveWindow函数以及下一课堂即将要学到的
GetCursorPos函数的相互配合能够实现一个拖动无标题栏的窗口。这是您必须掌握的技巧之一。感兴趣的朋友,可以到《前线》的《源码解析》栏目,下载第4号演示程序。以下是其主要的代码部分∶
Private MyRect As RECT
Private MyPoint As POINTAPI
Private Movex As Long, Movey As Long

Private Sub Image1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

Dim dl&
dl& = GetWindowRect(Form1.hwnd, MyRect)
dl& = GetCursorPos(MyPoint)
If Button = 1 Then
     Movex = MyPoint.X - MyRect.Left
     Movey = MyPoint.Y - MyRect.Top
End If
End Sub

Private Sub Image1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
       Dim dl&
       dl& = GetCursorPos(MyPoint)
       If Button = 1 Then
           dl& = MoveWindow(Form1.hwnd, MyPoint.X - Movex, MyPoint.Y - Movey, _

                          MyRect.Right - MyRect.Left, MyRect.Bottom - MyRect.Top, -1)
       End If
End Sub
    在MouseDown事件中,程序首先用 GetWindowRect 函数确定窗口在屏幕中的位置。再次是通过GetCursorPos函数确鼠标在屏幕中的位置。从而可通过计算获得鼠标位置与窗口左上角之间的横向与纵向距离(Movex与Movey)。
    在紧接着发生的MouseMove事件中程序不断地用GetCursorPos函数获得鼠标当前的位置,并按前面已经求得的Movex与Movey判断窗口所应处的位置,而这在MoveWindow函数调用中直接完成。MoveWindow函数将窗体移动到新的位
阅读(1272) | 评论(0) | 转发(0) |
0

上一篇:listview

下一篇:窗口信息函数

给主人留下些什么吧!~~