2022年IDL入门教程十二 .pdf

上传人:C****o 文档编号:33387705 上传时间:2022-08-10 格式:PDF 页数:12 大小:207.42KB
返回 下载 相关 举报
2022年IDL入门教程十二 .pdf_第1页
第1页 / 共12页
2022年IDL入门教程十二 .pdf_第2页
第2页 / 共12页
点击查看更多>>
资源描述

《2022年IDL入门教程十二 .pdf》由会员分享,可在线阅读,更多相关《2022年IDL入门教程十二 .pdf(12页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、第十二章对话框程序本章概述本章主要讲解两种编写对话框程序的方法。对话框是用于接收用户信息,并把信息传递到另一个程序模块,或程序中。其中,将学到以下几个方面的内容:1.如何编写模式对话框;2.如何编写非模式对话框;3.如何在组件程序中用指针存储信息;4.如何在组件程序中使用伪消息;5.如何在独立的组件程序之间传递信息;创建模式对话框在上一章的XImageBar 程序中,已经调用过一个模式对话框程序,即GetImage,它允许用户选择并读入一个影像文件。在XImageBar 程序中,这个对话框被调用过两次。一次是在组件定义模块中,当一个影像数据未被传入到程序时;另一次则是在Open Image 按

2、钮被按下的时候。 (如果在上一章中没有编写XImageBar 程序,可以调用与本书配套使用的文档 XImageBar.9.pro 。 )在第一个程序实例中调用方式如下:image = GetImage (Cancel = canceled) 在第二个程序实例中调用如下:image = GetImage (Cancel = canceled, Parent = event. Top) 在这两次调用过程中有几个微小的区别,不过调用时读者可能没有注意到。如果想编写对话框程序,就必须了解这两次调用的差别以及它们是如何工作的。阻塞的组件程序在上述例子中,第一次调用GetImage 时, GetImage

3、 程序运行时就好比是阻塞的组件程序。要看它是如何工作的,在IDL 命令行中键入如下所示:IDL image = GetImage ( ) 注意到 IDL 命令行要么是消失了要么是变灰了。这时要在IDL 命令行上键入命令并执行它们是不可能的。我们就称IDL 命令行是阻塞了。 (当命令行正处于消失或变灰状态时,可以键入命令,但只有在命令行解除了阻塞后命令才可以执行。)一般而言,无论运行哪一种IDL 程序都会阻塞IDL 命令行。换言之,只有等到当前的命令执行完毕后才有可能键入并执行另一命令。IDL 5 以前的版本中,所有的组件程序也都是如此运行的。 一旦运行了一个组件程序,只有等到这个组件程序执行完

4、毕后才可进入IDL命令行。但在IDL5中,刚才的现象已经改变了。现在,可以运行一个组件程序并立即在IDL命令行上输入命令然后执行它。我们称这种组件程序为无阻塞组件程序。要创建一个无阻塞的组件程序,只需要程序中的XManager 命令使用关键字No_Block 即可。这正如先前编写名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 12 页 - - - - - - - - - 的程序 XimageBar 中所做的那样。然而,在程序GetImage 中的 XManager 命令是

5、没有关键字Bo_Block 的。因而,它是一种阻塞程序。在这里的“阻塞” ,是指在执行Xmanager 命令的同时,IDL 就停止执行GetImage 组件定义模块中的代码。 组件定义模块中任何在XManager 命令下面的代码 (其中也有一些可以,待会可以看到) 都不能被执行, 直到组件程序被销毁后才被执行,也就是说这是阻塞被解除了。这对像 GetImage 这样的程序是合适的,因为阻塞给用户提供了足够的时间来填写表格或对话框中的信息。当用户添完表格, 他们就会点击Cancel 或 Accept 按钮。无论哪种情况,IDL 都将销毁组件,并解除阻塞,程序也可以用所收集的信息继续工作。对于Ge

6、tImage 而言,收集的信息是指关于数据文件、打开文件读取数据,将结果返回给用户。所有收集,读取,返还这一系列的操作都是在组件定义模块中的XManager 命令执行完毕后才进行。优点就这些。 但是, 阻塞也有个细微方面容易被忽视。那就是,只有第一个调用XManager为阻塞的组件程序才可以成为阻塞。后来所有的组件程序都将越过阻塞好像他们是无阻塞的组件程序一样。这种行为对于像GetImage 这样的程序而言,完全是一个灾难,因为程序将在用户获得填写表格的机会之前就开始读取数据文件。从一个自己对它一无所知的文件中读取数据会带来一些小麻烦。模式组件程序如果想确保在任何条件下一个组件程序都会阻塞,而

7、不是仅仅在第一次侥幸地调用Manager 后才成为阻塞,那么就必须建立一个模式的组件程序。模式的组件程序总是在执行XManager 命令时处于阻塞状态,直到组件被销毁。在 IDL5 以前的版本中, 编写一个模式的组件程序相对简单些。只要简单地在XManager命令后设置关键字Modal 即可。但在IDL5 中, Xmanager 命令中的关键字Modal 已经被废弃了。取而代之的是,在创建顶级base时的 Widget_Base 函数中增加一个Modal 关键字。这里有一个很小却很重要的补充。如果为一个base组件设置Modal 关键字,同时也必须为那个base组建设置一个有效的Group L

8、eader(通过设置Group_Leader 关键字)。这对要编写一个既能在IDL 命令行中运行,又能在程序中运行的对话框程序的难度就更大了。等一会编写程序时或许就会明白这个意思了。编写模式对话框的定义模块程序 GetImage 是一个对话框程序的绝好例子,但也是相当复杂的。如果是从一个更简单的例子开始, 那么就能够更容易理解创建对话框的规则。由于在与本书配套使用的文档下的 Coyote 目录中,有许多类似2D 字节数组的数据文件,那我们就从编写一个简单对话框程序开始,用于打开和读入Coyote 目录下的文件。通过调用这个程序,就可以获得这个文件的名字以及在X 和 Y 方向上的大小,暂且称这个

9、程序为GetData 吧。Coyote 目录下的数据文件以及文件大小的详细信息请参阅313 页的“附录B:数据文件描述”。如果希望让用户将某些信息输入到表格中,一般来说, 这办法不是很好,如果我们对用户一点也不了解的话,或许他们就无法输入。如果可能的话, 让用户选择一个文件名或用鼠名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 12 页 - - - - - - - - - 标点击选择文件的大小将会是个更好的主意。假定确实要让用户输入,那么让用户输入的越少越好。解决上述问题

10、一种方法就是,在输入框内提供一些默认值,这些值可能是对的,因此用户也不需要输入。同样,也希望在程序调用时用户能够指定一个文件名或文件的大小。因此, 如下打开一个文本编辑窗口,将对话框的定义语句定义如下:Function GetData, filename, XSize = xsize, YSize = ysize, $ Cancel = cancel, Parent = parent 关键字Cancel 是一个输出型变量,它用来标示是对话框中的Cancel 按钮还是Accept按钮被按下了。关键字Parent 包含了模式组件程序的GroupLeader 的标示符。(喜欢关键字Group_Lea

11、der 的名字吧)记住在定义模式的base组件时必须有Group Leader。接下来,决定程序在出现错误时怎么处理(作者喜欢将程序控制返回给调用者),以及在没有提供关键字时设置关键字的默认值。增加如下所示:On_Error, 2; Return to caller. IF N_Elements (filename) EQ 0 THEN $ filename = Filepath (Root_Dir=Coyote(), ctscan.dat ) ELSE $filename = Filepath (Root_Dir=Coyote(), filename) IF N_Elements (xsiz

12、e) EQ 0 THEN xsize = 256 IF N_Elements (ysize) EQ 0 THEN ysize = 256 这里的 Coyote 命令是用于查找Coyote 目录的。如果这个目录存在,那么Coyote 目录将是默认的路径,否则将在当前的目录中查找文件。Filepath 命令将返回一个与设备无关的文件名称。默认的文件为ctscan.dat,一个有256X256 的字节数组。接着,定义对话框的偏移值,时的它定位于屏幕的中心,键入如下:Device, Get_Screen_size = screenSize XCenter = FIX (screenSize 0 / 2

13、 . 0) YCenter = FIX (screenSize 1 / 2 . 0) Xoff = xCenter - 150 Yoff = yCenter 150 定义一个顶级的模式base接下来的就是为这个模式对话框创建一个顶级的base。在定义一个定级的模式base 必须有一个有效的Group Leader,这在前面已经强调了多次。如果把一个Group Leader 通过关键字 Parent传递给程序,那将没什么问题。但事实并非总是如此。例如:如果用户想在IDL命令行中调用该程序,一般来讲,这是不不太可能获得一个有效的Group Leader 的。没有有效的 Group Leader,因

14、而就不得不依赖它是一个阻塞组件。再者, 如果在 IDL 命令行上第一次调用 Xmanager,这个程序将会阻塞,这时再调用程序也不成问题。当 Group Leader 没有定义或者程序GetData 的调用者是它自己本身时,程序就会出现麻烦了。 作者也不清楚该如何走出这进退两难的境地。更让我不喜欢的是,在另一个程序中如果要正确调用该程序,参数Group Leader 就是必不可少的。此外,当在IDL 命令行调用它时, Group Leader 参数就不应该是一个必须的参数。不管如何, 如果指定了Group Leader, 就可以创建顶级的模式base。 如果没有指定Group Leader,那

15、么只有指望在IDL 命令行上调用该程序了,如下所示:IF N_Elements (parent ) NE 0 THEN $ Tlb = Widget_Base(Column =1 , Xoffset = xoff, Yoffset = yoff, $ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 12 页 - - - - - - - - - Title = Enter File Information , /Modal, $ Group_Leader=parent, /

16、Floating, /Base_Align_Center ) Else $ Tlb=Widget_Base(Column=1, Xoffset=xoff, Yoffset=yoff ,$ Title= Enter File Information , /Base_Align_Center) 注意,设置在顶级的模式base 上的关键字Floating。一个浮动组件总是浮现在Group Leader 程序之上。这可以防止程序隐藏在其他窗口之后。关键字Base_Align_Center 确保顶级 base的子组件在顶级base中以居中方式对齐。定义其他组件定义一个子base,来包含文件名域和文件大小

17、域。子base 并不是真的需要,但使用子base可以将在窗体周围设置一个框,并把它与窗体底部的按钮分隔开来。键入如下:Subbase = Widget_Base (tlb, Column = 1) Filesize = Strlen (filename) * 1.25 FileID = CW_Field (subbase, Title = Filename: ,$Value = filename, XSize = filesize) XsizeID =CW_ Field (subbase, Title = X Size: , $Value=xsize, / Integer) YsizeID =

18、 CW_Field (subbase, Title = Y Size: , $Value =ysize , / Integer) 注意在这里使用的是复合组件CW_Field 。 CW_Field 其实就是在一个可编辑文本框旁放置一个标签组件。而它的事件处理函数能够处理大量的细节。例如:设置CW_Field 的输入值为整数, 那么用户只能在输入域输入整数。另外,当使用这个文本框时,它的返回值就是一个整数,而不是字符数组。这样一来使用这些文本组件就便得更加容易了。接着,建立一个包含Cancel 按钮和 Accept 按钮的 base垒,键入:Butbase = Widget_Base(tlb, R

19、ow=1) Cancel = Widget_button (butbase, Value = Cancel )Accept = Widget_Button ( butbase, Value= Accept )现在已经建立了所有所需的组件,因此可以实现该程序:Widget_Control, tlb, / Realize 在模式对话框中保存信息对话框的作用就是从用户那儿收集信息,然后当用户按下Accept 按钮时将信息返回给用户。 (或根据这些信息做相应的操作)。但是,当用按下Accept 按钮时,对话框就被销毁,阻塞也被解除。 于是问题就出现了:程序所收集的信息应该保存在哪里,进而处理该信息或将

20、信息返回给用户呢?很显然,不要将信息保存在程序内部(比如说,保存在用户值中),因为当程序被销毁时信息也会被销毁。所以,信息必须保存在程序外部。公公块是一种方法,但作者喜欢将信息保存在指针内。在程序中创建一个指针,键入如下所示:ptr = ptr_New (Filename: , Cancel : 1, XSize :0, YSize: 0)这个指针指向一个匿名结构,里面包含了所有希望从窗体中收集的信息。注意有一个名为 Cancel 的字段, 是用来表明用户是按下了Cancel 按钮还是Accept 按钮。 这是信息非常重名师资料总结 - - -精品资料欢迎下载 - - - - - - - -

21、- - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 12 页 - - - - - - - - - 要,因为程序根据不同的值来采取不同的操作。创建 Info 结构与其他组件程序一样,本程序也要创建一个Info 结构来保存程序运行过程中所需的必要的信息。 从这一意义上来说,需要保存的信息有包含文件信息的组件标示符以及信息存储的位置。 info结构定义如下,并将它保存在顶级base 的用户值中。info = fileID: fileID, xsizeID: xsizeID,$ ysizeID:ysizeID,ptr:ptr Widget_Control,

22、 tlb, Set_UValue=info, /No_Copy 创建一个阻塞组件可以用 Xmanager 命令注册程序了。 注意,必须确保这各程序是一个不能使用No_Block关键字的阻塞程序。如果变此程序为无阻塞程序,那么可以在IDL 命令行上使用它而不必具有有效 Group Leader。键入如下所示:XManager, getdata , tlb, Event_Handler = Getdata_Events 从阻塞中返回在程序执行到上述代码时,IDL 已经停止执行组件定义模块中的代码了。程序的所有操作都发生在时间处理模块中。IDL 不会从阻塞中返回,进而执行组件定义模块的编码,直到用户

23、按下 Cancel 或 Accept 按钮后程序被销毁,阻塞被解除。当这发生后,对话框信息就会保存在指针内。在程序将信息返回给用户之前,要做的事情就是获取并处理信息。在本程序中, 要做的事情就是获取文件名、数据文件大小,然后读取文件并将影像数据返回给程序调用者。首先,获取指针内的信息。由于正在操作指针,所以可以删除它,如下:fileInfo = * ptr ptr_free, ptr 现在已经有了打开和读取数据文件所需的信息。当然, 还可以认为, 现在拥有了程序所需要的信息。事实上,程序可能只是获得了不正确的信息。用户可能忘记了键入文件名,或者在输入文件大小的文本框中多加了一位数字,或者他们根

24、本就不知道文件大小而只是猜测而已。 事实上, 当开始读取这个数据文件时,各种意想不到的事都可能发生,因此最好有个心理准备。建立一个 Catch 错误捕获语句来捕捉所有可能发生的意想不到的事,以及在读取数据文件时产生的错误。 (Catch 错误捕获语句的详细信息请参阅227 页的“ Catch 控制语句”。 )键入以下命令:Catch , error IF error NE 0 THEN BEGIN Catch, /Cancel Ok = Dialog_Message (!Err_String) Cancel = 1 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - -

25、- - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 12 页 - - - - - - - - - IF N_Elements (lun) NE 0THEN FREE_LUN, LUN Return, -1 ENDIF 这个错误处理语句将错误信息显示给用户,(以让他们知道出现了一些情况。)设置Cancel 标识(因而用户不必使用函数的返回值),如果文件已打开则关闭文件,并返回-1。接下来,检查一下用户按下了Cancel 按钮。如果是,设置Cancel 标识并返回 -1。键入如下语句:cancel=fileInfo.cancel IF cancel The

26、n Return, -1 好了,可以开始去读数据文件。Image=BytArr(fileInfo.xsize,fileInfo.ysize) OpenR, LUN, fileInfo.fileName, /Get_Lun ReadU, LUN ,Image Free_LUN, LUN 如果到了这儿,就已是大功告成了。返回影像数据:Return, Image End 在 320 页的 IDL 源代码附录中,可以在组件定义模块中找到最终的GetData 的源代码。编写模式对话框的事件处理模块现在可以编写这个模式对话框程序的事件处理模块了。事件处理模块的思路非常简单,因为只需要关心Cancel 和

27、Accept 按钮的事件,而对其他事件则是忽略。(当用户回车时,CW_FIELD组件会产生事件。 )如果用户按下了Cancel 按钮,对话框被销毁,阻塞因而也被解除。如果用户按下Accept 按钮,程序也要做相同的事,但是同时还得在对话框销毁之前将窗体信息保存在指针内。事件处理模块的前几行可能向如下所示。(确保将事件处理模块增加到组件定义模块之前。 )Pro GetData_Events, Event EventName = Tag_ Names (Event, /Structure_Name)If EventName NE WIDGET_BUTTON Then Return 注意, Tag_

28、Names命令将所有不是按钮的事件都输出到屏幕上。对了,程序只对按钮事件进行处理,获取info结构并找出产生事件的按钮。键入如下所示:Widget_Control, Event.Top, Get_Uvalue=info, /No_Copy Widget_Control, Event.ID, Get_Value=buttonValue 如果是 Cancel 按钮,那么只需要销毁对话框即可。这是因为指针初始化时已经设置了适合的值。(例如:将指针结构中的Cancel 字段设置为1) 。键入:Case buttonValue Of Cancel : Widget_Control,Event.Top,

29、/Destroy 如果是 Accept 按钮,那就必须在对话框销毁之前获取窗体的信息,并将它保存在指针内。 Accept 按钮事件处理的代码如下所示: Accept :Begin Widget_Control, Info.fileID, Get_Value=fileName 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 12 页 - - - - - - - - - Widget_Control, Info.xSizeID, Get_Value=xsize Widget_

30、Control, Info.ySizeID, Get_Value=ysize (*info.ptr).fileName=fileName0 (*info.ptr).xsize=xsize (*info.ptr).ysize=ysize (*info.ptr).Cancel=0 End EndCase End 注意在存入指针之前,变量fileName要用下标引用。这是因为即使文本框内只有一个字符串,文本框返回的值还是一个字符串数组。因而必须确保传入到指针的只是一个字符串。同样注意, 指针结构是怎样用下标来引用的。要引用指针内的字段,那么指针一定要用括号括起。最后,请注意,不一定非得将info结构

31、返回给顶级base 的用户值中,因为这个顶级base 在任何情况下都会被销毁。在 320 页的 IDL 源代码附录中,可以在组件定义模块中找到最终的GetData 的源代码。测试模式对话框程序把程序保存为GetData.Pro ,编译并调用、测试它。如下: IDL.Compile GetData IDLimage=GetData()运行结果看上去像图90 中的例子。在313 页附录 B的数据文件描述中,可以找到合适的文件名称以及其大小,用以输入到程序对话框中。通过上一章的XImageBar 程序,调用GetData ,看看它是如何工作的。(如果在上一章中自己没有编写XimageBar 程序,

32、也可以调用与本书配套使用的文档中的XimageBar.9.Pro )在程序 XimageBar 中查找用到了GetImage 命令的地方, 这应该有两处, 并将 GetImage 替换为 GetData 。 然后保存并编译该程序。运行结果和想象中一样吗?(改变后的XimageBar.Pro已经保存为XimageBar.10.Pro,在与本书配套使用的文档中可以找到)当GetData 已经显示在屏幕上而准备退出XimageBar 程序时,结果会如何?结果是所期望的吗?图 90:GetData 对话框程序如果程序运行正确,它会浮在XImagebar 程序之上。 当点击 XImagebar 程序时,

33、 可以听到一声短而尖的声音,以提醒在使用另一程序之前必须销毁该程序。完整的 GetData 程序可以在与本书配套使用的文档中找到。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 12 页 - - - - - - - - - 创建非模式的对话框有时候, 不希望在从用户那儿获取信息时所有的事情都停下来。更希望显示对话框是为了方便用户, 而不阻塞与之同时显示的程序的使用。这种情况就更难解决了,因为不知道什么时候用户能够准备好这些信息。很可能在用户使用之前该对话框就已经在屏幕上呆

34、了数小时。在这种情况下, 就不得不在程序中采用多个方法来告诉程序用户已经准备好了。为做到这一点, 我通常采用一个Apply 按钮, 这和前面编制的程序练习中的Accept 相类似。 同样,可以用一个等同于前面练习中的Cancel 的 Dismiss 按钮,其目的在于将对话框销毁。因此,无阻塞对话框看上去如图91 所示,即后面即将编写的程序GetFile的运行结果。编写非模式对话框程序 GetFile的组件定义模块和先前的GetData 程序的定义模块几乎是一样的。但存在着很大的区别,在下面例子中已用黑体字标出。下面是GetFile程序定义模块的完整代码。PRO GETfile, notifyI

35、D, Filename=filename, XSize=xsize, $ YSize=ysize, Parent=parent On_Error, 2 IF N_Params( ) EQ 0 THEN BEGIN Ok = Dialog_Message ( Widget ID parameter required. ) Return ENDIFIF N_Elements (filename) EQ 0 THEN $ filename= filepath (Root_Dir=Coyote (), ctscan.dat ) ELSE $ filename=filepath (Root_Dir=Co

36、yote(), filename) IF N_Elements(xsize) EQ 0 THEN xsize=256 IF N_Elements(ysize) EQ 0 THEN ysize=256 Device, Get_Screen_Size=screenSize Xcenter=FIX(screenSize(0)/2.0) Ycenter=FIX(screenSize(1)/2.0) Xoff=xCenter-150 Yoff=yCenter-150 IF N_Elements(parent) NE 0 THEN $ Tlb =Widget_Base (Column=1, XOffset

37、=xoffset=xoff, YOffset=yoff,$ Title= Enter File Information ,$ Group_Leader=Parent,/Base_Align_Center) ELSE $ Tlb =Widget_Base (Column=1, XOffset=xoffset=xoff, YOffset=yoff,$ Title= Enter File Information ,$ Subbase=Widget_Base(tlb,Column=1, Frame=1) Filesize=strlen(filename)*1.25 FileID= CW_Field(s

38、ubbase, Title= Filename: ,$ Value=filename, xsize=filesize) XsizeID=CW_Field (subbase,Title= XSize: ,$ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 12 页 - - - - - - - - - Value=xsize,/Integer) YsizeID=CW_Field (subbase,Title= YSize: ,$ Value=ysize,/Integer) B

39、utbase=Widget_Base(tlb,row=1) Dismiss=Widget_Button(butbase, Value= Dismiss ) Apply=Widget_Button(butbase, Value= Apply ) Widget_Control, tlb,/ Realize Info=fileID:fileID, xsizeID: xsizeID, $ YsizeID:YsizeID, notifyID:notifyID Widget_Control, tlb, set_uvalue=info,/no_copy Xmanager, getfile , tlb, Ev

40、ent_Handler= getfile_events , /no_block END 图 91:无阻塞对话框程序GetFile ,它类似于图90 的阻塞对话框GetData 。按钮上的文本表明了这是一个无阻塞程序。通报程序事件的组件代码中最大的变化是在组件定义模块的第一行,以前是函数现在变成了过程。 PRO GetFile, notifyID, Filename=filename, Xsize=xsize, YSize=ysize, Parent=parent 这个变化的原因在于此时不能像函数一样返回信息,因为当用户填完表格后,程序不会停止或阻塞。 因而必须找到另一种技术来告诉程序调用者或其

41、它程序,可以获取用户信息了。在这里,通过参数notifyID,一个组件标识符的矢量来通报事件是可行的。当用户按下 Apply 按钮时, 窗体中的信息被收集后,通过向对话框中所有的组件发送一个含有窗体信息的事件, 因而参数 notifyID所标识的组件将被通知。 (这种技术在274 页中的“创建并向其他程序发送事件”已经讨论过。)参数 notifyID是一个含有组件标识符的2*N 数组。, 第一个列是当按下Apply 按钮时即将被通知的组件标示符,第二个列是第一列所标示的组件的顶级base 的标示符。 在实际中,通常在同一个事件处理模块中调用程序GetFile 。如下所示GetFile, eve

42、nt.id, event.top 第二个变化是在组件定义模块中将参数notifyID变为一个必须参数,见下: IF N_Params() EQ 0 THEN BEGIN Ok=Dialog_Message ( Widget ID parameter required. ) RETURN ENDIF 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 12 页 - - - - - - - - - 顶级 base 的定义方式因此也相应地变了:IF N_Elents (parent

43、) NE 0 THEN $ Tlb=Widget_Base(Column=1.XOffset=xoff, YOffset=yoff, $ Title= Enter File Infoemation , $ Group_Leader=Parent, / Base_Align_Center) ELSE $ Tlb=Widget_Base(Column=1.XOffset=xoff, YOffset=yoff, $ Title= Enter File Infoemation , / Base_Align_Center) 注意,由于这是一个非模式对话框件,因而不需要使用关键字Modal 或 Float

44、ing了,参数 Parent 如果定义了,那它仍然作为对话框的Group Leader 来使用。用户可以通过选择Parent 关键字来决定该组件程序是否作为另一组件程序的成员。尽管按钮的名字变成了Dismiss和 Apply ,但它们的功能与GetData 程序中的Cancel和 Accept 按钮功能相类似。 Dismiss=Widget_Button ( butbase, Value= Dismiss ) Apply=Widget_Button (butbase, Value= Apply ) 改变按钮名字是对用户来讲是一个更为直观的功能提示。换言之,看到 Cancel 和 Accept按

45、钮, 用户就会期望这是模式对话框。看到 Dismiss 和 Apply 按钮, 用户期望的就是非模式对话框。如果将界面尽可能保持一致的风格,用户就会少一点困惑。程序中没有使用指针,因为没有必要使用全局的内存。但是,组件的标识符矢量(用来标识即将被通知的组件)必须存储在info结构中,因为在事件处理模块中需要用到这些信息。 Info=fileID:fileID, xsizeID:xsizeID, $ YsizeID:ysizeID, notifyID:notifyID 组件定义模块中的最后一个变化是通过XManager命令中的 No_Block 关键字将阻塞组件程序为无阻塞组件程序。如下:XMa

46、nager, getfile , tlb, Event_Handler= GetFile_Events , /No_Block 编写非模式对话框的事件处理模块程序 GetData 和 GetFile的最大差别在于当用户按下Accept 或 Apply 按钮时,事件处理模块是如何工作的。而其余的事件处理方式基本是相同的。下面是事件处理代码的前半部分,细微差别已用黑体字标出: Pro GetFile_Events, event EventName=Tag_Names (event, /Structure_Name) IF eventName NE widget_button then return

47、 Widget_Control, event.top, Get_UValue=info, / No_COPY Widget_Control, event.id, Get_UValue=buttonValue CASE buttonValue Of Dismiss : Widget_Control, event.top, /Destroy 将事件发送给其他组件当用户点击Apply 按钮时,事件处理程序将对话框中的信息收集,并提示notifyID所指定的组件事件已经发生了。这里是通过建立伪事件,并用Widget_Control命令的名师资料总结 - - -精品资料欢迎下载 - - - - - -

48、- - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 12 页 - - - - - - - - - Send_Event 关键字发送事件来完成的。第二部分如下所示,不同之处已用黑体字标出: Apply : BEGIN Widget_Control, info.fileID, Get_Value=filename Widget_Control, info.xsizeID, Get_Value=xsize Widget_Control, info.ysizeID, Get_Value=ysize S=Size(info.notifyID) If

49、 s0 EQ 1 THEN count=0 ELSE count=s2 1 FOR j=0, count DO BEGIN PseudoEvent=GETFILE_EVENT, ID:info.notifyID0,j, $ Top:info.notifyID1,j, Handler:0L, $ Filename:filename0, XSize:xsize, YSize:ysize IF Widget_Info (info.notifyID0,j, / Valid_ID) THEN $ Widget_Control, info.notifyID0,j, Send_Event=pseudoEve

50、nt ENDFOR Widget_Control, event.top, Set_UValue=info, / No_Copy END ENDCSAE END 伪事件是一个名为GETFILE_EVENT 的事件结构,字段ID 包含了接收这个事件的组件标识符。 字段 TOP标识了组件结构层次图中的顶级base。Handler 字段是空的, 但在事件传递到组件之前,IDL 自己能够正确地填写。在这里所做的只是创建几个长整型的字段,即fileName 、Xsize 和 Ysize ,它们包含了从对话框中所获得的信息。如果接收到事件结构的组件仍是个有效组件(即组件仍然存在),那么伪事件就将通过Widg

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com