На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Прокрутка скролла колесиком мыши, WinAPI, без MFC, без ресурсов
    Запускаю приложение, там моя самодельная таблица типа Grid.
    В ней есть скроллы, которые нормально работают, всё это в сабклассинге.

    Появилась следующая проблема. Когда моё приложение теряет фокус, например запустил калькулятор, а затем вернулся к таблице, то перестает работать сабклассинг, причем только обработчик прокрутки колесика мыши, обработчики кнопок скролла, и бегунок скролла работают без проблем.

    т.е WM_MOUSEWHEEL в субклассинг не приходит после потери и повторном взятии фокуса. Почему? и как исправить? Можно, конечно обрабатывать в основной процедуре, там приходит сообщение прокрутки колесика мыши, но это как-то не красиво, лишняя функция.

    Прикреплённая картинка
    Прикреплённая картинка


    Добавлено
    Основная процедура
    ExpandedWrap disabled
      LRESULT CALLBACK WndProcLink(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
      {
          HWND hparent;
          hparent = GetParent(hwnd);
          switch (message)
          {
          case WM_SIZE:
              LinkResize(hwnd);
              return 0;
          case WM_COMMAND:
              switch (LOWORD(wparam))
              {
              case 1002:
                  e::focus = 2;
                  MessageBox(hwnd, "Apply", "Message", MB_OK);
                  SetFocus(e::linkhwnd[e::focus]);
                  break;
              case 1003:
                  e::focus = 3;
                  MessageBox(hwnd, "OK", "Message", MB_OK);
                  SetFocus(e::linkhwnd[e::focus]);
                  break;
              case 1004:
                  SendMessage(hwnd, WM_CLOSE, NULL, NULL);
                  break;
              }
              return 0;
          case WM_KEYDOWN:
              switch (LOWORD(wparam))
              {
              case VK_TAB:
                  LinkFocus();
                  break;
              case VK_ESCAPE:
                  SendMessage(hwnd, WM_CLOSE, NULL, NULL);
                  break;
              }
              return 0;
          case WM_MOUSEWHEEL:
              //WndProcLinkSubclassing(hwnd, message, wparam, lparam); // <-- если это раскомментировать, то прокрутка будет работать, но неправильно, до потери фокуса - прокрутка на 2 строки, после потери и возвращения фокуса - прокрутка на 1 строку
              return 0;
          case WM_NOTIFY:
              LinkShowNotify(lparam);
              return 0;
          case WM_PAINT:
              LinkPaint(hwnd);
              return 0;
          case WM_CLOSE:
              EnableWindow(hparent, TRUE);
              SetFocus(hparent);
              BringWindowToTop(hparent);
              ShowWindow(hwnd, SW_HIDE);
              DestroyMenu(e::hpopupmenudlg);
              DestroyWindow(hwnd);
              return 0;
          }
          return DefWindowProc(hwnd, message, wparam, lparam);
      }


    Добавлено
    Сабклассинг
    ExpandedWrap disabled
      LRESULT CALLBACK WndProcLinkSubclassing(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
      {
          int i, n;
          HWND hwndfocus;
          POINT point;
          n = GetDlgCtrlID(hwnd) - 1000;
          LinkDllTableWndProc(hwnd, message, wparam, lparam, e::linkhwnd[1], e::linkgridcellubound, e::linkgridcellwidth, e::linkgridcellheight, e::linkgridstep, e::linkgridframe);
          switch (message)
          {
          case WM_COMMAND:
              switch (LOWORD(wparam))
              {
              case 2001:
                  MessageBox(hwnd, "PopupMenu 1", "Message", MB_OK);
                  break;
              case 2002:
                  MessageBox(hwnd, "PopupMenu 2", "Message", MB_OK);
                  break;
              case 2003:
                  MessageBox(hwnd, "PopupMenu 3", "Message", MB_OK);
                  break;
              case 2004:
                  MessageBox(hwnd, "PopupMenu 4", "Message", MB_OK);
                  break;
              }
              break;
          case WM_KEYDOWN:
              switch (LOWORD(wparam))
              {
              case VK_TAB:
                  LinkFocus();
                  break;
              case VK_ESCAPE:
                  SendMessage(GetParent(e::linkhwnd[0]), WM_CLOSE, NULL, NULL);
                  break;
              }
              break;
          case WM_LBUTTONUP:
              hwndfocus = GetFocus();
              for (i=0; i<e::linkhwndubound; i++)
              {
                  if (e::linkhwnd[i] == hwndfocus)
                  {
                      e::focus = i;
                  }
              }
              break;
          case WM_RBUTTONDOWN:
              if (hwnd == e::linkhwnd[1])
              {
                  point.x = LOWORD(lparam);
                  point.y = HIWORD(lparam);
                  ClientToScreen(hwnd, &point);
                  TrackPopupMenu(e::hpopupmenudlg, 0, point.x, point.y, 0, hwnd, NULL);
              }
              break;
          case WM_ERASEBKGND:
              return 0;
          }
          return CallWindowProc(e::linkwndproc[n], hwnd, message, wparam, lparam);
      }


    Добавлено
    Часть сабклассинга работа с таблицей
    ExpandedWrap disabled
      void LinkDllTableWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, HWND hwndpic, int cellubound[2], int cellwidth[50], int cellheight[1], int step[2], int frame[2])
      {
          switch (message)
          {
          case WM_KEYDOWN:
              switch (LOWORD(wparam))
              {
              case VK_HOME:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 1);
                  break;
              case VK_END:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 2);
                  break;
              case VK_PRIOR:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 5);
                  break;
              case VK_NEXT:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 6);
                  break;
              }
              break;
          case WM_HSCROLL:
              switch (LOWORD(wparam))
              {
              case SB_LINELEFT:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 3);
                  break;
              case SB_LINERIGHT:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 4);
                  break;
              case SB_THUMBPOSITION:
              case SB_THUMBTRACK:
                  LinkDllTableShiftTrack(message, wparam, hwndpic, cellubound, cellwidth, cellheight, step, frame, 0);
                  break;
              case SB_LEFT:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 1);
                  break;
              case SB_RIGHT:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 2);
                  break;
              }
              break;
          case WM_VSCROLL: // <-- это работает
              switch (LOWORD(wparam))
              {
              case SB_LINEUP:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 7);
                  break;
              case SB_LINEDOWN:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 8);
                  break;
              case SB_THUMBPOSITION:
              case SB_THUMBTRACK:
                  LinkDllTableShiftTrack(message, wparam, hwndpic, cellubound, cellwidth, cellheight, step, frame, 1);
                  break;
              case SB_TOP:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 5);
                  break;
              case SB_BOTTOM:
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 6);
                  break;
              }
              break;
          case WM_MOUSEWHEEL: // <-- а вот это после потери фокуса перестает работать, почему ???
              if (( (((POINTS*)&wparam) -> y) / WHEEL_DELTA ) > 0)
              {
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 7);
              }
              else
              {
                  LinkDllTableShift(hwndpic, cellubound, cellwidth, cellheight, step, frame, 8);
              }
              break;
          }
      }
    Сообщение отредактировано: E.A. -
      Цитата E.A. @
      Запускаю приложение, там моя самодельная таблица типа Grid.
      В ней есть скроллы, которые нормально работают, всё это в сабклассинге.

      Если это самодельный контрол, тогда исследовать
      его работу можешь только ты сам.
      ---
      я попробовал то же самое с Edit-ом - паталогии не обнаружено.
      Всё работает по документации на WM_MOUSEWHEEL.
      Если фокус на главном окне, эти сообщения приходят к нему.
      Если фокус на дочернем Edit-е, сообщения получает Edit.
      Дальше как сделаешь.
      Если вызывается оригинальная процедура контрола (из процедуры
      сабклассинга), сообщение WM_MOUSEWHEEL пересылается родительскому окну.
      ---
      Для прокручивания скролла вовсе не обязательно делать это из сабклассинговой
      процедуры. Если такие сообщения получает родительское окно, в его
      обработчике вполне естественно решать такие вопросы.
      Сообщение отредактировано: ЫукпШ -
      Подпись была выключена в связи с наложенным заземлением.
        Несколько слов о том что делаю.

        Самодельный контролл Grid по сути это окно созданное с помощью CreateWindowEx() со стилями WS_VSCROLL | WS_HSCROLL.
        Всё что там отображается я рисую. Контрол Edit должен будет отображаться только тогда, когда пользователь перейдет в режим редактирования. Edit будет только один и изначально он будет невидимым. Планирую сделать как в Excel-е выделять диапазон, а в режиме редактирования стрелками перемещаться по таблице. Но еще нужно, чтобы ячейки были разных типов (Edit, Combobox, Edit + browse).

        Сабклассинг я делаю для того, чтобы передавать фокус при нажатии Tab. Получается, в сабклассинге собираются функции, которые относятся к дочерним контролам. В данном случае дочерним явлется таблица Grid. Дальше, раз получается много писанины и этот контрол удобен и для других диалоговых окон, появляется желание "запихнуть" это дело в DLL и использовать уже там, где это нужно. Поэтому, желательно чтобы функций, которые привязываются к основной процедуре было как можно меньше. В идеале в сабклассинге должна вызывается одна DllTableWndProc(), которая будет находится в DLL.

        но уже формируется список того, что вызывается из основной процедуры:
        ExpandedWrap disabled
          void DllTableWndProc(); // нажатие кнопок и т.д.
          void DllTablePaint(); // рисование вызывается из основной процедуры из WM_PAINT
          void DllTableShift(); // пересчет позиции и размера скроллов при изменении размеров окна из основной процедуры из WM_SIZE
          void DllTableShiftTrack(); // пересчет позиции скроллов при перетаскивании за скролл // это получилось спрятать! внутри вызывается из DllTableWndProc
          void DllTableMouseWheel(); // прокрутка колесиком мыши // это не удалось спрятать внутри DllTableWndProc, значит будет вызываться из основной процедуры из WM_MOUSEWHEEL


        Добавлено
        PS ещё такой вопросик в рамках этой же темы.
        на просторах интернета я нашел два способа определения в какую сторону крутится колесико мыши.
        1.
        ExpandedWrap disabled
          zDelta = GET_WHEEL_DELTA_WPARAM(wparam)

        2.
        ExpandedWrap disabled
          zDelta = (((POINTS*)&wparam) -> y) / WHEEL_DELTA


        Первый способ у меня не работает, пишет
        error C3861: 'GET_WHEEL_DELTA_WPARAM': identifier not found, even with argument-dependent lookup

        что-то нужно подключить, я уже добавил
        #include <zmouse.h>

        А чего ещё не хватает ?

        Добавлено
        Цитата
        Если фокус на дочернем Edit-е, сообщения получает Edit.

        Да, кстати, может у меня фокус возвращается на окно диалога, а не к контролу Grid ...
        Пока у меня фокус на контроле Grid никак не отображается.
        Проверил, точно так и есть, при нажатии на Tab фокус переходит к контролу Grid и все опять работает.))
        // Нужно будет немного переделать кто первым получает фокус.

        Спасибо ЫукпШ, вопрос решен.
        Сообщение отредактировано: E.A. -
          Цитата E.A. @
          PS ещё такой вопросик в рамках этой же темы.
          на просторах интернета я нашел два способа определения в какую сторону крутится колесико мыши.
          1.
          ExpandedWrap disabled
            zDelta = GET_WHEEL_DELTA_WPARAM(wparam)

          2.
          ExpandedWrap disabled
            zDelta = (((POINTS*)&wparam) -> y) / WHEEL_DELTA

          я делал прямо по документации.
          Всё работало правильно.
          WM_MOUSEWHEEL
          Цитата

          ...
          wParam
          The high-order word indicates the distance the wheel is rotated,
          expressed in multiples or divisions of WHEEL_DELTA, which is 120.
          A positive value indicates that the wheel was rotated forward, away from the user;
          a negative value indicates that the wheel was rotated backward, toward the user.

          и в итоге у меня было как то так:
          ExpandedWrap disabled
             short int zDelta = (int) HIWORD(wParam); // wheel rotation
             short int status = (int) LOWORD(wParam);
             int points = zDelta / WHEEL_DELTA;
             bool decLN=true;
             
             if(points < 0)
             {
              points = - points;
              decLN = false;
             }
             if(status == MK_CONTROL)
             {
              if(decLN){decPageNumber();}
              else     {incPageNumber();}
             }
             else
             {
              for(int i=0;i<points;++i)
              {
               if(decLN){decLineNumber();}
               else     {incLineNumber();}
              }
             }
          Сообщение отредактировано: ЫукпШ -
          Подпись была выключена в связи с наложенным заземлением.
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script Execution time: 0,1378 ]   [ 20 queries used ]   [ Generated: 16.07.19, 08:17 GMT ]