Limits on single line edit control? GDI related? - windows

I am working with an edit control in a dialog--all MFC. The only style specified in the resource is ES_AUTOHSCROLL. The dialog comes up and displays correctly. The edit control also works and edits text correctly--up until a point. At that point, it stops displaying text completely. The edit control is just blank.
My first thought was to try and adjust the limits of the edit control by sending calling SetLimitText() on the edit control which just sends EM_SETLIMITTEXT. I set a big number which was 10x the previous limit, and verified by EM_GETLIMITTEXT that the number retrieved is equal to the number set. After that, I still have the problem and nothing is changed.
Next I tried trapping EN_MAXTEXT and EN_ERRSPACE. Neither one of those notifications was sent.
Lastly, I started trying a little different input, and if I entered a space or a period then I could get a few more characters displayed than if I entered a W. The font in the dialog is MS Shell Dlg which on my system maps to Microsoft Sans Serif. It's a proportional font, do different characters have different widths, so I was beginning to thing that maybe it was GDI related.
Next, I trapped EN_CHANGE, and when it is fired off, I went and created an IC for the display, selected the font into the IC from the edit control, and then called GetTextExtent() on the text in the edit control. The problems occur in display right around 32760 which is darn near the 16-bit signed integer limit.
So, I am thinking that my problem is GDI related in that the EDIT control cannot draw past that limit. I tried substituting a RICHEDIT2 control, but it displayed fewer characters before going blank.
The other weird thing is that if I keep on entering characters and call GetWindowText() on the edit control, all the characters will be returned. It is just that the edit control is blank.
Yeah, maybe I shouldn't be displaying that many characters, but it is what it is.
Does anybody have a better explanation, solution, or workaround?

Related

Entangled text boxes

A mere Windows textbox greatly surprised me today.
I have two unrelated text boxes inside an application. I can type in either text box and switch the focus by clicking on them. Then happens some event X, which I can't describe here for reasons given below. After this event happens, the two text boxes become "entangled" in an almost quantum way.
Say, text box A was focused before X happened. When I click text box B to type in some text, the new text appears in text box A, whereas the blinking cursor happily moves along in text box B through the void, as if the text were there.
No amount of clicking on either text boxes can resolve this. The cursor will always remain in B, whereas the text will always go to A.
Message spying reveals that after the event X, the text boxes lose the ability to lose or gain focus. When I click on B, WM_LOSE_FOCUS does not come to A, and WM_SET_FOCUS does not come to B. (The rectangles and visibility of the boxes are OK.)
The same thing happens in Windows XP and Windows 7.
Now, event X: it's a big event in a third-party UI library which I cannot reverse-engineer in a timely manner. (Namely, docking a pane in wxAUI.)
I am sure that this behavior is the result of incorrect WinAPI calls to the text boxes (garbage in - garbage out). I would like to know what could possibly cause such "textbox trip" to know where to start looking for the bug.
Thanks!
I found the problem. It was me. There was a silly bug in focus management. It caused the focus to be rapidly (immediately) transferred to text box B and then back to text box A immediately after "event X". And though it only happened once, it was enough to wreak havoc in the textboxes till the end of their lives.
Why the special effects? It turns out that Windows hates two rapid consecutive manipulations with UI elements. I once had a similarly weird bug when I tried to move a control by setting its origin and its size in two different steps. The control would behave very randomly after this. Only when I moved it properly - in one step - the weirdness stopped.
Thanks for your attention and sorry for bothering.
That's a pretty strange one, and without being able to look at some code the best I can do is an educated guess.
It sounds to me like the UI library is handling notifications (key down, focus, etc.) for text box B and acting on them as though they were meant for text box A. Like there's a variable like activeTextBox that holds the handle of text box A, even when it should be pointing to text box B.
Whereas I can imagine a UI library bug causing this kind of behavior, I would think it's much more likely that client code would cause it. Have you ruled out your code as the culprit?
Do the text boxes have unique identifiers?
did you tie their messages and message handlers up correctly?
In particular, it sounds like the control that has event X might have sub-control identifiers which clash with your control identifiers.
if the problem is reproducible, then I would make a small test example and send it to the control's vendor.

