1. 程式人生 > >分層視窗(Layered windows)翻譯

分層視窗(Layered windows)翻譯

Layered Windows

Windows 2000 introduces a new extended window style bit: WS_EX_LAYERED. When used properly, it can significantly improve performance and visual effects for a window that has a complex shape, animates, or wishes to use alpha-blending effects.

windows 2000引入了新的視窗擴充套件風格,其標識位為WS_EX_LAYERED.合理使用該風格即可顯著改善那些擁有複雜形狀、繁雜繪製或者希望擁有混合透明效果的視窗效能及其視覺效果。

Windows appear as rectangles on the screen clipped by other windows. For a window in an application to look like a circle, it's not enough for the application to simply paint a window as a circle; the system will continue to hit test this window as a rectangle and windows underneath this window will still be clipped by the window's rectangle. So, the window will look and behave like a gray rectangle with a circle in the middle.

Some applications might take a snapshot of the visual bits underneath the window before it was actually shown and later compose those bits with the window bits. This approach doesn't quite work in a multiprocess, multitasking environment, because other windows can paint underneath this window. The application has no way of knowing when such painting occurs or how to somehow retrieve the newly painted bits underneath.

視窗以矩形的形式出現在螢幕上,並且被其它視窗所裁剪。例如應用程式中一個圓形的視窗,僅僅依靠程式將其繪製為一個圓形是不夠的;系統仍然通過點選測試將其視為一個矩形,其下的視窗也仍然被這個矩形所裁剪。所以該視窗看似為圓形,但依然擁有矩形視窗的行為。

一些應用程式會採取在顯示自身視窗之前以快照的形式,記錄下自身視窗下其餘視窗的可視區域位,然後將記錄下的這些位與自身進行組合的方式,以實現透明。然而該方式在多程序、多工的環境中卻並不能很好工作,因為其餘的視窗會繪製該視窗之下的視窗部分。應用程式自身不能獲知該種繪製行為何時會發生,也不能夠取得那些最新的繪製資訊。

譯者注:這裡原文中的例子表述不夠形象,在此我更加白話描述一下吧。

假設我們要做一個時鐘應用程式,時鐘是圓形的,我們自然是用一個windows視窗予以實現。然而請注意一下幾點:

1.     windows中的每個視窗都是一個矩形,可以通過下面將要提到的視窗區域改變其形狀,但我們這裡保持視窗的矩形狀態。

2.     我們要用矩形的視窗實現圓形的時鐘視窗,怎麼辦呢?我將之稱為視覺虛擬方法。具體做法如下:

a.     在矩形視窗中央繪製一個圓形,作為時鐘形狀。

b.     將時鐘圓形面之外的所有矩形區域設定為透明。這樣使用者看到的就只有視窗的圓形區域,這樣就實現了時鐘的效果。但請記住我們的視窗仍然是矩形。接下來就是如何設定透明瞭,原文描述採用的是這樣的方式:設法獲得我們矩形視窗之下,其餘視窗與我們視窗重合區域的顏色資訊,然後將這些資訊繪製到我們視窗的非時鐘圓的其餘區域。說白了就是把下面視窗的樣子畫到我們自己視窗上,給人的錯覺就是自己的視窗透明瞭看到了下面視窗的樣子。---DONE

In Windows 95/98 and Windows NT® 4.0 the proper way for an application to create a window with a complex shape, such as a rounded balloon or a cool transparent digital clock, is to specify the shape by supplying the window region representing the shape via the SetWindowRgn API. There are several drawbacks to using window regions. If a regional window animates its shape frequently or is dragged on the screen, Windows will have to ask windows beneath the regional window to repaint. Besides generating more message traffic, the calculations that occur when Windows tries to figure out invalid regions or visible regions become increasingly expensive when a window has an associated region. In addition, using window regions only addresses transparency—that is, color-key effects. It does not address translucency—that is, a way to top-level windows.

