Исчерпывающее руководство по написанию всплывающих подсказок - [10]
> DWORD dwStyle = GetStyle();
> int nStatus = GetItemRect(nIndex, lpRect);
> if (nStatus != LB_ERR && !(dwStyle & LBS_OWNERDRAWFIXED) && !(dwStyle & LBS_OWNERDRAWVARIABLE)) {
> CString strItem;
> GetText(nIndex, strItem);
> if (!strItem.IsEmpty()) {
> // Вычислить длину идеального текста.
> CClientDC DC(this);
> CFont* pOldFont = DC.SelectObject(GetFont());
> CSize ItemSize = DC.GetTextExtent(strItem);
> DC.SelectObject(pOldFont);
> // Взять максимум от обычной ширины и идеальной ширины.
> const int cxEdgeSpace = 2;
> lpRect->right = max(lpRect->right, lpRect->left + ItemSize.cx + (cxEdgeSpace * 2));
> }
> } else {
> TRACE("Owner-draw listbox detected – override CTitleTipListBox::GetIdeaItemRect()\n");
> }
> return nStatus;
>}
>void CTitleTipListBox::AdjustTitleTip(int nNewIndex) {
> if (!::IsWindow(m_TitleTip.m_hWnd)) {
> VERIFY(m_TitleTip.Create(this));
> }
> if (nNewIndex == m_nNoIndex) {
> m_TitleTip.Hide();
> } else {
> CRect IdealItemRect;
> GetIdealItemRect(nNewIndex, IdealItemRect);
> CRect ItemRect;
> GetItemRect(nNewIndex, ItemRect);
> if (ItemRect == IdealItemRect) {
> m_TitleTip.Hide();
> } else {
> // Поправить координаты рядом с краем экрана.
> ClientToScreen(IdealItemRect);
> int nScreenWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);
> if (IdealItemRect.right > nScreenWidth) {
> IdealItemRect.OffsetRect(nScreenWidth – IdealItemRect.right, 0);
> }
> if (IdealItemRect.left < 0) {
> IdealItemRect.OffsetRect(-IdealItemRect.left, 0);
> }
> m_TitleTip.Show(IdealItemRect, nNewIndex);
> }
> }
> if (m_TitleTip.IsWindowVisible()) {
> // Удостовериться, что мышь захвачена, чтобы отследить
> // момент отключения подсказки.
> if (!m_bMouseCaptured && GetCapture() != this) {
> CaptureMouse();
> }
> } else {
> // Подсказка невидима, поэтому освободить мышь.
> if (m_bMouseCaptured) {
> VERIFY(ReleaseCapture());
> m_bMouseCaptured = FALSE;
> }
> }
>}
>void CTitleTipListBox::CaptureMouse() {
> ASSERT(!m_bMouseCaptured);
> CPoint Point;
> VERIFY(GetCursorPos(&Point));
> ScreenToClient(&Point);
> m_LastMouseMovePoint = Point;
> SetCapture();
> m_bMouseCaptured = TRUE;
>}
>/////////////////////////////////////////////////////////////////////////////
>// CTitleTipListBox message handlers
>LONG CTitleTipListBox::OnContentChanged(UINT, LONG) {
> // Turn off title tip.
> AdjustTitleTip(m_nNoIndex);
> return Default();
>}
>void CTitleTipListBox::OnMouseMove(UINT nFlags, CPoint point) {
> if (point != m_LastMouseMovePoint && IsAppActive()) {
> m_LastMouseMovePoint = point;
> int nIndexHit = m_nNoIndex;
> CRect ClientRect;
> GetClientRect(ClientRect);
> if (ClientRect.PtInRect(point)) {
> // Hit test.
> for (int n = 0; nIndexHit == m_nNoIndex && n < GetCount(); n++) {
> CRect ItemRect;
> GetItemRect(n, ItemRect);
> if (ItemRect.PtInRect(point)) {
> nIndexHit = n;
> }
> }
> }
> AdjustTitleTip(nIndexHit);
> }
> CListBox::OnMouseMove(nFlags, point);
>}
>void CTitleTipListBox::OnSelchange() {
> int nSelIndex;
> if (GetStyle() & LBS_MULTIPLESEL) {
> nSelIndex = GetCaretIndex();
> } else {
> nSelIndex = GetCurSel();
> }
> AdjustTitleTip(nSelIndex);
> m_TitleTip.InvalidateRect(NULL);
> m_TitleTip.UpdateWindow();
>}
>void CTitleTipListBox::OnKillFocus(CWnd* pNewWnd) {
> CListBox::OnKillFocus(pNewWnd);
> if (pNewWnd != &m_TitleTip) {
> AdjustTitleTip(m_nNoIndex);
> }
>}
>void CTitleTipListBox::OnDestroy() {
> AdjustTitleTip(m_nNoIndex);
> m_TitleTip.DestroyWindow();
> CListBox::OnDestroy();
>}
>void CTitleTipListBox::OnLButtonDown(UINT nFlags, CPoint point) {
> // Временно отключить захват мыши, так как базовый класс может
> // захватить мышь.
> if (m_bMouseCaptured) {
> ReleaseCapture();
> m_bMouseCaptured = FALSE;
> }
> CListBox::OnLButtonDown(nFlags, point);
> if (m_TitleTip.IsWindowVisible()) {
> m_TitleTip.InvalidateRect(NULL);
> if (this != GetCapture()) {
> CaptureMouse();
> }
> }
>}
>void CTitleTipListBox::OnLButtonUp(UINT nFlags, CPoint point) {
> CListBox::OnLButtonUp(nFlags, point);
> if (this != GetCapture() && m_TitleTip.IsWindowVisible()) {
> CaptureMouse();
> }
>}
>BOOL CTitleTipListBox::PreTranslateMessage(MSG* pMsg) {
> switch (pMsg->message) {
> case WM_RBUTTONDOWN:
> case WM_RBUTTONUP:
> case WM_LBUTTONDBLCLK:
> case WM_RBUTTONDBLCLK:
> // Активизировать окно представления, потому что такое
> // поведение подразумевается по сообщению WM_MOUSEACTIVATE,
> // когда над окном нет никаких подсказок.
> AdjustTitleTip(m_nNoIndex);
> CFrameWnd* pFrameWnd = GetParentFrame();
> if (pFrameWnd) {
> BOOL bDone = FALSE;
> CWnd* pWnd = this;
> while (!bDone) {
> pWnd = pWnd->GetParent();
> if (!pWnd || pWnd == pFrameWnd) {
> bDone = TRUE;
> }
> else if (pWnd->IsKindOf(RUNTIME_CLASS(CView))) {
> pFrameWnd->SetActiveView((CView*)pWnd);
> bDone = TRUE;
> }
> }
> }
> break;
> }
> return CListBox::PreTranslateMessage(pMsg);
>}
Функция CTitleTipListBox::GetIdealItemRect вычисляет размер и координаты идеальной строки списка. Параметр nIndex – это индекс нужной строки. Параметр lpRect используется для того, чтобы вернуть идеальный размер и координаты в клиентской системе координат. Вы должны переопределить этот метод для элемента "список" с пользовательской отрисовкой, и далее я покажу, как с этим справляется CODListBox. Если не переопределить этот метод для элемента "список" с пользовательской отрисовкой, то метод CTitleTipListBox::GetIdealItemRect выдаст TRACE-сообщение об ошибке. Однако для обычных элементов "список" этот метод автоматически вычисляет размер и координаты идеальной строки списка. Сначала он вызывает функцию CListBox::GetItemRect для вычисления высоты и ширины строки. Ширина строки, возвращенная CListBox::GetItemRect является шириной самого элемента "список", а не шириной текста. Чтобы вычислить настоящую ширину текста подсказки, я получаю текст и шрифт для строки и вызываю CDC::GetTextExtent. Затем в lpRect подставляется максимум от ширины строки и вычисленной ширины строки (плюс немного места по краям из эстетических соображений).
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.