2009-12-23 4 views
10

мне нужно реализовать функциональность EM_SETCUEBANNER, где появляется текст намек внутри элемента управления Edit:Win32: Как настроить нарисовать элемент управления Edit?

Example of cue banner in edit control

Улов является то, что я не могу использовать версии 6 Common Controls, которая является то, что требуется получить предоставленную Microsoft реализацию бинарного баннера.

Я посмотрел в просто изменяя текст управления редактирования, и формат шрифта для

Dark Gray Italic Text 

но он будет бросать Изменить события (component wrapper provided by higher component library), что я не могу найти способ избежать.

Так что я вместо этого собирался настраивать текст, рисуя текст Cue Banner, когда элемент управления не сфокусирован и пуст, и в противном случае полагайтесь на по умолчанию.

Элемент управления Edit красиво не выставляет пользовательский механизм рисования, like ListView, TreeView and others provide.

Other people have looked into it, но это, кажется, почти невыполнимая задача:

От того, как все выглядит, я должен обрабатывать следующие сообщения:

  • WM_ERASEBKGND, WM_PAINT (по понятным причинам)
  • WM_SETFOCUS, WM_KILLFOCUS (для предотвращения белая полоса от показа - описанный выше)
  • WM_CHAR (обрабатывать и обновлять текст в элементе управления)

И я также нужно найти способ отображения каретку в контроль, , так как я не нашел способ разрешить Windows, чтобы сделать это для меня без , рисуя белую панель, о которой я упоминал.

Это будет весело. : rolleyes:

Учитывая, что элемент управления Windows Edit никогда не предназначался для пользовательского рисования: кто-нибудь знает, как настроить пользовательское рисование элемента управления Windows Edit?


Примечание: я также буду принимать ответы, которые решают мою проблему, а не отвечая на мой вопрос. Но любой, кто хочет настроить элемент управления Edit, сталкиваясь с этим вопросом, скорее всего, ответит.

+0

Вы можете просто подделать его, как я сделал, с помощью окна быстрого поиска в Aero.Controls http://bitbucket.org/factormystic/aero.controls –

+0

Я уже пробовал свой подход. Мне было любопытно, как вы решили проблему рисования тематики «SearchBox». Но я вижу, что вы не решили проблему. –

+0

6 лет спустя, я говорю только CreateWindow с некоторым текстом по умолчанию. Когда пользователь нажимает на элемент управления, вы удаляете текст. Вы также можете установить шрифт курсивом, как в примере, и изменить его при щелчке. – kundrata

ответ

10

Пользовательский чертеж Управление редактированием практически невозможно. Есть несколько специализированных случаев, когда вы делаете так мало, что может уйти от него, но вы рискуете сильно пострадать в следующей ревизии окон (или когда кто-то запускает ваше приложение на более старой версии или через службы терминалов и т. Д.).

Просто захват WM_PAINT и WM_ERASEBKGROUND недостаточно хорош, потому что элемент управления иногда рисует и другие сообщения.

Вам лучше написать свой собственный элемент управления редактированием. Я знаю, что это огромная работа, но в конечном итоге это будет меньше работы, чем попытка взломать все элементы кода редактирования элементов управления Edit.

Помню, в старые добрые времена, когда все используют для подкласса кнопки управления, чтобы добавить цвет и графику и т. Д. Дело в том, что однажды я сел и просто написал свой собственный класс окна кнопок. и это был МЕНЬШИЙ КОД, чем то, что мы имели в нашем исходном дереве для подкласса, и пользовательский нарисовать кнопку Windows.

+0

Вы, кажется, правы.i подкласс Edit, обрабатывая WM_PAINT, если я хочу нарисовать текст метки. Иногда (используя мышь, чтобы выбрать, нажав backspace в пустом правлении), элемент управления красит себя как пустой без вызова WM_PAINT. С другой стороны, существует функциональность ** LOT **, которая существует в Редакторе, и я не могу оправдать все инвестиции в код. (вырезать/копировать/вставлять, отменить буфер, IME, RTL и т. д.) –

+1

Да, любой способ - это огромная куча кода. Я просто говорю, не обманывайте себя, думая, что подклассификация будет меньше кода. В конечном счете, этого, вероятно, не будет. –

+1

