Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 96
Текст из файла (страница 96)
All sprites have to be associated withA SIMPLE HANDWRITING ANIMATION DLL455a window, and they will always be clipped to the area of that window. Ifyou specify a group window, as I do in the previous code, then the spritewill be allowed to display over the whole screen. By default, the spritewill also be clipped to the window’s visible area. In this case, however,my code specifies the flag ESpriteNoChildClip, which means thatthis clipping is not done.
Thus the hand writing will always be ableto appear over the whole screen, even if the group window involvedis behind other windows. The other flag, ESpriteNoShadows, meansthat even if there is a shadow-casting window above the sprite window,WSERV will not shadow the pixels of the sprite. Once the sprite has beencreated, I add a member or frame to it. This is done in the final two linesof the function.The other point of note in this function is the color depth withwhich the sprite’s bitmaps are created. When sprites are drawn to thescreen, WSERV uses either BitBlt() or BitBltMasked() from theCFbsBitGc class.
These functions execute much faster when the bitmapthat they are drawing and the bitmap or screen that they are drawing itto have the same color depth. For a sprite that is normally viewed overa window, it is best to set the sprite’s bitmaps to the same color depthas the window. However, for the handwriting anim, where the sprite iseffectively viewed over the whole screen, it is best to choose the defaultcolor mode of windows, since most applications will be running withthis color depth.
You can find out what this is by calling the functionGetDefModeMaxNumColors().Having created the sprite, we can create the anim. There are two stagesto this – first we ask WSERV to load the anim DLL and then we createthe instance of the sprite animation. We do this using the following twofunctions, the second being called by the first:void CHandWriting::LoadDllL(){_LIT(DllName,"HandAnim.DLL");TInt err=iAnimDll.Load(DllName);if (err==KErrNone)err=iAnim.Construct(iSprite);if (err==KErrNone){iAnim.Activate();iActive=ETrue;}User::LeaveIfError(err);}TInt RHandWritingAnim::Construct(const RWsSprite& aDevice){TPtrC8 des(NULL,0);return RAnim::Construct(aDevice,0,des);}456THE WINDOW SERVERTo load the anim DLL, you must give WSERV the name of the DLLinvolved. You do this using an RAnimDll object.
Then you need anRAnim-derived class – since the interface of RAnim is protected to forceyou to derive from it. The interface to the anim constructor has threeparameters. These are the sprite of the window, a type and the configuration data packed in to a descriptor. The type allows one anim DLL tohave many anim types, this being the way to specify which one to create.In my example, the handwriting anim only has one type, and there is noconfiguration data used.11.7.7Other client-side codeRHandWritingAnim contains several other functions for communicating with the anim. Here are a couple of examples:void RHandWritingAnim::SetDrawData(const THandwritingDrawData& aDrawData){TPckgBuf<THandwritingDrawData> param;param()=aDrawData;Command(EHwOpSetDrawData,param);}TInt RHandWritingAnim::GetLastGeneratedCharacter(){return CommandReply(EHwOpGetLastChar);}The first of these functions tells the handwriting animation to drawthe digital ink differently (that is, with different color or line width).This requires the sending of data to the anim – this is packaged into adescriptor using the TPckgBuf class.
Since no return value is needed,it can just use the RAnim::Command() function. This will in turnbe passed to the function CHandWritingAnim::Command() function.The second function is passed the code of the last generated character.There is no data to send with this request, so it doesn’t need to use aTPckgBuf, but since it does require a reply, it uses RAnim::CommandReply() and this request gets sent in turn to the function CHandWritingAnim::CommandReplyL().11.8Window objects and classesWindows are the mechanism that Symbian OS uses to control accessto the screen.
They are rectangular by default and may overlap eachWINDOW OBJECTS AND CLASSES457other. They have a front to back order, and this defines which of twooverlapping windows is in front. Applications may create and destroywindows. Windows are individually addressable, and an application candraw to only one of its windows at a time. Typically an application willhave many windows.Windows are important since they allow different applications to drawto different parts of the screen at the same time. Furthermore, applicationsdo not need to concern themselves with which part of the screen they areallowed to draw to. An application just draws to its window, and only ifthat window is visible will it appear on the screen.In the following sections, I will cover the window tree, the ways inwhich WSERV navigates this structure, window classes and their structure,the properties of windows, drawing windows and more.
I will also coverDirect Screen Access (DSA), which could also be described as drawingwithout windows.11.8.1 Diagram of the window treeFigure 11.3 shows the relationships between different windows. It ispresented as an upside down tree. It shows what different window typescan appear at which point in the tree.Figure 11.3 shows four types of windows (although one of them, GroupWin, is never displayed and so is not a window as windows are definedabove). This diagram is an object diagram in which each row can onlycontain objects of a certain class type. The different types of windowsshown are:• The root window. WSERV creates this window; it is not directlyaccessible to any client.
It is used as a starting point for the windowstructure and exists throughout the life of the system. On multiplescreen devices there will one of these for each screen• Group windows. These windows can only be direct children of theroot window. WSERV’s client creates them, but they do not haveany associated screen area. They provide a way for a client to grouptogether some of its windows, so that it can move them together• Top client window. The third row in the figure consists only of topclient windows.
These windows are displayable, and so a client willneed at least one of these• Client windows. All the subsequent rows of the diagram consist ofclient windows. A client can have anything from no client windowsto multiple levels of nested client windows.458THE WINDOW SERVERRoot WinGroup WinGroup WinGroup WinTop ClientTop ClientTop ClientClient WinClient WinClient WinClient WinClient WinClient WinSiblingChild............KEYParentFigure 11.3 Relationships between windowsThe following table shows the classes that represent these types ofwindows, on both the client and server side:Window typeClient-side classServer-side classRoot Window<none>CWsRootWindowGroup WindowRWindowGroupCWsGroupWindowTop Client WindowSubclass of RWindowBaseCWsTopClientWindowClient WindowSubclass of RWindowBaseCWsClientWindowWINDOW OBJECTS AND CLASSES45911.8.2 Traversing the window treeFigure 11.3 contains three different types of arrows.
These representpointers to objects, and give the structure of the window tree thus:• Parent. These are the arrows that point upward. All windows havea pointer to their parent window on the line above. (Since the rootwindow doesn’t have a parent, its pointer will be NULL)• Child. These are the diagonal arrows down to the left. They showthat if a window has any child windows, then it will have a pointerto the first, usually the oldest, such window. (By default the pointerwill denote the first window created, but of course the order of thechildren can be changed, so this is not always the case)• Sibling.
These are the arrows going across to the right. They show thateach window knows the next oldest window with the same parent.Siblings form a singly linked list of all windows with the same parent.(As for the child pointer, this oldest to youngest ordering holds at thetime the windows are created, but may subsequently be altered.)These pointers are defined in the server-side class CWsWindowBase,which is the base class for all server-side window classes, as I will showlater. You can use the pointers to move through the window objects invarious ways.
For example, to get to the oldest sibling of your parent, younavigate using iParent->iChild.Let’s look at a more complex example of the use of these pointers. Thefollowing function updates the pointers when a window is removed fromthe window tree:void CWsWindowBase::Disconnect(){if (iParent!=NULL){CWsWindowBase** prev=&iParent->iChild;while ((*prev)!=this)prev=&(*prev)->iSibling;*prev=iSibling;}}When a window is removed from the window tree, only one pointerneeds to be updated. If the window is the oldest child of its parent, thenthe parent’s child pointer needs to be updated. If it is not, then its nextoldest sibling’s iSibling pointer needs updating.