模版
这个脚本的模版是在 Tcl/Tk 源代码发布中的 tkAppInit.c (在放置 Tk 源代码的目录下查找 - 象 ~pdsrc/TclTk/tk4.0 一类的东西)。复制一份 tkAppInit.c 到你的工作目录中。重命名为 myTclInit.c (在 ~cookbook/code/ch6 下的源代码中还有一个 Makefile 模版)
在下面的脚本中,使用粗体字来表示定制的程序代码,使用斜体字表示我们在代码中插入的注释:
#ifndef lint static char sccsid[] = "@(#) tkAppInit.c 1.12 94/12/17 16:30:56"; #endif /* not lint */ #include "tcl.h" #include "tk.h" /*Include files for PHIGS & X */ #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xatom.h> #include <phigs/phigs.h>/*Pconnid_x_drawable 是持有一个 X window 的 id 的一个结构,PHIGS 将在这个窗口中打开*/
Pconnid_x_drawable conn_id;/* 在 phigscbs.c 中定义的过程 */
extern int MakeCubeProc();
/* 在 phigscbs.c 中定义的一个基于 PHIGS 的 C 过程,它提供 PHIGS 变换矩阵来把对象(物体)旋转给定度数并帖出(post)这个结果(对象)。用户通过移动一个 Tk 缩放组件来输入旋转的角度。由 PHIGS 处理 3D 结构的编辑和更新工作站。*/
extern int rotate_boxProc();
/*在 phigscbs.c 中定义的一个基于 PHIGS 的 C 过程,它在发生一个外部事件或 PHIGS 工作站的状态改变的时候,例如帖出一个结构的时候,重画所有结构。PHIGS 处理工作站的更新。*/
extern int redrawProc();
/*在 phigscbs.c 中定义的一个基于 PHIGS 的 C 过程,它改变用 Tk 菜单条目选择的已显示的 3D 对象的颜色。PHIGS 处理 3D 结构的编辑并更新工作站。*/
extern int ChColProc();
/*在 phigscbs.c 中定义的一个基于 PHIGS 的 C 过程,它关闭 PHIGS 工作站和关闭 PHIGS 并在用户选择 Tk Quit 按钮的时候退出应用。*/
extern int CleanupAndQuitProc();
Tk_Window 是 Tk 表示一个窗口的记号(token)。在建立一个新窗口时返回这个记号。你可以使用它来查询信息或操纵一个 Tk 组件。
过程 "Tcl_AppInit" 在下述过程之后定义,调用 "Tk_CreateMainWindow" 来建立应用的主窗口。
Tk_Window mainwin, win;
/* 这个过程在 Tk 画布组件中安装 PHIGS 工作站并做一些家务。这个过程通过用户命令 SetupPhigs 向 Tcl/Tk 解释器注册。向 SetupPhigs 传递一个参数 - 画布组件的路径名。*/
int SetupPhigsProc (ClientData clientdata, Tcl_Interp *interp,
int argc, char *argv[])
{
Window winid;
Pxphigs_info xphigs_info;
unsigned long mask;
XSetWindowAttributes win_attrs;
Display *dsp;
在调用这个过程的时候,画布组件的路径名作为 argv[1] 参数来传递。Tk_NameToWindow 返回在叫做"mainwin"的主窗口中的画布组件的记号。
使用这个 "win" 记号来把必要的连接标识符赋予给 PHIGS 的画布。
Tk_Display 接受一个 Tk_Window 记号作为参数并返回一个指针,它指向结构显示器 - 画布组件的 X 显示器。
Tk_WindowId 返回画布窗口的 X 标识符。
win = Tk_NameToWindow(interp, (char *)argv[1], (Tk_Window) mainwin); dsp= Tk_Display(win); winid = Tk_WindowId(win); conn_id.display = dsp; conn_id.drawable_id = winid;
告诉 PHIGS 不监视调色板等。并以适当监视权限来打开 PHIGS 工作站。
mask = PXPHIGS_INFO_FLAGS_NO_MON; xphigs_info.flags.no_monitor =1; popen_xphigs (PDEF_ERR_FILE,PDEF_MEM_SIZE,mask,&xphigs_info); win_attrs.backing_store = NotUseful; XChangeWindowAttributes( dsp,winid, CWBackingStore, &win_attrs);
使用 Tk_CreateEventHandler 为指定的窗口事件设置处理器;在用第一个参数给出的窗口中的,通过给定的掩码选择的特定事件发生的时候,调用特定的过程。
Tk_CreateEventHandler(win, ExposureMask, (Tk_EventProc *) redrawProc,NULL); return 0; }
/*
* The following variable is a special hack that is needed in order for
* Sun shared libraries to be used for Tcl.
*/
#ifdef NEED_MATHERR
extern int matherr();
int *tclDummyMathPtr = (int *) matherr;
#endif
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* 给应用的解释器。*/
{
mainwin = Tk_MainWindow(interp);
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
if (Tk_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
/* 为包含的包调用 init 过程。每个调用看起来都象下面这样:Tcl_CreateCommand(interp, "SetupPhigs", (Tcl_CmdProc *)SetupPhigsProc,(ClientData )NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "ChCol", (Tcl_CmdProc *) ChColProc,(ClientData )NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "CleanupAndQuit", (Tcl_CmdProc *) CleanupAndQuitProc,(ClientData )NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "rotate_box", (Tcl_CmdProc *) rotate_boxProc,(ClientData )NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "MakeCube", (Tcl_CmdProc *) MakeCubeProc,(ClientData )NULL, (Tcl_CmdDeleteProc *) NULL);/*
tcl_RcFileName ="~/.myapprc";
return TCL_OK;
}
Tcl_CreateCommand 向要在其中使用命令的解释器 interp 注册一个用户命令。给 Tcl_CreateCommand 的第二个参数是在 Tcl/Tk 脚本中使用的命令的名字。第三个参数是命令过程。 使用 clientData 来传递与命令相关的对象的的地址,而 deleteProc 指定在命令被删除时要调用的过程。用它来释放作为而与命令相关的对象,如 clientData。
在这个例子中,我们建立了可以在 Tcl 脚本中使用的五个命令,它们可被我们的这个版本的 Tcl 解释器分析。
注意设置任何启动文件都需要 tcl_RcFileName。
/*
*----------------------------------------------------------------------
*
* main --
*
* This is the main program for the application.
*
* Results:
* None: Tk_Main never returns here, so this procedure never
* returns either.
*
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
int
main(argc, argv)
int argc; /* Number of command-line arguments. */
char **argv; /* Values of command-line arguments. */
{
Tk_Main(argc, argv,Tcl_AppInit);
return 0; /* Needed only to prevent compiler warning. */
}