Triệu chứng
Đệ quy gọi chức năng quản lý cửa sổ xuất USER32. DLL có thể trả lại mà không cần thực hiện thao tác đã yêu cầu và cài đặt mã lỗi. Điều này thường xảy ra trong ứng dụng hệ thống cửa sổ lồng nhau sâu. Trong các hiện tượng bạn có thể gặp phải:
-
Ứng dụng hệ thống cửa sổ lồng nhau sâu không thể thay đổi kích thước cửa sổ con đúng cách khi cửa sổ khung được thay đổi kích thước. Windows đang di chuyển hoặc thay đổi kích thước bằng cách gọi MoveWindow, SetWindowPos hoặc DeferWindowPos.
-
Cửa sổ thông báo không được chuyển sang mẹ windows hoặc con windows như mong đợi. DefWindowProc có thể không thành công truyền thư cha cửa sổ hoặc cửa sổ con của sổ nhận được thông báo.
-
Cửa sổ thư gửi đến một cửa sổ bằng cách gọi SendMessage, SendMessageTimeout hoặc SendMessageCallback không nhận được cửa sổ được chỉ định.
Ngoài ra, ứng dụng khác hoạt động bình thường cũng có thể gặp phải hiện tượng được mô tả ở trên nếu WH_CALLWNDPROC hoặc WH_CALLWNDPROCRET móc cửa sổ được đặt trên các chủ đề trong ứng dụng của windows. Cửa sổ móc có thể được đặt trên một chủ đề cụ thể hoặc chủ đề giao diện người dùng bằng cách gọi chức năng SetWindowsHookEx.
Nguyên nhân
Hiện tượng này là do Windows không thể phát triển lõi chồng gọi chuỗi để thực hiện thao tác đã yêu cầu. Do chồng thêm lõi xử lý thủ tục cần thiết trong x64 các môi trường Windows, ngăn xếp lõi có thể được tiêu thụ tốc độ nhanh hơn trong một x86 môi trường Windows khi tạo đệ quy gọi chức năng quản lý cửa sổ xuất USER32. DLL. mặc dù các hiện tượng mô tả trong bài viết này có nhiều khả năng xảy ra trong x64 nền tảng Windows, có thể gọi đệ quy tiêu thụ một luồng hạt nhân stack trên x86 nền tảng Windows.
Giải pháp
Các giải pháp có thể được sử dụng để giải quyết vấn đề này
-
Thay đổi kích thước cửa sổ con khi xử lý WM_WINDOWPOSCHANGED cửa sổ thông báo thay vì gửi thư cho DefWindowProc.
-
Không đồng bộ thay đổi kích thước cửa sổ con khi cửa sổ chính thay đổi kích thước thay vì thay đổi kích thước cửa sổ con trong khi xử lý WM_WINDOWPOSCHANGED hoặc WM_SIZE cửa sổ thư.
-
Thiết kế ứng dụng giao diện người dùng để giảm sâu cửa sổ lồng nhau.
Thông tin Bổ sung
Phần con Win32 được thực hiện trong một trình điều khiển thiết bị ở chế độ lõi (WIN32K. SYS). Cuộc gọi chức năng xuất USER32. DLL để thay đổi trạng thái của cửa sổ, bao gồm kích thước và vị trí, sẽ gọi vào WIN32K. SYS để thực hiện thao tác đã yêu cầu. Chức năng thay đổi trạng thái của cửa sổ thông thường kết quả trong cửa sổ thư được gửi đến cửa sổ được thay đổi, trong đó WIN32K. SYS làm cho một chế độ người dùng gọi gọi thủ tục cửa sổ cửa sổ được sửa đổi. Ví dụ: WIN32K. SYS sẽ gửi một cửa sổ thư sổ WM_WINDOWPOSCHANGING và WM_WINDOWPOSCHANGED cửa sổ thư khi kích thước hoặc vị trí của cửa sổ được điều chỉnh bằng cách gọi chức năng SetWindowPos. DefWindowProc sẽ gửi cửa sổ chỉ định một WM_SIZE khi thông báo WM_WINDOWPOSCHANGED và thay đổi kích thước cửa sổ. Ứng dụng thông thường thay đổi kích thước cửa sổ con khi cửa sổ cha nhận WM_WINDOWPOSCHANGED hoặc WM_SIZE cửa sổ thư, dẫn đến gọi đệ quy vào WIN32K. SYS cho cửa sổ lồng nhau sâu phân cấp. Ứng dụng khác hoạt động bình thường cũng có thể gặp các hiện tượng được mô tả trong bài viết này khi WH_CALLWNDPROC hoặc WH_CALLWNDPROCRET móc được đặt trên các chủ đề trong quá trình. Điều này là do không gian ngăn xếp thêm lõi là tiêu thụ khi WIN32K. SYS xử lý gọi thủ tục móc. Gọi SendMessage để gửi một cửa sổ một cửa sổ của chuỗi gọi thông thường sẽ gọi thủ tục sổ sổ nhận được thông báo mà không cần phải gọi vào WIN32K. SYS. Tuy nhiên, SendMessage sẽ gọi vào WIN32K. SYS nếu có WH_CALLWNDPROC móc hoặc WH_CALLWNDPROCRET móc đặt trên các chủ đề gọi là WIN32K. SYS quản lý móc và xử lý gọi thủ tục móc. Như đã nêu ở trên, DefWindowProc sẽ gửi cửa sổ chỉ định một WM_SIZE khi thông báo WM_WINDOWPOSCHANGED và thay đổi kích thước cửa sổ. Câu WH_CALLWNDPROC hoặc một WH_CALLWNDPROCRET sẽ khiến cuộc gọi SendMessage DefWindowProc làm cho chuyển đổi chế độ lõi để gọi thủ tục móc. Thay đổi kích thước cửa sổ con khi xử lý WM_WINDOWPOSCHANGED cửa sổ thông báo thay vì WM_SIZE cửa sổ thông báo sẽ giảm lõi chồng sử dụng bằng cách loại bỏ cần SendMessage chuyển đổi chế độ lõi để gọi thủ tục móc. Nhà phát triển ứng dụng Windows Forms gặp vấn đề này nên tham khảo bài viết KB 953934để biết thêm thông tin.