Thanks everybody.
for it yet). It resides in a portion of code that I did not show before. Se
If I disable the handling above, the edit control does not crash.
It seems that I'm wasting resources in some way.
Please help.
Thank you all.
"Joseph M. Newcomer" wrote:
See below...
On Mon, 18 Feb 2008 23:00:00 -0800, ElCarso <elcarso@somewhere.com> wrote:
Hi,
I have built a dialog based application that uses a CEdit control.
No problems initializing it, I can change the font and other similar stuff,
but it crashes when I resize it.
The application it self does not crash, but it becomes impossible to continue.
****
I have no idea what this means. If it doesn't crash, then why say it crashes. You do not
describe what you mean by "impossible to continue".
****
Please see the two images, before and after the resize operation:
http://www.saffi.nu/cedit/pic1.gif
http://www.saffi.nu/cedit/pic2.gif
****
It looks like you have gone into an infinite loop somewhere. So why not break into your
program with the debugger and see what it is doing?
****
The edit control is declared in the .rc file as:
-------------------------
EDITTEXT IDC_EDIT_WINDOW,103,5,93,78,ES_MULTILINE | ES_AUTOVSCROLL |
WS_VSCROLL | NOT WS_TABSTOP
-------------------------
My code looks basically like:
-------------------------
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_WINDOW, m_EditWindow);
........
m_EditWindow.SetLimitText( (UINT)wcslen(TextBuffer)*3 );
m_EditWindow.SetWindowText( TextBuffer );
****
This doesn't make any sense at all. It looks like the code you have is in the
DoDataExchange. This is almost certainly the wrong place to do this.
Why are you using SetLimitText at all here? Note that if TextBuffer is an empty string at
the point when you call this, the control will instantly become unusable. So don't
SetLimitText at all here. If you are going to set the text limit, set it to some specific
length which is not a function of some unpredictable value, and most especially do not set
it on every DoDataExchange.
I work on the assumption that UpdateData is never, ever called explicitly in your code. I
consider the use of UdpateData to be a mistake. See my essay on "Avoiding UpdateData".
****
........
void CdaVinciAuxDlg::OnSize( UINT nType, int cx, int cy )
{
static bool BusyResizing = false;
****
I have no idea what this does. But one thing is absolutely true: using a static bool is
intrinsically a design failure. Please forget this technique exists. It is unsuitable
for C++. In fact, if you EVER write a 'static' declaration inside a function, and the
word 'const' does not ALSO appear in the declaration, you are using obsolete and totally
unsuitable programming methodology. Thinking that antiquated techniques like this would
make sense will put you into a situation someday where you will have a truly fatal design
error. This is not K&R C and you should not program using obsolete methodologies. This
is C++, and you should use it as C++. Avoid EVER thinking this technique could make
sense. Your code is not reentrant, and that is exceptionally bad style. Not just a
little bit bad, it is a whole lot bad.
****
CDialog::OnSize( nType, cx, cy );
if( BusyResizing ) return;
BusyResizing = true;
****
Remove ALL instances of BusyResizing, and get rid of the variable. This code makes no
sense at all. If it works, it is miraculous. Given the bugs you are seeing, I wouldn't
even try to debug code that looked like this; I'd rewrite it first before trying to figure
out what is wrong.
What belongs here is
if(m_EditWindow.GetSafeHwnd() != NULL)
{ /* resize edit control */
*****
RECT rect;
GetClientRect( &rect );
m_EditWindow.SetWindowPos( NULL, 0, 0, rect.right+2, rect.bottom,
SWP_SHOWWINDOW );
****
This code doesn't make any sense. It is resizing an edit control to a width is 2 units
wider than the client area! It also is resizing the edit control to fill the entire area;
is that what you intended? Even the value 2 is deeply suspect, since no matter what
criterion you used to figure it out, it probably only works on your machine. You have to
think in a display-independent fashion.
Note that if your objection is the edit control border, you would create an edit control
without a border.
Why doesn't it just say cx, cy here? You have the client coordinates already, you don't
need to GetClientRect(), and in addition, if you DID do this (given you created the
control 10 pixels from the right and 10 pixels from the top) it will suddenly jump left
and up. The correct computation would be
CRect r;
m_EditWindow.GetWindowRect(&r);
ScreenToClient(&r);
m_EditWindow.SetWindowPos(NULL, 0, 0, cx - r.left, cy - r.top);
} /* resize edit control */
*****
Now delete the next line. It serves no useful purpose, because it is using a static
variable, which is inherently a design error. I can't even work out the logic by which
this variable makes sense, or ever could have made sense, even if it had been made a
member variable of the class.
*****
BusyResizing = false;
}
-------------------------
I hade tried to work around this problem by generating a CEdit control in
the code:
-------------------------
CEdit *EditWin = new CEdit();
****
This makes no sense. You can create the control at design time. This code is pointless.
For one thing, there is ABSOLUTELY NO REASON to use 'new' here. Just declare a CEdit
variable! You don't need a CEdit *! Declare this as a member variable of your class.
You should use 'new' only when it is required. It is not required to solve this problem,
and therefore its use is inappropriate.
Key question: why did you consider that creating a control at runtime would fix a bug in
your code that is unrelated to how the control is created? The reason this probably works
is that the silly SetLimitText is not executed, so it doesn't get a chance to screw up the
control state.
****
DWORD style = ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOVSCROLL;
CurrWin->Create( style, CRect(10, 10, 100, 100), this, IDC_EDIT_WINDOW );
****
It is reasonably safe to assume that the values 10, 10, 100, 100 are to be considered
completely random numbers, with no meaning other than being placeholders, since the size
of the control will always be that size and position, independent of the actual screen
resolution. This means your dialog will look different on any machine other than your
own, and you can safely assume that no two machines will show the window the same.
Of course, since there is no reason to create the control at run time, I consider further
analysis of this to be a waste of time.
****
........
-------------------------
The control generated this way *does not crash* when resized, but it cannot
be initialized correctly (font settings are not working), and the graphical
lookout is poor (no ClearType effects).
****
As far as "font settings not working", WHAT "font settings"? There are no font settings!
When you create a control dynamically, it is created with the default system font, and
that is what you should expect to happen. If you want to change the font of a
dynamically-created control, it is your responsibility, and entirely your responibility,
to set the font to a font you want. For example
c_EditWin.Create(style, ...etc...)
(note that I did not use, and would not consider using, 'new' here). Then you would do
CFont * f = GetFont();
c_EditWin.SetFont(f);
The system font is not a ClearType-capable font, so it wouldn't be influenced by the
ClearType settings.
*****
See the image http://www.saffi.nu/cedit/pic3.gif
****
I don't see anything wrong with that image, unless for some reason you are trying to say
the font is not correct.
****
Why this strange behaviour?
****
Because your program has a number of serious errors in it. Fix all the above problems,
and see if you still have a remaining problem.
****
What need I to do in order to make this to work properly (one way or the
other)?
****
Get rid of the SetLimitText that uses some random string of unknown value to establish the
width. Either set a fixed width, or set no width. But value*3 is just insane. Get rid
of it.
****
I would be very greateful for any suggestion that can put me in the right
direction.
****
Read my essay on dialog control management, and my other essays in my "dialog box series",
on my MVP Tips site.
If you still have a problem, that is why you have a debugger. When you see a problem such
as a redraw problem, your first reaction should be to use the debugger to break into the
program and see where it is and what it is doing, and tell us what that is. Trying to
infer the behavior by ethereal vibrations (which is what you are trying to do, and then
asking us to do) is not a productive debugging technique. Use the Debug>Break All option
to see what your program is doing. THat's a whole lot more useful.
joe
****
Thank you
ElCarso
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm