返回首页

简介
本教程将展示如何创建对接工具窗口,使用标准的Win32图形和Windows功能(即没有MFC,WTL的,自动化等)。对接工具窗口是一个窗口,可以是"附加"(即"对接")的其他一些窗口内边框,或"撕下",边境自由浮动(最终用户),并为之感动周围鼠标。一个窗口,其中一些工具窗口可以停靠,被称为所有者(或容器)窗口。高于其所有者窗口浮动工具窗口。相同的工具窗口停靠到其所有者窗口底部的内边框。
首先,我们将讨论"浮动"工具窗口的方面 - 即如何让留在所​​有其他窗口的顶部,如何获得正常工作的窗口激活的浮动工具窗口,等稍后,我们将如何让这些浮动工具窗口"码头"的所有者窗口的一侧,并讨论了窗口管理的各种方法。
的源代码,最终将称为DockWnd.dll,其功能可用于任何Win32程序,能够方便地支持对接工具窗口的Win32 DLL。有很多不同的方法来创建一个对接的窗口。我想在互联网上的大部分代码使用精心设计的C类,隐藏实现。不过,我还是喜欢在C代码中,所以这个库的设计将是一个非面向对象的方法,因此很容易在任何语言编写的应用程序可用。
此代码/条是根据詹姆斯布朗提供一些原始的自由代码。他,包含此代码的较早,不同版本(以及许多其他免费的Win32教程/例子)。目录   ; 结构
因为我们的对接库需要保持一些管理有关每种工具的窗口的信息,我们需要一些结构来存储信息。我们将定义一个DOCKINFO结构(中dockwnd.h),并分配每个工具创建的窗口DOCKINFO。在我们的对接库,应用程序将调用DockingAlloc功能分配DOCKINFO(初始化为默认值),然后把它传递给DockingCreateFrame功能创建实际的工具窗口,DOCKINFO。这个结构将举行信息,如处理代码(HWND)的工具窗口,的工具窗口的所有者窗口的句柄,是否工具窗口,是目前停靠我们在管理对接工具私人使用其所有者或浮动,和其他信息窗口。我们在工具窗口中的DOCKINFO的HWND字段存储的处理。我们存储DOCKINFO的集装箱场的所有者窗口的句柄。 DOCKINFO uDockedState领域的价值告诉工具窗口是否是浮动或停靠。此字段是"或"运算的DWS_FL​​OATING(,因此负值)时,一个工具窗口是浮动的。我们稍后将讨论的其他DOCKINFO领域。
注意:它是应用程序的创建和管理责任的所有者窗口。我们的资料库只涉及创建/管理工具窗口。
我们注册自己的窗口类(类的名称与"DockWnd32"),为我们的工具窗口。这个类的窗口过程(dockWndProc)是我们的图书馆内。我们使用的工具窗口GWL_USERDATA字段来存储一个指针,工具窗口的DOCKINFO结构。这样,我们就可以方便,快捷地获取相应的DOCKINFO只有一个句柄(HWND),一个特定的工具窗口。
我们不希望限制只有一个业主的窗口,其设置停靠窗口的应用程序。例如,一个应用程序可能将有两个所有者窗口,每个都有其自己的一套停靠窗口。也不是,我们要限制的应用程序特定的工具窗口。因此,我们可能会要求创建无数套工具窗口和业主DOCKINFOs。通过存储一个指针到一个工具窗口的DOCKINFO的工具窗口本身,和存储的工具窗口和其内的DOCKINFO所有者窗口的句柄,我们可以很容易得到所有信息,我们为我们的图书馆需要什么,需要做的,对应用程序的一部分最小工作。
的时候,我们的图书馆需要能够列举一个特定的所有者窗口的所有工具窗口。我们将在稍后的详情。在一些我们的例子下面的代码中,我们将不仅仅是指DockingNextToolWindow一个占位符,函数调用,你应该假设将获取一个特定的所有者窗口的下一个工具窗口(实际上,工具窗口的DOCKINFO)。在实际的源代码库,这是更复杂的代码取代,稍后,我们将探讨。 DockingCreateFrame创建一个浮动工具窗口
浮动工具窗口仅仅是一个标准的窗口WS_POPUP风格。当与所有者窗口创建一个弹出窗口,弹出的位置,使其始终停留,所有者窗口的顶部。这是我们如何能够创建并显示一个浮动工具窗口:/​​ /创建一个浮动(弹出)工具窗口HWND HWND = CreateWindowEx( WS_EX_TOOLWINDOW, "; ToolWindowClassquot","ToolWindowquot; WS_POPUP | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION | WS_VISIBLE, 200,200,400,64, hwndOwner,NULL,GetModuleHandle(0),NULL );
注意:在上面的例子,它是假设hwndOwner是其他一些应用程序创建的,是我们的工具窗口的所有者窗口的窗口句柄。应用程序必须创建这个窗口,然后通过它的处理DockingCreateFrame。换句话说,应用程序必须建立所有者窗口,可以为它创建的任何工具窗口前。
WS_EX_TOOLWINDOW额外的样式没有做什么特别的,其他较小的标题栏比作一个窗口。它不会使奇迹般​​地浮动的窗口 - 这是自动实现指定WS_POPUP风格和所有者窗口。下面的上述C​​reateWindowEx可能会显示:漂浮工具窗口高于其所有者窗口("主窗口")。 窗口停用
上面的图片显示与非活动标题栏的所有者窗口("主窗口")。这是完全正常的,因为在一个时间只有一个窗口可以有输入焦点,操作系统通常只有一个活跃的标题栏的窗口。所以,当我们创建工具窗口,操作系统显示为活动的工具窗口,并显示停用的所有者窗口。
但是,这是正常的做法工具窗口和他们在同一时间出现积极的所有者窗口。这样看起来更自然。因此,我们需要制定一项战略,以保持我们的工具窗口和所有者窗口,同时出现活跃,即使只有一个技术上具有输入焦点。
解决方案涉及WM_NCACTIVATE消息。操作系统发送的消息时,一个窗口的非客户区(标题栏和边框)需要激活或停用。与所有的窗口消息,WM_NCACTIVATE发送带有两个参数 - wParam和lParam。当一个窗口收到WM_NCACTIVATE其中wParam = TRUE,这表明,标题栏和边框应显示为活跃。当wParam参数= FALSE,这表明,标题栏和边框应显示为不活跃。
注意:MSDN上指出,WM_NCACTIVATE的lParam将始终为0。不过,我观察到的lParam表示被停用的窗口的窗口句柄。这似乎是WIN95,98和NT,2000和XP下的真实。我们的解决方案依赖于这个未公开的特性。
所以,当我们创建我们的工具窗口,我们的所有者窗口接收到的wParam = FALSE,和我们​​的工具窗口WM_NCACTIVATE收到一个WM_NCACTIVATE其中wParam = TRUE。
当这个消息传递给DefWindowProc(),操作系统做两件事情。首先,标题栏绘制为有效或无效,分别取决于后wParam是否是真的还是假。其次,操作系统设置一个窗口,它可以记住如果窗口被涂为有效或无效的内部标志。这使得DefWindowProc()处理后续WM_NCPAINT消息,油漆与正确的激活标题栏。这是可取总是传递WM_NCACTIVATE DefWindowProc(),使这种内部标志设置,即使你还做你自己的WM_NCACTIVATE处理。
这WM_NCACTIVATE消息给我们提供了一种方法,使我们所有的工具窗口,所有者窗口,显得活跃,即使只有一个窗口,在技术上重点。要做到这一点,我们的工具窗口或所有者窗口时收到一个WM_NCACTIVATE,我们将始终代替真正的wParam当我们通过"WM_NCACTIVATE DefWindowProc()。其结果是,操作系统始终呈现为活跃我们的工具窗口和所有者窗口的标题栏。
下面是一些代码,我们可以添加到我们所有的工具窗口的窗口过程,和所有者窗口,向他们展示的同时激活的情况下WM_NCACTIVATE:  0; 返回DefWindowProc(HWND,味精,为TRUE,LPARAM);工具窗口和它的所有者窗口显示活跃。
顺便说一下,MDI子窗口也可以使用同样的技术,以保持其标题栏积极。唯一不同的是,MDI窗口WS_CHILD样式,而不是WS_POPUP,。 为活动的所有工具窗口
上面的方法似乎做我们想做的,但有一个问题。我们的所有者窗口和工具窗口总是会出现积极的,即使我们的应用程序是不是在前台。例如,如果最终用户切换到其他一些应用程序的窗口,我们的工具窗口和所有者窗口仍然看起来活跃,它可以是一个令人不安的最终用户的位。
此外,当我们显示一个消息框,或一个正常的对话框的所有者窗口和工具窗口仍然会出现活跃,在这种情况下,我们的理想,使它们看起来不活跃。
这就需要一个窗口激活消息更仔细的研究。下面是一系列窗口激活一个窗口变为活动状态时发送消息的描述,而另一个不活跃:WM_MOUSEACTIVATE发送到窗口即将成为活跃,问是否应该允许激活请求。你的窗口过程返回(即MA_ACTIVATE或MA_NOACTIVATE)影响后续的激活消息。WM_ACTIVATEAPP发送如果属于不同的应用程序的一个窗口,成为活跃(或无效)。此消息被发送的当前活动的窗口(告诉它是变得不活跃)以及窗口变得活跃。返回值应该始终为零,并不会影响后续消息的行为。如上所述,WM_NCACTIVATE一个窗口的非客户区时发送需要显示激活或停用。所有发送WM_ACTIVATE是最后一个窗口,成为活跃。当这个消息传递给DefWindowProc(),操作系统设置到该窗口输入焦点。
所有这些激活消息,只有两个窗口,实际参与 - 被停用的窗口,窗口被激活。所以,即使我们有许多浮动工具窗口,不是所有会收到这些消息。只有一个窗口被激活,而被停用的一个窗口,收到的消息。但是,为了使事物的外观和感觉的权利,我们希望每个工具窗口的显示状态(即工具窗口的标题栏显示是否有效或无效),作为所有其他工具窗口一样。所以,即使不是我们的窗户都将收到上述消息,我们还需要有所有窗口同步到相同的状态。
此相同的讨论适用,每当我们需要禁用或启用我们的所有者窗口。如果要禁用或启用的所有者窗口是,我们要同步所有的工具窗口,到相同的状态。 (但是,不同的消息发送被禁用或启用一个窗口。)
所以,我们的对接库有位的工作,为了使事情看起来和感觉不对:当我们的应用程序是激活/停用,我们需要互相同步的所有工具窗口的有效/无效的显示。
这也适用于活化在我们自己的应用程序。例如,如果用户激活一个窗口,我们创建的是不是我们的工具窗口之一,那么我们想显示所有停用的工具窗口。如果用户切换回该窗口工具窗口,我们希望所有工具中显示活动窗口。当所有者窗口被禁用由于正在显示一个模式对话框或消息框,然后我们必须禁用所有工具窗口(任何模式对话框),以防止用户与他们的互动模式对话框/消息框在屏幕上。在第一次尝试的解决方案
我们在一个解决方案的第一刺,将集中于WM_ACTIVATE消息。收到此消息时,一个窗口被激活或停用。我们将采取的方向,将决定是否接收此消息的窗口是有效或无效,并通过手动发送一个"欺骗"WM_NCACTIVATE消息同步到同一状态的所有其他窗口。这种欺骗的消息将迫使其他Windows更新他们的标题栏,窗口收到的WM_ACTIVATE相同的状态。
在这里的一个功能,我们可以将其添加到我们的对接库。我们的工具窗口,或所有者窗口之一,每当接收到WM_ACTIVATE消息,它会调用这个函数来同步所有的工具窗口的状态:/******************* **** DockingActivate()********************** *发送WM_NCACTIVATE所有者的所有工具窗口。一 *工具或所有者窗口响应接收这个调用 * WM_ACTIVATE消息。 * *容器=所有者窗口的句柄。 * HWND =处理窗口收到WM_ACTIVATE( *所有者,或它的一个工具窗口)。 *的wParam = WM_ACTIVATE消息的wParam。 *的lParam = WM_ACTIVATE消息的lParam。 * /LRESULT WINAPI DockingActivate(HWND的容器, & #160; HWND HWND,WPARAM WPARAM,LPARAM lParam的){  ; DOCKINFO * D​​WP; BOOL fKeepActive;   ;fKeepActive =(WPARAM = WA_INACTIVE!); / /获取DOCKINFO这所有者窗口的下一个工具窗口。当0 / /返回,这个老板有没有更多的工具窗口。 而((DWP = DockingNextToolWindow(容器))) { / /同步工具窗口相同的状态,所谓的窗口 / / DockingActivate。 SendMessage消息(DWP - GT; HWND,WM_NCACTIVATE,fKeepActive,0); } / /允许所谓DockingActivate的窗口来处理其WM_NCACTIVATE / /因为它通常会。 返回DefWindowProc(HWND,WM_ACTIVATE,WPARAM,LPARAM);}
,它的工作原理,后一种时尚。所有工具窗口激活和停用正确,并在同一时间所有。该解决方案是不是最好的,虽然。
问题是,每一个工具窗口的标题栏闪烁时,活动窗口的变化。这是因为操作系统的方式发送WM_ACTIVATE消息。此消息首先被送到正在被停用的窗口。如果出现这种情况是一个工具窗口或所有者窗口,它会调用DockingActivate停用所有的工具窗口。 WM_ACTIVATE,然后发送到活动窗口。如果该窗口也恰好是一个工具窗口或所有者窗口,它会调用DockingActivate(正确)激活所有的工具窗口。它是DockingActivate是迅速调用两次(一次关闭工具窗口,然后激活它们)的事实,导致所有的窗户闪烁。
的部分解决方案是执行一个检查前停用的工具窗口。我们知道,如果一个窗口被停用,lParam的标识(其他)窗口被激活。其他窗口如果这是我们的工具窗口之一,我们可以跳过停用的工具窗口,因为我们知道其他(工具)窗口,随后激活他们anyway.if(fKeepActive == FALSE){  60;而((DWP = DockingNextToolWindow(容器))) {  60; 如果(DWP GT; HWND ==(HWND)lParam的) & #160; 返回DefWindowProc(HWND,WM_ACTIVATE,WPARAM,LPARAM);& #160; }}
这可以防止简单地停用每一个工具窗口,然后再次激活。还有一个问题,尽管是轻微的。问题是,单是被停用的工具窗口,仍然会闪烁简要之前再次被激活。这是因为它已经收到其WM_NCACTIVATE消息,这引起窗口重绘停用。窗口被激活看看最终的,但这个简短的闪烁仍然可见。 激活所有工具窗口
我们需要采取的步骤和方法从一个略有不同的方向的问题。相反WM_ACTIVATE处理,这就是所谓后重绘一个窗口的标题栏是,我们就直奔心脏问题,并改写DockingActivate每当一个窗口收到WM_NCACTIVATE的消息,被称为。这将确保没有不必要的激活或停用会发生。
下面介绍的函数执行几个任务窗口,调用DockingActivate代表的工具(或所有者):搜索列表中的其他窗口被激活/停用(由lParam参数指定的窗口,而不是接收窗口WM_NCACTIVATE)。如果这个窗口是一个工具窗口,然后我们力量的所有工具窗口激活。目前所有的工具窗口同步我们(可能是新的)状态。激活/关闭窗口调用DockingActivate,取决于我们的新国家。
的代码看起来像这样:LRESULT WINAPI DockingActivate(HWND的容器, HWND HWND,WPARAM WPARAM,LPARAM lParam的){ DOCKINFO * D​​WP; BOOL fKeepActive; 布尔fSyncOthers;  0; / /如果这是一个spoof'ed我们发出的消息,然后处理它 &# 160; / /通常(但LPARAM重置为0)。 (LPARAM == -1) 返回DefWindowProc(HWND,WM_NCACTIVATE,WPARAM,0); fKeepActive = wParam参数; fSyncOthers = TRUE; 而((DWP = DockingNextToolWindow(容器))) & #160;{ / /未公开的特性: / /如果其他窗口被激活/停用(即不是一个 & #160;/ /这里调用)是我们的一个工具窗口,然后转到(或居留)积极。 ((HWND)lParam的== DWP - GT; HWND) &# 160; { fKeepActive = TRUE;  60; fSyncOthers = FALSE; 打破; } } 如果(fSyncOthers == TRUE) { / /同步所有其他工具窗口相同的状态。 而((DWP = DockingNextToolWindow(容器))) { / /发送一个spoof'ed WM_NCACTIVATE消息到这个工具窗口,   ; / /但如果它是在同一个窗口,在这里调用。请注意,&# 160; / /我们替代的LPARAM -1表明这是一个 / / spoof'ed消息发送。操作系统将永远 / /发送WM_NCACTIVATE LPARAM = -1。 如果(DWP - GT; HWND = HWND放大器;放大器;!HWND =(HWND)lParam参数)   ; SendMessage消息(DWP - GT; HWND,WM_NCACTIVATE,fKeepActive,-1); } } 返回DefWindowProc(HWND,WM_NCACTIVATE,fKeepActive,LPARAM);}
上面的代码使用无证WM_NCACTIVATE消息,我观察到,而这些激活消息试验的功能。 MSDN文档,lParam是未使用(大概是零),但是这是不是下的Windows 95,98,ME和NT,2000,XP的。
相反,lParam是一个被激活/停用在我们的地方(即,如果我们被停用,lParam的将被激活的窗口句柄)到其他窗口处理。这是情况并非总是如此,特别是当其他窗口被激活/停用属于另一个进程。在这种情况下,LPARAM将为零。 所有工具窗口的启用状态
现在,我们需要解决的其他问题。当我们的所有者窗口被禁用(也许是因为一个模态对话框或消息框弹出),我们需要禁用所有工具窗口。此功能可以防止用户点击,不仅激活主窗口,而且任何工具窗口,而模态对话框或消息框显示。
解决方案是我们如何解决激活问题类似,只不过这一次,我们写一个函数,调用时,它接收到WM_ENABLE的消息的一个工具窗口或所有者窗口。 DockingEnable简单地启用/禁用所有的工具窗口,同一个国家作为所有者窗口./*********************** DockingEnable()***** ***************** *发送WM_ENABLE所有者的所有工具窗口。 *一个窗口接收呼叫 * WM_ENABLE消息。 * *容器=所有者窗口的句柄。 * HWND =处理窗口收到WM_ENABLE( *所有者,或它的一个工具窗口)。 *的wParam = WM_ENABLE消息的WPARAM。 * lParam的WM_ENABLE消息的LPARAM。 * /LRESULT WINAPI DockingEnable(HWND的容器, &# 160; HWND HWND,WPARAM wParam参数,GT; LPARAM lParam的){ & #160;DOCKINFO * D​​WP; 而((DWP = DockingNextToolWindow(容器))) { / /同步工具窗口相同的状态,所谓的窗口 / / DockingEnable(但如果是这里所谓的窗口)。 (DWP - GT; HWND HWND)EnableWindow(DWP - GT; HWND的话,wParam);  60;} / /允许的窗口称为DockingEnable处理其WM_ENABLE / /因为它通常会。 返回DefWindowProc(HWND,WM_ENABLE,WPARAM,LPARAM);} 一个工具窗口
前面的讨论,通过必要的步骤来创建浮动工具窗口。现在,我们将讨论的技术要得到这些"码头"与他们的所有者窗口的浮动窗口。我不会重现图书馆的所有在本教程的源代码,因为相当多的是参与。我,而不是去给所采取的方法的概述,你可以学习的大汗注释的源代码。
首先,我们需要定义"停靠"和"脱开"的条款。脱开时,浮动工具窗口。因为我们已经知道,为了做到这一点,该工具窗口必须具有WS_POPUP风格。
另一方面,一个工具窗口停靠时,在视觉上完全包含在它的所有者窗口,除了主人的边界之一。为了做到这一点,我们必须与WS_CHILD没有WS_POPUP风格(或更改从WS_POPUP风格WS_CHILD)创建工具窗口,其所有者窗口也是它的父窗口。当一个工具窗口WS_CHILD样式,操作系统限制它的父窗口的面积内,和工具窗口图形"挂靠"到它的父窗口(即最终用户移动时,孩子的父窗口窗口自动移动)与它。
,但是请注意,当父窗口大小,父窗口也需要移动/调整停靠的工具窗口,使工具窗口仍然"所附的"边境。 (当然,我们的图书馆功能的所有者窗口可以调用使尽可能容易。)
一个良好的对接库必须让最终用户可以停靠和移除任何工具窗口,用鼠标抓取工具窗口,拖动它到一个可停靠或undockable地区。有许多不同的方式来实现对接窗口。这是因为没有标准,对接内置在Windows窗口支持。应用程序开发人员必须实现自己的对接窗口,或呼吁依靠第三方库,为他们做的工作(如MFC)。
对接窗口的实现有两种常见的类型。最常见的(和直观的,在我看来)是用鼠标,你抢的工具窗口("抓手栏"或它的标题栏),并在屏幕上拖动的类型。时当您拖动工具窗口,而不是窗口本身在动,一拖的矩形(反馈长方形)异或在屏幕上,显示窗口将移动到你释放鼠标时的轮廓 - 窗户喜欢的方式工作全窗口拖动是关闭的。使用这种方法,当一个窗口,是从一个窗口拖到/,反馈矩形明显的变化表明,该窗口可以被丢弃。这是对接的实施,我们的对接库使用。的被拖动工具窗口。你可以看到拖动矩形。
对接实施的第二类中可以找到一些新的风格的应用程序(如Microsoft Outlook)。 ,取而代之的是反馈矩形,窗口可直接"teared"或"啪"打开或关闭所有者窗口 - 即其卡入到位,只要你操纵他们。就我个人而言,我不喜欢这种类型的用户界面,和我们对接库不使用它。
我们的工具窗口将具有以下特点:停靠工具窗口将有一个沿其左侧的"抓手栏",使用户能够抓住它和移除。一个工具,因为它是在屏幕上移动窗口将使用反馈(拖动)矩形 - 即使"全窗口拖动"系统设置生效。这是显示在上面的图片。虽然在屏幕上拖一拖矩形,在某些时候,它会相交它的所有者窗口的边界之一。发生这种情况时,拖动矩形将要发生明显变化,以反映该工具窗口现在在"区域"对接。正常的惯例是宽(说三个像素)的阴影矩形代表一个浮动的位置,并为一个单一的像素矩形代表一个停靠位置。当鼠标拖动工具窗口后释放,测试必须看到,如果窗口应停靠或浮动。 (即拖动矩形最终转移到这些"区域"对接之一,或者是它之外的任何这类地区,因此工具窗口是浮动的吗?)最终用户的自由裁量权,可以迫使一个工具窗口浮动,即使当拖动矩形是一个可停靠区域释放。这通常是实现最终控股LT的用户; Controlgt;键向下。当浮动工具窗口可以调整大小,就像任何普通的窗口。没有特殊的处理,必须要做到这一点 - 在这种情况下可以使用标准的Windows上浆行为。停靠时,可以调整大小工具窗口,垂直或水平(而非两组)增加或减少其大小。停靠工具窗口的顶部或底部的边界,它的主人,可以调整水平。工具窗口停靠在左或右的边界,可以调整垂直。当用户双击浮动工具窗口的标题栏,或停靠窗口的抓手栏,工具窗口切换浮动停靠,或反之亦然。
我们的对接库储存是否工具窗口停靠或浮动的轨道。而如果是停靠,我们需要知道,所有者的边界的工具窗口停靠。 uDockedState领域的DOCKINFO用于存储这种状态。如前所述,如果这一领域是与DWS_FL​​OATING"或"运算,然后工具窗口是浮动的。 ,如果没有DWS_FL​​OATING"或"运算,然后停靠工具窗口,和外地的其余位是DWS_DOCKED_LEFT,DWS_DOCKED_RIGHT,DWS_DOCKED_TOP,或DWS_DOCKED_BOTTOM点名工具窗口停靠边境。
我们需要可以切换之间的一个子窗口(对接)和一个弹出窗口(浮动),工具窗口。这是与下面所示的代码基本完成。 / /假设"; dwpquot;是一个工具窗口的DOCKINFO指针。 DWORD dwStyle = GetWindowLong(DWP - GT; HWND,GWL_STYLE); / /目前浮动的窗口? 如果(DWP - GT; uDockedState放大器; DWS_FL​​OATING) { / /从WS_POPUP WS_CHILD切换。我们通过改变 &# 160; / /窗口的风格标志,删除WS_POPUP,并添加  60; / / WS_CHILD。接着,我们作为母公司的所有者窗口。  ; SetWindowLong函数(DWP - GT(HWND,GWL_STYLE,dwStyle放大器;〜WS_POPUP)| WS_CHILD); SetParent(DWP - GT; HWND,DWP - GT;容器); } 其他 &# 160;{ / /从WS_CHILD WS_POPUP切换。我们通过改变 / /窗口的风格标志,删除WS_CHILD,并添加 / / WS_POPUP。然后,我们要确保它没有父。 SetWindowLong函数(DWP - GT; HWND,GWL_STYLE,(dwStyle放大器;〜WS_CHILD)| WS_POPUP);  60; SetParent(DWP - GT; HWND,NULL); }
看第二SetParent在上面的代码中的API调用。只有这样,才能使之成为一个弹出窗口(浮动)一个孩子(对接)窗口是它的父窗口设置为零(NULL)。因为该工具窗口不再有父母,这是不是在视觉局限于一些其他的窗口。它可以自由浮动在桌面。但是,因为它仍然有一个所有者窗口,操作系统不断,所有者窗口上方的浮动。换句话说,当一个窗口停靠,它的所有者窗口,也是它的父窗口。当一个窗口是浮动的,其所有者窗口不再是其母公司以及。 规模与停靠
如前所述,一个工具窗口,可以在两种状态之一:停靠或浮动(脱开)。我们将记住无论在其浮动状态的工具窗口的大小,其停靠状态,此信息存储在DOCKINFO。这样,最终用户可以给工具窗口大小不同的两个国家。因为我们还允许最终用户快速双击抓手/标题栏切换这两个国家之间,我们需要记住的工具窗口的最后定位在这两个州。
当一个工具窗口是浮动的,它可以调整其大小就像一个正常的窗口。这意味着我们将需要在DOCKINFO存储的宽度和高度。当然,为了记住它的位置,我们需要存储它的X和Y位置(屏幕坐标)。这些值存储在DOCKINFO的cxFloating,cyFloating,xpos和yPos领域分别。
注:cxFloating和cyFloating实际上是设置为浮动工具窗口的客户端(内部)面积,而不是工具窗口本身(包括其标题栏和边框)的物理尺寸的大小。这是因为我们总是希望客户区大小保持不变,即使在系统设置的变化(即修改标题栏的高度是使用控制面板)。
当一个工具窗口停靠,它可以被调整只在一个方向 - 垂直或水平。这意味着,我们需要记住的只是它的宽度或高度,但不能同时。如果该工具窗口停靠所有者的顶​​部或底部的边界,那么我们记得它的高度。如果该工具窗口停靠到主人的左或右的边界,那么我们记得它的宽度。无论我们记得的价值,我们店DOCKINFO的nDockedSize领域。至于其立场而言,已经记住DOCKINFO uDockedState领域。 与拖动矩形的窗口
我们遇到的第一个障碍是让Windows显示反馈矩形,当最终用户移动浮动窗口。与Windows 95开始,一个新的用户界面功能进行了介绍。此功能通常被称为"显示窗口内容拖动时"。启用时,窗口不再移动和大小使用标准的反馈矩形。
不幸的是,有没有办法把特定的Windows功能。 SystemParametersInfo API调用(SPI_GETDRAGFULLWINDOWS设置),可以把这个功能关闭,但是这是一个系统范围的设置,是不是真的适合。当然,我们可以设计一种方法,我们暂时关闭拖动窗口的系统设置在窗口移动(实际上,这将是很直接)。的一点是,它的一劈位,我喜欢这样的问题的妥善解决。
唯一的解决办法是重写标准的Windows的行为和手动提供反馈矩形。这意味着加工几下鼠标消息。现在,我不希望显示任何代码 - 再次,源代码清楚地演示了如何得到这方面的工作(在工具窗口的窗口过程,dockWndProc)。 {五}{ { };&# 160; &# 160;  60;  0;  0; } * * /{  0; & #160; } * * /{ 0;  60; { & #160; } 返回TRUE;} 应用程序 { & #160; {   ; { &# 160;   ; &# 160;   ; & #160;  0; {  60; 回报; & #160; }  0; }& #160; } 其他 } { &# 160; &# 160;   ; & #160;   ;  0;   ;  60; 返回0; } { &# 160; }& #160; { & #160;   ; } { & #160; ... ...{ 开关(消息) { 案件的WM_COMMAND: & #160;{ {  60;   ; { & #160;  60; 返回0; }  60; } } } 返回-1;} {  60; &# 160; ... ...{ & #160; & #160;}  60; { & #160; RegCloseKey(HKEY); } { & #160; {  0; &# 160; RegCloseKey(HKEY); }  0; ... ... 结论历史































谢谢!








行为。



----{ BR}

回答