|
|

楼主 |
发表于 2003-11-22 14:05:36
|
显示全部楼层
Drawing A Bitmap In A Window
在窗口中画出Bitmap
Once we got a handle to the pixmap generated from a bitmap, we can draw it on some window, using the XCopyPlane() function. This function allows us to specify what drawable (a window, or even another pixmap) to draw the given pixmap onto, and at what location in that drawable.
一旦我们得到一个从bitmap产生的pixmap的句柄,我们能够使用XCopyPlane(),在某个窗口中把它画出来。这个函数允许我们指定可画的物体(一个窗口,甚至是另外一个pixmap)来把给定的pixmap画到上面去,以及指定画出的位置。
。
/* draw the previously loaded bitmap on the given window, at location */
/* 'x=100, y=50' in that window. we want to copy the whole bitmap, so */
/* we specify location 'x=0, y=0' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy. */
XCopyPlane(display, bitmap, win, gc,
0, 0,
bitmap_width, bitmap_height,
100, 50,
1);
As you can see, we could also copy a given rectangle of the pixmap, instead of the whole pixmap. Also note the last parameter to the XCopyPlane function (the '1' at the end). This parameter specifies which plane of the source image we want to copy to the target window. For bitmaps, we always copy plane number 1. This will become clearer when we discuss color depths below.
如你所能看到的,我们还能拷贝pixmap个给定矩形内的内容,而不是整个pixmap。还要注意传递给XCopyPlane函数额最后一个参数(最后的'1')。该参数指定了我们想要拷贝到目标窗口的源图像是什么plane的。对于bitmap,我们总是拷贝第一号plane。这在我们下面 讨论色深的时候会变得明白一点。
Creating A Pixmap
创建Pixmap
Sometimes we want to create an un-initialized pixmap, so we can later draw into it. This is useful for image drawing programs (creating a new empty canvas will cause the creation of a new pixmap on which the drawing can be stored). It is also useful when reading various image formats - we load the image data into memory, cerate a pixmap on the server, and then draw the decoded image data onto that pixmap.
有时我们想要创建一个未初始化的pixmap,然后我们能在它上面画图。这对于作图程序来说有用(创建一个新的空画布将导致一个新的将要在其上储存绘画内容的pixmap的创建)。在读取各种图像格式的时候也有用处 - 我们把图像数据载入到内存中,在服务器上创建pixmap,然后把图像数据解码之后画到pixmap上。
/* this variable will store the handle of the newly created pixmap. */
Pixmap pixmap;
/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created. */
Window root_win = DefaultRootWindow(display);
/* this variable will contain the color depth of the pixmap to create. */
/* this 'depth' specifies the number of bits used to represent a color */
/* index in the color map. the number of colors is 2 to the power of */
/* this depth. */
int depth = DefaultDepth(display, DefaultScreen(display));
/* create a new pixmap, with a width of 30 pixels, and height of 40 pixels. */
pixmap = XCreatePixmap(display, root_win, 30, 40, depth);
/* just for fun, draw a pixel in the middle of this pixmap. */
XDrawPoint(display, pixmap, gc, 15, 20);
Drawing A Pixmap In A Window
在窗口中画出Pixmap
Once we got a handle to pixmap, we can draw it on some window, using the XCopyArea() function. This function allows us to specify what drawable (a window, or even another pixmap) to draw the given pixmap onto, and at what location in that drawable.
一旦我们获得了pixmap的句柄,我们能在某个窗口上用XCopyArea()函数把它画出来。这个函数允许我们指定给定pixmap要画到的是那个可画对象(窗口,甚至是另一个pixmap),以及画出的位置。
/* draw the previously loaded bitmap on the given window, at location */
/* 'x=100, y=50' in that window. we want to copy the whole bitmap, so */
/* we specify location 'x=0, y=0' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy. */
XCopyArea(display, bitmap, win, gc,
0, 0,
bitmap_width, bitmap_height,
100, 50);
As you can see, we could also copy a given rectangle of the pixmap, instead of the whole pixmap.
如你能看到的,我们也能拷贝pixmap的给定区域,而不是整个pixmap。
One important note should be made - it is possible to create pixmaps of different depths on the same screen. When we perform copy operations (a pixmap onto a window, etc), we should make sure that both source and target have the same depth. If they have a different depth, the operation would fail. The exception to this is if we copy a specific bit plane of the source pixmap, using the XCopyPlane() function shown earlier. In such an event, we can copy a specific plain to the target window - in actuality, setting a specific bit in the color of each pixel copied. This can be used to generate strange graphic effects in window, but is beyond the scope of out tutorial.
一点重要的值得注意的是 - 能够在同一窗口上创建不同色深的pixmap。当我们执行拷贝操作的时候(把pixmap拷贝到窗口,等),我们应当确保源和目标有相同的色深。如果他们色深不同,操作将失败。例外是如果我们使用前面展示的XCopyPlane()函数,拷贝源pixmap的指定bit plane。在这种情况下,我们能拷贝指定plain到目标窗口上 - 实际上,设置一个指定位位每个拷贝象素的颜色。这能用于在窗口中产生奇异的图形效果,但是超过了我们教程的范围。
Freeing A Pixmap
释放Pixmap
Finally, when we are done using a given pixmap, we should free it, in order to free resources of the X server. This is done using the XFreePixmap() function:
最后,当我们用完给定pixmap,为了释放X服务器的资源,我们应当释放它。这通过使用XFreePixmap()函数来完成。
/* free the pixmap with the given ID. */
XFreePixmap(display, pixmap);
After freeing a pixmap - we must not try accessing it again.
在释放pixmap之后 - 我们不能再次访问了。
To summarize this section, take a look at the draw-pixmap.c program, to see a pixmap being created using a bitmap file, and then tiled up on a window on your screen.
总结本节,看看draw-pixmap.c程序,看看使用bitmap文件创建出一个pixmap,并且然后再屏幕上显示于窗口中。
Messing With The Mouse Cursor
改变鼠标光标
Often we see programs that modify the shape of the mouse pointer (also called the X pointer) when in certain states. For example, a busy application would often display a sand clock over its main window, to give the user a visual hint that they should wait. Without such a visual hint, the user might think that the application got stuck. Lets see how we can change the mouse cursor for our windows.
我们时常看到程序在某个状态下改变鼠标指针(也称为X指针)的外形。例如,一个繁忙中的程序时常在它的主窗口上显示沙漏时钟,以给用户一个你应当等待的可视化提示。没有这么一个视觉提示,用户可能认为程序死掉了。让我们看看我们如何改变我们窗口的鼠标光标。
Creating And Destroying A Mouse Cursor
创建和销毁鼠标光标
There are two methods for creating cursors. One of them is by using a set of pre-defined cursors, that are supplied by Xlib. The other is by using user-supplied bitmaps.
有两种创建光标的办法。其中的一种是使用一套预先定义好了的光标,它们是由Xlib提供的。另一个是使用用户提供的bitmap。
In the first method, we use a special font named "cursor", and the function XCreateFontCursor(). This function accepts a shape identifier, and returns a handle to the generated cursor. The list of allowed font identifiers is found in the include file <X11/cursorfont.h>. Here are a few such cursors:
在第一种方法中,我们使用一个名为“光标”的特殊字体,和XCreateFontCursor()函数。这个函数接受一个外形标识符,并且返回产生的光标的句柄。能用的字体标识符的列表可以在<X11/cursorfont.h>中找到。这儿是一些这样的光标:
XC_arrow
The normal pointing-arrow cursor displayed by the server.
XC_pencil
A cursor shaped as a pencil.
XC_watch
A sand watch.
And creating a cursor using these symbols is very easy:
#include <X11/cursorfont.h> /* defines XC_watch, etc. */
/* this variable will hold the handle of the newly created cursor. */
Cursor watch_cursor;
/* create a sand watch cursor. */
watch_cursor = XCreateFontCursor(display, XC_watch);
The other methods of creating a cursor is by using a pair of pixmaps with depth of one (that is, two color pixmaps). One pixmap defines the shape of the cursor, while the other works as a mask, specifying which pixels of the cursor will be actually drawn. The rest of the pixels will be transparent. Creating such a cursor is done using the XCreatePixmapCursor() function. As an example, we will create a cursor using the "icon.bmp" bitmap. We will assume that it was already loaded into memory, and turned into a pixmap, and its handle is stored in the 'bitmap' variable. We will want it to be fully transparent. That is, only the parts of it that are black will be drawn, while the white parts will be transparent. To achieve this effect, we will use the icon both as the cursor pixmap and as the mask pixmap. Try to figure out why...
另一个创建光标的方法是使用一对色深为1的pixmap(也就是,双色的pixmap)。一个pixmap定义了光标的外形,另一个作为一个遮罩,指定了光标的哪些象素是要画出来的。剩下的象素将是透明的。创建这样的光标是使用XCreatePixmapCursor()函数来实现的。作为一个例子,我们将使用"icon.bmp"bitmap来创建光标。我们将假定它已经载入了内存,并且转换为pixmap了,而且它的句柄储存在'bitmap'变量中。我们想它全部是透明的。也就是,只有黑色的部分将被画出来,而白色的部分将是透明的。为了达到这个效果,我们是同时把图标用作光标的pixmap和遮罩pixmap。试着想想看为什么……
/* this variable will hold the handle of the newly created cursor. */
Cursor icon_cursor;
/* first, we need to define foreground and background colors for the cursor. */
XColor cursor_fg, cursor_bg;
/* access the default color map of our screen. */
Colormap screen_colormap = DefaultColormap(display, DefaultScreen(display));
/* allocate black and while colors. */
Status rc = XAllocNamedColor(display,
screen_colormap,
"black",
&cursor_fg,
&cursor_fg);
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - cannot allocate 'black' ??!!??\n");
exit(1);
}
Status rc = XAllocNamedColor(display,
screen_colormap,
"white",
&cursor_bg,
&cursor_bg);
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - cannot allocate 'white' ??!!??\n");
exit(1);
}
/* finally, generate the cursor. make the 'hot spot' be close to the */
/* top-left corner of the cursor - location (x=5, y=4). */
icon_cursor = XCreatePixmapCursor(display, bitmap, bitmap,
&cursor_fg, &cursor_bg,
5, 4);
One thing to be explained is the 'hot spot' parameters. When we define a cursor, we need to define which pixel of the cursor is the pointer delivered to the user in the various mouse events. Usually, we will choose a location of the cursor that visually looks like a hot spot. For example, in an arrow cursor, the tip of the arrow will be defined as the hot spot.
这儿要解释的一件事情是'热区'参数。当我们定义了光标,我们需要定义光标的那个象素是投递给用户的各种鼠标事件的指针位置。通常,我们将选择通常看来像热区的光标位置。例如,在一个箭头状的光标中,箭的尖端将被定义为热区。
Finally, when we are done with a cursor and no longer need it, we can release it using the XFreeCursor() function:
最后,当我们用完了光标不再需要它了,我们能够使用XFreeCursor()函数释放它:
XFreeCursor(display, icon_cursor);
Setting A Window's Mouse Cursor
设置窗口的鼠标光标
After we have created a cursor, we can tell the X server to attach this cursor to any of our windows. This is done using the XDefineCursor(), and causes the X server to change the mouse pointer to the shape of that cursor, each time the mouse pointer moves into and across that window. We can later detach this cursor from our window using the XUndefineCursor() function. This will cause the default cursor to be shown when the mouse enter that windows.
在我们创建了光标之后,我们能告诉X服务器把这个光标附着在我们任意一个窗口上。这是通过使用XDefineCursor()来完成的,并且导致X服务器在鼠标每次移入或者通过那个窗口时,把鼠标指针改变为那个光标的样子。我们然后用XUndefineCursor()函数把光标和我们的窗口解开。这个将导致当进入能够窗口时,缺省的鼠标显示出来。
/* attach the icon cursor to our window. */
XDefineCursor(display, win, icon_cursor);
/* detach the icon cursor from our window. */
XUndefineCursor(display, win);
As an example, look at our cursor.c program, and see how mouse cursors are set, changed and removed. Run the program, place the mouse pointer over the created window, and watch.
作为一个例子,看看我们的cursor.c程序,并且看看鼠标光标是如何被设置,改变和移除的。运行这个程序,把鼠标指针放在创建的窗口之上,观察。 |
|