WM_VSCROLL / WM_HSCROLL 来自 TrackBar 的消息未发送到子类 MessageHandler。为什么?
WM_VSCROLL / WM_HSCROLL message from TrackBar is not sent to the subclassed MessageHandler. Why?
我有一个疯狂的问题。我对按钮、richedits、复选框进行了子类化,.. 一切似乎都工作正常。但是在我对 trackbar 进行子类化之后,我现在遇到了一些麻烦。问题是我的子类消息处理程序没有收到 WM_VSCROLL / WM_HSCROLL 消息。它们仍然被发送到父级的消息处理程序。 WM_PAINT 消息和其他一些消息已成功发送到子类消息处理程序。
有人知道我做错了什么吗? ......也许知道如何解决这个问题?我使用以下所需代码创建了一个干净的项目:
#include <windows.h>
#include <CommCtrl.h>
#pragma comment(lib,"comctl32.lib")
//Prototyps
HWND CreateMainWindow(HINSTANCE hInstance);
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK SubMessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
WNDPROC oldWndProc;
HWND hWnd = 0;
HWND hTrackBar = 0;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
WNDCLASSEXA wndClass = {sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, MessageHandler, 0,0, hInstance, LoadIcon(NULL, IDI_WINLOGO),
LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, "WindowClass", LoadIcon(NULL, IDI_WINLOGO)};
RegisterClassExA(&wndClass);
//Creat MainWindow
hWnd = CreateWindowExA(NULL, "WindowClass", "Test Windows", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
100, 100, 400, 300, NULL, NULL, hInstance, NULL);
//Creat Trackbar
INITCOMMONCONTROLSEX initCtrlEx;
initCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
initCtrlEx.dwICC = ICC_BAR_CLASSES;
if (InitCommonControlsEx(&initCtrlEx)){
hTrackBar = CreateWindowExA(NULL,TRACKBAR_CLASSA, "TrackBar_Test", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | TBS_AUTOTICKS |
TBS_ENABLESELRANGE | TBS_VERT | TBS_BOTH, 10, 10, 50, 200, hWnd, NULL, hInstance, NULL);
oldWndProc = (WNDPROC)SetWindowLongPtrA(hTrackBar, GWLP_WNDPROC, (LONG_PTR)SubMessageHandler); //Subclassing messagehandler
}
//Message loop
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return 0;
}
LRESULT CALLBACK SubMessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_VSCROLL: //callback is subclassed but WM_VSCROLL is not send. why?
MessageBoxA(hWnd, "WM_VSCROLL sent (to SubMessageHandler)", "Test", MB_OK);
break;
}
if (oldWndProc != 0)
return CallWindowProcA(oldWndProc, hwnd, msg, wParam, lParam);
else
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_VSCROLL: //Why the hell is the Trackbar WM_VSCROLL still sent here to the parent callback!?!?
MessageBoxA(hWnd, "WM_VSCROLL sent (to Parent)", "Test", MB_OK);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
来自 the MSDN documentation on Trackbar controls:
A trackbar notifies its parent window of user actions by sending the
parent a WM_HSCROLL or WM_VSCROLL message.
Trackbar 的合同是用 WM_HSCROLL
/WM_VSCROLL
通知父级 window。 Trackbar 控件生成并发送 这些消息;它不接收它们。
另请注意,Default Trackbar Message Processing section 未列出 WM_HSCROLL
/WM_VSCROLL
(但列出了 WM_LBUTTONDOWN
、WM_MOUSEMOVE
、WM_LBUTTONUP
、 WM_KEYDOWN
、WM_KEYUP
,这是处理交互所需处理的原始消息)。
至于怎么办,这可能完全取决于你想做什么。您可以尝试子类化并拦截所有用户输入消息,但这似乎需要大量工作并且可能很脆弱。我的建议是让父级 window 明确反映 WM_HSCROLL
/WM_VSCROLL
回到您的自定义 Trackbar 控件。
我有一个疯狂的问题。我对按钮、richedits、复选框进行了子类化,.. 一切似乎都工作正常。但是在我对 trackbar 进行子类化之后,我现在遇到了一些麻烦。问题是我的子类消息处理程序没有收到 WM_VSCROLL / WM_HSCROLL 消息。它们仍然被发送到父级的消息处理程序。 WM_PAINT 消息和其他一些消息已成功发送到子类消息处理程序。 有人知道我做错了什么吗? ......也许知道如何解决这个问题?我使用以下所需代码创建了一个干净的项目:
#include <windows.h>
#include <CommCtrl.h>
#pragma comment(lib,"comctl32.lib")
//Prototyps
HWND CreateMainWindow(HINSTANCE hInstance);
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
LRESULT CALLBACK SubMessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
WNDPROC oldWndProc;
HWND hWnd = 0;
HWND hTrackBar = 0;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
WNDCLASSEXA wndClass = {sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, MessageHandler, 0,0, hInstance, LoadIcon(NULL, IDI_WINLOGO),
LoadCursor(NULL, IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, "WindowClass", LoadIcon(NULL, IDI_WINLOGO)};
RegisterClassExA(&wndClass);
//Creat MainWindow
hWnd = CreateWindowExA(NULL, "WindowClass", "Test Windows", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
100, 100, 400, 300, NULL, NULL, hInstance, NULL);
//Creat Trackbar
INITCOMMONCONTROLSEX initCtrlEx;
initCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
initCtrlEx.dwICC = ICC_BAR_CLASSES;
if (InitCommonControlsEx(&initCtrlEx)){
hTrackBar = CreateWindowExA(NULL,TRACKBAR_CLASSA, "TrackBar_Test", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | TBS_AUTOTICKS |
TBS_ENABLESELRANGE | TBS_VERT | TBS_BOTH, 10, 10, 50, 200, hWnd, NULL, hInstance, NULL);
oldWndProc = (WNDPROC)SetWindowLongPtrA(hTrackBar, GWLP_WNDPROC, (LONG_PTR)SubMessageHandler); //Subclassing messagehandler
}
//Message loop
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return 0;
}
LRESULT CALLBACK SubMessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_VSCROLL: //callback is subclassed but WM_VSCROLL is not send. why?
MessageBoxA(hWnd, "WM_VSCROLL sent (to SubMessageHandler)", "Test", MB_OK);
break;
}
if (oldWndProc != 0)
return CallWindowProcA(oldWndProc, hwnd, msg, wParam, lParam);
else
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_VSCROLL: //Why the hell is the Trackbar WM_VSCROLL still sent here to the parent callback!?!?
MessageBoxA(hWnd, "WM_VSCROLL sent (to Parent)", "Test", MB_OK);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
来自 the MSDN documentation on Trackbar controls:
A trackbar notifies its parent window of user actions by sending the parent a WM_HSCROLL or WM_VSCROLL message.
Trackbar 的合同是用 WM_HSCROLL
/WM_VSCROLL
通知父级 window。 Trackbar 控件生成并发送 这些消息;它不接收它们。
另请注意,Default Trackbar Message Processing section 未列出 WM_HSCROLL
/WM_VSCROLL
(但列出了 WM_LBUTTONDOWN
、WM_MOUSEMOVE
、WM_LBUTTONUP
、 WM_KEYDOWN
、WM_KEYUP
,这是处理交互所需处理的原始消息)。
至于怎么办,这可能完全取决于你想做什么。您可以尝试子类化并拦截所有用户输入消息,但这似乎需要大量工作并且可能很脆弱。我的建议是让父级 window 明确反映 WM_HSCROLL
/WM_VSCROLL
回到您的自定义 Trackbar 控件。