windows95/98 windows NT 4.0中,應用程式要建立一個具有複雜形狀視窗(例如圓形的氣球狀、透明的數字時鐘)的一般方法,是通過呼叫SetWindowRgn併為其提供描繪視窗形狀的視窗區域引數。然而,使用視窗區域是帶有一些缺陷的:如果一個視窗反覆的繪製自己或被頻繁地在螢幕上拖曳,windows就會要求該視窗之下的其餘視窗重繪自己。其結果除了因大量訊息而導致的擁堵外,也將使windows因為反覆地計算視窗無效區域和可視區域,而浪費昂貴的資源與時間。此外使用視窗區域只能處理視窗透明而不能處理半透明的效果。

譯者注:

1.     例如我們要建立一個橢圓形的視窗,在MFC中的實現方法是:

  1. CRect rect;  
  2. GetWindowRect(&rect);  
  3. this->ScreenToClient(&rect);  
  4. CRgn region;  
  5. region.CreateEllipticRgn(rect.left, rect.top, rect.right, rect.bottom);  
  6. SetWindowRgn((HRGN)region.GetSafeHandle(), TRUE);  
2.   視窗透明與半透明的區別:

視窗透明: 針對某一特定顏色。透過該顏色的區域可以看到下層視窗,並且該區域不捕獲滑鼠訊息,

點選這些區域會使下層視窗獲得捕獲滑鼠,而使其獲得輸入焦點。

視窗半透明:針對整個視窗。透過整個視窗都可以看見下層視窗,當alpha值不為0時,該視窗能捕

所有自身的滑鼠點選訊息。當alpha值為0時,所有滑鼠點選訊息都被下層視窗擁有。

This is where layered windows come to the rescue. Layered windows really encompass two different concepts: layering—windows' ability to exhibit sprite-like behavior; and redirection—the system's ability to redirect the drawing of legacy windows into an off-screen buffer.

這便是分層視窗發揮作用的地方。分層視窗包含了兩個概念:分層---視窗展示自己幽靈般行為的能力(半透明);重定向---系統將原有視窗的繪製重定向到一個離屏緩衝區的能力。

Using a layered window can significantly improve performance and visual effects for a window that has a complex shape, animates its shape, or wishes to use alpha blending effects. The system automatically composes and repaints layered windows and the windows of underlying applications. As a result, layered windows are rendered smoothly, without the flickering typical of complex window regions. In addition, layered windows can be partially translucent, that is, alpha-blended.

使用分層視窗可以顯著提高那些擁有複雜形狀、或希望使用alpha混合效果的視窗效能及其視覺外觀。系統會自動組合並重繪分層的視窗和其下的其餘視窗。最終分層視窗會被平滑地繪製,而不會出現閃爍。此外,分層視窗還可以擁有alpha混合效果,即半透明效果。

Using Layered Windows使用分層視窗

For any layering to take place, the WS_EX_LAYERED bit needs to be set, either at window creation time or by callingSetWindowLong with GWL_EXSTYLE. Next, the developer has a choice: Use the existing Microsoft Win32® painting paradigm by responding to WM_PAINT and/or other paint messages, or make use of a more powerful layering API,UpdateLayeredWindow.

To use UpdateLayeredWindow, the visual bits for a layered window have to be rendered into a compatible bitmap. Then, via a compatible GDI Device Context, the bitmap is provided to the UpdateLayeredWindow API, along with the desired color-key and alpha-blend information. The bitmap can also contain per-pixel alpha information.

Note that when using UpdateLayeredWindow the application doesn't need to respond to WM_PAINT or other painting messages, because it has already provided the visual representation for the window and the system will take care of storing that image, composing it, and rendering it on the screen. UpdateLayeredWindow is quite powerful, but it often requires modifying the way an existing Win32 application draws.

