Lock down TextBox location?

  • Thread starter Thread starter Bob Dankert
  • Start date Start date
B

Bob Dankert

I am looking for a way to lock down the textbox location. It would be nice
if there were a LocationChanging event, and you could call
LocationChangingEventArgs.Cancel = true; but, this does not exist, which
leads me here. Does anyone know how I can lock down the location of a
textbox so that it absolutely can not move?

Thanks,

Bob Dankert
 
Nope, not design-time -- that's an easy one. I mean throughout the entire
program. I know it seems like an odd type thing, and I would normally
suggest "well, just dont move it", but unfortunately in my case, that's not
going to work. I tried intercepting the WndProc messages for move and
cancelling these, but it still seemed to move it. I'm sure there is SOME
way to prevent the location from changing, I'm just not quite sure how to
get there.

Thanks,

Bob Dankert
 
So I assume that you have either written code that will allow the user to
move the control at run-time, or the control is being moved as a result of
some docking or anchoring. How is the control being moved currently?
 
The textbox is attached to an ownerdrawn listbox, and Windows XP SP1 has a
bug where it moves its location all over the place. I worked with Rhett
Gong finding a work-around so that it will re-place the textbox to the
correct position, but this causes a bit of flicker as it moves to the other
location, and then back. If I can lock down the position of the textbox, it
will not flicker.

Let me know if you want any further information. I am pretty sure the only
solution here is going to be controlling when you allow textbox location
changes.

Thanks for any help,

Bob Dankert
 
So the TextBox is actually being used to do in-place editing in the ListBox,
sort of like the DataGrid? Is this correct? If not what is the TextBox used
for? So you are saying that there is a bug with the owner-drawn aspect of
the ListBox under XP SP1. So you have somehow confirmed that to be the
problem?
 
Hi Bob,

To my understanding now, you are trying to implement an in-place edit
feature on listbox items, and you would like to keep the edit box on a
certain list item after scrolling. Do I understand your problem correctly?

I discussed this issue with Rhett, here is a modified version of the list
box code, you may try it to see if the flicking problem is reduced.
If the problem still persists, please feel free to reply this thread.
Thanks!

<code>
using System;
using System.Windows.Forms;
using System.Drawing;

public class MyListBox : System.Windows.Forms.ListBox
{
public MyListBox()
{
this.ItemHeight = 22;
this.DrawMode = DrawMode.OwnerDrawFixed;
this.SelectionMode = SelectionMode.MultiExtended;
this.DrawItem += new DrawItemEventHandler(MyListBox_DrawItem);
}
private void MyListBox_DrawItem(object sender, DrawItemEventArgs e)
{
//check if the textbox has been added.
if (this.Controls.Count != 0)
{
//assume the TextBox is the first child control in the
ListBox.ControlsCollection
TextBox ctrl = this.Controls[0] as TextBox;
Point pt = this.GetItemRectangle(10).Location;
if (ctrl.Location != pt)
{
ctrl.Location = pt;
ctrl.Refresh();
}
}
e.DrawBackground();//draw background based on BackColor and Selection
state.
e.Graphics.DrawString("Row " + e.Index,this.Font,Brushes.Black,e.Bounds);
e.DrawFocusRectangle();//add focus rect.
}
}
</code>



Best regards,

Ying-Shen Yu [MSFT]
Microsoft community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Hello Ying-Shen,

As you described is precisely my problem. I had previously modified my code
to include the change, to only re-position if necessary, but it still has
the problem that when scrolling, I can see the textbox jump to down and to
the right a little bit and then jump back. I was hoping there was a way I
could tell the textbox to reject all position changes if it puts the
Y-position greater than some number, so as to prevent it from being able to
move it to the right at all. For the test application I use, it is not such
a big deal (the flicker), but with the production control I am using there
can be 10 textboxes on the control at various points at one time, and the
flicker gets to be quite noticeable.

Thanks for all the help,

Bob Dankert
 
Hi Bob,

I'm not very clear about the your meaning of "reject changes",
actually, we need re-positioning the textboxes to keep the textbox in the
bounds of the item.

I think we can not avoid this flicking completely in this way, since we
need move the all the listboxes at every draw item call.

Can we workaround this issue by ownerdrawing a "TextBox" on these items in
draw_item event handler to simulate this effect?
We can show a TextBox on the item when double clicking on it or a single
click on a selected item to enter the edit mode. we can hide the TextBox
when the listbox is scrolling.
Since there are no window-repositioning happens, the listbox will not
flicker when scrolling.

Is this workaround suitable for your scenario?

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Hello Ying,

The concept of rejecting location hanges would be only if the X position
were greater than the maximum specified X coordinate. Basically, you set
the location of the textbox, and set the maximum X-position to be the same
as the current position. Therefore, when the listbox tries to move the
textbox over to the right, it will reject the location change and not move.
Similarily, we could control the Y-coordinate and change the maximum values
for these coordinates before we change the position during scrolling.

I had thought about the ownerdrawing of a textbox, however I am not sure how
I would edit the contents of the textbox when it is ownerdrawn. The other
problem would be drawing the text, because the textbox can span more than
one listbox item. I am hoping there is some way to get around the ugly
flicker, plus the fact that repositioning the textbox so much during
scrolling causes the processor to devour the CPU resources.

Thanks for the help,

Bob Dankert
 
Hi Bob,

