home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 10: Diskmags / nf_archive_10.iso / MAGS / CHOSNECK / CHOS2.ZIP / CHOSNECK.2ND / STUFF / DATAS.ZIP / ART50B.SCR < prev    next >
Encoding:
Text File  |  2003-12-09  |  14.2 KB  |  281 lines

  1. <head>
  2. <title="...forever...">
  3. <font=monaco10.fnt>
  4. <font=newy36.fnt>
  5. <font=time24.fnt>
  6. <image=back.raw w=256 h=256 t=-1>
  7. <buf=4163>
  8. <bgcolor=-1>
  9. <background=0> 
  10. <link_color=000>
  11. <module=console.mod>
  12. <pal=back.pal>
  13. colors:
  14. 251 - black
  15. </head>
  16. <body>
  17. <frame x=0 y=0 w=640 h=4163 b=-1 c=-1>
  18.  
  19.  
  20. .: GEM in one pill :.
  21. -----------------------------
  22. 3) WINDOWS
  23. --------------------
  24. Do me window, do me now...
  25.  
  26. Function wind_create() returns the handle of the newly created window. It takes 
  27. as a paremeters, which determine the maximal size of window which can be set by 
  28. the user. 
  29. The  maximal size of window is usually not the whole screen area. In most cases 
  30. it's  (the  total  size of the screen) - (size of menu). We are lucky enough to 
  31. have  function  wind_get(),  which  gives  several  useful informations. One of 
  32. parameters  which  can  be passed to this function is a flag. If this flag will 
  33. have  a  value  of  WF_WORKXYWH  and the window handle will be 0 (0 it's always 
  34. desktop handle!), then we receive the x,y,w,h values of the desktop. 
  35.  
  36. Next  thing  to do is to call wind_create() and determine which portions of the 
  37. window  should  be displayed. Each window can have: scrollable bars, closer etc 
  38. (all that you know from GEM). 
  39. Window without specified objects will appear as a simple frame. Defined objects 
  40. are  indicating what actions your program has to handle. This can also tell you 
  41. what your program need not to include. 
  42. For  example  we cannot receive the message "the size of window has changed" if 
  43. we don't include resizer in our window. Most of compilers define GEM objects as 
  44. a constants in header files (or another ones...). 
  45. In  most  cases the logica AND operation is performed with predefined names and 
  46. variable passed to the function, e.g window for receiving messages can have two 
  47. objects -closer (to close the window) and title bar (to drag it along), but not 
  48. resizer. So we put as a variable NAME|CLOSER. 
  49.  
  50. After  the  window  creation  we  are  ready to display it. Before we do it, we 
  51. should  change  the  text  in the title bar. To do this we use wind_set(). With 
  52. this  function  we  can  change  the  size,  position of scrollbars, change the 
  53. content  of  the text strings etc. After setting everything the window is ready 
  54. to display with the function call wind_open(). This one sets the beginning size 
  55. of  the  displayed  window  (maximum  size  or a standard one). The overal size 
  56. should  depend  on the role that windows will plays in your program. Window can 
  57. contain   nearly  everything.  Every  graphical  operation  (it  also  includes 
  58. displaying  text  in  GEM  window)  should  be in "working area" of the window. 
  59.  
  60.  
  61. Finding the working area of the GEM window
  62.  
  63. To  find  the  windows "working area" we need to call wind_get() and pass to it 
  64. handle  of our window and WF_WORKXYWH flag. It will return the size of "working 
  65. area"  as x,y,w,h (but with omission of various window gadgets like scrollbars, 
  66. title  bar  etc.). If as a flag we will use WF_CURRXYWH then this function will 
  67. return  the  full size of the window (WITH widow gadgets). Alternatively we can 
  68. use  wind_calc() to transform the "working area" to the full one. The functions 
  69. wind_get()  and wind_set() are the most frequently used in the whole process of 
  70. handling windows. 
  71. So  we  have  the needed coordinates. Next step is to pass those coordinates to 
  72. VDI  (which  is  some kind of GEM display manager) to limit the display to only 
  73. the  "working  area" of the window (this is called clipping). And now we have a 
  74. PROBLEM.  The  nature  of this problem is that AES and VDI are handling windows 
  75. differently.  AES  defines  the  coordinates as a starting vertex and width and 
  76. height,  but  VDI  prefers  coordinates of the top left vertex and bottom right 
  77. vertex. 
  78. The  solution is GRECT structure. Converting from AES representation to VDI one 
  79. isn't problematic anymore, because we do it with simple equations: 
  80.             x1= x
  81.             y1= y
  82.             x2= (x1-(w-1))
  83.             y2= (y1-(h-1))
  84. If we don't do this (and this is the the frequent source of errors) we can bomb 
  85. out everything. 
  86.   
  87. Graphics clipping
  88.  
  89. The  clipping  of  the graphics inside the windows is performed with vdi_clip() 
  90. and  it  takes as a parameter the VDI rectangle with the VDI handle (NOT window 
  91. handle!).  After  that we can draw the graphics or text. The most common way is 
  92. to  write  one  flexible  procedure to which we can pass the coordinates of the 
  93. area  to  redraw together with the window handle. So the function can be reused 
  94. to redraw another portions of the window. 
  95. But  the  best  solution  is  the  use  of  the  message  "redraw  the  window, 
  96. pleaassseee" which we can issue to our system. 
  97.   
  98. Window handling
  99.  
  100. System is communicating with the user via messages. Each time the user performs 
  101. an  action,  the EVENT occurs. Each event sends one or more messages, which are 
  102. handled in one gigantic if-else processing loop. The bad news are that there is 
  103. an  enormous  amount of messages we can get. Firstly there are messages sent by 
  104. other  applications,  secondly  the  messages  sent  by the windows itself. The 
  105. messages can be checked by one of several function calls. 
  106. One of those function calls is evnt_multi(), which informs you about EVERYTHING 
  107. that  will  occur  -  it  can be from keystroke to menubar selection. It is for 
  108. fully  fledged  GEM  applications. As we wan't only to handle windows correctly 
  109. the function evnt_mesag() will be good enough. 
  110.   
  111. Multitasking considerations
  112.  
  113. In  some  circumstances the system leaves your application and leaves to let go 
  114. another  programs  (cooperative  multitasking).  This  is the case in which the 
  115. evnt_xxx() calls occur. 
  116. Until  the  event, which you are expecting will not occur your application will 
  117. simply sit and do nothing at all. If you want to make your program multitasking 
  118. friendly  you  should  put evnt_xxx() call in each long processing job, even if 
  119. you  really  don't  want  to  know  what is really happening. Environments with 
  120. preemptive  multitasking (like MultiTOS, Magic or MiNT) don't need this, but as 
  121. this(next?)  method  is  universal  to  both kinds of multitasking systems.
  122. The  standard  function  call is evnt_timer(), which forces the program to wait 
  123. the  given amount of milioseconds. Evnt_timer() with 0 as a parameter let's the 
  124. system continue switching between the tasks. 
  125. The  evnt_mesag()  function waits for a messages from pipe to your program. The 
  126. messages  can  be  from  system,  from  another  applications or even from your 
  127. program  (sended  with appl_write() feeded with id of your application). So you 
  128. can  send  the  message  to  redraw  the windows anytime you want. You can send 
  129. another  messages,  but sending information about events that didn't occured is 
  130. very stupid. 
  131.   
  132. Messages
  133.  
  134. WM_SIZED (sizer) - use wind_set() to set the new size of the window. After that 
  135. use wind_get() to set the new "working area", set the sliders to the new values 
  136. and redraw the window. 
  137.  
  138. WM_MOVED (title bar) - use the wind_set() to set new size. 
  139.  
  140. WM_FULLED (fuller) - if window is not "fulled" then save the actual window size 
  141. and set it to the maximal size with wind_set(). 
  142.  
  143. WM_CLOSED(closer)  -  use the wind_delete() to erase the window fro the screen. 
  144. You  should  give the possibility to the user to save the content of the window 
  145. before closing it. 
  146.  
  147. WM_ARROWED (scroll bar and arrows) - this message means several things. Firstly 
  148. it can mean that the user has pressed on the scrollbars. If yes then scroll the 
  149. window  content  to right/left/up/down by amount of width/height (it can be any 
  150. amount  suitable  to  your  application:  for  text  editor height/width of the 
  151. character,    for   image  displayer  it  can  be  1  horizontal/vertical  line 
  152. up/down/right/left).  If user pressed the free area of the slider bar, then you 
  153. should  scroll  the  window  one  screen  down  (or one line as /|\ ATARI Corp. 
  154. states)  in  appropriate  direction.  Of  course  screen  redraw is needed plus 
  155. adequate setting of the scrollbars. 
  156.  
  157. WM_HSLID (horizontal slider) - it passes the number from 0 to 1000. This number 
  158. tells  how  far  to  the  right the horizontal slider was moved in his movement 
  159. range  (window  width  =scrollbar width + width of arrow + sizer width). Simply 
  160. speaking  0=beginning  of  the  document,  1000  =  end of the document. Ranges 
  161. between  are calculated in dependency from the shape of displayed window. After 
  162. that we have to redraw the screen. 
  163.  
  164. WM_VSLID (vertical slider) - the same as above, but vertically.
  165.  
  166. WM_REDRAW  -  the  most  important  message.  Your  application  uses  it  very 
  167. frequently,  so handler should be free of errors. Redraw handler is needed even
  168. if  you  plan  the  use of 1 window and single tasking environment. All of this 
  169. fuss is by those awful accessories, because they also can open windows. If your 
  170. program  has menubar, then we can assume that one of accessories will be opened 
  171. over your application. 
  172.  
  173. Details of WM_REDRAW
  174. All  the  messages  generated by the system have the same lenght (16 bytes or 8 
  175. words or 4 long words as you like). evnt_mesag() returns the pointer to message 
  176. buffer.  If  you  expect  messages  from other applications, 16 bytes will be a 
  177. little  too  small. But to keep things simple we will stay with 16 byte buffer. 
  178.  
  179. Message buffer looks like this: 
  180. message[0] - type of message 
  181. message[1] -  ID of sending application (we can ignore it at this stage)
  182. message[2] -  lenght of the message over 16 bytes (0 in our case)
  183. message[3] -  handle of the window to redraw
  184. message[4] -  x coordinates of "dirtied" rectangle
  185. message[5] -  y coordinates of "dirtied" rectangle
  186. message[6] -  width of "dirtied" rectangle
  187. message[7] -  height of "dirtied" rectangle
  188.  
  189. In  theory  the sufficient way is to get the proper coordinates and pass the to 
  190. the  redraw function. But things can get complicated (as usual). Yo can get for 
  191. example  redraw  message  when  active  window  will be partially obscured. The 
  192. solution  is  wind_get(),  which has several predefined values, in which it can 
  193. look  in.  GEM  divides the window onto visible and invisible parts. It divides 
  194. the  visible  part into smallest possible amount of rectangles. It gives us the 
  195. method for systematic check of "dirtied" rectangle against all visible ones. If 
  196. any  of visible rectangles is covering the "dirtied" rectangle you know what to 
  197. redraw.  So  going  down  the  visible  rectangle list you will finally refresh 
  198. window successfully. 
  199.  
  200. Window redraw list "to do"
  201.  
  202. a) Get "dirtied" rectangle sended in window redraw message.
  203. b)  Use  WF_FIRSTXYWH  in  wind_get()  to  get the first rectangle from visible 
  204. rectangle list. 
  205. c)  If  width  or  height  =  0 we are in the end of visible rectangle list and 
  206. redraw is finished. 
  207. d)  If  width or height not 0 we have to calculate the obscured area and redraw 
  208. this rectangle. 
  209.    Calculating of obscured area:
  210.    "dirtied" rectangle - x1, y1, w1, h1
  211.    visible rectangle - x2, y2, w2, h2
  212.    rectangle to redraw - x3, y3, w3, h3
  213. x3 = choose the greater (x1 or x2)
  214. y3 = choose the greater (y1 or y2)
  215. w3 = (choose the greater (x1+w1) or(x2+w2)) - x3
  216. h3 = (choose the greater (x1+h1) or(x2+h2)) - y3
  217.  
  218. In Lattice C there is rc_intersect() function which does the same.
  219.  
  220. e) If w3 and h3 are greater than 0, then we redraw the window:
  221. - graf_mouse(M_OFF,0x0L) to switch off the mouse
  222. - wind_update (BEG_UPDATE) to freeze the screen during redraw
  223. - vs_clip() to limit the area of redrawed rectangle
  224. - wind_update (END_UPDATE) to unfreeze the screen
  225. - graf_mouse(M_ON,0x0L) to switch the mouse back on
  226. f)  Get  the  next visible rectangle from list with the use of WM_NEXTXYWH flag 
  227. and wind_get(). 
  228. g) Go to c).
  229.  
  230. The  best  solution is to pack everything in one function call and additionally 
  231. put  the  scrollbars  redraw  check  (to see if we need to redraw scrollbars or 
  232. not). 
  233. We can also use the two standard functions:
  234. redraw_wind()  gets  the  window  handler and "dirtied" rectangle and checks if 
  235. obscuring  occured.  If the redraw is needed then it calls draw_rect() function 
  236. with  window  handle  and  the rectangle to redraw. It can be repeated changing 
  237. only the arguments for draw_rect() to redraw the proper rectangle. 
  238.  
  239. Scrollbars 
  240. Proportional  scrollbars  are a cool thing, but as always they need the special 
  241. treatment.  Each  time  the  user  inputs the new data, changes the size of the 
  242. window  or clicks on scrollbar we have to redraw it. Everything that is managed 
  243. by  wind_set(). 
  244.  
  245. Firstly,  we  have  to  estimate  how  big  they  have  to  be.  GEM  sets them 
  246. proportionally  to  the  size  of the window and uses the range: 0 (nothing) to 
  247. 1000 (full lenght/width - arrow size). 
  248. Calculating  of  the position is a little bit complicated, that's because range 
  249. 0-1000  holds  the possible movement range of the upper part of scrollbar. As a 
  250. bar is moving on finite width, the upper part cannot be on the bottom. 
  251. Example:
  252. We have 100 line document. We show 30 lines at time, so the scrollbar holds 20% 
  253. of  the  whole  area. So our range is shortened a little to 0-800, but we still 
  254. receive the number from 0-1000. Range 0-1000 is a whole bar, but movement range 
  255. is  0-800.  If  we want for scrollbar to start at 48% of then the bar is setted 
  256. on: 
  257. 1000*48/(100-20) or 600-60% of the way down.
  258. All  of  this means that if we will go right to the end of the file, our slider 
  259. will  be  only 80% way down of a bar and it gives our more general equation for 
  260. scrollbar starting point: 
  261. position=1000*starting point/(whole lenght-showed lenght)
  262.  
  263. Scrollbars redraw
  264. To redraw scrollbars we have to:
  265. -  calculate  the  total  of  a  file  in  given  direction  (in pixels, lines, 
  266. characters) 
  267. - calculate the size of image/ document shown in the same units (pixels, lines, 
  268. characters). 
  269. - use the equation mentioned above to get the proper parameter
  270. - use the wind_set() to set the scroll bar
  271.  
  272. Closing windows
  273. Firstly we use wind_close() to remove the window from the screen (it also sends 
  274. the  redraw  message).  After that we use the wind_delete to release the window 
  275. handle and free memory.
  276.  
  277. <link=art50c.scr>Go to PART #3</l>
  278. </frame>
  279. </body>
  280.  
  281.