Я закончил подклассификацию редактирования, вызвав краску в ответ на другие сообщения, а не только «WM_PAINT». Некоторые другие сообщения, которые вызывают внутреннюю краску, без каких-либо ошибок «WM_PAINT», и требуют, чтобы я перерисовал их перерисовку: «WM_SETFOCUS», «WM_KILLFOCUS», «WM_KEYUP», «WM_KEYDOWN», и когда мышь входит и листья. –

3

Подкласс управления редактированием. Обработайте WM_PAINT, сначала вызов исходную процедуру окна, а затем, если она пуста и не в фокусе, нарисуйте текст метки. Передавайте каждое другое сообщение в процедуру исходного окна.

Я сделал это - он работает. Проблема, с которой сталкивался человек CodeGuru, похоже, не относится к вашей ситуации. Я считаю, что он пытается сделать больше для внешнего вида. Для производительности похоже, что элемент управления редактирования выполняет некоторые обновления за пределами обработки WM_PAINT (возможно, для производительности). Это сделает почти невозможным полный контроль над внешним видом. Но вы можете нарисовать подсказку cue.

+0

Проблема заключается в том, что не вся картина происходит в/из/durng с 'WM_PAINT'. Иногда элемент управления «EDIT» будет рисовать сам после того, как сообщение 'WM_KILLFOCUS' и * no WM_PAINT будет отправлено в элемент управления * (т. Е. Оно не аннулирует себя). Это означает, что вы также должны обрабатывать WM_KILLFOCUS и запускать свою собственную краску после нее. И «WM_SETFOCUS», и «WM_KEYUP», и «WM_KEYDOWN», и другие события, которые вызывают краску без «WM_PAINT». –

+0

@IanBoyd: Я признал, что редактирование управляет читами и красками в другое время, но я реализовал ключевой текст, используя эту технику, и он отлично работает. –

+0

@AdrianMcCarthy 'BeginPaint', после того как вызывается процедура исходного окна, имеет пустую область недействительных прямоугольников (поскольку она обрабатывается). Вызов 'BeginPaint' перед вызовом исходной процедуры Windows не будет работать. Создание моего собственного контекста устройства вызывает мерцание (в частности, в случае щелчка правой кнопкой мыши), и представляется довольно сложным оптимизировать строковый чертеж (поскольку он должен ограничивать его обновлениями в произвольной области). Короче говоря, я не могу придумать простой способ рисовать баннер кий и не мерцать; очень интересно, хотя :) – Pooven

5

Создайте собственный класс окон, который выглядит как пустой пульт управления, который рисует текст метки и показывает каретку и имеет фокус. Создайте также элемент управления редактирования, но расположите его за окном. (или оставить его скрытым)

Затем, когда вы получаете первое сообщение WM_CHAR (или WM_KEYDOWN?). Вы помещаете свое окно за редактирование, даете фокус на редактирование и передаете сообщение WM_CHAR. С этого момента управление редактированием займется.

Вы можете прослушивать уведомления EN_CHANGE с помощью элемента управления редактирования, если вам нужно вернуться к показу вашего ключевого текста, когда редактирование станет пустым. Но я бы подумал, что было бы неплохо вернуться к текстовому тексту только тогда, когда редактирование теряет фокус и пуст.

+0

Интересный подход вместо простого подкласса. Для этого требуется два отдельных окна и код обработки как для элемента управления наложением, так и для родительского окна, но он будет работать. Интересно, какие функции вы используете для дублирования необходимого фрейма и стиля элемента управления EDIT, хотя, включая любые активные темы (ThemeDrawText?). Возможно, было бы проще создать второй элемент управления редактирования для соответствия внешнему виду, а затем другой, который вы фактически используете для хранения контента, обращая внимание на EN_CHANGE как для родителя. –

0

И еще мне нужно найти способ, чтобы отобразить каретку в контроле, , так как я не нашел способ, чтобы позволить Windows, чтобы сделать это для меня без также покраски белой полосы, я уже упоминал.

Если вы хотите обрабатывать WM_PAINT самостоятельно, не пересылая сообщение исходному окну proc вашего суперкласса, не забудьте вызвать DefWindowProc. Чтобы каретка была нарисована. Чтобы избежать белой полосы, вы должны удалить кисть класса с помощью SetClassLongPtr. И как-нибудь сохраните область отсечения DC в клипе. Выполните редактирование выводов ExtTextOut. Белая полоска может быть результатом опции OPAQUE, переданной в ExtTextOut с помощью элемента управления Edit.