為了對top-level視窗進行分層,必須為視窗新增WS_EX_LAYERRED擴充套件風格標誌位,方法之一是在視窗建立時呼叫SetWindowLong為其指定GWL_EXSTYLE引數。接下來程式設計師可以選擇使用傳統繪製模式,響應WM_PAINT等繪製訊息,或者可以呼叫更加強大的分層函式UpdateLayeredWindow.

使用UpdateLayeredWindow,分層視窗內的可視資訊必須被繪製到一幅相容點陣圖,然後通過相容GDI裝置上下文,將該點陣圖連同期望的色鍵值和alpha-blend(透明混合)資訊傳遞給UpdateLayeredWindow。同時點陣圖還可以包含單個畫素的alpha資訊。

請注意當使用UpdateLayeredWindow時,應用程式並不需要相應WM_PAINT等繪製訊息,因為它已經提供了描述視窗視覺化的資訊,然後系統會負責處理儲存圖片、組合圖片並將其繪製到螢幕。UpdateLayeredWindow相當強大,但它卻時常要求修改一個win32應用程式的繪製方式。

The second way to use layered windows is to continue using the Win32 painting paradigm, but allowing the system to redirect all the drawing for the layered window and its children into an off-screen bitmap. This can be done by callingSetLayeredWindowAttributes with the desired constant alpha value and/or the color-key. Once the API has been called, the system will start redirecting all drawing by the window and automatically apply the specified effects.

To set the opacity level or the transparency color key for a given layered window, callSetLayeredWindowAttributes.After the call, the system may still ask the window to paint when the window is shown or resized. However, because the system stores the image of a layered window, the system will not ask the window to paint if parts of it are revealed as a result of relative window moves on the desktop. Legacy applications do not need to restructure their painting code if they want to add translucency or transparency effects for a window, because the system redirects the painting of windows that called SetLayeredWindowAttributes into off-screen memory and recomposes it to achieve the desired effect.

使用分層視窗的第二種方式,是遵循win32的繪製模式,但允許系統將分層視窗連同其子視窗的所有繪製操作,重定向到一幅off-screen點陣圖中。其實現方法是呼叫SetLayeredWindowAttributes函式,並指定期望的alpha常量值,也可同時指定色鍵值。一旦呼叫了該API,系統便開始進行繪製重定向實現指定的效果。

為了設定分層視窗的不透明度,或者其透明色鍵值,呼叫SetLayeredWindowAttributes函式。之後,當該視窗需要顯示或其大小改變時,系統仍然會要求其自身進行重繪。然而,由於系統儲存了分層視窗映象,當視窗本身因為桌面其餘視窗的移動而使自身視區改變時,系統並不會要求視窗繪製自己。原有應用程式並不需要重新組織自身的繪製程式碼結構,以實現透明效果,因為系統會將那些呼叫SetLayeredWindowAttributes的視窗的繪製,重定向到一塊離屏記憶體區域,然後重新組合視窗以獲得期望效果。

Using UpdateLayeredWindow attributes may be more efficient at times, because the application may not need to store a memory bitmap for every layered window. The application can keep one memory bitmap and render into it just before calling UpdateLayeredWindow for a number of layered windows. Depending on how often the application calls UpdateLayeredWindow, it can also delete the bitmap after calling the API. On the other hand, windows redirected by the system will always carry the overhead of having to maintain a memory bitmap for every redirected window. This is in addition to the memory normally consumed by a layered window if UpdateLayeredWindow was used to display it. Thus, while certainly more convenient, using SetLayeredWindowAttributes comes with a price tag. If your window does a fast animation, UpdateLayeredWindow is the way to go.

通常使用UpdateLayeredWindow會更加高效,因為使用這種方式應用程式無需為每一個分層視窗都儲存一張點陣圖,而只需儲存一張點陣圖,並在呼叫UpdateLayeredWindow之前對其進行填充繪製。根據應用程式呼叫UpdateLayeredWindow的頻率,可以選擇在呼叫該API之後刪除點陣圖。另一方面,使用SetLayeredWindowAttributes模式時,總是要求系統為每一個被重定向的視窗都維護一塊點陣圖記憶體區域。

