Providing Windowless Activation
Home | Overview | How Do I | FAQ | Tutorial | Sample
Window creation code (that is, everything that happens when you call CreateWindow) is costly to execute. A control that maintains an on-screen window has to manage messages for the window. Windowless controls are therefore faster than controls with windows.
A further advantage of windowless controls is that, unlike windowed controls, windowless controls support transparent painting and nonrectangular screen regions. A common example of a transparent control is a text control with a transparent background. The controls paints the text but not the background, so whatever is under the text shows through. Newer forms often make use of nonrectangular controls, such as arrows and round buttons.
Often, a control does not need a window of its own and, instead, can use the window services of its container, provided that the container has been written to support windowless objects. Windowless controls are backward compatible with older containers. In older containers not written to support windowless controls, the windowless controls simply create a window when active.
Since windowless controls do not have their own windows, the container (which does have a window) is responsible for providing services that would otherwise have been provided by the control’s own window. For example, if your control needs to query the keyboard focus, capture the mouse, or obtain a device context, these operations are managed by the container. The container routes user input messages sent to its window to the appropriate windowless control, using the IOleInPlaceObjectWindowless interface. (See the ActiveX SDK for a description of this interface.) COleControl member functions invoke these services from the container.
To make your control use windowless activation, include the windowlessActivate flag in the set of flags returned byCOleControl::GetControlFlags. For example:
The code to include this flag is automatically generated if you select the Windowless Activation option on the Advanced ActiveX Features page of the ControlWizard dialog box.
When windowless activation is enabled, the container will delegate input messages to the control’s IOleInPlaceObjectWindowless interface. COleControl’s implementation of this interface dispatches the messages through your control’s message map, after adjusting the mouse coordinates appropriately. You can process the messages like ordinary window messages, by adding the corresponding entries to the message map. In your handlers for these messages, avoid using the m_hWnd member variable (or any member function that uses it) without first checking that its value is not NULL.
COleControl provides member functions that invoke mouse capture, keyboard focus, scrolling, and other window services from the container as appropriate, including:
GetFocus,SetFocus
GetCapture,SetCapture,ReleaseCapture
GetDC,ReleaseDC
InvalidateRgn
ScrollWindow
GetClientRect
In windowless controls, you should always use the COleControl member functions instead of the corresponding CWnd member functions or their related Win32 API functions.
You may want a windowless control to be the target of an OLE drag-and-drop operation. Normally, this would require that the control’s window be registered as a drop target. Since the control has no window of its own, the container uses its own window as a drop target. The control simply provides an implementation of the IDropTarget interface to which the container can delegate calls at the appropriate time. To expose this interface to the container, overrideCOleControl::GetWindowlessDropTarget. For example:
Message dispatching
Windowless objects rely on their containers to dispatch window messages to them, capture the mouse, and get the keyboard focus. The container calls IOleInPlaceObject::OnWindowMessage to dispatch a window message to a windowless object. This method is similar to the SendMessage Windows API function except that it does not require an HWND parameter and it returns both an HRESULT and a LRESULT.
A windowless object must not call the DefWindowProc Windows API function directly. Instead, it calls IOleInPlaceSiteWindowless::OnDefWindowMessage to invoke the default action, for example with WM_SETCURSOR or WM_HELP that should be propagated back up to the container. Thus, the container has a chance to handle the message before the object processes it.
For mouse messages, the object calls IOleInPlaceSiteWindowless::Set Capture to obtain the mouse capture and IOleInPlaceSiteWindowless::SetFocus to get the keyboard focus.
A windowless object handles accelerators and mnemonics as follows:
Accelerators
The UI active object checks for its own accelerators in IOleInPlaceActiveObject::TranslateAccelerator. A windowless object does the same. However, a windowless object cannot send a WM_COMMAND message to itself, as a windowed object would do. Therefore, instead of translating the key to a command, a windowless object should simply process the key right away.
Except for that one difference, windowless objects should implement the IOleInPlaceActiveObject::TranslateAccelerator method as defined in the OLE specifications. In particular, a windowless object should pass the accelerator message up to its site object if it does not wish to handle it. The windowless object and returns S_OK if the message got translated and S_FALSE if not. In the case of a windowless object, the message is processed instead of translated. Non translated messages will come back to the object through the IOleInPlaceObjectWindowless::OnWindowMessage method.
Note that because the container's window gets all keyboard input, a UI active object should look for messages sent to that window to find those it needs to process in its IOleInPlaceActiveObject::TranslateAccelerator method. An object can get its container's window by calling IOleWindow::GetWindow.
Mnemonics
Control mnemonics are handled the same way whether the control is windowless or not. The container gets the control mnemonic table by calling IOleControl::GetControlInfo and then calls IOleControl::OnMnemonic when it receives a key combination that matches a control mnemonic.
Drag & drop onto windowless objects
Since a windowless object does not have a window when it is active, it cannot register its own IDropTarget interface with the RegisterDragDrop function. However, to participate in drag and drop operations, a windowless object still must implement this interface. The object supplies its container with a pointer to its IDropTarget interface through IOleInPlaceObjectWindowless::GetDropTarget instead of having the container call QueryInterface for it. See IOleInPlaceObjectWindowless::GetDropTarget for more information on drag and drop operations involving windowless objects.
In-place drawing for windowless objects
With windowed objects, the container is only responsible for drawing the object when it is inactive. Windowed objects have their own window when they are active and can draw themselves independently of their container.
A windowless object, however, needs services from its container to redraw itself even when it is active. The container must provide the object with information about its surrounding environment, such as the clipping region, the background, overlapping objects in front of the object being redrawn, and a device context in which to draw.
The IOleInPlaceSiteWindowless interface on the container's site object provides these services: drawing the object, obtaining and releasing the device context, invalidating the object's on-screen display, scrolling the object, or showing a caret when the object is active.
Note All methods of IOleInPlaceSiteWindowless take position information in client coordinates of the containing window, that is, the window in which the object is being drawn.
Drawing windowless objects
To maintain compatibility with windowed objects, the container still uses IViewObject::Draw to redraw the in-place active, windowless object. See IViewObject::Draw for information on how the method is used with windowless objects.
Obtaining and releasing a device context
To draw on its own when in-place active, a windowless object must call its site's IOleInPlaceSiteWindowless::GetDC method to get a device context in which to draw. Then, it draws into the device context and releases it by calling IOleInPlaceSiteWindowless::ReleaseDC.
Display Invalidation
In-place windowless objects may need to invalidate regions of their on-screen image. Even though the notification methods in IAdviseSinkEx can be used for that purpose, they are not ideal for in-place active objects because they take HIMETRIC coordinates. In order to simplify and speed up in-place drawing, the InvalidateRect and InvalidateRgn methods in the IOleInPlaceSiteWindowless interface provide the same functionality.
An object cannot call the Windows API functions InvalidateRect and InvalidateRgn directly on the window handle it gets from calling IOleInPlaceSiteWindowless::GetWindow on its site.
Scrolling
In-place active windowless objects may need to scroll a given rectangle of their on-screen image, for example, with a multi-line text control. Because of transparent and overlapping objects, the Windows API functions ScrollWindow and ScrollDC cannot be used. Instead, the IOleInPlaceSiteWindowless::ScrollRect method enables objects to perform scrolling.
Caret support
A windowless object cannot safely show a caret without first checking whether the caret is partially or totally hidden by overlapping objects. In order to make that possible, an object can submit a rectangle to its site object when it calls the site's IOleInPlaceSiteWindowless::AdjustRect method to get a specified rectangle adjusted (usually, reduced) to ensure the rectangle fits in the clipping region.
你是不是没有装帮助。我给你拷下来。
IOleInPlaceSiteWindowless
The IOleInPlaceSiteWindowless interface is derived from and extends the IOleInPlaceSiteEx interface. IOleInPlaceSiteWindowless works with IOleInPlaceObjectWindowless which is implemented on the windowless object. Together, these two interfaces provide services to a windowless object from its container allowing the windowless object to:
process window messages
participate in drag and drop operations
perform drawing operations
Having a window can place unnecessary burdens on small objects, such as controls. It prevents an object from being non-rectangular. It prevents windows from being transparent. It prevents the small instance size needed by many small controls.
A windowless object can enter the in-place active state without requiring a window or the resources associated with a window. Instead, the object's container provides the object with many of the services associated with having a window.
Windowless object model
Windowless objects are an extension of normal compound document objects. They follow the same in-place activation model and share the same definitions for the various OLE states, with the difference that they do not consume a window when they enter the in-place and UI active states. They are required to comply with the OLE compound document specification, including in-place and UI activation.
Windowless objects require special support from their container. In other words, the container has to be specifically written to support this new kind of object. However, windowless objects are backward compatible with down level containers. In such containers, they simply create a window when active and behave as a normal compound document object.
As with other compound document objects, windowless objects need to be in-place active to get mouse and keyboard messages. In fact, since an object needs to have the keyboard focus to receive keyboard messages, and having the keyboard focus implies being UI active for an object, only UI active objects will actually get keyboard messages. Non-active objects can still process keyboard mnemonics.
Since windowless objects do not have a window, they rely on their container to receive window messages for them. The container dispatches its own window messages to the appropriate embedded, windowless object through calls to IOleInPlaceObjectWindowless methods. Similarly, windowless objects can obtain services from their container such as capturing the mouse, setting the focus, getting a device context in which to paint, and so on. The control calls IOleInPlaceSiteWindowless methods. In addition, the container is responsible for drawing any border hatching as well as the grab handles for the control.
These two interfaces are derived from existing interfaces. By extending existing interfaces rather than creating new ones, no new VTable pointer is added to the object instance, helping to keep the instance size small.
Client and server negotiations with windowless objects
When a windowless object gets in-place activated, it should query its site for the IOleInPlaceSiteWindowless interface. If this interface is supported, the object calls IOleInPlaceSiteWindowless::CanWindowlessActivate to determine if it can proceed and in-place activate without a window.
If the container does not support IOleInPlaceSiteWindowless or if the IOleInPlaceSiteWindowless::CanWindowlessActivate method returns S_FALSE, the windowless object should behave like a normal compound document object and create a window.
The container can get the window handle for an embedded object by calling IOleWindow::GetWindow. This method should fail (return E_FAIL) for a windowless object. However, a container cannot be sure that the object is windowless by calling this method. The object may have a window but may not have created it yet. Many existing objects only create their window after calling the OnInPlaceActivate method on their site object.
Consequently, a windowless object must call the new IOleInPlaceSiteEx::OnInPlaceActivateEx method on its site object, instead of OnInPlaceActivate. The dwFlags parameter for this new method contains additional information in the ACTIVATEFLAGS enumeration. The ACTIVATE_WINDOWLESS enumeration value indicates that the object is activated without a window. Containers can cache this value instead of calling the GetWindow method on the IOleWindow interface repeatedly.