IDL指针
IDL指针指向堆变量
空指针的含义(NULL pointers)
空指针是一个特殊的指针值即NULL,保证这个指针不指向有效的堆变量,在IDL中没有有效的变量时,可以用Null来初始化指针变量,也用于数据结构中树和连接链表的尾节点。 理解Null指针和未定义(undefined)指针或无效的堆变量很重要,后者是指一个有效的指针指向了一个当前没有包含一个可用的值的堆变量。为理解它们的不同,参考一下IDL语句:
;变量A包含一个null指针 A = PTR_NEW()
;变量B包含一个指向未定义值的堆变量的指针 B = PTR_NEW(/ALLOCATE_HEAP) HELP, A, B, *B
主要的区别在于,可以向指向未定义值变量的指针写入值,而不能像null指针写入值,例如试图给A赋值34将会提示错误
*A = 34
而向B赋值则可以。
同样注意,PTR_NEW()和PTR_NEW(0) 是不同的,后者返回指向一个堆变量,这个堆变量被赋初值0。 创建指针的函数 PTR_NEW函数
IDL函数(function)方法
函数方法包含一句或多句IDL语句的程序单元,它返回一个值,这个程序单元独立于它的调用者执行,它有自己的局部变量和执行环境,引用函数(referenceing function)引起程序单元的执行。所有的函数方法都用return返回一个值,同时return也结束函数的执行。 IDL过程(procedure)方法
IDL对象(object)
一、使用类参考(class reference) 1对象方法的语法(Syntax)
对象方法语法介绍了调用方法的合适的语法 过程方法 过程方法有以下调用语法
Obj.Procedure_Name, Argument [, Optional_Arguments] Obj->Procedure_Name, Argument [, Optional_Arguments]
函数方法 函数方法有以下调用语法
Result = Obj.Function_Name(Argument [, Optional_Arguments]) Result = Obj->Function_Name(Argument [, Optional_Arguments])
注意函数的所有的参数和关键字都应该用圆括号括起来 2参数
创建窗口应用程序
一、关于组件(Widget)
IDL可以通过组件(widget)创建图形用户界面,组件widget(或者其他开发环境中的术语控件control)是简单的图像对象,例如按钮、滑动条等,它允许用户通过鼠标、键盘进行交互。
二、组件编程的一些概念
这一部分介绍一些关于编写IDL组件应用程序的基本概念和思想。
组件值(Widget Value)
许多简单组件和复合组件(compound widget)都有一个与自己关联的组件值(widget value)。根据组件的类型,组件值可能是一个静态的值,如按钮组件的标签label,也可能是一个动态值,如滑动条slider的数值。
组件值可以通过Widget_Control过程用关键字Get_Value从组件中获得,也可以在组件创建的时候设置或通过Widget_Control过程用关键字Set_Value来设置。 组件还可以有用户值(user value),组件的用户值可以是任意IDL类型的变量,用户值可以包含程序员想要包含的任何信息,用户值不会被IDL检查或使用,除非程序员在程序中指定了。
组件ID(Widget ID)
IDL组件是通过它们的组件ID被唯一识别的,组件ID是组件在第一次创建时就被赋予的一个长整型数,它作为组件创建函数的返回值被返回,例如,可以通过下面语句创建一个base组件:
base = WIDGET_BASE()
这里创建了一个顶层Base组件,变量base接收了组件ID。在程序中需要从组件取得数据或者改变他们的显示时需要组件ID
组件的父/子关系
当使用组件创建函数Widget_*创建一个新组件时,需要指明新组件的父组件的组件ID,如下:
button1 = WIDGET_BUTTON(base, VALUE='Test button')
上面语句创建了一个按钮组件,它是一个base组件的子组件,它的父组件及base组件的ID存储在变量base中。
在组件层关系中,button1在base组件的下面一层,当base组件被实现时,button1也出现在base组件的内部。
在组件的父子规则中的一个特例是顶层组件(Top-Level base),顶层base组件不同于普通的base组件,有如下不同: 它没有父组件
它在组件关系层中位于最高层,像是数据结构中树的根节点 它的组件ID被包含在每个组件的事件结构的TOP字段中。 实际上,一个组件程序通常以一个顶层组件为开始,组件事件的事件结构中一直都包含顶层base组件的ID在管理事件处理时很有用。
初始化与显示组件
当调用创建组件的函数时,IDL就会创建一个组件并赋给它一个唯一的标示号(组件ID),例如:
base = WIDGET_BASE()
button = WIDGET_BUTTON(base, VALUE='My Button')
上面程序先创建了一个base组件,然后创建的一个button组件,且button组件是base组件的子组件,它们的ID分别存在变量base、button中。但是,这只是在内存中创建了组件,屏幕上没有任何显示,实际上,IDL还要计算组件的大小以及它们显示的方式。
因此,初始化组件后还要显示它们到屏幕上,即realize,显示组件的方法是调用Widget_Control过程并使用Realize关键字:
WIDGET_CONTROL, base, /REALIZE
这个命令被触发后,组件就会显示到电脑屏幕。
在组件层次关系中没有实现的组件(unrealized)可以通过程序来控制,比如你可以在实现(realize)之前控制组件界面的大小、组件值、用户值,甚至可以取得组件值。没有实现的组件不能产生事件。
三、组件应用程序的生命周期
创建一个组件应用程序,需要做以下这些事情: 构建组件层次关系 编写事件处理程序 实现组件
注册程序到XManager 与程序交互 销毁组件
四、操纵组件
操纵组件常用到Widget_Control、Widget_Event、Widget_Info、XManager、XRegistered
WIDGET_CONTROL
Widget_Control允许你实现、管理、销毁组件层次结构,它通常用来改变已经实现的组件的默认的行为和显示。
实现组件层次 WIDGET_CONTROL, base, /REALIZE
销毁组件层次 WIDGET_CONTROL, base, /DESTROY
获取和改变组件值(Widget Value)
可以利用Get_Value和Set_Value关键字通过Widget_Control过程来获取和改变组件值(Widget Value)。同样方法适用于组件的用户值(Widget User Value)。
例如,要将一个绘图组件(Draw Widget)设为当前图形窗口,这个绘图组件的组件ID存储在变量drawwid中,则如下:
WIDGET_CONTROL, drawwid, GET_VALUE=draw WSET, draw
同样的,可以在一个事件处理过程中使用Widget_Control,获得产生事件的组件的用户值(User Value)。
WIDGET_CONTROL, event.id, GET_UVALUE=uval
控制组件的可见与不可见
你可以通过Map或者UnMapping控制组件在屏幕显示或者不显示,不显示的组件仍然存在与组件层次中,但是它们不显示,也不产生事件。
设置Map关键字为零隐藏组件,设置为不为零的数让组件重新显示。
WIDGET_CONTROL, base1, MAP=0
注意:尽管对任何组件都可以调用Widget_Control,Map=0,但是实际上只有base组件才能隐藏(Unmapped),如果你指定了一个不是base组件的组件ID,IDL会沿着组件层次向上寻找最近的base组件,然后将操作应用到这个base组件。 控制组件的可用与不可用(sensitivity)Enabled
通过sensitivity可以控制组件是否能接受用户输入,当一个组件是可用(sensitive)的,它有普通的显示并能接受用户输入,反之,如果是不可用的(insensitive),它不能接受输入操作。
WIDGET_CONTROL, bgroup, SENSITIVE=0
WIDGET_EVENT
Widget_Event函数可以返回事件,但是并不直接用它,而是用XManager来管理组件事件。 WIDGET_INFO
WIDGET_INFO函数用来获得组件层次或者单个组件的信息,提供一个组件ID和一个指定类型信息的关键字就可以获得相应信息。例如,相要知道一个列表组件(List Widget)中选中条目的编号,就可以用下面语句:
listindex = WIDGET_INFO(list, /LIST_SELECT)
一个比较有用的方面是利用Widget_Info通过user name找组件ID,user name是在创建组件是指定的信息,通过顶层组件ID和FIND_BY_UNAME关键字来找。
Result = WIDGET_INFO( Widget_ID,FIND_BY_UNAME=UNAME string)
找不到返回0 XREGISTERED 通常用它来
五、组件事件进程
事件和事件进程的概念存在于组件编程的各个方面,理解IDL是如何操纵组件事件对有效使用组件很重要。
什么是组件事件?
一个组件事件就是用户操作一个组件时窗口返回的一个信息,作为对事件的回应,组件程序通常执行相应的行为。
组件事件的结构Structure
事件来源于窗口,IDL将它们存在一个队列中,Widget_Event函数以IDL结构体的形式把它们传递给IDL程序,每个组件事件结构体前三个字段都相同,都是长整型数据,名字分别为ID、TOP、HANDLER:
ID是产生事件的组件的组件ID号(Widget ID)。
TOP是也是一个组件ID号,产生事件的组件位于一个组件层次中,TOP存储的ID号就是这个组件层次中位于最高层的组件的ID号。
HANDLER也是一个组件ID号,它是与事件处理程序相关的组件的ID,HANDLER会在下面讨论事件程序和复合组件时显现出来。
不同组件的事件结构可能会含有其他不同的字段
使用XManager管理组件事件
XManager过程提供了一个方便、简单的接口来管理组件事件,总的来说,创建组件程序包括以下四部分:
1、 编写对组件事件做出反应的程序 2、 编写作为应用程序接口的组件的代码 3、 实现组件
4、 调用XManager对事件流进行管理
IDL窗口组件
组件程序中的组件定义,IDL窗口组件要求有一个顶层BASE组件,base组件作为其他组件的容器。Widget_Base函数用来创建base组件。 设置子组件在base组件中的位置
一般情况下可以让IDL来决定其他组件在base组件中的位置。标准的base组件对其子组件不做任何的位置约束,
Widget_Base函数的一些关键字
TLB_KILL_REQUEST_EVENTS 这个关键字只有顶层组件才有,当用户试图使用窗口上的关闭按钮结束程序时想顶层组件发送WIDGET_KILL_REQUEST组件销毁请求事件(默认的是组件简单的销毁)。可以利用这个关键字在程序退出前执行一些复杂的操作,需要注意的是如果设置了这个关键字要自行销毁窗口。
与TLB_KILL_REQUEST_EVENTS相似的还有TLB_MOVE_EVENTS和TLB_SIZE_EVENTS
TLB_FRAME_ATTR
这个关键字只有顶层组件才有,设置这个关键字可以限制一些顶层组件窗口的属性,具体如下表 1 2 4 8 16 窗口不能最小、最大化,不能改变大小 系统菜单及窗口自带最小、最大化、关闭按钮不存在 窗口没有标题 窗口不能被关闭,最小、最大化、关闭按钮存在,只是关闭按钮不可用 窗口不可被移动 这个关键字的取值是按位的,所以可以对窗口施加多重影响,如果想让窗口没有标题(4)并且不能移动(16),就将该关键字设为20,即16+4.