Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WM_VSCROLL / WM_HSCROLL message from TrackBar is not sent to the subclassed MessageHandler. Why?

Tags:

c++

c

winapi

I have a crazy issue. I subclassed buttons, richedits, checkboxes,.. and all seems working fine. But after I subclassed a trackbar I’m having some trouble now. The problem is that my subclassed messagehandler don’t receive the WM_VSCROLL / WM_HSCROLL messages. They are still sent to the parent's messagehandler. WM_PAINT message and some others are successfully sent to the subclassed messagehanlder. Someone knows what I’m doing wrong? …And maybe knows how to solve this problem? I created a clean project with the following needed code:

#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);
}
like image 874
Bluefire Avatar asked Sep 14 '25 20:09

Bluefire


1 Answers

From 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.

The Trackbar's contract is to notify the parent window with WM_HSCROLL/WM_VSCROLL. The Trackbar control generates and sends those messages; it does not receive them.

Also note that the Default Trackbar Message Processing section does not list WM_HSCROLL/WM_VSCROLL (but does list WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP, WM_KEYDOWN, WM_KEYUP, which are the raw messages it would need to handle to handle interaction).

As for what to do about it, it probably depends on exactly what you want to do. You could try subclassing and intercepting all of the user input messages, but that seems like a lot of work and is potentially brittle. My recommendation would be to have the parent window explicitly reflect WM_HSCROLL/WM_VSCROLL back to your custom Trackbar control.

like image 157
jamesdlin Avatar answered Sep 17 '25 10:09

jamesdlin