CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
In his book About Face: The Essentials of User Interface Design (ISBN: 1-56884-322-4), Alan Cooper discusses extensively the art and science of user interface design. I will be drawing a lot on Mr. Coopers work because he has given us some great terminology for discussing user interface design. Being able to use his vocabulary makes examining a complex subject much easier. If you have read Mr. Coopers book, you will find that I dont always agree 100 percent with his perspective on things, but his work certainly does force me to give the issues some serious thought. In this chapter, I hope to introduce the problem of user interface design and to present some ideas on how to approach solving that problem. One goal I have is to prod your mind into thinking creatively about presenting data to users. In this chapter, I will pay a lot of attention to users and how they do their job. This is because the quality of a user interface is measured not by the artful flair of the design or the creativity of the presentation, but rather the functionality of the interface in helping users to get a job done.
Alan Cooper presents three major interface styles in his book: Process, Data, and Goal-centric.
The process-centric interface has a specific system process at the center of the interface. This approach is by far the worst from users perspective, because it provides them no control other than choosing which process to begin.
Many of the older interfaces displayed the process-centric style. Those systems were fondly referred to as 'menu-driven' systems. In these menu-driven interfaces, the user was usually presented with a full-screen menu from which he could choose from a list of possibilities.
Once the user had made a choice from this menu, he was presented with another menu, and then another, and so on until the menu choice initiated a system process such as creating a new invoice. Once the process was begun, there was no way to do anything else in the system without completing or aborting the creation of the invoice.
Because the system process defines the style of the user interface, it is a process-centric interface. Most developers today have left this interface style in the dust because it gives the user very little control over what the system will do and when it will do it.
The data-centric design is probably the most commonly used interface in database systems. That is not because it is necessarily the best design, but rather it is the design that seems most natural to the developer.
The data-centric design has all of the systems features built around the nature of the underlying data structures. This is most comfortable to database system developers because these developers are always thinking in terms of data and its structure.
Figure 1 shows a common menu structure of a data-centric design.
Figure 1. A data-centric menu system.
Notice that each of the choices on the file menu gives direct access to a specific entity in the underlying data structure. Data-centric interfaces also typically have a large number of grids to show the row and column orientation of the data. For example, Figure 2 shows a data-centric interface to customer information.
Notice that page one of the PageFrame is a grid of customers, which presents the customer information in a one-row-per-customer and one-column-per-field orientation. This is a very common way to present data, and the most common argument in favor of it is 'Thats the way the users like it.' Hogwash! The only group of folks I know of who see customer information in a row-and-column orientation is database developers.
Secretaries see customer information as a set of folders in a file cabinet. Salespeople see customer information as a set of entries in a day-timer. Collections people see customers as a name on the screen to be cajoled out of money. Marketers see customers as a line or bar on a market analysis chart.
Figure 38. A data-centric editing form.
As you can see, each user sees the same information in a different way. Each user uses that information for different purposes. Each user has a different set of goals in his job. Which leads to the third interface style.
The goal-centric user interface requires that we know something about the users job. We need to know the users goals and then design the application interface around those goals.
Alan Cooper, on page 12 of his book About Face, says the goals of most users are:
These goals are not very surprising; I think most people would include these among their own sets of goals at work. However, Mr. Cooper goes on to list the things that most commercial software is quite adept at doing:
The only way we can design interfaces that work well for the user is to learn to see the users job from the users perspective. Lets take a moment to look at the four items in Mr. Coopers second list.
Making the user look stupid
How often have you seen a dialog box that looks like the one in Figure 3?
Figure 39. A dialog box from some application.
The first thing I notice is the title of the dialog box: 'Fatal Error.' Most people I know think a fatal error is holding a 44-magnum gun to your head and pulling the trigger, having forgotten that the gun was loaded. Secondly, the word alias has many meanings; the least common meaning is the name for a work area. To the average user, the text of this dialog box seems to say that the 'also known as name' for the patient was not located, so the surgeon stopped the surgery. With words like 'fatal' and 'the operation cannot be continued,' does it make sense to ask the user to click a button that says 'OK'?
Perhaps this dialog box could be presented as in Figure 4.
Figure 40. A slightly better dialog box.
I present Figure 4 as slightly better because, first, it does not use the Fatal Error caption to scare the wits out of the user. Secondly, it takes the time to explain in simple English what exactly is happening. It does not accuse the user of anything. It suggests the next action for the user to take (notify the administrator). Finally, it does not ask the user to OK the problem, but rather to acknowledge the receipt of the message.
Let me take this moment to let you know that Steve and I have checked with the powers above and have found that, in fact, there is no prize waiting for the developer who used the least number of words in their dialog boxes and prompts.
Causing the user to make big mistakes
Again, it isnt difficult to find user interfaces that easily allow a user to make a very costly mistake. Although there are times when confirmation dialogs can be a hindrance to the users efficiency, when the action that is about to commence is irreversible and drastic, a simple confirmation dialog is in order.
Keep in mind that the days of computer phobia are gone. Most users today are comfortable with their machines, and because of that their human nature takes over. People are curious by nature, so if there is a button or menu option that they are unsure of, they will click it or choose it to find out what it does.
If you have menu options or buttons that perform irreversible and drastic changes to the data or application environment, provide a confirmation dialog box between the menu or button and the actual action. Figure 5 shows a potentially problematic menu option.
Figure 41. A potentially problematic menu option.
The Clear Data for Year end menu option could be a big mistake if all of the year-end reports and operations had not yet been completed. This is a good place for a confirmation dialog to assist the user in preventing a big mistake. Figure 6 shows just such a dialog.
Figure 42. A confirmation dialog box for a
potentially destructive menu option.
In this dialog box, the operation is explained in simple English so the user can understand clearly what it will do. The text also suggests which other operations should be completed before this one is executed. Also, note that the prompts on the buttons dont say OK and Cancel, but rather are descriptive of their actions. Most importantly, though, is the fact that the non-destructive button is the default. This allows for the user who clicks or presses Enter without reading anything.
Keep in mind which actions in the application are potentially destructive and protect the user from making any BIG mistakes. I emphasize the word 'big' because you wont assist the user by including confirmation dialogs for every button and menu option. Rather youll slow the user down, as youll see in the next section.
Slowing the user down so he doesnt get an adequate amount of work done
One common problem with user interfaces is that they get in the users way. Consider the confirmation dialog box I discussed in the previous section. If those dialogs are used everywhere, all they do is require the user do more to get less done.
I use one software product daily in my consulting practice to track my billing. One option in this software is to make a backup of the data every time I exit the program. I have set this option on because the data is critical to my business and I want it backed up every time I exit. Figures 7, 8, 9, 10 and 11 illustrate the dialogs I see when I exit the program.
Figure 7. Confirm exit.
The Confirm Exit dialog box in Figure 7 comes up immediately after I click the Exit button. Is exiting the program such a terribly destructive operation that I couldnt just rerun it if I was mistaken?
Figure 43. A dialog box to select the name of the backup file I want to create.
The next dialog I can understandit gives me the opportunity to select which file I would like to create as my backup. This can be very useful if I keep sequential backups by a naming convention, but wait until you see the next screen.
Figure 9. Confirm the name of the file I chose in the previous dialog.
Come on now! I just selected the file I want, and now the program is treating me as if I am some kind of idiot who doesnt know what I want. Please, Mr. or Ms. Program, just do what I said. However, its not over yet.
Figure 44. Confirm the backup again.
This is a very intelligent dialog box. It tells me that I have 867,934,702 bytes of space free on my disk and that the backup will take up 564,711 bytes of that space, then asks me to confirm that operation. If the program is so smart that it knows how much space I have and how much space the backup will take, could it not see that the backup will occupy less than 0.06 percent of my available space? Shouldn't it be able to decide for itself that it doesnt need to ask me for confirmation? Theres still one more, though.
Figure 11. The backup was successful.
Now, this is critically important to tell me. Come on now, if the backup failed I would want to be told. However, making me click one more OK button to get out of this program is simply getting in my way.
I am not trying to drag down this specific application; in fact, I find it to be one of the best programs for tracking time-based billing available on the market. But this exit process sure does show how the user interface can get in the users way and slow him down. Later in this chapter, youll see some other things that can both slow down and speed up the user in handling her data.
Preventing fun and boring the user
The most common violation of this principle is dull and uninteresting screen designs. Youve all seen the data-entry screens that look like Figure 12.
Figure 12. A boring data-entry form.
This form could be dressed up and made much more interesting with a little rearrangement of the controls and some other minor enhancements. See Figure 13.
Figure 13. A more interesting presentation of the customer information.
Essentially, there is a container behind the data-entry controls with a sunken special effect. The horizontal bars between the sections are comprised of a white two-pixel line, a box that is light gray with a light gray border, and a two-pixel dark gray line. Also, notice that the icon in the title bar of the form has been replaced with the clients logo.
The essential point here is not the artistry, but rather the acknowledgement that the average user will stare at these forms for hours on end. If you can provide some embellishment that makes the form more interesting to look at or easier on the eyes, then do it.
Also, dont leave the aesthetics for later. Later never comes! Make the forms aesthetically pleasing on the first prototype you mock up for approval. Remember that aesthetics is not an afterthought. It is an integral part of design.
Contrary to popular belief, making a data-entry form aesthetically pleasing does not mean that it cannot also be an efficient way to get the job done. The functionality of the controls need not be dictated by their appearance.
Alan Cooper presents a very important concept in his book for classifying applications that can and should have a great influence in the user interface design. Mr. Cooper speaks of Sovereign and Transient applications. Sovereign applications are those that generally take the users full attention when they are in use. Transient applications are those 'tools' that we use along with our sovereign applications.
Classifying any application into one of these two categories is instrumentally important in defining the most efficient style of user interface. The database applications that you build with Visual FoxPro may fall into either of these categories, and may even be comprised of parts that cover both categories.
Certain applications require a users full attention while in use. These applications are sovereign because they take control of the machine. A sovereign application should occupy most of the visible display area and demand most of the users attention.
Some examples of sovereign applications are word processors, where the user is fully involved in the typing and formatting of the document and isnt multitasking a dozen other processes simultaneously. Spreadsheet applications are also sovereign, in that when the user is working on a spreadsheet his undivided attention is given to that task. Other examples would be accounting applications, business decision support applications, and travel reservation systems.
Many applications that we database system developers build will be sovereign.
Sovereign applications are allowed to do things like occupy the entire display area of the screen and cover other applications when they have the users focus. These applications are allowed to use a larger slice of the computers resources because of their sovereign nature. The user wont care that her e-mail pop-up is suspended or hidden while she closes the accounting books for the month.
Transient applications are the antithesis of sovereign applications. These are the little 'applets' that assist with other tasks. One example is the Calculator program that users can open on top of the accounting application to do some quick math. Another example is the Character Map applet that lets you look up the ASCII code for a special character you need to put on a label. These transient applications should not overtake the system when used. They need to be designed to coexist with the sovereign applications that may or may not be in use when the transient application is called on for a service.
The transient application should not occupy any more of the display area than is necessary for it to perform its task. As database developers, we dont find ourselves building quite as many transient applications as we do the sovereign ones, but we do build some. Many times, there are parts within one of our sovereign applications that need to behave like a transient application, such as small utility forms or lookup forms. Perhaps the sales management system has a form for managing a salespersons Rolodex data. This Rolodex form would certainly qualify as a transient module within the sales management system.
Give careful consideration to this important question. You should classify your systems, and forms within those systems, into sovereign and transient categories so you have guidelines on how to design the interface for the user of those systems and forms.
If the previously mentioned Rolodex form in the sales-management application were modal, it would be much less useful to the system user. That Rolodex form would be more valuable to the user if it could be opened and left open while other tasks were performed within the system.
Being able to call up the Rolodex at any time to look up a persons phone number, and perhaps even dial the phone, would be very helpful throughout the course of a users day. Recognizing the Rolodex form as a transient application within the larger system would predict the required behaviors.
However, closing the accounting books for a period is such an important and complex task that it most certainly would be classified as a sovereign application within the system. This might even cause you to design the period-closing operation so that it was modal, except for certain controlled points in the process, in order to protect the integrity of the data.
You can see from this discussion that different user interfaces are 'correct' for different parts of a system. I would go so far as to say that there probably isnt a user interface approach that can be classified as the best or the worst without first knowing the sovereignty or transience of the task at hand.
Id like to clear up a frequently misunderstood issue before I go any further into interface design. Weve all heard the cry for the modeless application. Weve also heard about modal and non-modal forms. Weve even heard the comparison of modal vs. modeless discussed, which is equivalent to comparing automobiles to televisions. Modality has nothing to do with modes.
Modality refers to the availability of switching to other tasks while one task has been set in motion. A modal task, or form, prevents switching to anything else until the modal task or form is dispensed with. A non-modal task or form allows other tasks or forms to be launched while the first task or form is still in process.
Modeless vs. modes is a completely different issue. In a modeless form, there is no concept of editing mode, adding mode, or viewing mode. The form is able to accomplish all tasks without visibly changing modes. A moded form is in some mode or another at all times. When the form is in edit mode, data can be edited, but when the form is in view mode the data cant be edited.
You have certainly seen forms that have Edit, Add, Save, and Revert buttons. These buttons change the form from one mode to another. The user clicks the Edit button and the form changes from view-only mode into edit mode. Just because a form is in edit mode does not necessarily mean that that form must be modal. We can certainly build systems that allow multiple forms to be open and in edit mode simultaneously.
Now that you understand the difference between modes and modality, lets examine some issues related to managing modes on our user interface. Contrary to the popular notion, there is no such thing as a modeless application, at least not in the database management arena. The application always has to be aware of whether or not there are pending data changes. When data changes are pending, the form is in edit mode (you might differentiate between edit and add mode, but in fact both are states of pending data changes). When a form has no pending data changes, it is not in edit mode; it is in viewing mode.
Developers frequently confuse the situation of whether the user is required to take any specific action to place a form into edit mode or not as defining the form's modality. That is, must the user click an Edit button before she can cause pending data changes? Or does the form automatically switch itself to edit mode when the user begins to change a piece of data in the form? In truth, regardless of whether the user clicks a button or starts to overwrite a value, the form is always in one mode or another.
The arguments between the two schools of thought regarding using edit buttons or not using edit buttons will never be resolved. There is no one right answer. The correct approach is dependent on the details of the application and its requirements.
The argument in favor of using buttons to start the edit mode is primarily to protect the user from unintentionally changing something. The idea is that nothing can be changed until the user has intentionally clicked the edit button.
This interface style can be very good in those situations where changes to the data have critical effects on the business, and if those changes are difficult to revert.
The major argument against the edit button style is that it requires the user to take an additional action in order to change data. The very aspect of this approachs strength is also its weakness.
When should you use the edit button approach? Use it when, in your judgement, the additional action required of the user is of less importance than the result of an inadvertent change in data.
With Visual FoxPros strong object model and its array of events on each of the data editing controls, it is easy to create an automatic mode switching system. It is easy to sense when the user changes the value of a control and then switch the mode of the form to edit mode.
The best argument in favor of the automatic approach is that it takes less effort on the part of the user to initiate an edit. He has only to begin typing and the form shifts to edit mode.
The best argument against the automatic edit mode shift is that its easy for the user to unintentionally change data. Again, the very issue that makes this approach desirable is the same issue that can make it undesirable.
When should you implement automatic mode switching? Use it when, in your judgement, the result of an unintentional change to data is of less importance than the extra action that would be required of the user with the edit button approach.
The truthful answer is that, regardless of whether the user clicks a button first or switches to edit mode by typing in a control, there is always an edit mode. The form must always deal with resolving the edit mode before closing. By using data buffering, the user always has the option of saving the changes or reverting them to the pre-edited state. That means that there are very few situations where the use of an edit button would be an interface requirement.
This means the decision will be one of preference, and when an interface decision is one of preference you should let the users preference win. Remember, you may work with the system for a few months or longer, but the user will live with the result eight hours a day, five days a week, for a number of years.
Ah, yesthe old room with desks all lined up in rows, and at each desk sits a data-entry person being paid by the number of records he adds per day. This situation, although somewhat exaggerated, can still be found in many medium to large business environments. Unfortunately, the graphical environment does not lend itself well to this type of interface requirement.
Pretty buttons and ComboBoxes do not assist the heads-down data entry person in entering data faster. A keyboard-controlled data entry interface that anticipates the users next action is needed here. For example, this interface should immediately append a new record and put focus in the first control upon the user completing a records entry. The users eyes should never need to stray from the worksheets from which she is entering data.
Although this interface needs to give the user rapid-fire, keyboard-controlled data entry, it can and should provide some method of reviewing the work entered so far. Controls that are not part of the natural tab order should allow the user to see what she has entered, perhaps in a grid. The user should be able to select a record already entered and correct any errors. However, these capabilities and controls should not get in the users way from doing the primary function of entering data.
Luckily for us, most data entry operations in todays business world are not of this heads-down nature. They are more relaxed in terms of speed on entry and generally require more thinking on the part of the user. With this type of data entry interface, if you master the controls you can assist the user in getting her job done faster and give her less opportunity for mistakes.
My response to this issue is, 'Why not have them all?' A menu option that saves data changes does not interfere with a toolbar button of the same functionality. Giving the menu option a shortcut key does not interfere with a command button in the form with the same purpose. The key to reusability is having all of those mechanisms call the same piece of code to do the work.
I know folks who are touch-typists who absolutely hate interfaces that require them to remove their fingers from the home row. I also know folks who hate to let go of the mouse to type something that could have been handled by using the mouse creatively (I am one of these people).
To design a successful user interface, you must make the user comfortable with the way things work. Different users are comfortable with different ways of doing things. Therefore, why not design the interface with the maximum methods available for accomplishing a certain task? This type of design pleases the highest number of users. Only a few 'stick in the mud' folks will cringe at the 'inefficiency' of having more than one way to do something. Most people will only notice that their favorite way works, and not even see that there are other ways to accomplish the same task.
Dialog boxes ask the user a question. When necessary, you certainly do need to request information from the user. However, with good planning you can design a single dialog, displayed at the beginning of a process, that asks the user everything you need to know throughout the process.
Other things to watch out for with dialogs are asking stupid questions that dont need to be asked. Earlier in this chapter I presented a dialog that asked me to confirm that a good backup was OK. That is as unnecessary a question as I have ever seen.
You walk a tight line here, though, because a form or dialog that is too crowded is almost as disturbing as too many smaller dialogs. The line is also tight because it isnt a good idea to allow the user to execute a drastic action that is either not reversible or not easily reversible without confirming the decision beforehand. Therefore, you might find yourself in a bind, which is common in this application development business. The answer lies in using common sense.
Dont bring up a dialog box to confirm the change of a phone number on a customer edit form. Do bring up a confirming dialog on erasing the entire customer file. The change of a phone number is easily reversed and does not require user confirmation before the change is made. However, erasing he entire customer file will require a large and expensive effort to reverse, so confirm the issue before the deletion.
To handle those crowded forms that you are often tempted to break into multiple forms and present them in some order or sequence, Visual FoxPro offers the PageFrame. You can put all of those forms into one and allow users to navigate them in any fashion they choose. The screen wont be cluttered with a bunch of windows. The user has only one window to close when she is finished.
As a developer, you dont have to write all the code to coordinate the separate windows. You only need to design and code one window. So for complex data entry problems, the PageFrame is an ideal tool.
In Chapter 10, I gave an example of the PageFrame being used without tabs. This approach allowed the developer to provide additional functionality to a process without requiring the user to navigate to or deal with another form or dialog box. This is helpful to the user in simplifying the interface, but for the developer it is even more helpful because all of the functionality related to that form is contained within that one form.
Heres another example of using a PageFrame to create what might otherwise be a crowded form. Figures 14, 15, and 16 show the sequential pages of a tabless PageFrame in an Invoice Wizard form. The form is not functional because there is no data connected to it, but it does demonstrate the use of the PageFrame.
Figure 14. Page 1 of the wizard form.
Figure 15. Page 2 of the wizard form.
Figure 16. Page 3 of the wizard form.
Notice that the buttons at the lower right of the form become enabled and disabled in a context-sensitive fashion. They are also positioned in exactly the same place on each page. In truth, they arent actually on any of the pages; theyre in the form placed on top of the PageFrame. The ResetButtons method of the form enables and disables these buttons. Here is the code for the ResetButtons method:
WITH THISFORM.PageFrame1
THISFORM.cmdBack.Enabled = THISFORM.PageFrame1.ActivePage > 1
DO CASE
CASE .ActivePage = 1
THISFORM.cmdNext.Enabled = NOT EMPTY(.Page1.txtCustomer.Value)
CASE .ActivePage = 2
THISFORM.cmdNext.Enabled = NOT EMPTY(.Page2.txtInvNum.Value)
CASE .ActivePage = 3
THISFORM.cmdNext.Enabled = .F.
THISFORM.cmdFinish.Enabled = NOT EMPTY(.Page3.Grid1.Column3.Text1.Value )
ENDCASE
ENDWITH
I simplified this code to demonstrate the idea. In an actual form, you would be testing for more information before turning on the Next button or the Finish button.
The code in the click event of the Next button simply adds one to the ActivePage of the PageFrame, and the Back button subtracts one from the ActivePage.
Users often need to select from among a group of choices. With the exception of the heads-down data entry operation, Lists and ComboBoxes are very good controls for assisting the user in making these types of choices. When the possible choices are known ahead of time, OptionGroups and even CheckBoxes can be useful.
Lets leave the CheckBoxes and OptionGroups alone for now and investigate the use of ComboBoxes and Lists. These two controls, when used properly, should render it impossible for the user to make a wrong selection. Take the form in Figure 17 for example.
Figure 17. One form using a combo and a list for selecting values.
This form lets the user first choose from the combo whether he wants fruits or vegetables. Then he selects the particular item from the list below. In this form, the list contains both fruits and vegetables. If the user makes an incorrect choice, he gets a message box telling him that he made an error.
Whats wrong with this scenario? First, why does the list have vegetables in it if the combo says fruits? Visual FoxPro certainly gives the developer the ability to change the contents of a control based on the value of another. The second, and more important, problem is that the message box makes users feel dumb. That message clearly points out to them that they dont know the difference between a fruit and a vegetable.
Figures 18 and 19 show the same interface style but with a slight change.
Figure 18. The fruits and vegetables form
with Fruits selected in the combo.
Figure 19. The fruits and vegetables form
with Vegetables selected in the combo.
Notice that the list adjusts its contents according to the value in the combo. This is accomplished by calling the lists Requery method from the combos InteractiveChange event and coding the Requery of the list to populate itself with values according to the value of the combo. In this form, the user cannot make an invalid choice. She will never see a message box telling her that she is stupid.
The critical point here is that it is the job of the developer to prevent the user from making errors. You have to detect errors and handle them when they occur, but you should first prevent the errors as much as is humanly possible.
There are times when we must allow the user to select multiple items at once. One option is to use a multi-select list. Figure 20 shows a multi-select listing in which multiple items are selected. How many items are selected and what are they?
Figure 20. A multi-select list form.
If you answered twoapples and pearsyou are incorrect. There are actually nine items selected, but most of them are out of view. Now compare that presentation of multi-selection to the one in Figure 21.
Figure 21. A different type of multi-select list form.
In this form, there is no question as to how many or what items have been selected. This 'mover' type of list takes up more space, but it also leaves no question for the user about what has been selected and what has not. It is also clear to the user what is left for selection. You can use this type of mover list to allow multiple selections of the same item when appropriate.
You may also notice the gray buttons to the left of each item in the selected list. These mover buttons allow the user to rearrange the order of the items in the selected list. You may need this ability if the processing that follows is order-dependent. With a single multi-select list, this reordering is impossible.
A user performs direct manipulation when she directly modifies objects on the screen by drawing with a pencil tool, connecting items by drawing lines between them, dragging and dropping, or any other method. Direct manipulation within the interfaces you build is almost exclusively confined to drag and drop. Visual FoxPro 6.0 has two types: native Visual FoxPro drag and drop and the new OLE drag and drop.
Be aware that the native and the OLE drag-and-drop methodologies cannot be used together. These two options are mutually exclusive.
The form in the example that follows has been simplified to demonstrate a technique. Imagine you are creating an interface for scheduling a product through various steps in the manufacturing process and that those products may not require every step. Figure 22 shows a possible form for doing this.
Figure 22. A form for selecting a manufacturing process for customers.
The idea in this example application is that your company makes products to four levels of quality. Different customers want to purchase different quality levels. Customers are listed down the left side with their names in the boxes. This form is an example of the direct manipulation methodology of user interface design; in a real application the customer display would be managed differently. The larger boxes to the right represent the quality ranges. To assign a quality range to a customer, the user drags that customer and drops it on the chosen quality range. The user gets feedback when the customers background color becomes that of the quality range. Figure 23 shows some customers with their quality ranges set.
Figure 23. Certain customers with their quality ranges set.
This process of dragging the customer to the quality range is not readily obvious when the form is first seen, but once the user has been shown how to do this she will never forget.
The terms source object and target object will be used to explain how drag and drop works. It is important to realize that the drag-and-drop operation is divided into three stages.
The first stage is the start of the drag. This stage occurs at the source object when the user presses the mouse button while the mouse is over the object.
The second stage, called capture, occurs during the dragging. This is the reaction of the various objects as the source is dragged over them. Perhaps the mouse icon changes to indicate whether or not a drop is allowed.
The final stage is the end drop. The end drop occurs at the target object when the user releases the mouse button, thus completing the drag-and-drop operation.
Lets look behind the scenes of the previous form to see how the drag-and-drop operation was accomplished. First of all, both the products and the processes are classes defined in a class.
Here is the code in the MouseDown event of the Product:
THIS.Drag(1)
The Drag method will start or end a drag operation. The parameter of 1 tells the Drag method to start a drag operation. The mouse cursor seen when dragging the object is controlled by the source objects DragIcon property. In this case, the cursor file is named DragCopy.cur. In the MouseUp event method of the Product class, the drag is stopped by making the same call as in the MouseDown event method, except it passes the number 2 as the argument.
In the DragOver event method of the Product class, the mouse icon is changed to reflect that the user cannot drop there. Here is the code:
THIS.DragIcon = 'NoDrop.CUR'
The DragOver event is fired whenever something is being dragged over the object. The mouse cursor is changed in the DragOver because dropping the product on itself would do nothing at all. The change in cursor is visual feedback to the user. This same code is in the DragOver event method of the form itself, since dropping on the form will do nothing.
In the DragOver event method of the Process class, however, the code assigns the DragCopy.cur cursor to the DragIcon property of the source object being dragged. The code does this because this process object is where the drop has a purpose.
The major work is done in the DragDrop event method of the Process class:
oSource.Shape.FillType = THIS.Shape.FillType
oSource.BackColor = THIS.BackColor
oSource is one of the parameters passed to the DragDrop and DragOver event methods. It is an object reference to the object that is being dragged. The code above simply sets the backcolor of the object being dragged to the same as the backcolor of the object it was dropped on as well has the fill pattern of the shapes.
In studying this code, notice that both the Product and Process classes are complex controls. That is, they have many parts to them. The Product class is comprised of a container (the actual product object), a shape inside that container, and a label on top of the shape. One problem the code needs to deal with is that the events fire for the object that is directly under the mouse pointer. Therefore, if you check the shape and the label objects in the Product class, you will see that events like DragOver are being passed up to the container with code like this:
THIS.Parent.DragOver(oSource, nXCoord, nYCoord, nState)
The parameters being passed are the same parameters that Visual FoxPro passed to the event in the first place. Why do this? Why not handle the drag-over action right in the label or shape? The reason is a simple one: All of the code that performs the action is written in one place only, and the long-term maintenance of this code will be much easier if it is in only one place. As Steve McConnell says in his book Code Complete, 'Code written twice has been written once too often.'
Lets look at another example of using the native drag and drop of Visual FoxPro. This time I've modified the mover list form above to include drag and drop to move items from one list to the other. Following is the code needed to add drag and drop from either list. (Each code listing identifies the object.method at the beginning with a comment, then the code follows.)
* lstSource.MouseMove
IF nButton = 1
THIS.DragIcon = 'NoDrop.cur'
THIS.Drag(1)
ENDIF
* lstSource.DragOver
oSource.DragIcon = 'DragList.cur'
* lstSource.DragDrop
IF oSource.Name = THIS.Name
RETURN
ENDIF
THISFORM.UnselectOne()
The next section of code is from lstTarget. Notice the similarity. In actual development, you would have probably created a list class that had this functionality built into it already.
* lstTarget.MouseMove
IF nButton = 1
THIS.DragIcon = 'NoDrop.cur'
THIS.Drag(1)
ENDIF
* lstTarget.DragOver
oSource.DragIcon = 'DragList.cur'
* lstTarget.DragDrop
IF oSource.Name = THIS.Name
RETURN
ENDIF
THISFORM.SelectOne()
The reason for the IF statement in each lists DragDrop event method is to prevent the list from being dropped on itself. Notice that the DragDrop event method of each list is calling the forms methods to do the work. Again, why have the code in more than one place?
The only other code in the form was added to the DragOver event method of the form and the buttons, and it is the same in all places:
* The DragOver of the Form and the Buttons
oSource.DragIcon = 'NoDrop.cur'
You can see that adding drag and drop is not 'rocket science.' It does take some planning and often requires passing messages from one object to another in order to coordinate the activity. Also, drag and drop is a very natural method for users to interact with the objects in your applications.
Direct manipulation is intuitive and easily learned; once learned, it is seldom forgotten. What better method of working with your data controls could there be?
Now lets investigate this new beast, OLE drag and drop. OLE drag and drop provides the same functionality as the native drag and drop, except it isnt limited to Visual FoxPro objects. Visual FoxPros OLE drag and drop can function with any other application that is OLE drag and drop-capable. The ability to function with other applications is not the only advantage of OLE drag and drop over the Visual FoxPro native drag and drop.
OLE itself
OLE has been around for a while now, and we have used it in Visual FoxPro for automating processes in other applications as well as in building ActiveX servers for other applications to automate. The overriding issue with OLE is the fact that it always involves communication between two or more objects. These objects might be within the same application, like using a Visual FoxPro ActiveX server from a Visual FoxPro application. Or they might be in different applications, as in automating a mail-merge operation in Microsoft Word from Visual FoxPro. No matter what the details may be, there is always two-way communication. A message is sent and a reply is received. OLE drag and drop is no different in this aspect, although starting a drag might involve only one object. What goes on during that drag, and what happens in the subsequent drop, is the result of communication between the source object (the object being dragged) and those objects it gets dragged over and ultimately the target object (that object where it is finally dropped).
The key issue from the user interface perspective in this process is to provide clear visual feedback to the user about the process. Give the user clear indications of where the source can and cannot be dropped.
The objects involved
In OLE drag and drop, three objects are always involved in the operation. They are the source, the object where the drag began; the target, the object where the drop occurred; and the data object, the object carrying the data from one to the other. Lets start by examining the data object.
The OLE data object
The data object is created when the drag begins. The oDataObject does not directly belong to the drag source or to the drag target; it belongs to OLE (which is a separate service under Windows). Different drag sources have different types of data they will place in the data object automatically. A data type or format identifies all data in the data object. See Table 1 for the usual formats found in the data object.
Table 1. Common data formats found in the OLE data object.
CF_TEXT |
Text. |
|
CF_OEMTEXT |
Text format containing characters from the OEM character set. |
|
CF_UNICODETEXT |
Text containing Unicode. |
|
CF_FILES |
A handle to a list of files. |
|
CF_HDROP |
Same as above CF_FILES. |
|
CFSTR_OLEVARIANTARRAY |
'OLE Variant Array' |
An array of OLE variant values. |
CFSTR_OLEVARIANT |
'OLE Variant' |
A variant. All data types in Visual FoxPro are represented as variants. |
CFSTR_VFPSOURCEOBJECT |
'VFP Source Object' |
An object reference to a Visual FoxPro object. |
The drag operation
The drag operation starts at the source object. As the data object is dragged over a drop-enabled object, communication between the potential target and the data object occurs. This communication may cause the data object to communicate with the drag source object. Figure 24 shows this communication chain.
Figure 24. Communication flow during an OLE drag and drop operation.
Lets examine an actual example of this to understand the process better. Figure 25 shows a form with three OLE drag-enabled and/or drop-enabled objects in it.
Figure 25. A form with OLE drag-enabled and drop-enabled objects.
First, look at the properties for the textbox. Figure 26 shows the non-default properties for that object.
Figure 26. The non-default properties of the textbox.
The only two properties of this textbox that have been changed from their defaults that relate to OLE drag and drop are OLEDragMode and OLEDropMode, which have been set to automatic and enabled, respectively. Setting the properties this way makes this object OLE-draggable and allows OLE drops to occur. Because its a textbox, the only data format it will understand is Text. An OLE data object carrying non-text data will show as a non-drop icon when dragged over this textbox.
Lets examine the properties of the container with the label 'Drop here.' Figure 27 shows the property sheet for this object.
Figure 27. The non-default properties of the container.
Notice that OLEDropMode is enabled, but also notice that there is some user code in two of the OLE drag and drop eventsnamely OLEDragOver and OLEDragDrop. In here we will begin to see the communication chain that occurs during OLE drag-and-drop operations. Before we delve into this code, lets look at the image of the American flag. Figure 28 shows the non-default properties and events of the American flag image.
Figure 28. The American flag image properties.
Notice that the OLEDragMode property is set to Automatic. This will allow the image to be dragged automatically without any intervention from your code. Note, however, that there is code in the OLEStartDrag event for this image. Lets examine this code:
LPARAMETERS oDataObject, nEffect
* Clear out all data from the data object
oDataObject.ClearData
*-- Specify that data can only be copied
nEffect = 1
*-- Register the text (1) format
oDataObject.SetFormat( 1 )
*-- Register my private format in the data object
oDataObject.SetFormat( 'Private Format' )
There are a few things going on in this code. First, the line oDataObject.ClearData removes any data that may have been automatically placed into the data object of the drag. Next, this method registers two formats in the data object with the two lines oDataObject. SetFormat( 1 ), which registers the text format, and oDataObject.SetFormat( 'Private Format' ), which registers a format named 'Private Format.' This shows that not only can you clear the data object and place your own formats into it, but that the formats you place there do not need to come from the list shown previously.
Listed below is the code in the Drop Here containers OLEDragOver method, which will fire whenever the data object is dragged over that object.
LPARAMETERS oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord, nState
IF nState == 0 && Drag Enter
*-- We only need to check out the data format once upon enter
IF oDataObject.GetFormat( 'Private Format' )
* I can handle drops of 'Private Format'
* Tell OLEDragDrop that I know how to handle this
This.OLEDropHasData = 1
* Tell OLEDragDrop that I want to copy this
This.OLEDropEffects = 1
ENDIF
ENDIF
This code starts out by checking the data object to see if it has a registered format named 'Private Format.' This checking does two things: It returns true or false as to whether that format is registered in the data object, and it also fires the OLESetData event of the drag source object and passes it the format being requested (youll see this code in a moment). Here, if the data object returns true, it does have this Private Format registered, and two properties of the target object are set. OLEDropHasData is set to 1, meaning that the data object does have data that this object understands. OLEDropEffects is also set to 1, meaning that this object only knows how to copy the data. Other settings for the OLEDropEffects would be 2, meaning Move, or 3, meaning copy and/or move.
Now lets look at the OLESetData method of the drag source object. Keep in mind that the data format requested is 'Private Format.'
LPARAMETERS oDataObject, eFormat
DO CASE
CASE trans( eFormat ) == '1' && Text format
* If Text data is requested by the drop target
* Put 'American Flag' in the data object
oDataObject.SetData( 'American Flag', 1 )
CASE trans( eFormat ) == 'Private Format' && Private format
* If 'My Own Private Format' is requested
* put the picture file name into the data object
* as 'My Own Private Format'
oDataObject.SetData( This.Picture, 'Private Format' )
ENDCASE
In this code, the eFormat parameter received is the format that has been requested by the drop target. In the DO CASE for the 'Private Format' the line oDataObject.SetData( This.Picture, 'Private Format' ) sets the data of that format to the contents of the Picture property of the image control. You know the picture property of the image control is a path and file for the American Flag bmp file.
Finally, the OLEDragDrop event of the container has the following code:
LPARAMETERS oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord
IF oDataObject.GetFormat( 'Private Format' ) && Private format
* I can handle 'Private Format' data
* Hide the label
This.lblDropSpace.Visible = .F.
* Set the picture property
This.Picture = oDataObject.GetData( 'Private Format' )
* Set the copy attribute
nEffect = 1
* Draw the container
THIS.Draw
* Stop the default action of the drag and drop event
NODEFAULT
ENDIF
This code simply makes the label that says Drop Here invisible and sets the picture property of this container to the picture passed in the data object. The line nEffect = 1 causes this to be a copy operation, and the call to the draw method redraws the container to show the new flag image. The NODEFAULT command at the end of this code is important; it prevents the OLEDragDrop event method from doing any of the things it might automatically do for you. You want to stop this because you have already fully handled the drop operation
Drag and drop is a good idea whenever it makes sense to the user to move items from one place to another. Lets go back and revisit the mover dialog with the two lists, which we saw in Figure 21.
How much work would it take to enable OLEDragandDrop into this dialog?
To provide basic drag and drop operations between those two lists, you only need to set the OLEDragMode of each list to Automatic and the OLEDropMode of each list to Enabled. Figures 29 and 30 show that form running after those properties have been changed.
Figure 29. The drag operation in process.
Figure 30. The drop operation is completed.
Whenever it makes sense to allow the user to manipulate the objects in your forms, do so. Direct manipulation is the most intuitive methodology for users to manipulate data in a system.
This chapter has covered a vast amount of information about user interface design. A lot of the information has been presented in abstract concepts and guidelines. There are few cold hard facts in this area of application design. An interface that works well in one place may fail horribly in another.
Many different issues influence user interface design. The projects budget might have an impact on how you build the interface. The nature of the application and its functional requirements will certainly influence the interface design. The philosophy of the management of the client will have its effect on the user interface. Dont underestimate the impact of interface on an applications success or failure.
In certain areas, this chapter contradicts itselffor example, the area of modeless vs. modes in interface design. The contradiction is part of the real world. Often the decisions made relating to the user interface are subjective. The intuition and experience of the developer plays a major role in making these decisions. One point of this chapter is to provide a set of guidelines to help make interface design decisions.
This chapter has presented and explained many design styles and pointed out their strengths and weaknesses. You need to choose the right way to build your applications interface within the context of that application and its users.
Some information presented in this chapter resulted from looking at poor interface designs and evaluating what was wrong with them. The benefit of this is that you can now try to avoid making those same mistakes in your work.
The area of drag and drop was examined in some detail, partially because it isnt covered very well in other places, but also because directly manipulating objects on screen is a fairly easy thing to teach users. Barring other constraints, direct manipulation can be a good interface. If you keep your mind on users and their goals in any given application, you will likely design an acceptable interface.
The bottom line of all of this is that user interface design is a science and an art. Here we discuss the science, but the art is just as important to the final result. Mastering the art takes experience and intuition.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1069
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved