2013-11-28 66 views
4

如果您看一下Visual Studio 2012,您會注意到,如果您使用鼠標滾輪,鼠標下的窗口將滾動,而不是焦點窗口。也就是說,如果您將光標放在代碼編輯器中,並將鼠標移至解決方案資源管理器窗口並滾動,則解決方案資源管理器將滾動,而不是代碼編輯器。但是WM_MOUSEWHEEL消息只會被髮送到焦點窗口,所以在這種情況下是代碼編輯器。我們如何實現我們的程序,使WM_MOUSEWHEEL消息在鼠標下滾動窗口,這是直觀的,而不是聚焦的窗口?在鼠標下滾動窗口

回答

6

顯然我們可以在程序的核心處理這個問題。看看你的代碼的消息循環,這應該是在你的WinMain方法:

while (GetMessage (&msg, NULL, 0, 0) > 0) 
{ 
    TranslateMessage (&msg); 
    DispatchMessage (&msg); 
} 

在這裏,我們只需要說的是,如果消息是WM_MOUSEWHEEL消息,我們希望它在傳遞給窗口鼠標,而不是焦點窗口:

POINT mouse; 

while (GetMessage (&msg, NULL, 0, 0) > 0) 
{ 
    //Any other message. 
    if (msg.message != WM_MOUSEWHEEL) 
    { 
     TranslateMessage (&msg); 
     DispatchMessage (&msg); 
    } 
    //Send the message to the window over which the mouse is hovering. 
    else 
    { 
     GetCursorPos (&mouse); 
     msg.hwnd = WindowFromPoint (mouse); 
     TranslateMessage (&msg); 
     DispatchMessage (&msg); 
    } 
} 

而現在,你的鼠標下的窗口總是會得到滾動的消息,而不是聚焦窗口。

+0

這是一個很好的想法,但不幸的是,'WM_MOUSEWHEEL'被直接發送到帶有焦點的窗口,所以它不會出現在'GetMessage'循環中。 –

+0

嗯,它似乎雖然工作。如果消息由SendMessage,SendMessageCallback,SendMessageTimeout或SendNotifyMessage(MSDN)發佈,我認爲GetMessage只會將消息直接發送到Windows,併爲TranslateMessage和DispatchMessage檢索所有其他消息,WM_MOUSEWHEEL就是其中之一。 – GILGAMESH

+0

這很好地模擬了Windows 10中鼠標滾輪的新默認行爲。 – krlmlr

2

在應接收消息的父窗口和子窗口中處理WM_MOUSEWHEEL消息。

做這樣的事情在你的WM_MOUSEWHEEL處理程序的子窗口:

POINT mouse; 
    GetCursorPos(&mouse); 
    if (WindowFromPoint(mouse) != windowHandle) 
    { 
     // Sends the WM_MOUSEWHEEL message to your parent window 
     return DefWindowProc(windowHandle, message, wParam, lParam); 
    } 

然後在WM_MOUSEWHEEL處理程序的父窗口,你這樣做:

POINT mouse; 

    GetCursorPos(&mouse); 
    HWND hwnd = WindowFromPoint(mouse); 

    SendMessage(hwnd, message, wParam, lParam); 

這樣,如果子窗口有焦點,實際上鼠標指針懸停在其上的其他窗口將收到WM_MOUSEWHEEL消息。

+0

如果您沒有自己的消息泵(即,如果使用DialogBoxParam),則此解決方案要容易得多。 –

+0

@DavidGausmann:這很難。你將不得不繼承每個子控件以使其工作。你錯過了一個,它以非常微妙的方式突破。並不是說你有很多選擇,但肯定不是那麼容易。 – IInspectable

2

我發現在應用程序類中重寫PreTranslateMessage函數要簡單得多。

BOOL MyApp::PreTranslateMessage(MSG* pMsg) 
{ 
    POINT mouse; 
    CWnd* windowUnderMouse; 

    if (pMsg->message == WM_MOUSEWHEEL) 
    { 
     GetCursorPos(&mouse);  
     pMsg->hwnd = WindowFromPoint(mouse); 
    } 

    return CWinApp::PreTranslateMessage(pMsg); 
} 

希望它能幫助別人。

+0

感謝您發佈此解決方案 - 正如您所說,這比以前發佈的解決方案簡單得多。 – PIntag