T.R | Title | User | Personal Name | Date | Lines |
---|
931.1 | Use the window manager | BAGELS::FELDMAN | Jerry Feldman DTN 227-3279 | Tue Jul 31 1990 12:14 | 73 |
| > I wrote a Gem program in C, based on a dialogue box as a 'main menu'.
> That worked fine. I then converted it to a desk accessory. Although
> the program still functions, the screen gets a little untidy. (Well,
> a complete mess if you must know.) The first use of the dialogue is OK,
> but I seem to be out of sync with other windows being tidied up thereafter.
> What have I missed?
> Brian.
>
>
>
> Here is an outline of the program:-
>
> main()
>
> start up stuff, rsrc_load etc
>
> forever
> event_multi(MU_MESAG)
> if( MU_MESAG )
> do_panel()
>
>
> do_panel()
> rsrc_getaddr()
> form_center()
> exit=FALSE ;
> do
> form_dial(0,.... /*save screen*/
> obj_draw( /*draw dialog*/
> button=form_do() /*do dialog*/
> form_dial(3, /*restore screen*/
> switch button
> case ...
> /* do something useful here*/
>
> case EXIT:
> exit=TRUE ;
>
> while( !exit )
I have several programs which are either desk accessories or main line.
I found that one of the cleanest ways to manage a desk accessory is to
use the window interface.
1. Create a window. (wind_create())
2. Issue a form_center() to position your dialog box.
3. Use the outside dimensions of your dialog box object as the inside
dismensions of your window and get the outside dimensions of the
window created in 1, above. (I forget the exact function name at
this point, but the function allows you to compute the outside
dimensions (x,y,b,h) of the window given the workarea and window
type (eg the parts such as scroll bars, title bar, etc)).
4. Use these dimensions, and open your window.
5. At this point, you will have a virgin window on the screen. When
a new window is opened, a redraw is requested. You can then proceed
to do the objc_draw(), form_do, etc.
6. After completing the menu, close the window. If you are going to
reuse the window, don't bother to do a wind_delete().
There are some other problems with the program. Since you are a desk
accessory, the message will contain other things. You should probably
case for them.
If you place your dialog box in a window, GEM will tell you when the
user has placed your window on top, and send you a redraw message.
Thus, by placing your stuff in a window, you will know what needs to be
redrawn. You may elect to dispense with the form library and handle
the user interface yourself. You can still use the dialog boxes that
you created.
Jerry
|
931.2 | My best guess. | PRNSYS::LOMICKAJ | Jeffrey A. Lomicka | Tue Jul 31 1990 13:32 | 5 |
| In all likelihood, the problem is that when you do the form_dial( 3...),
you have to list the rectangle twice:
form_dial( 3, x, y, w, h, x, y, w, h)
|
931.3 | More on form library | BAGELS::FELDMAN | Jerry Feldman DTN 227-3279 | Wed Aug 01 1990 11:26 | 22 |
| As I mentioned in .1, placing the dialog box in a window is better for
a desk acc. I have used form_alert() and form_do() in desk accs, but
strange things happen. I normally use form_alert() while debugging
programs, but this tends to be ineffective for desk accessories. By
using the window manager, you will have more control. You might note
that many of the accessories which appear to use dialog boxes, place
them in fixed size windows. These include calculators, print spoolers,
ram disks, etc. I wrote a calculator that can operate as either a DA or
as a stand alone. I use form_center() to initially position the opject
in the window, and then reposition it in the upper left.
Note that, when a DA is loaded, it may not allocate any additional
memory. (You can still use malloc() if your compiler pre allocates a
heap). Form_dial(0,...) allocates memory to save the underlying
screen, and form_dial(3,...) returns it. By using the window manager,
you are eliminating these instructions which I think are probably the
culprits. I think that form_do() will probably work ok.
Also, note that, in a desk accessory, you should never exit, or issue
an appl_exit(). You should tidy up the screen by closing your window,
and continue looping on evnt_multi. You will then be restarted through
the ac_open message.
|
931.4 | FORM_ALERT and FORM_DO are JUST FINE in desk accessories | PRNSYS::LOMICKAJ | Jeffrey A. Lomicka | Thu Aug 02 1990 13:27 | 83 |
| > As I mentioned in .1, placing the dialog box in a window is better for
> a desk acc. I have used form_alert() and form_do() in desk accs, but
> strange things happen. I normally use form_alert() while debugging
> programs, but this tends to be ineffective for desk accessories.
I disagree. There is no good way to put a GEM form in a window without
re-implementing all of the form editing. form_do() and form_alert()
work GREAT with desk accessories, since they are pre-emptive and don't
count on the application living gracefully in a full windowing environment.
If you want a small programming example of a form-based desk accessory,
read PRNSYS::USER2:[LOMICKAJ.HOBBY.ST]KJV.C. This is a program for
searching for keywords in a directory full of King James Bible stuff.
It uses a resource file (created with Mark Williams C resource editor)
to contain the form itself. The whole program is just a pop-up form
that get's modified as the program rolls along. It's only 515 lines top
to bottom. The key portion is as follows:
kjvsearch()
{
register int i;
register TEDINFO *t;/* Used to get actual search string */
rsrc_gaddr( 0, KJVHUNT, &formtree);
form_center( formtree, &x, &y, &w, &h);
form_dial( FMD_START, x, y, w, h, x, y, w, h);
t = (TEDINFO *) formtree[ SEARCHRE].ob_spec;
. . .
objc_draw( formtree, 0, MAX_DEPTH, x, y, w, h);
for(;;)
{ /* Repeatedly process form until a good reason to exit is encountered */
formtree[ SEARCHRE].ob_flags |= EDITABLE;
i = form_do( formtree, 0);
i &= 0xFFF; /* Strip off high order bits, because double
clicks come back negative. (How odd) */
. . . Process EXIT and TOUCHEXIT items . . .
if( this is an EXIT item ... )
{
form_dial( FMD_FINISH, x, y, w, h, x, y, w, h);
break;
}
}
return;
}
main( )
{
register int event; /* Event kind delivered */
int menuid;
short msg[ 8]; /* Messages from GEM */
rscok = 0; /* Start with no resource */
appl_init( );
testrsc( "D:\\KJV\\KJV.RSC"); /* Load the resource file */
if( rscok) menuid = menu_register(gl_apid, " KJV Word Search");
else menuid = menu_register(gl_apid, " KJV.RSC not found");
for(;;)
{ /* Process each request one at a time */
int j;
event = evnt_multi(
MU_MESAG , /* event(s) */
1, 1, 1, /* clicks, button, state */
0, 0, 0, 0, 0, /* m1inout, rect1 (x, y, w, h) */
0, 0, 0, 0, 0, /* m2inout, rect2 (x, y, w, h) */
msg, /* message buffer */
50, 0, /* time interval (low, high) */
&j, &j, &j, &j, /* mouse (&x, &y, &b, &k) */
&j,&j /* &key, × */
);
if( event & MU_MESAG)
{
if( msg[ 0] == AC_OPEN)
{
if( msg[ 4] == menuid) /* Note, not [3]. */
if( rscok) kjvsearch( KJVHUNT);
}
}
}
}
|
931.5 | Thanks | MINDER::GILBERT | Systems Design & Eng Cntr @ MCO | Thu Aug 02 1990 18:43 | 11 |
|
Thanks for the responses.
Re .2: I tried the suggestion, but no change.
I've downloaded the example (thanks Jeff) and compare it with my
efforts. I'll let you know how I get on.
BTW: Is DECwindows programming as difficult a learning curve as GEM?
Brian.
|
931.6 | In my opinion | PRNSYS::LOMICKAJ | Jeffrey A. Lomicka | Fri Aug 03 1990 11:08 | 1 |
| DECwindows is much harder, but it works better once you get there.
|
931.7 | New input | MINDER::GILBERT | Systems Design & Eng Cntr @ MCO | Mon Aug 06 1990 04:34 | 30 |
| Some further information on the issue:-
1) Comparing the design of my opus versus Jeff's, the two are very
similar until we get to execution of actions from user input to the
dialog box. Jeff's *only* interacts with the user via the dialog box,
whereas I'm trying to use file selectors and alerts at that point. I
dummied out one of the action routines to prove the point.
2) I have experimented with either removing my dialog box before executing
the action, or letting the action output overlay the dialog box. These
differ only in the pattern of the screen confusion.
3) If I put an evnt_timer() call with a 2 second delay immediately before
the obj_draw() in my menu loop, the screen corruption goes away, the
underlying windows are redrawn OK and my dialog is displayed correctly.
4) I then modified my program to do an evnt_mesag() later in the menu
loop, hoping to pick up a message telling me to re-draw. No such
message arrives - the accessory hangs at that point and only continues if
re-open it.
Conclusions:
I appear to be displaying the dialog OK, but use of further screen
outputs (e.g. file selector) causes a sync problem.
The lack of a re-draw message may be because there is no window open -
i.e. tending to confirm the recommendations in .1 and .3.
Brian.
|
931.8 | More on using AES windows | BAGELS::FELDMAN | Jerry Feldman DTN 227-3279 | Mon Aug 06 1990 10:29 | 23 |
| Your symptoms appear to be similar to mine. It is a possibility that
there may be a bug in GEM that may have been fixed in 1.4. By placing
the dialog box in a window, and eliminating the form_dial() functions,
you have more control, but it does require more work. When building the
window to hold a dialog box, you only need to define a title bar.
Normally, I also define a move bar adn a closer so that the window can
be moved and closed. The only tricky thing is the technique used to
place the box into the window. The form_center() function fills in the
rectangle in the dialog box's object structure. This then becomes the
rectangle for the window work area. (I normally change x and y to the
top left corner of the screen for my calculator). The wind_calc()
function can be used to convert the work area dimensions to outside
dimensions. I you desire, I can upload one of my programs that use this
technique tomorrow.
I fully agree with Jeff on Decwindows. However, X windows (which is the
basis for Decwindows) is the standard for window programming. When the
ST came out, GEM was one of the better windowing systems, and is far
superior to Microsoft's garbage. (In all fairness, Windows 3 may be
decent, but I have not yet seen it). I think that you will see more X
window implementations accross more platforms in the future. In other
words, in the long run, knowledge of DECwindows is more useful. Not to
denigrate GEM, but GEM is also somewhat obsolete technologically.
|
931.9 | I see what's happening now. | PRNSYS::LOMICKAJ | Jeffrey A. Lomicka | Mon Aug 06 1990 11:39 | 41 |
| > 3) If I put an evnt_timer() call with a 2 second delay immediately before
> the obj_draw() in my menu loop, the screen corruption goes away, the
> underlying windows are redrawn OK and my dialog is displayed correctly.
What you are doing here is making sure that GEM schedules the desktop
application's redraw before it schedules yours. This means it is done
drawing before you start drawing, and you can put your pre-emptive form
back up. The reason putting the form in a window fixes this problem,
is that the desktop will then get clipping information about your
window and will not draw on top of it.
> 4) I then modified my program to do an evnt_mesag() later in the menu
> loop, hoping to pick up a message telling me to re-draw. No such
> message arrives - the accessory hangs at that point and only continues if
> re-open it.
As you have surmised, you only get redraw messages on windows.
> Conclusions:
>
> I appear to be displaying the dialog OK, but use of further screen
> outputs (e.g. file selector) causes a sync problem.
Whe you issue form_do, form_alert, or file selector, the form handler's
internal event_multi is allowing the destop application to take control,
which is violating your fundamental assumption that you have pre-emptive
control of the machine. The other applications are getting control at
this point, and processing their pending redraw messages. When you
think about it, everything is in perfect synchronization. The only
problem is that you are drawing outside the constraints of the
underlying window system.
I hadn't considered this is the past. Jerry is quite correct that the
best way to solve this probem is by placing your forms in a stationary
window. In this case, you CAN still use form_do for pre-emptive
editing in the window. There is nothing you can do to prevent
form_alert and the file selector from generating redraw events, so the
probelm is quite real. Your workaround of waiting for the desktop
application(s) to finish drawing first will work most of the time, but
would break down if the desktop application did I/O in windows based on
timers. WHACK is a good example of such a program.
|
931.10 | | PRNSYS::LOMICKAJ | Jeffrey A. Lomicka | Mon Aug 06 1990 11:41 | 3 |
| By the way, my experience is that the only event_ routine that works
right in desk accessories is evnt_multi(). I've had problems with
event_timer(). It was a long time ago, I don't remember the details.
|
931.11 | BIG thank you | MINDER::GILBERT | Systems Design & Eng Cntr @ MCO | Wed Aug 08 1990 04:33 | 26 |
|
Thanks to Jeff and Jerry for your help, I have a solution. And, more
importantly, I (nearly) understand why! Many of the mysteries of Gem have
come clear to me on the way.
The diagnosis is confirmed. If I use the dialog-in-a-window technique,
window boundaries are no longer corrupted and *my* window is updated OK.
However, dependent on the order in which re-draws are sent by Gem, one or
more underlying windows may be out-of-date because they are held up by the
form_do().
Therefore, I replaced form_do() by an objc_find() (my dialog form only
has button fields), and added mouse click (MU_BUTTON) sensing to the
evnt_multi() call. Result...
- JOY -
...all windows updated in sync, problem fixed.
Now, onwards and upwards... I still need to sort out partial re-draws,
but I *think* I can fix that myself...
Many thanks again,
Brian.
|
931.12 | Por Nada | BAGELS::FELDMAN | Jerry Feldman DTN 227-3279 | Wed Aug 08 1990 12:52 | 14 |
| Great. This is partially the way my calculator works, except I allow for
keyboard and keypad input.
One recommendation. When I want to refresh all or part of my screen,
since my window may not be the top window when one clicks on a button,
I send my redraw requests as a message. In the calculator, I normally
only redraw the window to update the amount, but in other applications
where I may have a display in a covered window, by sending the redraws
through a message, GEM combines these, and I know what rectangles
are uncovered. ( I wrote a text editor which allows 1 file to be
included in multiple windows). If a non primary window needs to be
updated, I do not want to bring it to the top, all I want to
do is to refresh it.
|