Принятый ответ почти работает, но немного неловко из-за ненужного использования event
, явного создания экземпляра делегата и нестатического метода обратного вызова.
Я говорю «почти», потому что онтакже есть небольшая ошибка: делегат, созданный для обратного вызова, не сохраняется ни в одной переменной, что делает его пригодным для сбора мусора.Сборщик мусора не имеет никакого способа узнать, что вы передали делегат, завернутый в указатель на объект окна, и, таким образом, в конечном итоге сможет отказаться от делегата, что приведет к аварийному завершению приложения.в следующий раз элемент управления TextBox
необходим для переноса любого текста.
Вот версия, которая мне больше нравится:
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static IntPtr SendMessage(IntPtr hwnd, uint message, IntPtr wParam, IntPtr lParam);
private const uint EM_SETWORDBREAKPROC = 0x00D0;
private delegate int SetWordBreakProc(IntPtr text, int pos_in_text, int bCharSet, int action);
private readonly SetWordBreakProc _wordBreakCallback = (text, pos_in_text, bCharSet, action) => 0;
public Form1()
{
InitializeComponent();
textBox1.HandleCreated += TextBox1_HandleCreated;
}
private void TextBox1_HandleCreated(object sender, EventArgs e)
{
IntPtr callback = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(_wordBreakCallback);
SendMessage(((Control)sender).Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, callback);
}
}
Другое отличие состоит в том, что я инициализирую слово-прервать процесс в обработчике событий TextBox.HandleCreated
.Это выполняет две вещи: во-первых, инициализация происходит как можно скорее, сразу после того, как дескриптор элемента управления является действительным, и, во-вторых, путем инициализации на этой ранней стадии процесса, если свойство TextBox.Text
уже было установлено, например, в Designer.или конструктор формы, обтекание все равно будет выполнено правильно даже для этого исходного текста.
Текст, вставленный позже, все еще будет в порядке, и, конечно, вы могли бы даже временно временно сбросить текст после инициализации, чтобы вызвать пересчетупаковкаНо ИМХО, во-первых, лучше просто заставить его работать достаточно рано.
Также обратите внимание, что приведенное выше требует явной инициализации каждого TextBox
, который вы добавили в форму.Очевидно, что если вы хотите применить эту технику более чем к одному TextBox
, имеет смысл создать новый подкласс TextBox
, который выполняет эту инициализацию в своем собственном методе переопределения OnHandleCreated()
.