Перейти до основного
Підтримка
Вхід
Вхід за допомогою облікового запису Microsoft
Увійдіть або створіть обліковий запис.
Вітаємо,
Виберіть інший обліковий запис.
У вас є кілька облікових записів
Виберіть обліковий запис, за допомогою якого потрібно ввійти.

Ознаки

Смуга прокручування постійно прокручується навіть після того, як ви відпустите ліву кнопку миші. Тип смуги прокручування не відповідає цій проблемі, тобто така сама проблема виникає незалежно від того, чи смуга прокручування входить до складу вікна або – елемент керування смугою прокручування.

Причина

Ця проблема виникає, зазвичай, коли цикл витягнення повідомлень виконується в результаті дій, зроблених для прокручування під час отримання однієї з сповіщень смуги прокручування. Під час прокручування в операційній системі Windows запущена внутрішня петля пошуку повідомлень. Завдання цього циклу повідомлень – відстежувати прокручування та надсилати відповідні сповіщення смуги прокручування, WM_HSCROLL та WM_VSCROLL. Прокручування припиняється після отримання WM_LBUTTONUP. Якщо під час прокручування запускається інший цикл повідомлень, WM_LBUTTONUP буде отримано цей цикл повідомлень, і тому, що програма не має доступу до внутрішнього циклу витягнення в області прокручування, WM_LBUTTONUP не можна правильно виконати. Таким чином, WM_LBUTTONUP ніколи не приймається внутрішнім повідомленням ретрівер, і прокручування ніколи не завершується. У програмі, яка прокручуються, не потрібно отримувати повідомлення явно, щоб це викликало цю проблему. Виклик будь-якого з наведених нижче функцій і оброблення будь-якого повідомлення, яке має цикл витягнення повідомлень, під час прокручування може призвести до того, що WM_LBUTTONUP буде втрачено. Наведені нижче функції потрапляють до цієї категорії:

DialogBox() DialogBoxIndirect() DialogBoxIndirectParam() DialogBoxParam() GetMessage() MessageBox() PeekMessage()

Спосіб вирішення

Під час прокручування WM_LBUTTONUP повідомлення не повинно бути отримано з черги в будь-якому циклі пошуку повідомлень, відмінного від внутрішнього. Програма може зіштовхнутися з цією проблемою, як описано нижче.

  • Програма реалізує цикл отримання повідомлень, щоб виконувати обробку фону, наприклад обробку фону під час виконання часу.

  • Програма реалізує цикл отримання повідомлень, щоб реалізувати зв'язок з іншою програмою або DLL. Наприклад, щоб прокрутити, програма має отримувати дані з інших країн.

Можливі способи вирішення

Нижче наведено два можливі способи вирішення. Перший спосіб вирішення використовується багатьма програмами, які можна використовувати, і в ОС Windows; Однак, за рідкісним обставинами перший спосіб вирішення може бути не можливим. У цьому випадку можна використовувати другий спосіб вирішення. Однак, якщо це можливо, спробуйте повністю уникнути застосування повідомлення під час прокручування.

  • Використання таймера – обробки на основі повідомлення. Розбийте складну обробку на менші завдання та Відстежуйте розташування кожного завдання та завершується, а потім виконайте кожне завдання на основі повідомлення таймера. Коли всі компоненти обробки завершено, вбивайте таймер. Нижче наведено приклад цього способу вирішення.

  • Виконання циклу витягнення повідомлень, але переконайтеся, що WM_LBUTTONUP не отримано. Це можна зробити за допомогою фільтрів. Нижче наведено кілька прикладів цього способу вирішення.

Приклад демонстрації способу вирішення 1

У програмі є складна процедура обробки фарби. Під час прокручування вікна (), щоб прокручувати повідомлення, буде створено заливку. Обробка тла відбувається під час фарбування.

  1. Під час отримання повідомлення WM_PAINT виконайте наведені нижче дії.

    1. Викличте BeginPaint ().

    2. Скопіюйте недійсним Rect до глобальної змінної Rect (наприклад, grcPaint), який використовуватиметься на кроці 2. Глобальний відповідний grcPaint буде Союз раніше отриманого Rect (grcPaint) і нового недійсним Rect (PS. Röpaint). Код для цього матиме такий вигляд:

               RECT grcPaint;    // Should be initialized before getting the                           // first paint message.            :            :         UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. Викличте Валідерта () із PS. Rtpaint.

    4. Викличте EndPaint ().

    5. Установлення таймера.

    Таким чином, більше не WM_PAINT повідомлень створюються, тому що немає недійсних регіонів і настроєно таймер, який створить WM_TIMER повідомлення.

  2. Під час отримання повідомлення WM_TIMER перевірте, чи Глобальна змінна Rect; Якщо вона не пуста, зробіть розділ і фарбуйте його. Потім налаштуйте глобальний змінну Rect, щоб вона більше не була в області з розписом.

  3. Після того як глобальна змінна Rect пуста, потім натисніть кнопку "таймер".

Приклад демонстрації способу вирішення 2

Програма має отримати деякі дані через DDE або інший механізм з іншої програми, що відображається у вікні. Щоб прокрутити програму, потрібно надіслати запит, а потім отримати дані з серверного застосунку. Існує три різні фільтри, які можна використовувати, щоб налаштувати повідомлення PeekMessage () і отримати інформацію. Фільтри можна налаштувати за допомогою параметрів Ufillefirst і Ufilklast (). uFilterFirst визначає кулаком-повідомлення в діапазоні, який потрібно перевірити, і Ufilterfirst визначає останнє повідомлення в діапазоні, який потрібно перевірити.

  1. Установіть та витягуємо лише пов'язані повідомлення, щоб отримати необхідні дані.

  2. Перевіряти наявність WM_LBUTTONUP, не видаляючи її форму; Якщо вона знаходиться в черзі, перервіть. В іншому випадку, отримання та розсилання всіх повідомлень.

  3. Отримувати всі повідомлення, менші за WM_LBUTTONUP і більше WM_LBUTTONUP, але не отримують WM_LBUTTONUP.

Додаткові відомості

Відтворення проблеми

Нижче наведено послідовність подій, які призводять до втрати WM_LBUTTONUP повідомлення.

  1. Клацніть смугу прокручування за допомогою миші.

  2. Крок 1 створює WM_NCLBUTTONDOWN повідомлення.

  3. Крок 2 спричиняє початок роботи з циклом внутрішнього повідомлення Windows. Цей цикл повідомлень шукає повідомлення, пов'язані зі прокручування. Мета цього циклу повідомлень – створити відповідні WM_HSCROLL або WM_VSCROLL повідомлення. Цикл повідомлення та прокручування завершується після отримання WM_LBUTTONUP.

  4. Коли ви отримуєте повідомлення WM_HSCROLL або WM_VSCROLL, програма отримує повідомлення або виконує функції, які призводять до вилучення повідомлень.

  5. WM_LBUTTONUP буде видалено з черги в циклі повідомлення, згаданому на кроці 4. WM_LBUTTONUP потім буде направлена.

  6. У результаті кроку 5 WM_LBUTTONUP повідомлення надсилається в іншому місці та у внутрішньому циклі витягнення повідомлень, згаданим на кроці 3, ніколи не отримує її. Цикл повідомлення на кроці 3 шукає WM_LBUTTONUP, щоб зупинити прокручування. Оскільки вона не отримана, смуга прокручування продовжує прокручування.

Потрібна додаткова довідка?

Потрібні додаткові параметри?

Ознайомтеся з перевагами передплати, перегляньте навчальні курси, дізнайтесь, як захистити свій пристрій тощо.

Спільноти допомагають ставити запитання й відповідати на них, надавати відгуки та дізнаватися думки висококваліфікованих експертів.

Чи ця інформація була корисною?

Наскільки ви задоволені якістю мови?
Що вплинуло на ваші враження?
Натиснувши кнопку "Надіслати", ви надасте свій відгук для покращення продуктів і служб Microsoft. Ваш ІТ-адміністратор зможе збирати ці дані. Декларація про конфіденційність.

Дякуємо за відгук!

×