Плъзгачът продължава да превърта, след като отпуснете бутона на мишката.


Симптоми


Плъзгачът непрекъснато превърта, дори след като сте отпуснали левия бутон на мишката. Типът на плъзгача не е релевантен за този проблем, което е, че един и същ проблем възниква независимо дали плъзгачът е част от прозореца или е контрола на плъзгач.

Причина


Този проблем възниква обикновено при изпълнение на циклично извличане на съобщения като резултат от действия, предприети за превъртане при получаване на един от съобщенията за уведомяване на плъзгача. При превъртане се стартира циклично вътрешно съобщение в Windows. Целта на това съобщение е да следите превъртането и да изпратите подходящите съобщения за известяване на плъзгача, WM_HSCROLL и WM_VSCROLL. Превъртането се прекратява, след като WM_LBUTTONUP бъде получено. Ако по време на превъртане се стартира друга линия за съобщения, WM_LBUTTONUP ще бъде извлечено от това съобщение и тъй като приложението няма достъп до контура за извличане на вътрешни съобщения на плъзгача, WM_LBUTTONUP не може да се изпрати правилно. Следователно WM_LBUTTONUP никога не се получава от вътрешния Ретривър на съобщения, а превъртането никога не свършва. Приложението, което е превъртане, не трябва да извлича съобщения изрично, за да предизвика този проблем. Извиквате някои от следните функции или обработвате всяко съобщение, което има циклично извличане на съобщения, докато превъртате, може да доведе до загубване на WM_LBUTTONUP. Функциите, изброени по-долу, попадат в тази категория:
DialogBox() DialogBoxIndirect() DialogBoxIndirectParam() DialogBoxParam() GetMessage() MessageBox() PeekMessage()

Решение


Докато превъртате, WM_LBUTTONUP съобщение не трябва да се извлича от опашката чрез произволна линия за извличане на съобщения, различна от тази на плъзгача. Приложението може да се натъкне на този проблем по следния начин:
  • Приложение реализира циклично извличане на съобщение за реализиране на обработка на заден фон, като например обработка на фона, когато се изпълнява Paint за много време.
  • Приложението реализира циклично съобщение, за да осъществи комуникацията с друго приложение или DLL. Например, за да превъртите, приложението трябва да получава данни от друго място.

Възможни заобиколни решения

По-долу са описани два възможни заобиколни решения. Първото заобиколно решение се използва от много приложения за излизане и от Windows; в редки случаи обаче първото заобиколно решение може да не е възможно. В този случай може да се използва второто заобиколно решение. Въпреки това, ако е възможно, опитайте се да избегнете пълното прилагане на изтеглянето на съобщения, докато превъртате.
  • Използвайте таймер – базирано на съобщения обработка. Прекъснете сложната обработка на по-малки задачи и следете къде започва и свършва всяка задача, след което изпълнете всяка задача на базата на съобщение за таймер. Когато всички компоненти на обработката са изпълнени, Убийте таймера. Вижте по-долу пример за това заобиколно решение.
  • Реализиране на циклично извличане на съобщения, но се уверете, че WM_LBUTTONUP не е извлечено от нея. Това може да бъде постигнато с помощта на филтри. Вижте по-долу за някои примери на това заобиколно решение.

Пример, показващ Решение 1

Приложението има сложна процедура за боядисване. Извикване на ScrollWindow (), за да превъртате, генерира съобщения за Paint. Обработката на фона се извършва при боядисване.
  1. Когато получите WM_PAINT съобщение, направете следното:
    1. Обадете се на BeginPaint ().
    2. Копирайте невалидното правилното към глобално правилното променлива (например grcPaint), която трябва да се използва в стъпка 2. Глобалната правилното grcPaint ще бъде съюз на предварително получените правилното (grcPaint) и нови невалидни правилното (PS. rcPaint). Кодът за това ще наподобява на следното:
               RECT grcPaint;    // Should be initialized before getting the                           // first paint message.            :            :         UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. Обадете се на ValidateRect () с PS. rcPaint.
    4. Обадете се на EndPaint ().
    5. Задайте таймер.
    По този начин не се генерират повече WM_PAINT съобщения, тъй като няма невалидни региони и е настроен таймер, който ще генерира WM_TIMER съобщения.
  2. При получаване на WM_TIMER съобщение Проверете глобалната променлива на правилното; Ако не е празно, вземете секция и я нарисувайте. След това настройте глобалната променлива на правилното, така че повече да не включва боядисаната област.
  3. След като глобалната променлива на правилното е празна, тогава Убий таймера.

Пример, показващ решение 2

Приложението трябва да получи някои данни чрез DDE или друг механизъм от друго приложение, което се показва в прозореца. За да превъртате, приложението трябва да поиска и след това да получи данните от сървърното приложение. Има три различни филтъра, които могат да се използват за настройване на PeekMessage () и получаване на информация. Филтрите могат да бъдат настроени с помощта на uFilterFirst и uFilterLast параметри на PeekMessage (). uFilterFirst указва първото съобщение в диапазона за проверка и uFilterLast указва последното съобщение в диапазона за проверка.
  1. Проверявайте и извличайте само свързаните съобщения, за да получите нужните данни.
  2. Проверете за WM_LBUTTONUP, без да го премахвате от опашката; Ако е на опашката, Прекъсни. В противен случай извличайте и изпращайте всички съобщения.
  3. Извлечете всички съобщения, по-малки от WM_LBUTTONUP и по-големи от WM_LBUTTONUP, но не извличайте WM_LBUTTONUP.

Повече информация


Стъпки, за да възпроизведете проблема

Следва последователността от събития, които водят до загубване на WM_LBUTTONUP съобщение:
  1. Щракнете върху лентата за превъртане с помощта на мишката.
  2. Стъпка 1 генерира съобщение за WM_NCLBUTTONDOWN.
  3. Стъпка 2 кара да се стартира вътрешно съобщение в Windows. Тази линия за съобщения търси съобщения, свързани със SCROLL Bar. Целта на това съобщение е да генерира подходящи 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, за да спрете превъртането. Тъй като не е получено, плъзгачът продължава да превърта.