How to visually reject user input in a table?

In the programming of a table-based application module (i.e. the user mostly enters tabular data in an already laid-out table), how would you reject user input for a given cell?
The scenario is: the user edits the cell, enters something (text, picture, ...) and you want them to notice when they finish editing (hitting enter, for example) that their entry is not valid for your given "format" (in the wider meaning: it can be that they entered a string instead of a number, that their entry is too long, too short, they include a picture while it's not acceptable, ...).
I can see two different things happening:
You can rather easily fit their entry into your format, and you do so, but you want them to notice it so they can change if your guess is not good enough (example: they entered "15.47" in a field that needs to be an integer, so your program makes it "15")
You cannot guess what to do with their entry, and want to inform them that it's not valid.
My question specifically is: what visual display can you offer to inform the user that his input is invalid? Is it preferable to refuse to leave the editing mode, or not?
The two things I can imagine are:
using colors (red background if invalid, yellow background for my case 1 above)
when you reject an input, do something like Apple does for password entry of user accounts: you make the cell "shaking" (i.e. oscillating left and right) for one second, and keep the focus/editing in their so they don't loose what they've typed.
Let's hear your suggestions.
PS: This question is, at least in my thought process, somehow a continuation and a specialization of my previous question on getting users to read error messages.
PPS: Made this community wiki, was that the right thing to do on this kind of question or not?
Be careful using autocorrection such as forcing user input to fit your format. See:
Is it acceptable to normalize text box content when it loses focus?.
It’s generally better to prevent invalid entries in the first place than to autocorrect them later. For example, if only integers are allowed, then you ignore any keying of the decimal point (along with all letters and most special characters). In some environments, you may want to provide a quiet audible signal that input is ignored (e.g., a dull thud).
As for when you need to alert the user to an error, how about a callout? Draw a bright line from the control or point in question (field, status annunciator, button, menu, location of a drag and drop) to the margin of the window and put a brief message (two or three words, like "Unrecognized date") in a balloon. Placing the message on the margin should keep it from occluding anything of interest in a crowded table.
The sudden appearance of the call-out should be sufficient to catch user attention, so it's okay to let the user move on to other cells in case they want to fix the error later. For efficiency, you may want to hold the user in the error-related field when the error originally occurs (since often the user wants to correct it right away), but then allow the next tab or mouse click to navigate the user away.
On mouseover or when focus is on the control associated with the error, the line is highlighted (to distinguish it from other callout lines that may be present) and the balloon expands to a full error message, providing more details on how to fix the problem (up to two sentences). Allow the user to drag and drop the balloon to a new location in case this occludes something of interest.
Include a Help button in the expanded balloon for further details. You can also include a button to fix the error (e.g., Retry, Reconnect, or set to default value).
The balloon disappears automatically when the error is fixed. Undo reverts whatever caused the error (e.g., reverts the field to its original value), which should clear the error.
If the user scrolls away from the place associated with the error, the balloon shrinks to an icon that remains in view so that the user is less likely to forget about it. Maybe an exclamation point in a triangle is a good icon. Place the icon beside or in the scrollbar track to indicate its relative location in the table, so the user can quickly scroll to find it later. Mouseover expands the icon to its full message. Perhaps clicking the icon can scroll to the right place in the table and put focus in the relevant control.
Balloons could also shrink to icons if they start visually interfering with each other. You may even want to include a control in a balloon to allow the user to force it to assume an icon.
For consistency, use for all errors, not just those associated with fields in tables.
The last time I did such a form (on a web page) I put a red box around the offending input.
I thought it was really neat... until a user asked me "Why's there a red box around this cell?"
What'd be nice is also displaying why the input's incorrect: "This field accepts only numbers", say.
You could display an icon in the cell, or a tooltip. The tooltip could open automatically or when mouse pointer hovers over the icon. It could disappear automatically when user edits another cell or when some timeout expires.
You can go with arrow tooltips like Adobe Flex's error tooltips. It focuses the attention to the error and supplies a brief description.

TabCtrl_SetItemSize and user drawn tab controls

I have this Win32 user-drawn tab control that is created as:
CONTROL "Tab1",IDC_TAB_CONT,"SysTabControl32",TCS_BOTTOM |
TCS_OWNERDRAWFIXED | NOT WS_VISIBLE,0,14,185,88
I'd like for this control to have its tabs resize as never to have to see the "sliding arrows":
Now, pretty much everything about this control works as expected, except for that fact that it won't respond to TabCtrl_SetItemSize. Try as I may, the size I get for the tabs when I get to draw them (in the DRAWITEMSTRUCT passed to WM_DRAWITEM) is always the size that fits the longest caption in them and never the size I've set with TabCtrl_SetItemSize.
However, in the TabCtrl_SetItemSize documentation, it says that:
[TabCtrl_SetItemSize] sets the width and height of tabs in a
fixed-width or owner-drawn tab
control.
The only way I've managed to have a decent resizing is by setting a dummy string of the desired length in it by sending the control a TCM_SETITEM message, and writing the desired text in it at draw time. This is rather inconvenient and not a particularly nice hack.
Is there anybody who would know
Why TabCtrl_SetItemSize isn't working as expected? and/or
How to set the tab size properly?
Many thanks,
joce.
Setting TCS_OWNERDRAWFIXED style is not enough, you have also to add TCS_FIXEDWIDTH style.
The minimum size of a tab is at least icon width + 3 if icon is present.
If you have icons (imageList attached to tabControl), you might get those "sliding arrows" even with fixed width (if there is less space available than: number of tabs*(icon width+3)

How to implement (UI-wise) a button

I am designing the (G)UI of a program, and have stumbled across a problem; The program will convert a number into different units, and the layout of a unit been converted to is:
[Unit name (when clicked gives information)]
[Special status, if any]
[Output in textfield that can also be used for input (to convert to other units)]
I want the user to be able to copy an outputnumber onto the clipboard, without having to mess around with highlighting and finding the right buttons to press. So, I thought I'd make a button after the text-output field, saying something like "C" or "Copy".
But I was reading on joelonsoftware.com yesterday, and discovered that users seem to be cursorclumsy. So what should I do?
I've thought about a number of different options:
Click on textfield to copy to clipboard - BUT: I want to use it for input as well
Pressing a numeral on the keyboard to copy the respective one - BUT: There will probably be more than 10, and I need them for new input
Bigger Copy button, like on that actually says "Copy" - Hmm, would this work? I know that I like to use the keyboard when I can, so a solution involving it would be nice.
Each unit will have its own space, where everything (name, textfield etc.) fits in. What if it would copy to clipboard when clicked anywhere in that space except for on the name or textfield. - BUT: What if you miss, meaning to click below one textfield, and clicking above another?
But what about highlighting the unit's space as I went along? - Could still mean trouble...
What do you think? I think I just might opt for #3 - Bigger copy-button..
There's nothing wrong with a Copy button after every field if you feel that it's going to be a very common operation.
Two suggestions, however:
In terms of look and feel, make sure that the button is clearly associated with the field. For a text field, the best way to do this is to put the Copy button inside the text field (on the right side - but be prepared to handle RTL languages by switching its position as needed!).
To avoid making it overly big, don't use any text, but rather use the stock Windows icon for Copy (like this one: ), and put the text into its tooltip. If you do that, you may also get rid of button border entirely, further reducing its size, though you'd still want some visual hover indicator to make it clear that it's an active UI element. In fact, you might want to specifically copy Vista/Win7 Explorer (also seen in IE7/8) UI for location field and the Reload icon in it.
I think the solution #3 is the best in your list, but I would like to see a sketch of your GUI.
What ever you do, it is important to use the OS standard keyboard and mouse event bindings and preferable look-and-feel too otherwise users get confused.
For sheer speed, the keyboard is the way to go. How about letters A-Z to copy the text boxes instead? Skip “E” to allow scientific notation to be inputted. Potential speed is high, but learnability is low. I’d expect users will have a hard time figuring out this UI even with explanatory text on the page/window, and if users have to read explanatory text, then the time that takes will likely negate the time savings of the UI, unless the user is using the app all the time (Joel also writes correctly that users hate to read).
For an app that will be used only occasionally, the big button is a better choice, the bigger the better, as predicted by Fitts’s Law. And absolutely label it “Copy,” not “C” and not an icon, to maximize learnability. Your other ideas have learnability and tolerance issues without the speed of the keyboard.
That said, I think you’re taking what Joel says too far. Certainly you want to eliminate unnecessary clicks, but the typical design for this type of app would require one click on the text box (which should by default highlight the whole value) followed by one click on a Copy menu item –or better, Alt-C or Ctrl-C from the keyboard. It’s hard for me to imagine a task where saving one click or a couple keyboard presses would be worth the clutter of a bank of Copy buttons beside your text boxes. Are you also going to have buttons for Paste and Clear? At some point the clutter will slow your users down more than the extra click.
How often are users going to be copying? If it’s really dozens of times per session, then you should re-think the whole design approach because any copying and pasting of one number at a time is going to get tedious. Maybe you should support batch processing, taking multiple numbers at once and outputting results in a form already suitable for the expected use. Maybe have it work within other apps like the way Enso does: user highlights a number in any document or text field of any app, commands Convert - Feet - Meters and it’s changed in the document or field.
If you accidentally click on the wrong area, you could just click on the right area after that. If your issue lies in the user not knowing when they click on the wrong area, just highlight the last-clicked area.
Is there a problem with copying whatever is in the textfield when they click on it? So what if it's being used for input? They're just going to copy the value they need after they type values in.
You could also have a ctrl-click or shift-click in the text box be a copy.
Most people know how to copy text on their own computer. Perhaps the best solution is to just auto-highlight all the text in a textbox when it gets focus so they can just ctrl-c to copy or start typing to begin input.

VB6 silently deleting huge chunks of control data from forms

My project has maybe 130 controls (total of all labels, textboxes, etc.) in an SSTab (4 tabs). The project loads fine, it runs fine, I don't see a single error or warning at any point, but when I save the form with the SStab on it, the SStab data isn't saved (it is completely gone). Normally the relevant portion of the .frm file looks like this:
Begin TabDlg.SSTab SSTab1
Height = 8895
[1550 more lines of code for all the controls]
Width = 540
End
Begin VB.Menu FileMenu
But lately it's getting cropped to:
Begin TabDlg.SSTab SSTab1
Begin VB.Menu FileMenu
This is very frustrating! In my VB IDE, the frame, sstab, and all the controls are there, editable, running/compiling fine, no error messages at any point, but when you save the file, 1550 lines of precious sstab data just disappears - again, with no warning or error messages. So if you exit and restart the IDE, you get a form load error because 60% of the code is now missing. The log file points to the first error it finds (in this case a Begin TabDlg with no End) - there's no other info in it. (The log file was generated after the code was deleted and saved, so it makes sense that it wouldn't be helpful.)
When I first posted this question, I thought it had to do with the number of controls, because it appeared after I added a control, and in my first few tests, seemed to disappear when that control (or other controls) was deleted. Now I can't seem to get that form to save under any circumstances, even when I delete many controls (bringing the number of controls far below where it was when it was last stable).
I also tried deleting the SStab and moving all the controls to 4 different frames. I successfully did that in the IDE, but when I saved, a huge chunk of the data (starting with a slider control) was missing. So I have no fraking idea what is going on.
The problem is reproducible on two different PCs, so it doesn't appear to be a hardware/corrupt software VB install issue.
Has anyone else run into something like this?
Create a UserControl for each tab. That makes editing MUCH easier. It also allows you to nicely modularize the code, so each tab lives in its own file, and it'll allow you to reuse tabs elsewhere if you want.
Sounds horrible, never heard of anything like that.
Presumably you aren't getting an error log file from VB6 when you load the form into the IDE before it gets corrupted? The log file has the same filename as the form file but with a .log filename extension. For example, if errors occurred when loading Myform.frm, Visual Basic would create a log file named Myform.log. The error messages you might see there are documented in the manual.
Have a look in the Windows Event Log, see whether it records any interesting problems against the VB6 IDE?
Are you using any weird controls? Maybe one of them is somehow corrupting the FRM or FRX. FRM files are just text as you obviously know & the format is documented in the VB6 manual. Can you see any corruption in the FRM in a text editor? If you remove any properties defined in the FRX, does it still fail.
I think I would try creating a new project and a new form, and then use the IDE to copy and paste all the control definitions into it - no code. Play with the new form, see whether it has the same problem. Maybe you can recreate the form this way without the problem. If the new form does have the problem, do the same thing but only take half the controls. Maybe you can find a problem control by "binary search".
I get the same problem when attempting to save a form when the .FRM is writable but the .FRX is read-only
Not sure if this is the issue, but on a VB6 form, there is a limit to 255 (or is it 256) named controls. Perhaps you are running into that?
One way around that limitation is to use control arrays. For example, if you had 10 labels, instead of label1, label2, label3, etc, you could do label(0) through label(9), and use up only one named control.
The other thing worth mentioning about the SSTAB is the way it shows/hides controls. While it may appear that the controls are on separate tabs, what is really happening is that the controls are getting moved waaaayyyyy to the left (and consequently out of view). Perhaps with so many components, the SSTAB is choking on this in the IDE as it tries to render the controls in design view?
Again, not sure if this is the issue, but I know these two tidbits are relatively unknown.
So the SAVE function is not working.
I suspect one of the components you are placing on the tab strip is the culprit.
So ..
1) Take an inventory of each and every kind of component you are placing on the form
2) eliminate one (kind), SAVE
3) Did it SAVE?
-> Yes = that was the problematic control
-> No = return to step 2, but pick another kind
Of course, its important to remove all controls of a certain kind in step #2 (for example, ALL labels, or ALL textboxes, etc).
I have never heard of this happening however.
You are not alone! I've seen this problem. . .in fact I'm dealing it right now, which is what brought me to this site.
I've been working with VB since '94 (VB3) and I first saw this problem about 5 or 6 years ago, while using VB6. My solution then, was not unlike some of the suggestions that you have recieved from the good folks who've responded above: throw out the existing file and rebuild the form in a new file. I did that back and the affected form has worked ever since.
My current problem is appearing in another, much newer form, and the replace/rebuild option (performed about a month ago) only worked for about three weeks. Now the problem is back and each new iteration of the file gets corrupted very quickly. Following the reply above regarding the total number of allowable controls, I'm looking into just how many controls I have. . .and, as it happens, I was in the process of consolidating the primary the buttons and menus into control arrays, simply because it was going to streamline their management.
I can also confirm your observations about moving the project to a second PC. . . I've done that too, and problem persists. Moreover, I can add that I have moved the project from one shared storage system to another to no avail. (The original storage location was on a drive mounted to a Win-tel system and the new location is on a UNIX-based NAS!)
Just rebuilt the file again and checked: Controls.Count = 62, so I am no where near the 255 control limit mentioned previously. This is indeed strange! (Not to mention furstrating!)

Resources