且這些記憶體區域並不包括使用UpdateLayeredWindow顯示視窗所需要的記憶體空間。因此,如果你的視窗需要快速的繪製,UpdateLayeredWindow才是最好的選擇。

Please remember that once SetLayeredWindowAttributes has been called on a layered window, subsequentUpdateLayeredWindow calls will fail until the layering style bit is cleared and set again. This is becauseSetLayeredWindowAttributes turns on the redirection of the window's drawing, and once that happensUpdateLayeredWindow can give contradictory information as to what the window really looks like.

請注意一旦為分層視窗呼叫了SetLayeredWindowAttributes,之後的UpdateLayeredWindow呼叫將失敗,直到分層視窗樣式標識位WS_EX_LAYERED被清除,然後被重新設定。因為分層視窗的重定向行為因SetLayeredWindowAttributes而開始,但UpdateLayeredWindow卻提供了關於視窗形狀的相反資訊。

Hit Testing點選測試(命中測試)

Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through.

分層視窗的點選測試,是基於視窗形狀及其透明效果的。這意味著視窗中那些被設定為透明(color-key屬性或alpha值為0)的區域,忽略滑鼠點選訊息而使其被下面的視窗捕獲。

If the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to the other windows underneath the layered window.

如果一個分層視窗含有WS_EX_TRANSPARENT擴充套件風格,那麼視窗形狀將被忽略,滑鼠事件會被傳遞給該視窗之下的其他視窗。

Transition Effects 過渡效果

You don't need to write a lot of code to fade a window in or out. The AnimateWindow API can do all the work for you. In fact, this is how the shell's Start menu and other menus do the open fade-in effect.

你不必編寫許多程式碼去實現視窗的淡入或淡出效果。AnimateWindow函式將為你提供所有支援。實際上這便是shell中開始按鈕或其它選單淡入效果的實現方式。

Internally, AnimateWindow will make your windows layered and give the desired transition effect.

Besides fades, AnimateWindow can also do sliding effects. In fact, if you're writing custom menus, this API can be quite useful. To be a good desktop citizen, your application should figure out whether, when showing the menu, to animate it at all. To get that information, you should query the system via the SystemParametersInfo API using SPI_GETMENUANIMATION. Furthermore, you can use SPI_GETMENUFADE to determine whether to use the slide or the fade

animation effect. Once you know what effect to use, pass in AW_SLIDE to AnimateWindow to get the slide effect and AW_BLEND to get the fade effect.

AnimateWindow also has a parameter that specifies how long the transition should take. Typically, a transition effect shouldn't take longer than 200 milliseconds.

在內部,AnimateWindow會分層你的視窗,並賦予其過渡的效果。

除了淡化效果,AnimateWindow還能實現滑動效果(幻燈片效果)。當你建立一個自定義選單時,該函式將會大有用處。要作為桌面上良好的一員,你的應用程式就應該知道何時去繪製,啟用自己的選單。為了獲得這些資訊,你得通過向SystemParametersInfo傳遞SPI_GETMENUANIMATION標識,以詢問系統。然後你可以使用SPI_GETMENUFADE來決定是否使用淡化或滑動效果。在決定了該使用的效果之後,你就可以向

AnimateWindow傳遞AW_SLIDE以指定滑動效果,或者AW_BLEND指定淡化效果。

AnimateWindow還有一個用於指定過渡時間的引數。通常,一次過渡效果不應超過200毫秒。

Examples of Using Layered Windows(使用分層視窗示例)

If you want a dialog box to come up as a translucent window:

為對話方塊指定半透明效果:

1.     Create the dialog box as usual.

2.     On WM_INITDIALOG, set the layered bit of the window's extended style and callSetLayeredWindowAttributes with the desired alpha value.

The code might look like this:

// Set WS_EX_LAYERED on this window

SetWindowLong(hwnd, GWL_EXSTYLE,GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);

// Make this window 70% alpha

SetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA);