Sunday, December 19, 2004

Q: When I append text to the end of the current content of a multiline listbox, it is always scrolled back to the first line. Even if I later use ScrollToCaret to return to the end of the text, the whole control briefly flickers. Is there a way to avoid it?

A: Indeed there seems to be an issue in Compact Framework where replacing selection in an edit control. Apparently someone wanted to be clever and even though there is a dedicated control message EM_REPLACESEL, he implemented set_SelectedText in the following way:

string SelectedText
{
   
get
   
{
       
if
( SelectionLength == 0 )
           
return
"";
       
return new string
(Text.ToCharArray(), SelectionStart, SelectionLength);
    }
   
set
   
{
       
this.Text = this.Text.Remove(SelectionStart, SelectionLength).Insert(SelectionStart, value
);
        SelectionStart =
this
.Text.Length;
        SelectionLength = 0;
    }
}

 

Why is it done this way, I don't know. There are perfectly good tools at the edit control message level to work with selection. What's important here is that set_SelectedText internally calls Control.set_Text which translates into WM_SETTEXT message. In case of an edit control it has a side effect of moving caret to the beginning and scrolling the text to the same place, thus creating an unpleasant flicker.

To remedy this problem we simply replace set_SelectedText with our own implementation:

Instead of
textBox.SelectedText = "A quick brown fox jumped over lazy dogs. ";
use
SendMessage(hWnd, EM_REPLACESEL, false, "A quick brown fox jumped over lazy dogs. ");

You will also need the following PInvoke definitions:

 

const uint EM_REPLACESEL = 0xc2;

[DllImport("coredll")]
extern static IntPtr GetCapture();
[DllImport("coredll")]
extern static int SendMessage(IntPtr hWnd, uint Msg, bool WParam, string LParam);

 

To get HWND of your textbox use something like this:

 

private IntPtr GetHWND(Control ctl)
{
    ctl.Capture =
true
;
    IntPtr hWnd = GetCapture();
    ctl.Capture =
false
;
   
return
hWnd;
}

 

12/19/2004 10:12:42 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]  |