I need do some research to see if it is possible and how to do this.
I'll get back to you as soon as I get some findings.

Thanks for your patience!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no
rights.This mail should not be replied directly, please remove the word
"online" before sending mail.
 
Hi Bob,

My modified listbox works well in my test machine, I'm not sure where is
the problem, I sent my test code to your mail box, you may try it to see if
works on your machine.

In my experience, Analyzing the underlying Win32 messages of the Listbox
and the TextBox will be helpful to determine the cause of the ficker since
flicker is caused by frequent WM_PAINT messages. You may capturing the
messages using Spy++, In my testing, I captured the List box and its child
windows, I only choosed "general" and the Listbox messages in "Messages"
Tab.

Also, in my test, There is an option in windows system settings names
"smooth-scroll list boxes", which will change the behavior of the listbox,
if it is enabled the Listbox will send WM_PRINT to save the bitmap first,
which will cause trouble to the Textbox since it does not aware the
scrolling. That's why I disabled the WM_PRINT message.

When this option is disabled, it will just repaint the item as needed, in
my test Rhett's workaround works better with this option disabled.

Here is just some findings in my investigation, I hope it will help you a
bit. If you need help in investigating the flicker issue, don't hesitate to
post it in the newsgroup.

Good Luck!

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Ying,

Thank you for the help. After applying some of your various modifications
as well as a few others I came up with, the issue is much less prevelent.
Thanks a lot for your help!

Bob Dankert
 
I think I finally got a good solution. In the listbox, I completely took
control of the scrolling using the following:

/// <summary>
/// This scrolls the control up or down one unit, depending on the parameter
/// </summary>
/// <param name="dir">The direction to scroll. 0 is down and 1 is up</param>
private void scrollMe(System.IntPtr dir)
{
System.Windows.Forms.Message ScrollMessage = new Message();
ScrollMessage.HWnd = Handle;
ScrollMessage.Msg = 0x0115;
ScrollMessage.WParam = dir;
this.DefWndProc( ref ScrollMessage );
}

private void scrollMe(System.IntPtr dir, int count)
{
for (int a=0;a<count;a++)
scrollMe(dir);
}

protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == 0x020A) // WM_MOUSEWHEEL
{
if (m.WParam.ToInt32() > 0)
this.scrollMe(new IntPtr(0),5);
else
this.scrollMe(new IntPtr(1),5);
return;
}
if (m.Msg == 0x0115) // WM_VSCROLL
{
int w = m.WParam.ToInt32();
if (w == 0) // clicked the scroll arrow down
this.scrollMe(new IntPtr(0),3);
else if (w == 1) // clicked the scroll arrow up
this.scrollMe(new IntPtr(1),3);
else if (w == 2) // clicked to scroll down a page
this.scrollMe(new IntPtr(0),10);
else if (w == 3) // clicked to scroll up a page
this.scrollMe(new IntPtr(1),10);
else if (w != 8) // 8 happens at the end, dont like 8
{
int num = (int)Math.Round((double)Math.Abs(this.scrollmark -
w)/65536); // 65536 is one item up/down (0x10000), num is the number of
scrolls
if (w > this.scrollmark) // scroll up
{
this.scrollMe(new IntPtr(1),num);
this.scrollmark = w;
}
else if (w < this.scrollmark) // scroll down
{
this.scrollMe(new IntPtr(0),num);
this.scrollmark = w;
}
}
return;
}
base.WndProc(ref m);
}

This, coupled with the textbox modifications you provided, works great. It
gets a little slow with 100 textboxes, but this is to be expected.

Thanks

Bob

Bob Dankert said:
Ying,

Thank you for the help. After applying some of your various modifications
as well as a few others I came up with, the issue is much less prevelent.
Thanks a lot for your help!

Bob Dankert

"Ying-Shen Yu[MSFT]" said:
Hi Bob,

My modified listbox works well in my test machine, I'm not sure where is
the problem, I sent my test code to your mail box, you may try it to see if
works on your machine.

In my experience, Analyzing the underlying Win32 messages of the Listbox
and the TextBox will be helpful to determine the cause of the ficker since
flicker is caused by frequent WM_PAINT messages. You may capturing the
messages using Spy++, In my testing, I captured the List box and its child
windows, I only choosed "general" and the Listbox messages in "Messages"
Tab.

Also, in my test, There is an option in windows system settings names
"smooth-scroll list boxes", which will change the behavior of the listbox,
if it is enabled the Listbox will send WM_PRINT to save the bitmap first,
which will cause trouble to the Textbox since it does not aware the
scrolling. That's why I disabled the WM_PRINT message.

When this option is disabled, it will just repaint the item as needed, in
my test Rhett's workaround works better with this option disabled.

Here is just some findings in my investigation, I hope it will help you a
bit. If you need help in investigating the flicker issue, don't hesitate to
post it in the newsgroup.

Good Luck!

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Hi Bob,

I'm glad to hear you finally found a good solution to this issue,

Handling WM_SCROLL and WM_MOUSEWHEEL is a feasible way,
And you may use API SystemParametersInfo to get the number of mouse wheel
scroll lines, the following link provide some detail information:
<Retrieving the Number of Mouse Wheel Scroll Lines>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui
/windowsuserinterface/userinput/mouseinput/usingmouseinput.asp

Besides, you may also need to test the behavior when the "smooth scroll
listbox" feature is enabled or disabled.

Thanks!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Back
Top