증상

마우스 왼쪽 단추를 놓은 후에도 스크롤 막대는 계속 스크롤됩니다. 스크롤 막대의 유형은이 문제와 관련이 없으며, 스크롤 막대가 창의 일부 인지 스크롤 막대 컨트롤에 관계 없이 같은 문제가 발생 합니다.

원인

이 문제는 스크롤 막대 알림 메시지 중 하나를 받을 때 스크롤에 수행 된 작업의 결과로 인해 메시지 검색 루프가 실행 되는 경우 일반적으로 발생 합니다. 스크롤할 때 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을 보여 주는 예제

응용 프로그램에는 복잡 한 그리기 프로시저가 있습니다. ScrollWindow ()를 호출 하 여 스크롤하려면 paint 메시지를 생성 합니다. 백그라운드 처리는 그리기 중에 발생 합니다.

  1. WM_PAINT 메시지가 나타나면 다음을 수행 합니다.

    1. BeginPaint ()로 전화를 겁니다.

    2. 무효화 된 rect를 2 단계에서 사용 되는 전역 rect 변수 (예: grcPaint)에 복사 합니다. 전역 rect grcPaint는 이전에 가져온 rect (grcPaint) 및 새로운 무효화 된 rect (.ps Paint)의 합집합입니다. 이 작업을 수행 하는 코드는 다음과 유사 합니다.

               RECT grcPaint;    // Should be initialized before getting the                           // first paint message.            :            :         UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. .Ps 그림판을 사용 하 여 ValidateRect ()를 호출 합니다.

    4. EndPaint ()로 전화를 겁니다.

    5. 타이머를 설정 합니다.

    이렇게 하면 잘못 된 영역이 없고 타이머가 설정 되어 WM_TIMER 메시지가 생성 되므로이 방법으로 WM_PAINT 메시지가 더 이상 생성 되지 않습니다.

  2. WM_TIMER 메시지가 수신 되 면 전역 rect 변수를 확인 합니다. 비어 있지 않으면 섹션을 가져와 그립니다. 그런 다음 해당 전역 rect 변수를 조정 하 여 그려지는 영역을 더 이상 포함 하지 않도록 합니다.

  3. 전역 rect 변수가 비어 있으면 타이머를 중단 합니다.

해결 방법 2를 보여 주는 예제

응용 프로그램은 다른 응용 프로그램에서 DDE 또는 다른 메커니즘을 통해 일부 데이터를 가져와야 하며, 그 다음 창에 표시 됩니다. 스크롤을 위해 응용 프로그램에서 서버 응용 프로그램을 요청한 다음 데이터를 가져와야 합니다. PeekMessage ()를 설정 하 고 정보를 가져오는 데 사용할 수 있는 세 가지 다른 필터가 있습니다. PeekMessage ()의 uFilterFirst 및 Ufilterfirst 매개 변수를 사용 하 여 필터를 설정할 수 있습니다. 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. WM_LBUTTONUP 5 단계의 결과로 메시지가 다른 곳에서 발송 되 고 3 단계에서 언급 한 내부 메시지 검색 루프는이를 받지 않습니다. 3 단계의 메시지 루프는 스크롤을 중지할 WM_LBUTTONUP을 찾습니다. 이 (가) 수신 되지 않으므로 스크롤 막대가 계속 스크롤을 수행 합니다.

도움이 더 필요하세요?

더 많은 옵션을 원하세요?

구독 혜택을 살펴보고, 교육 과정을 찾아보고, 디바이스를 보호하는 방법 등을 알아봅니다.

커뮤니티를 통해 질문하고 답변하고, 피드백을 제공하고, 풍부한 지식을 갖춘 전문가의 의견을 들을 수 있습니다.