簡體   English   中英

來自TrackBar的WM_VSCROLL / WM_HSCROLL消息不會發送到子類MessageHandler。 為什么?

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

我有一個瘋狂的問題。 我將按鈕,richedits,復選框等子類化,並且一切似乎都正常。 但是在我將一個軌道欄子類化后,我現在遇到了一些麻煩。 問題是我的子類消息處理程序沒有收到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);
}

Trackbar控件上的MSDN文檔

跟蹤欄通過向父組件發送WM_HSCROLL或WM_VSCROLL消息來通知其父窗口用戶操作。

Trackbar的合同是通過WM_HSCROLL / WM_VSCROLL通知父窗口。 Trackbar控件生成並發送這些消息; 它沒有收到它們。

另請注意, 默認軌道欄消息處理部分未列出WM_HSCROLL / WM_VSCROLL (但列出了WM_LBUTTONDOWNWM_MOUSEMOVEWM_LBUTTONUPWM_KEYDOWNWM_KEYUP ,它們是處理交互所需處理的原始消息)。

至於該怎么做,它可能取決於你想要做什么。 您可以嘗試子類化和攔截所有用戶輸入消息,但這似乎很多工作並且可能很脆弱。 我的建議是讓父窗口明確地將WM_HSCROLL / WM_VSCROLL反映回您的自定義Trackbar控件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM