📄 ch34.htm
字号:
<P>In Motif, almost all declarations begin with <TT>Xm</TT>. Therefore, <TT>XmC</TT>
refers to a class, <TT>XmR</TT> refers to a resource, <TT>XmN</TT> refers to a name,
and <TT>XtN</TT> refers to Xt resources used by Motif. Declarations ending with the
words <TT>WidgetClass</TT> define the base class for a type of Widget. A few conventions
to remember about parameters for most <TT>Xlib</TT> functions are
<UL>
<LI>Width is always to the left of height
<P>
<LI>X is always to the left of y
<P>
<LI>Source is always to the left of destination
<P>
<LI>Display usually is the first parameter
</UL>
<P>With practice, you will be able to identify the type of parameters to pass and
which toolkit a function belongs to, and be able to make some educated guesses as
to what parameters an unknown function might expect.
<H3 ALIGN="CENTER"><A NAME="Heading6<FONT COLOR="#000077">Writing Your First
Motif Application</FONT></H3>
<P>Let's look at the basic format for a Motif application, shown in Listing 34.1.
(I added line numbers for your benefit.) I will discuss this application in detail.
You will build other Motif applications based on the structure in this particular
application as you progress through this chapter.
<DL>
<DT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading7<FONT COLOR="#000077"><B>NOTE:</B> </FONT>The line numbers
are for reference only.
<HR>
</DL>
<H3 ALIGN="CENTER"><A NAME="Heading8<FONT COLOR="#000077">Listing <A NAME="Heading934.1.
A sample Motif application.</FONT></H3>
<PRE><FONT COLOR="#0066FF"> 1 /*
2 ** This is a typical Motif application with one button that
3 ** exits it.
4 */
5 #include <X11/Intrinsic.h>
6 #include <Xm/Xm.h>
7 #include <Xm/Form.h>
8 #include <Xm/PushB.h>
9 void bye(Widget w, XtPointer clientdata, XtPointer calldata);
10 int main(int argc, char **argv)
11 {
12 Widget top;
13 XtAppContext app;
14 Widget aForm;
15 Widget aButton;
16 Arg args[5];
17 /**
18 *** Initialize the toolkit.
19 **/
20 top = XtAppInitialize(&app, "KBH", NULL, 0, (Cardinal *)&argc,
21 argv, NULL, args, 0);
22 /**
23 *** Create a Form on this top level Widget. This is a nice Widget
24 *** to place other Widgets on top of.
25 **/
26 aForm = XtVaCreateManagedWidget("Form1",
27 xmFormWidgetClass, top,
28 XmNheight,90,
29 XmNwidth,200,
30 NULL);
31 /**
32 *** Add a button on the form you just created. Note how this Button
33 *** Widget is connected to the form that it resides on. Only
34 *** left, right, and bottom edges are attached to the form. The
35 *** top edge of the button is not connected to the form.
36 **/
37 aButton = XtVaCreateManagedWidget("Push to Exit",
38 xmPushButtonWidgetClass, aForm,
39 XmNheight,20,
40 XmNleftAttachment,XmATTACH_FORM,
41 XmNrightAttachment,XmATTACH_FORM,
42 XmNbottomAttachment,XmATTACH_FORM,
43 NULL);
44 /**
45 *** Call the function "bye" when the PushButton receives
46 *** an activate message; i.e. when the pointer is moved to
47 *** the button and Button1 is pressed and released.
48 **/
49 XtAddCallback( aButton, XmNactivateCallback,
50 Âbye, (XtPointer) NULL);
51 XtRealizeWidget(top);
52 XtAppMainLoop(app);
53 return(0);
54 }
55 void bye(Widget w, XtPointer clientdata, XtPointer calldata)
56 {
57 exit(0);
58 }
</FONT></PRE>
<P>The listing shows an application in which a button attaches itself to the bottom
of a form. See Figure 34.2. <BR>
<BR>
<A HREF="../art/34/34lnx02.jpg"><B>Figure 34.2.</B></A> <I>The output of Listing
34.1 <TT>(L34_1.c)</TT>.</I></P>
<P>No matter how you resize the window, the button will always be on the bottom.
The application does the following things in the order listed:
<DL>
<DD><B>1.</B> Initializes the toolkit to get a shell Widget.<BR>
<BR>
<B>2.</B> Makes a Form Widget.<BR>
<BR>
<B>3. </B>Manages all Widgets as they are created.<BR>
<BR>
<B>4.</B> Makes the Button Widget on top of the Form Widget.<BR>
<BR>
<B>5. </B>Attaches a callback function to the button.<BR>
<BR>
<B>6.</B> Realizes the Widget (that is, makes the hierarchy visible).<BR>
<BR>
<B>7. </B>Goes into its event loop.
</DL>
<P>Let's look at the application in more detail. The <TT>include</TT> files in the
beginning of the listing are required for most applications. Notably, the two files
shown in lines 5 and 6 are required for just about any Motif application you'll ever
write.</P>
<PRE><FONT COLOR="#0066FF">#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
</FONT></PRE>
<P>These two lines declare the definitions for <TT>XtIntrinsics</TT> and Motif, respectively.
In some systems, you may not require the first inclusion, but it's harmless to put
it in there because multiple inclusions of <TT>Intrinsic.h</TT> are permitted. In
addition, each Motif Widget requires its own header file. In Listing 34.1, the Widgets
Form and PushButton are included via statements in lines 7 and 8:</P>
<PRE><FONT COLOR="#0066FF">#include <Xm/Form.h>
#include <Xm/PushB.h>
</FONT></PRE>
<P>The variables in the program are declared in lines 12 through 16:</P>
<PRE><FONT COLOR="#0066FF">Widget top;
XtAppContext app;
Widget aForm;
Widget aButton;
Arg args[5];
</FONT></PRE>
<P>The <TT>top</TT>, <TT>aForm</TT>, and <TT>aButton</TT> represent Widgets. Even
though their functions are different, they can all be referred to as Widgets.</P>
<P>The <TT>XtAppContext</TT> type is an opaque type, which means that a Motif programmer
does not have to be concerned about how the type is set up. Widgets are opaque types
as well; only the items that are required for the programmer are visible.</P>
<P>The first executable line of the program calls the <TT>XtAppInitialize()</TT>
function (in line 20) to initialize the <TT>Xt</TT> toolkit and create an application
shell and context for the rest of the application. This value is returned to the
Widget top (for top-level shell). This Widget will provide the interface between
the window manager and the rest of the Widgets in this application.</P>
<P>The application then creates a Form Widget on this top-level Widget. A Form Widget
is used to place other Widgets on top of itself. It is a Manager Widget because it
"manages" other Widgets.</P>
<P>There are two steps required for displaying a Widget: First you have to manage
it (with <TT>XtVaCreateManagedWidget)</TT> and then you have to realize it (with
<TT>RealizeWidget</TT>).</P>
<P>Managing a Widget enables it to be visible. If a Widget is unmanaged, it will
never be visible. By managing a Widget, the program gives the viewing control over
to the windowing system so it can display the Widget. If the parent Widget is unmanaged,
any child Widgets remain invisible, even if they are managed.</P>
<P>Realizing a Widget actually creates all the subwindows under an application and
displays them. Normally, only the top-level Widget is realized after all the Widgets
are managed. This call will realize all the children of this Widget.</P>
<P>Note that realizing a Widget takes time. A typical program will manage all the
Widgets except the topmost one. This way the application will only have to realize
the topmost Widget when the entire tree has to display only the topmost parent. You
have to realize a Widget at least once, but you can manage and "unmanage"
Widgets as you want to display or hide them.</P>
<P>You can always create and manage a Widget to call <TT>XtCreate</TT> and <TT>XtManageChild</TT>
in two separate calls. However, the samples in this chapter will use a single call
to create and manage a Widget: <TT>XtVaCreateManagedWidget</TT>.</P>
<P>Note the parameters in this call to create the Form Widget shown in lines 26 through
30:</P>
<PRE><FONT COLOR="#0066FF">aForm = XtVaCreateManagedWidget("Form1",
xmFormWidgetClass, top,
XmNheight,90,
XmNwidth,200,
NULL);
</FONT></PRE>
<P>The first parameter is the name of the new Widget. The second parameter describes
the class of the Widget being created. Recall that this is simply the Widget name
sandwiched between <TT>xm</TT> and <TT>WidgetClass</TT>. So, in this case, it is
<TT>xmFormWidgetClass</TT>. Note the lowercase <TT>x</TT> for the class pointer.
This class pointer is declared in the header files included at the beginning of the
file, <TT>Form.h</TT>.
<DL>
<DT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading10<FONT COLOR="#000077"><B>TIP: </B></FONT>As another example,
the class pointer for a Label would be called <TT>xmLabelWidgetClass</TT> and would
require the <TT>Label.h</TT> file. Motif programmers have to be especially wary of
the case of all variables.
<HR>
</DL>
<P>The next argument is the parent Widget of this new Widget. In this case, <TT>top</TT>
is the parent of <TT>Form1</TT>. The <TT>top</TT> Widget is returned from the call
to <TT>XtAppInitialize</TT>.</P>
<P>The remaining arguments specify the parameters of this Widget. In this case you
are setting the width and height of the Widget. This list is terminated by a <TT>NULL</TT>
parameter.</P>
<P>After the form is created, a button is placed on top of it. A Form Widget facilitates
placement of other Widgets on top of it. In this application you will cause the button
to "attach" itself to the bottom of the form. The following three lines
(40-42) attach themselves to the form:</P>
<PRE><FONT COLOR="#0066FF">
XmNleftAttachment,XmATTACH_FORM,
XmNrightAttachment,XmATTACH_FORM,
</FONT></PRE>
<PRE><FONT COLOR="#0066FF">
XmNbottomAttachment,XmATTACH_FORM,
</FONT></PRE>
<P>The class of this button is included in the <TT>PushB.h</TT> file and is called
<TT>xmPushButtonWidgetClass</TT>. The name of this Widget is also the string that
is displayed on the face of the button. Note that the parent of this button is the
<TT>aForm</TT> Widget. The hierarchy is as follows:</P>
<PRE><FONT COLOR="#0066FF">
top -> is the parent of aForm -> is the parent of -> aButton.
</FONT></PRE>
<P>The next step is to add a callback function when the button is pressed. This is
done with the call to <TT>XtAddCallback</TT>, as shown in the following:</P>
<PRE><FONT COLOR="#0066FF">XtAddCallback( aButton, XmNactivateCallback, bye, (XtPointer) NULL);
</FONT></PRE>
<P>Here are the parameters for this call:
<UL>
<LI><TT>aButton</TT> is the PushButton Widget.
<P>
<LI><TT>XmNactivateCallback</TT> is the action that will trigger a call to this function.
<P>
<LI><TT>bye</TT> is the name of the function that will be called when the action
is triggered. (You should declare this function before making this function call,
or you will get a compiler error.)
<P>
<LI><TT>NULL</TT> is a pointer. This pointer could point to some structure meaningful
to function <TT>bye</TT>.
</UL>
<P>This will register the callback function <TT>bye</TT> for the Widget. Now the
topmost Widget, <TT>top</TT>, is realized. This causes all managed Widgets below
<TT>top</TT> to be realized. The application then goes into a loop that processes
all incoming events.</P>
<P>The <TT>bye</TT> function of this program simply exits the application.
<H3 ALIGN="CENTER"><A NAME="Heading11<FONT COLOR="#000077">Compiling This Application</FONT></H3>
<P>Now comes the tough part of compiling this application into a working application.
You will use the gcc compiler that comes with Linux for this purpose.</P>
<P>First, check the location of the libraries in your system. Check the <TT>/usr/lib/X11</TT>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -