我的PR输出里,图形选项没有输出至图片选项,怎么办?急急急

摄图网_提供各类高清视频素材,pr,正版免费下载,片头制作\背景视频\特效..多种风格素材齐全,编辑简便,给你创意灵感,让设计不再难!百万视频模板无限下载!

5、事件 5、编译给予Xlib的程序 6、打开和关闭一个连接到X服务器的连接 7、检查关于Display的基本信息 8、创建一个简单的窗口-我们的“hello Window环境下进行图形化编程的教程的第一个系列。其自身是用处不大的。一个真正的X程序员一般使用一个更高层次的抽象,比如用Motif(或者它的的免费版本,lesstiff),GTK,QT和类似的库。然而,我们需要从一个地方开始入手。不仅如此,知道表象之下的事情是如何工作的决不会是坏的主意。   After window系统开发之初有一个最大的目标-灵活性。想法是这样的东西看上如如何一回事,东西如何工作的又是另外一回事。因而,底层提供在画窗口,处理用户输入,允许使用颜色画图形(或者黑白屏幕)等动作中需要的工作。就这点决定了把系统分为两个部分。客户决定作什么,而服务器实际在屏幕上画图并读出用户输入以发给客户进行处理。   This window. 这个模型正好和人们在客户和服务器中所习惯的行为相反。在我们的例子,用户坐在由服务器控制的机器旁边,而客户可能运行于一个远程的机器上。服务器控制屏幕,鼠标和键盘。客户可能连接到了服务器,发出画一个(或者多个)窗口的请求,并要求服务器把任何用户发送给这些窗口的输入给他。因而,几个客户可能连接到了同一个X服务器-一个可能在运行email软件,一个可能在运行WWW浏览器,等等。当由用户发送输入给某些窗口时,服务器向控制这些窗口的客户发送消息以供处理。客户决定对输入作什么,并给服务器发送请求来在窗口中绘图。   The processes).  整个会话过程是用X消息协议执行的。该协议最初时由TCP/IP协议包执行的,允许客户运行于任何和服务器连接在相同网络上的机器上。后来,X服务器被扩展为允许客户运行在本地机器上更优的访问服务器(注意到X协议消息可能有几百KB那么大),比如使用共享内存,或者使用Unix域sockets(一个在Unix系统上的两个进程间创建逻辑通道的方法)。   GUI thumb). 不同于包含某种顺序化执行内质的传统的计算机程序。GUI程序通常使用同步化的编程模型,也被称为“事件驱动编程”。这个意味着程序大部分时候时闲着的,等待由X服务器发送的事件,然后根据这些事件作出反应。事件可能时”用户在点x,y处按下第一个按钮“,或者时”你控制的串口需要重画“。为了程序能够响应用户输入以及刷新请求,它需要在一个相当短的时间内处理每个事件(比如作为一个大体的规则,小于200毫秒)。   This thread. 这也意味着程序可能不执行在处理过程也许需要很长时间的事件的操作(例如打开一个连接到远程服务器的网络连接,或者连接到数据库服务器,甚至执行一个大文件的拷贝)。而是,它需要同步化的执行所有这些操作。这可能通过使用各种同步模型来执行长时间的操作,或者通过用不同的进程或者线程来执行他们。   So today.  为了消除程序事件实现X协议层的需求,一个称为‘Xlib’的库被创造出来。该库给程序提供了一个对任何X服务器非常底层的访问。因为协议是标准化的,客户使用Xlib的任何一种实现都可以和和X服务器通话。这些可能在今天看来没什么大用,但回到使用字符模式终端和专有方法在屏幕上绘图的日子,这是一个很大的突破。事实上,你将注意到咱爱瘦客户,窗口终端服务器,等等周围进行的各种虚伪的骗局。他们在今天实现X协议在80年代晚期已经能够作的事情。另外一方面,X universe在玩一个关于CUA(共通用户感观,一个由IBM制造的概念,指的是对所有程序使用共通的观感以使得用户能够更加轻松)的catch-up游戏。没有共通的感观是X window系统创造者的哲学。明显,它有许多在今天看来显然的缺陷。   The X display。这是一个代表我们和一个给定X服务器打开的连接的结构体。它隐藏了服务器的消息队列,客户将要发送给服务器的请求队列。在Xlib中,这个结构体被命名为‘Display’。当我们打开一个连接到X服务器的连接的时候,库返回一个指向这种结构体的指针。然后,我们把这个指针提供给任何需要发送消息给X服务器或者从这个服务器接收消息的Xlib函数。   The -图形上下文   当我们执行各种绘出(图形,文本,等)操作的时候,我们可能要指定几个选项以控制数据怎么被绘出 - 前景色和背景色是什么,线的边缘如何连接,在绘出文本的时候使用何种字体,等。为了避免给每个绘出函数提供n多参数,一个类型为‘GC’的图形上下文结构被启用。我们在这个结构中设置各种绘出选项,并且把指向这个结构的指针传递给每个绘出函数。这个是相当方便的,因为我们通常需要用相同选项执行好几个绘出请求。因而,我们初始化图形上下文,设置所需的选项,并把这个GC结构传递给所有的绘出函数。   Object 相关的函数返回一个句柄。这是实际存在于X服务器的内存中的对象的标识符。我们能够在后面通过把这些句柄提供给各种Xlib函数来操纵这些对象。服务器保存了这些句柄和它们管理的对象之间的映射。Xlib提供各种型别定义给这些对象(窗口,光标,色表等等),它们实际上最终映射为简单的整数。我们在定义保存这些句柄的变量的时候仍然应当使用这些型别名-为了有更好的可移植性。   Memory options. 在Xlib的接口中使用了各种结构型别。他们中的一些直接由用户分配内存。其他的使用Xlib函数分配。这使得库能够恰当的初始化这些结构。这非常方便,因为这些结构倾向于包含很多变量,使得对于差劲点的程序员非常难于初始化它们。记住-Xlib尝试着尽可能的了灵活,而且这意味着他也是尽可能的复杂。由缺省值使得初学X的程序员能够使用这个库,而不打扰有经验的程序员在n多选项中作调整的可能。   As block. 对于释放内存,由两种方法完成。在我们分配内存的情况-我们用相同方法释放它们(也就是使用free()来释放由malloc()分配的内存)。在我们用某Xlib函数分配的时候,或者我们使用返回动态分配的内存的Xlib查询方法的时候-我们使用XFree()函数来释放这些内存块。   Events 事件   A etc.    型别‘XEvent’的结构被用来传递从X服务器接收来的事件。Xlib支持很大数量的事件型别。XEvent结构包含接收事件的类型,以及与该事件相关的数据(例如事件产生的屏幕位置,与事件相关的鼠标按钮,和‘redraw’事件相关的屏幕区域,等)。读取事件的数据的方法和事件类型有关。因而,XEvent结构包含一个C语言对于所有可能事件型别的联合(如果你不确知C的联合是什么,该是查查你的C语言手册的时候...)。因而,我们能够有一个XExpose事件,XButton事件,XMotion事件,等。   Compiling opened: X程序首先需要打开连接到X服务器的连接。在我们完成这件工作的时候,我们需要指定运行X服务器的机器的地址,以及display号码。X window系统能够支持全部连接于同一个机器的好几个display。然而,通常只有一个这样的display,它的display号是‘0’。如果我们想要连接到本地display(也就是我们客户程序所运行的机器的display),我们可以指定display为’:0‘。要连接到地址为”simey“的机器的第一个display,我们能够使用地址”simey:0“。这儿是连接是如何被打开的:   #include that. 这将导致所有由程序创造的窗口(如果还有剩下的话)自动被服务器关闭,而且为了客户的利益任何留在服务器上的资源-将被释放。注意这将不会导致我们的客户程序终止-我们使用普通的exit()函数来完成。   Checking Basic Information XOpenDisplay().   一旦我们打开了一个连接到X服务器的连接,我们应当检查有关它的一些基本信息:他有什么样的屏幕,尺寸是多少(宽和高),它支持多少颜色(黑白?灰度?256色?更多?),以及等等。我们将展示一些作一些这样检查的代码片段,以及在使用中解释每个函数的注释。我们假定‘display’是一个指向‘Display’的结构的指针,由前面对XOpenDisplay()的调用返回的。   /* parameters: 在我们获得了一些有关我们的屏幕的基本信息之后,我们可以开始创建我们第一个窗口。Xlib提供数个函数来创建新窗口,其中的一个是XCreateSimpleWindow()。这个函数或者少量几个决定窗口的大小和位置等的参数。这有一个这些参数的完整列表:   Display* 很想用来清除标准输出的fflush()函数。XSync()函数也清除所有仍未发送给X服务器的消息,而且等待X服务器结束处理所有这些请求。在一个通常的程序中,这将不会是必要的(你可以看到为什么在我们开始写一个普通的X程序的时候),但对于现在我们把它放在那儿。尝试着有和去掉这些函数调用来编译程序,以观察它们行为上的不同点。   Drawing (GC).  在窗口中绘图能够通过使用各种图形函数来完成 - 画点,线,圆,矩形,等。为了能够在窗口中绘图,我们首先需要定义几种通用的绘图参数 - 线宽使用多少的,绘图的颜色是什么,等。这个是用图形上下文(GC)来完成的。   Allocating A window): 如我所说,图形上下文给出几个用于绘图函数的属性。因此,我们定义一个图形上下文。我们能够在一个窗口中使用多余一个的图形上下文,以达到用多种风格(不同的颜色,线宽,等)绘图。分配一个新的GC是通过使用XCreateGC()函数来完成的,如下(在这个代码片段中,我们假定“display”是一个只想Display结构的指针,而起“win”是先前创建的窗口的ID):     /* attributes: 注意“valuesmask”和“values”的角色。因为图形上下文有n多属性,并且我们不想定义它们中的一些,我们需要能够告诉XCreateGC()哪些属性是我们想要设置的。这就是“valuesmask”变量的用处。我们然后使用“values”变量来指定我们在“valuesmask”中定义的属性的值。因而,对于每个在“values”中使用的常量,我们将使用在“valuesmask”中相应的常量。在此例中,我们用两个属性定义图形上下文:       1. window. 在我们创建了GC之后,我们能够使用这个GC在窗口上用一套Xlib函数绘画了,这些函数合成为“基本绘图函数”。废话不多说了,让我们看看它们是如何使用的吧。我们假定”gc“是先前初始化了的GC,而且‘win’包含了先前创建的窗口的句柄。   /* draw a XFillRectangles(). 但愿你跟上了我的进度。我们还将提到更多的一些使用上差不多的函数。例如,XFillArc()和XDrawArc()带有相同的参数,但是只画出弧的内部(像XFillRectangle()函数所作的和用XDrawRectangle()函数画出的矩形一样)。还有一个填充多边形内部的XFillPolygon()函数。它和XDrawLines()基本上有相同的参数。然而,如果数组的最后一个点和第一个点处于不同的位置,XFillPolygon()函数自动添加一条”virtual“线,连接这两个点。两个函数的另外一个不同点就是XFillPolygon()带另外一个参数,shape。它用来帮助X服务器优化它的行为。你能够在手册页上学到这些。对于这些函数还有复数版本,名字为XFillArcs()和XFillRectangles()。   The events.  在Xlib程序中,所有的事情都是被事件驱动的。事件绘图有时是对事件-一个”暴露的“事件-的反应。如果程序窗口被隐藏的一部分重又暴露了(例如窗口从另外一个窗口后面升上来了),X服务器将发送一个”暴露的“事件让程序知道它应当重新画处窗口的这个部分。用户输入(按键,鼠标移动,等)也是作为一套事件被接收的。   Registering in?). 在程序创建了一个窗口(或者几个窗口)之后,它应当告诉X服务器它想让这个窗口接收什么型别的事件。缺省的,没有事件发送给程序。它可能注册各种鼠标(也被称为”指针“)事件,键盘事件,暴露事件等等。这是用于优化服务器和客户之间的连接(也就是,为什么要发送给程序(那可能是运行于地球的另外一边的)它不感兴趣的事件的?)。   In display结构,窗口的ID,以及它想要收到的事件型别的遮罩。窗口ID这个参数使得我们能够为不同的窗口注册接收不同型别的事件。这儿是我们如何给ID为‘win’的窗口注册”暴露”事件的:     XSelectInput(display, win, events.  注意:一个常见的蹩脚程序员所作的是在它们的程序中添加代码来处理新的事件型别,而忘记了在调用XSelectInput()中添加这些事件的遮罩。这样的程序员然后坐下来花数个小时调试它们的程序,奇怪于“为什么我的程序没注意到我释放鼠标??”,最后只是发现它们忘记了只注册鼠标按下事件,而不是鼠标释放事件。   Receiving see. XNextEvent()函数取得从X服务器发送来的下一个事件。如果没有事件在等待,它阻塞在那知道接收到了一个。当它返回了,事件的数据被放置给函数的第二个参数XEvent变量中。之后,变量的“type”域指定了我们得到的事件的型别。事件的型别是Expose告诉我们窗口的一部分布需要重画。在我们处理了事件之后,我们回过头来继续等待下一个要处理的。明显,我们需要给用户某种终止程序的途径。如我们即将看到的,这通常是通过处理“quit”事件来完成那个的。   Expose 我们窗口的内容在被其他窗口遮盖时候丢失了。你可能奇怪X服务器为什么不保存这些内容。答案是 - 为了节省内存。毕竟,窗口在display上的数量在给定时间是非常巨大的,而且保存它们的所有内容可能需要很多的内存(例如,大小为400*400象素的256色位图占据160KB的内存存储。现在想想20个窗口,比这个数字要大得多)。事实上,在特殊情况下有告诉X服务器保存窗口内容的办法,我们将在后面看到。   When on.  传统上用户输入有两个来源 - 鼠标和键盘。存在多种事件型别来通知我们用户的输入 - 键盘上的按键被按下,在键盘上释放按键,鼠标移动于我们的窗口之上,鼠标进入(或者离开)我们的窗口等等。   Mouse Button Click And Release white. 作为例子,这儿是我们如何每当接收到”鼠标按下“事件时,当按下的是第一个鼠标按钮的时候在鼠标点击位置画一个黑点的,而是第二个的时候擦除该点(也就是画个白点)。我们假定存在两个GC,gc_draw设置为前景色为黑,而gc_erase前景色为白。 Assume that the following events: 与鼠标按下和释放事件类似,我们也可以得到各种鼠标移动事件的通知。这些能够划分为两类。一类是按钮没有被按下时鼠标指针的移动,而第二类时当一个或者多个按钮被按下的时候鼠标指针的移动(这有时被称为“鼠标托放操作”,或者仅仅“拖放”)。下面的事件遮罩可以加到XSelectInput()的调用中以让我们的应用程序得到这些事件的通知。   PointerMotionMask      command. 作为例子,以下的代码处理一个绘图程序的“绘图模式”,也就是说如果用户在鼠标1键按下的时候移动了,那么我们在屏幕上“绘图”。注意代码有一个惯性:因为鼠标移动可能产生许多事件,可能我们不会在每个鼠标移到的点都得到鼠标移动事件。我们的程序应当能够处理这么一个情况。解决的一个办法可能是记住鼠标托过的上一个点,并在和新的鼠标指针位置之间画直线。假定下面的‘case’是事件循环的switch语句的一部分。        function: 另一个应用程序可能感兴趣的事件型别,是鼠标指针进入或者离开程序控制的窗口。一些程序使用这些事件来向用户展示应用程序现在在焦点状态。为了注册这么一个事件型别,我们将把下面的一个(或者多个)遮罩添加到我们给XSelectInput()函数指定的事件型别中:   EnterWindowMask      types...). 屏幕上有许多窗口,但是仅仅有一个键盘和他附着。X服务器如何知道键盘输入是发送给哪个窗口的呢?这个是通过键盘焦点来完成的。在给定的时间,屏幕上只有一个窗口能够有键盘焦点。存在Xlib函数来使得程序给某个窗口设置键盘焦点。用户通常能够使用窗口管理器来安排键盘焦点(通常是通过点击所需窗口的标题栏)。一旦我们的窗口拥有了键盘焦点,每个键的按下和放开都将导致事件发送给我们的程序(如果它注册了这些事件类型...)。   Keyboard command.  如果我们提到过的,按键代码于其本身是相当没有意义的,并且是受到了附着于运行X服务器的机器的键盘设备的影响。为了真正使用这些代码,我们要把他们翻译为按键符号,它们是标准的。我们能用XKeycodeToKeysym()函数来完成翻译工作。这个函数需要3个参数:只想display的指针,要翻译的按键代码,和一个索引(我们将用‘0’来作这个参数)。标准Xlib案件代码可以在”X11/keysymdef.h“中找到。作为一个使用键按下事件和XKeycodeToKeysym函数的例子,我们将展示如何处理这种的按键:按下‘1’将导致鼠标当前所在的点涂黑。按下DEL键将导致点的擦除(使用‘gc_erase’GC)。按下任何字母(a到z,大写或者小写)将使得他们显示在标准输出上。任何其他键的按下都被忽略。假定下面的‘case’是事件循环的switch语句的一部分。      worked. 如你所见,按键符号以某种方法与键盘上的屋里按键对应,因而你应当谨慎以恰当检查到所有的可能情况(如我们在上面例子中对‘1’所作的那样)。我们假定字母键有连续的符号值,否则范围检查的技巧与按键符号到ASCII代码之间的翻译将不能正常工作。   X Events exits. 作为一个处理事件的例子,我们将展示events.c程序。这个程序创建一个窗口,在其上作一些绘画,然后进入事件循环。如果它得到一个暴露时间 - 它重画整个窗口。如果它得到一个左键按下(或者移动)事件,它用白色画在鼠标指针下面的点(也就是说擦除这个点)。应当注意这些画面的改变是怎么被处理的。仅仅用恰当的颜色画出点是不够的。我们需要注意到颜色的改变,因而下一个暴露事件我们将能够再用合适的颜色画点。就这个目的,我们使用一个巨大的(1000乘1000)数组代表窗口的点。初始时,数组中的所有的元素被初始化为‘0’。当以黑色画点的时候,我们设置相应的数组元素为‘1’。当以白色画点的时候我们设置相应的数组元素为‘-1’。我们不能仅仅把他们重新设置为‘0’,否则我们原来画在屏幕上的东西总是会被擦除。最终,当用户按下键盘的任意键,程序退出。   When 如果鼠标快速从一个点移到另一个点,我们将不会在某个鼠标指针移过的点处得到移动事件。因而,如果我们故意好好处理这些间隙,我们也许需要记住上次移动事件发生的位置,然后再那个地点和下一个移动事件的地点之间画一条线。这就是绘画程序通常干的事情。   Handling Text And GC.  除去在窗口上画图,我们经常需要绘出文本。文本字符串有两个主要的属性-要画出的字符,和用什么字体画出。为了画出文本,我们首先需要X服务器载入字体。我们然后把字体赋给GC,最终我们在窗口上使用那个GC画出文本。   The Font drawing.  为了支持灵活的字体,定义了类型为XFontStruct的字体结构。这个结构体用来包含有关一个字体的信息,并传递给好几个处理字体选择和文本绘出的函数。   Loading A shell): 作为画出文本的第一步,我们使用字体装载函数,比如XLoadQueryFont()。这个函数要求X服务器来载入用一个给定名字定义的字体的数据。如果字体没有被找到,或者载入操作失败了,返回NULL。每个字体都可能有两个名字。一个是长字符串,确定了字体的完整属性(字体名,大小,斜体/粗体/下划线 used: 一旦我们把我们要用的字体载入并赋给了GC,那么就能在窗口上用像XDrawString()这样的函数绘出文本。这个函数将在窗口的一个给定位置画出给定的文本字符串。位置将成为画出的文本字符串的左下角。这儿是它如何使用的:   /* assume that 一个字体有两个称为”ascent“和”descent“的属性,用来指定字体的高。基本的,一种字体的字符是就像对某个映象述水平线来画的。字符的部分高出该线,部分又低于这线。字符的部分最高画时超出该线“font_info->ascent”个象素,而字母的最低部分将不会低于该线”font_info->descent“个象素。因而,这个两个数字的和决定了字体的高。 The propagation. 当窗口显示于X服务器上时,他们总是以某中阶层状排列的 - 每个窗口都可能有子窗口,每个子窗口可能又有他们自己的子窗口,等等。让我们看看一些关于这种阶层的事情,以及它们时如何影响像绘图或者事件传播这些操作的。   Root, Parent And etc. 在每个屏幕上,都有一个根窗口。根窗口总是占据了整个屏幕的大小。这个窗口不能被销毁,缩放或者图标化。当应用程序创建窗口时,它首先必须至少创建一个顶层的窗口。这个窗口成为根窗口的一个直接的后代,直到它第一次映射于屏幕上。窗口映射之前,窗口管理器被通知了将要发生的操作。窗口然后有特权重新确定这个新的顶层窗口的父窗口。这个是用来增加将要包含新窗口的窗口,以及画出的框架,标题栏,系统按钮,等等。   Once 如果他被移出,它被它的父窗口的边缘给切割了。任何窗口都可能包含多于一个的窗口,并且如果是这样,这些窗口以一种内部堆叠次序排好。当顶层窗口被升上来 - 它的所有后代窗口在保持他们内部排序的同时跟着它升上来。如果一个子窗口被升上来 - 他只是在他的兄弟窗口间升上来了。   Lets see how to function is associated.  前面我们已经讨论过事件传播了 - 如果窗口被发送了一个事件而且它没有处理这个事件 - 事件被传递给这个窗口的父窗口。如果父窗口没有处理这个事件 - 它被传递给父窗口的父窗口,以此类推。这个行为对于简单的Xlib程序没有什么大的关系,但它在使用高层的图形库时有用。他们通常把函数和发生在指定窗口中发生的事件关联起来。在这么一个情况下,把事件发送给相关窗口,于其中一个合适函数关联着,是有用的。   Interacting With The Window windows. 在我们已经看到了如何创建窗口并在其上绘图之后,我们回过一步来,看看我们的窗口如何与他们的环境交互-整个屏幕,以及其他的窗口。首先,我们的程序需要与窗口管理器交互。窗口管理器负责装饰画好的窗口(也就是添加框架,图标按钮,系统菜单,标题栏),以及在窗口被图标化的时候处理显示的图标。它还处理屏幕上的窗口排序,以及其他管理之职。我们需要给他各种信息来说明我们想要它如何对待我们程序的窗口。   Window it: 许多与窗口管理器通信的参数是使用名为“属性”的数据传递的。这些属性由X服务器附着给不同的窗口,并且储存在一个使得能够从不同的机器,不同的架构读取的格式(记住X客户程序可能运行于一个远程机器)。属性可能有多种类型 - used: 第一件事情是设置我们窗口的名字。这个是通过使用XSetWMName()函数来完成的。这个名字被窗口管理器用作窗口的标题(在标题栏上),在任务列表中,等等。这个函数接受3个参数:一个指向display的指针,一个窗口句柄,以及一个包含希望的标题的XTextProperty。这儿是它如何被使用的:   /* done: 在各种情况中,我们想要让窗口管理器知道我们想要我们的窗口有一个给定的尺寸,以及想让我们的用户以给定数量缩放我们的窗口。例如,在一个终端程序中(像xterm),我们想让我们的窗口总是包含完整的行列,因而我们显示的文本不会在中间截断。在其他情况中,我们完全不想让我们的窗口缩放(像许多对话框一样),等等。我们能把这些信息传递给窗口管理器,虽然它可能只是简单的忽略我们的请求。我们首先要创建保存信息的数据结构,用恰当的数据填充,然后使用XSetWMNormalHints()函数。这儿是这些如何完成的:   /* code: 为了我们应用程序图标化时,被设置窗口管理器使用的图标,我们使用前面提到的XSetWMHints()函数来完成。然而,我们首先需要创建一个包含图标数据的pixmap。Pixmap是X服务器操纵图象的办法,并且会在后面详细的解释。现在,我们仅仅向你展示如何给你的应用程序设置图标。我们假定你得到一个代表这个图标的位图文件,以X位图的格式保存着。一个这样的名字叫"icon.bmp“的文件附带于这个教程而在。不管,这是代码:     /* portability.  为了完善本节,我们提供simple-wm-hints.c,它创建窗口,设置前面所展示的窗口管理器选项,并且进入一个十分简单的事件循环,使得用户能够摆弄窗口并看到这些选项是如何影响应用程序的行为的。尝试各种选项,以及尝试在不同窗口管理器下运行程序,来观察在每个环境下的行为上的不同点。它将交给你一些关于X程序移植性的事情。   Simple purpose. 我们能够对我们窗口作的另外一件事情是在屏幕上操纵它们-缩放,移动,升起来或者降下去,图标化等等。为了这个目的,Xlib提供一套窗口操作函数。   Mapping And UN-mapping A side. 我们能够应用于窗口的第一对操作是把它映射和取消映射。映射窗口导致它显示在屏幕上,如我们在我们的简单窗口程序例子中所见到的那样。取消映射导致它从屏幕上移出(虽然窗口作为一个逻辑实体仍然存在着)。这产生了隐藏窗口(取消映射)以及又显示出来(映射)的效果。例如,如果我们在程序中有一个对话框。我们不在每次用户要求打开它的时候都创建它,我们能只以未映射的模式创建窗口一次,而当用户要求打开它的时候,我们简单地把窗口映射到屏幕上。当用户点击'OK'或者'Cancel'按钮地时候,我们简单地把窗口取消映射。这个笔创建和销毁窗口要快许多,只是以浪费客户端和X服务器端的资源为代价。   You operation. 注意当窗口被移动的时候,它可能会被部分暴露或者部分被其他窗口遮盖,因而我们可能因为这个操作的缘故和收到暴露事件。   Resizing A order: 直到现在我们改变的只是单一窗口的属性。我们将看到还有相关到窗口和其他窗口之间的属性。它们中的一个就是叠放顺序。也就是,窗口被放置在各自之上的顺序。最前面的窗口被称为堆叠的顶部,而最后面的窗口是位于堆叠的底部。这儿是我们如何操纵我们窗口的叠放顺序:   /* de-iconify it: 我们将在这儿展示的最后一个操作是把窗口变为图标化模式和反过来操作的能力。这个是使用XIconifyWindow()函数完成 - 来图标化窗口,以及XMapWindow()来取消图标化。为了弄清楚为什么对于XInconifyWindow()没有一个反转的函数,我们必须意识到当窗口图标化的时候,实际发生的是窗口被取消映射了,而作为替代窗口的图标被映射了。因而,为了使得原来的窗口重新显示,我们简单需要重又映射一遍。图标确实是另外一个不过严重与我们的普通窗口相关联的另外一个窗口-它不是我们窗口的另外一个状态。这儿是如何图标化一个窗口并且然后把它取消图标化:     /* used: 正如你能够设置我们窗口的各种属性,我们也能要求X服务器提供这些属性的当前值。例如,我们能检查窗口位于屏幕上的什么位置,当前的大小是多少,是否已经映射或者没有,等等。XGetWindowAttributes()函数能用来得到这些信息。这儿是它如何使用的:   /* only. 这个函数的一个问题是它返回窗口相对于它的父窗口的位置。这使得这些坐标对于任何窗口操作函数相当的没有用处(例如:XMoveWindow)。为了克服这个问题,我们需要进行两步操作。首先,我们找出我们窗口的父窗口的ID。然后我们翻译上面的相对坐标为屏幕坐标。我们使用两个新的函数来完成这个计算,名字为XQueryTree()和XTranslateCoordinates()。这两个函数能够作比我们所需要的更多,因而我们只集中注意力于相关信息。   /* fail.  起初,没有足够的色彩。屏幕控制器仅能同时支持有限数目的色彩(最初是16,然后是256)。因为这个,程序不能仅仅要求以“light-purple-red”色彩绘画,并且期望颜色是可用的。每个程序分配它需要的色彩,并且当所有16或者256色项都在使用中时,下一种颜色的分配将失败。   Thus, color.  因而,“色表”的概念被引入了。色表时一个尺寸和给定屏幕控制器的同时发色数相同的表格。每个项包含不同颜色的RGB(红,绿,蓝)的值(使用红,绿蓝能够画出所有颜色)。当程序想要在屏幕上画画,它不指定要使用的颜色。而是,它指定在画画中要使用的某个色表中的表项。改变在这个色表中的项的值-然后绘画将使用不同的颜色。   In same.  为了能够使用程序员中意的颜色来绘画,色表分配函数被提供了。你能够要求给一个RGB颜色集的颜色分配色表表项。如果它已经存在,你可能要获得它在表中的索引。如果不存在,而且表没有满,一个新的表项将分配来包含给定的RGB值,并返回它的索引。如果表格是满的,这个过程将失败。你然后可能要求获得一个最接近于你想要的色彩的色表表项。这也许意味着屏幕上的实际绘画可能使用类似于你想要,而不是相同的颜色。   On work.  在今天运行X服务器的更现代的屏幕上,支持百万种颜色,这个限制看上去有些好笑。但是记住总是有电脑用的是旧的图形卡。使用色表,对这些屏幕的支持对于你来说变得是透明得。在一个支持百万种颜色得显示器上,任何色彩分配请求都会成功。在一个支持有限颜色的显示器上,某些颜色分配请求将返回近似的颜色。它看上去不会那么好,但你的程序还能运行。   Allocating option.  当你使用Xlib绘图的时候,你能够选择使用你的窗口将要显示在的屏幕的标准色表,你也可以分配一个新的色表并且应用于你的窗口。在后面的例子中,每次鼠标一如你的窗口,屏幕色表将被你窗口的色表给代替,而且你将看到窗口上的其他窗口把他们的颜色变得有一些混乱。实际上,这就是你使用"-install"命令行选项给X程序带来的效果   In fields:  一旦我们得到了某个色表的访问权限,我们可以开始反配颜色了。这个是通过使用XAllocNamedColor()和XAllocColor()函数来完成的。第一个XAllocNamedColor()接受一个颜色名字(例如,“红色”,“蓝色”,“棕色”等)以及分配能够实际绘于屏幕上的最接近的颜色。XAllocColor()接受一个RGB色值,并且分配能够绘于屏幕上的最接近的颜色。两个函数都使用XColor结构,它有以下相关域:   unsigned follows:  在我们已经分配了所需的颜色后,我们能在绘出文本和图形的过程中使用他们。要这么作,我们需要设置这些颜色为某GC(图形上下文)的前景色和背景色,然后使用这个GC进行绘图。整个过程使用XSetForeground()和XSetBackground()函数,如下:   /* colors.  如你所见,这个相当简单。实际的绘画使用我们已经在前面看过的函数来完成。注意为了使用许多不同的颜色来绘图,我们能采取这两个办法中的一个。我们要么在调用任何绘图函数之前改变GC的前景以及/或者背景色,或者我们能使用几个不同的GC以不同的颜色绘画。最终采用那种办法是你各人选择的事情。注意分配虚度GC将使用X服务器更多的资源,但有时能使得代码更紧凑,而且替换画出的颜色要容易些。   As far.  许多所谓的“多媒体”程序需要做的一件事情是显示图片。在X世界中,这个是通过使用bitmap和pixmap来完成的。我门已经在给我们程序设置图标时看到了他们的一些使用。让我们进一步学习他们,来看看如何在窗口中与我们已经看过了的简单图形和文本一起,画出这些图像。   One pixmaps.  在进行更深的钻研之前要注意一件事情是Xlib没有提供一种操作流行图像格式的办法,如gif,jpeg或者tiff。这些是留给程序员(或者是更高层的图形库)来翻译这些图像格式为X服务器熟悉的格式 - x bitmap与x window系统规定的格式存储的双色图像。当存为文件时,bitmap数据看上去和C源代码一样。它包含定义bitmap宽和高的变量,一个包含bitmap的各个位的值的数组(数组的尺寸=width*height),以及可选的热区位置(将在后面讨论鼠标光标时解释)。   A X pixmap is a etc.  实际上,X pixmap能够认为是一个不显示在屏幕上的窗口。许多工作于窗口之上的图形操作,也能够工作于pixmap之上 - 仅仅以pixmap ID替代window ID来提供。事实上,如果你查阅手册,你能看到所有这些函数结构一个“可画”对象,不是一个“窗口”。窗口和pixmap都是可画的,因为他们都能用像XDrawArc()函数来“在其上做画”。   Loading A Bitmap From A directly.  在我们演示给程序设置图标时,我们已经看到如何从文件载入bitmap到内存中。我们前面展示的方法需要在我们的程序中使用C预处理器的“#include”指示符包含bitmap文件。我们将在这儿看到如何直接访问文件。   /* this bitmap没有关联到这个窗口。这个窗口句柄仅仅用于指定我们想要bitmap创建到的窗口。这很重要,因为pixmap为了使得它有用,必须支持屏幕一样多的色彩数。   Drawing A Bitmap In A drawable.  一旦我们得到一个从bitmap产生的pixmap的句柄,我们能够使用XCopyPlane(),在某个窗口中把它画出来。这个函数允许我们指定可画的物体(一个窗口,甚至是另外一个pixmap)来把给定的pixmap画到上面去,以及指定画出的位置。 。 /* below.  如你所能看到的,我们还能拷贝pixmap个给定矩形内的内容,而不是整个pixmap。还要注意传递给XCopyPlane函数额最后一个参数(最后的'1')。该参数指定了我们想要拷贝到目标窗口的源图像是什么plane的。对于bitmap,我们总是拷贝第一号plane。这在我们下面 pixmap.  有时我们想要创建一个未初始化的pixmap,然后我们能在它上面画图。这对于作图程序来说有用(创建一个新的空画布将导致一个新的将要在其上储存绘画内容的pixmap的创建)。在读取各种图像格式的时候也有用处 - tutorial.  一点重要的值得注意的是 - 能够在同一窗口上创建不同色深的pixmap。当我们执行拷贝操作的时候(把pixmap拷贝到窗口,等),我们应当确保源和目标有相同的色深。如果他们色深不同,操作将失败。例外是如果我们使用前面展示的XCopyPlane()函数,拷贝源pixmap的指定bit plane。在这种情况下,我们能拷贝指定plain到目标窗口上 - 实际上,设置一个指定位位每个拷贝象素的颜色。这能用于在窗口中产生奇异的图形效果,但是超过了我们教程的范围。   Freeing A windows.  我们时常看到程序在某个状态下改变鼠标指针(也称为X指针)的外形。例如,一个繁忙中的程序时常在它的主窗口上显示沙漏时钟,以给用户一个你应当等待的可视化提示。没有这么一个视觉提示,用户可能认为程序死掉了。让我们看看我们如何改变我们窗口的鼠标光标。   Creating why...  另一个创建光标的方法是使用一对色深为1的pixmap(也就是,双色的pixmap)。一个pixmap定义了光标的外形,另一个作为一个遮罩,指定了光标的哪些象素是要画出来的。剩下的象素将是透明的。创建这样的光标是使用XCreatePixmapCursor()函数来实现的。作为一个例子,我们将使用"icon.bmp"bitmap来创建光标。我们将假定它已经载入了内存,并且转换为pixmap了,而且它的句柄储存在'bitmap'变量中。我们想它全部是透明的。也就是,只有黑色的部分将被画出来,而白色的部分将是透明的。为了达到这个效果,我们是同时把图标用作光标的pixmap和遮罩pixmap。试着想想看为什么……     /* spot.  这儿要解释的一件事情是'热区'参数。当我们定义了光标,我们需要定义光标的那个象素是投递给用户的各种鼠标事件的指针位置。通常,我们将选择通常看来像热区的光标位置。例如,在一个箭头状的光标中,箭的尖端将被定义为热区。   Finally, when windows.  在我们创建了光标之后,我们能告诉X服务器把这个光标附着在我们任意一个窗口上。这是通过使用XDefineCursor()来完成的,并且导致X服务器在鼠标每次移入或者通过那个窗口时,把鼠标指针改变为那个光标的样子。我们然后用XUndefineCursor()函数把光标和我们的窗口解开。这个将导致当进入能够窗口时,缺省的鼠标显示出来。   /* watch.  作为一个例子,看看我们的cursor.c程序,并且看看鼠标光标是如何被设置,改变和移除的。运行这个程序,把鼠标指针放在创建的窗口之上,观察。 

我要回帖

更多关于 图形选项没有输出至 的文章

 

随机推荐