Заключение: Напишите свой собственный контроль. Под лежачий камень вода на течет.

3

Подкласс управления EDIT хорошо работал для меня - для отображения информации о некоторых форматах пользователю при редактировании атрибутов объекта (а некоторые атрибуты могут быть несколькими строками). Важная вещь, как сказал Адриан в его ответе, заключается в том, чтобы вызвать процедуру управления EDIT до вашего собственного рисунка.Вызов его после или выдача собственного BeginPaint/EndPaint (с возвратом 0 или DefWindowProc) вызвал проблемы для меня из текста, который вообще не отображается, чтобы он отображался только при изменении размера, но не после редактирования, в сторону остатка на экране оставшейся каретки. При этом у меня не было никаких проблем, независимо от времени повторной обработки элемента управления EDIT.

Некоторые настройки:

SetWindowSubclass(attributeValuesEdit, &AttributeValueEditProcedure, 0, reinterpret_cast<DWORD_PTR>(this)); 

// Not only do multiline edit controls fail to display the cue banner text, 
// but they also ignore the Edit_SetCueBannerText call, meaning we can't 
// just call GetCueBannerText in the subclassed function. So store it as 
// a window property instead. 
SetProp(attributeValuesEdit, L"CueBannerText", L"<attribute value>"); 

Обратный вызов:

LRESULT CALLBACK AttributeValueEditProcedure(
    HWND hwnd, 
    UINT message, 
    WPARAM wParam, 
    LPARAM lParam, 
    UINT_PTR subclassId, 
    DWORD_PTR data 
    ) 
{ 

... 

case WM_PRINTCLIENT: 
case WM_PAINT: 
    { 
     auto textLength = GetWindowTextLength(hwnd); 
     if (textLength == 0 && GetFocus() != hwnd) 
     { 
      // Get the needed DC with DCX_INTERSECTUPDATE before the EDIT 
      // control's WM_PAINT handler calls BeginPaint/EndPaint, which 
      // validates the update rect and would otherwise lead to drawing 
      // nothing later because the region is empty. Also, grab it from 
      // the cache so we don't mess with the EDIT's DC. 
      HDC hdc = (message == WM_PRINTCLIENT) 
       ? reinterpret_cast<HDC>(wParam) 
       : GetDCEx(hwnd, nullptr, DCX_INTERSECTUPDATE|DCX_CACHE|DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS); 

      // Call the EDIT control so that the caret is properly handled, 
      // no caret litter left on the screen after tabbing away. 
      auto result = DefSubclassProc(hwnd, message, wParam, lParam); 

      // Get the font and margin so the cue banner text has a 
      // consistent appearance and placement with existing text. 
      HFONT font = GetWindowFont(hwnd); 
      RECT editRect; 
      Edit_GetRect(hwnd, OUT &editRect); 

      // Ideally we would call Edit_GetCueBannerText, but since that message 
      // returns nothing when ES_MULTILINE, use a window property instead. 
      auto* cueBannerText = reinterpret_cast<wchar_t*>(GetProp(hwnd, L"CueBannerText")); 

      HFONT previousFont = SelectFont(hdc, font); 
      SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); 
      SetBkMode(hdc, TRANSPARENT); 
      DrawText(hdc, cueBannerText, int(wcslen(cueBannerText)), &editRect, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_NOCLIP); 
      SelectFont(hdc, previousFont); 

      ReleaseDC(hwnd, hdc); 

      // Return the EDIT's result (could probably safely just return zero here, 
      // but seems safer to relay whatever value came from the edit). 
      return result; 
     } 
    } 
    break; 

Дать собственный контроль EDIT (который я фактически сделал больше, чем один раз, к частичному степени завершенности по сравнению с встроенным в одном) не так много работы, если вы делаете минимум (возможно, только на английском языке только с базовой поддержкой каретки), но это большая работа, чтобы получить правильное решение, если вы хотите осторожную навигацию по сложным сценариям с кластерами с переменным размером, выбор по диапазонам, IME поддержка, контекстные меню с копией и вставкой, высокая контрастные режимы и функции доступности, такие как текст в речь. Поэтому, в отличие от многих других ответов, я рекомендую не, реализующий ваш собственный элемент управления EDIT только для текста баннерной метки.

Смежные вопросы