Příznaky
Posuvník se nepřetržitě posouvá i po uvolnění levého tlačítka myši. Typ posuvníku je pro tento problém nevýznamný, to znamená, že ke stejnému problému dochází bez ohledu na to, jestli je posuvník součástí okna nebo jde o ovládací prvek posuvníku.
Příčina
K tomuto problému dochází obvykle v případě, že se smyčka při načítání zpráv zobrazuje jako výsledek akce pro posouvání při příjmu jedné z posouvaných zpráv posuvníku. Při posouvání se ve Windows spouští vnitřní smyčka načítání zpráv. Úkolem této zprávy je sledování posouvání a odeslání příslušných zpráv s oznámením posuvníku, WM_HSCROLL a WM_VSCROLL. Po přijetí WM_LBUTTONUP se posouvání zastaví. Pokud je během posouvání zahájená jiná smyčka zpráv, WM_LBUTTONUP se načte pomocí této smyčky zpráv a protože aplikace nemá přístup k internímu cyklu načítání zpráv posuvníku, WM_LBUTTONUP nepůjde správně odeslat. Z toho důvodu není WM_LBUTTONUP nikdy přijato interní zprávou a posouvání se nikdy neukončí. V aplikaci, která slouží k posouvání, není nutné, aby byl tento problém vyřešen. Když zavoláte některou z následujících funkcí nebo zpracování jakékoli zprávy s cyklem načítání zpráv, může při posouvání dojít ke ztrátě WM_LBUTTONUP. Níže uvedené funkce spadají do této kategorie:
DialogBox() DialogBoxIndirect() DialogBoxIndirectParam() DialogBoxParam() GetMessage() MessageBox() PeekMessage()
Řešení
Při posouvání se WM_LBUTTONUP zpráva nenačítá z fronty, a to pomocí žádného dalšího opakování zpráv, než je vnitřní. Aplikace se mohou v tomto problému vysílat takto:
-
Aplikace implementuje smyčku načítání zpráv k implementaci zpracování na pozadí, například při zpracování na pozadí při provádění času, který maluje.
-
Aplikace implementuje smyčku načítání zpráv pro implementaci komunikace s jinou aplikací nebo DLL knihovnou. Aplikace například vyžaduje přijímání dat z jiného místa.
Možná alternativní řešení
Níže jsou uvedena dvě možná řešení. První alternativní řešení se používá při mnoha ukončování aplikací a v systému Windows. za výjimečných okolností však nemusí být první alternativní řešení možné. V tomto případě se dá použít druhé alternativní řešení. Pokud je to možné, můžete se ale pokusit, aby se při posouvání nedošlo k úplnému načítání zpráv.
-
Používejte zpracování založené na zprávách časovače. Rozdělte komplikované zpracování na menší úkoly a sledujte, kde každý úkol začíná a končí, a proveďte jednotlivé úkoly na základě zprávy časovače. Po dokončení všech součástí zpracování časovač ukončete. Příklad tohoto alternativního řešení najdete níže.
-
Implementujte smyčku pro načítání zpráv, ale ujistěte se, že se WM_LBUTTONUP nenačítá. Toho lze dosáhnout pomocí filtrů. Několik příkladů tohoto alternativního řešení najdete níže.
Příklad ukazující alternativní řešení 1
Aplikace má složitý postup malování. Když voláte ScrollWindow (), vygenerujete zprávy nátěr. Zpracování na pozadí probíhá během malování.
-
Když se zobrazí zpráva WM_PAINT, postupujte takto:
-
Volejte BeginPaint ().
-
Zkopírujte neověřený Rect do globální proměnné Rect (třeba grcPaint), která se použije v kroku 2. Globální Rect grcPaint by představovala sjednocení dříve získaného Rect (grcPaint) a nového invalidované Rect (PS. rcPaint). Kód pro toto bude vypadat takto:
RECT grcPaint; // Should be initialized before getting the // first paint message. : : UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
-
Volejte ValidateRect () s PS. rcPaint.
-
Volejte EndPaint ().
-
Nastavení časovače
Tímto způsobem se negenerují žádné další zprávy WM_PAINT, protože nejsou k dispozici žádné neplatné oblasti a je nastaven časovač, který generuje WM_TIMER zprávy.
-
-
Po přijetí WM_TIMER zprávě zkontrolujte globální proměnnou Rect. Pokud není prázdný, povezměte oddíl a malujte ho. Pak upravte globální proměnnou Rect tak, aby už nezahrnovala prodanou oblast.
-
Po vyprázdnění globální proměnné Rect zrušte časovač.
Příklad ukazující alternativní řešení 2
Aplikace potřebuje získat některá data prostřednictvím DDE nebo jiného mechanismu z jiné aplikace, která se pak zobrazí v okně. Abyste se mohli posunout, aplikace potřebuje žádost požádat a získat data z serverové aplikace. Existují tři různé filtry, které můžete použít k nastavení PeekMessage () a získávání informací. Filtry se dají nastavit pomocí parametrů uFilterFirst a uFilterLast PeekMessage (). uFilterFirst Určuje zprávu Fist v oblasti, kterou chcete zkontrolovat, a uFilterLast Určuje poslední zprávu v oblasti, kterou chcete zkontrolovat.
-
Zkontrolovat a načíst jenom související zprávy pro získání potřebných dat
-
Kontrola WM_LBUTTONUP bez jejího odebrání z fronty; Pokud je ve frontě, přerušit. V opačném případě načtěte a odešlete všechny zprávy.
-
Načíst všechny zprávy menší než WM_LBUTTONUP a větší než WM_LBUTTONUP, ale Nezískávat WM_LBUTTONUP
Další informace
Kroky pro reprodukci problému
Následující je posloupnost událostí vedoucích ke ztrátě WM_LBUTTONUP zprávy:
-
Klikněte na posuvník pomocí myši.
-
Krok 1 vygeneruje zprávu WM_NCLBUTTONDOWN.
-
Krok 2 způsobí spuštění interní zprávy Windows. Tato smyčka zpráv vyhledává zprávy související s posuvníky. Cílem této zprávy je vygenerovat vhodné WM_HSCROLL nebo WM_VSCROLL zprávy. Po přijetí WM_LBUTTONUP se smyčka zpráv ukončí.
-
Když obdržíte zprávu WM_HSCROLL nebo WM_VSCROLL, aplikace se přidělí na smyčku nebo volá funkce, které vedou k načtení zpráv.
-
WM_LBUTTONUP se z fronty odebere pomocí smyčky zpráv zmíněné v kroku 4. WM_LBUTTONUP se pak odešle.
-
Jako výsledek kroku 5 WM_LBUTTONUP zpráva odeslána jinde a vnitřní smyčka pro načítání zpráv zmíněná v kroku 3 ji neobdrží. Smyčka zpráv v kroku 3 hledá WM_LBUTTONUP pro zastavení posouvání. Přesunutí posuvníku pokračuje.