2010-04-13 124 views
0

我正在使用自定義繪製對CSliderCtrl進行一些更改,該控件將用於對話框中。下面是結構: 在我MessageMap我:ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, OnNMCustomdraw)CustomDraw中的SetWindowLong導致未處理的異常

的OnNMCustomdraw方法如下所示:

BOOL CCustomSliderCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    *pResult = CDRF_DODEFAULT; 
    LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR); 

    switch(pNMCD->dwDrawStage) 
    { 
     case CDDS_PREPAINT: 
     { 
      //Dialogs don't receive CDRF_NOTIFYITEMDRAW notifcations by returning it as part of pResult, we must 
      //use the following so we ensure we receive the msg 
      SetWindowLong(pNMHDR->hwndFrom, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW); 
      return TRUE; 
     } 
     case CDDS_ITEMPREPAINT: 
      if(pNMCD->dwItemSpec == TBCD_CHANNEL) 
      { 
       ...SNIP... 
       SetWindowLong(pNMHDR->hwndFrom, DWL_MSGRESULT, CDRF_SKIPDEFAULT); 
       return TRUE; 
      } 
    } 
    return FALSE; 
} 

讀圍繞我瞭解到,您必須使用SetWindowLong函數來設置的返回值自定義繪製,否則你的方法不會總是收到CDDS_ITEMPREPAINT消息。但是,使用SetWindowLong時,我的應用程序永遠不會收到CDDS_ITEMPREPAINT,所以我的滑塊看起來就像一個標準滑塊。當在滑塊上發生任何類型的交互時,應用程序崩潰,例如懸停在其上,或者最小化和最大化對話框。

我剪掉了TBCD_CHANNEL代碼,因爲它永遠不會到達。

在調試模式下運行時,它在AfxClock.cpp中的AfxUnlockGlobals方法結束時崩潰。這是一個堆棧跟蹤: 更新:由於添加了調試符號,崩潰似乎在CWnd :: DefWindowProc mwthod中找到。

comctl32.dll!_TrackBar[email protected]() + 0x551 bytes 
[email protected]() + 0x28 bytes 
[email protected]() + 0xb7 bytes 
[email protected]() + 0x51 bytes 
[email protected]() + 0x1b bytes 
mfc90ud.dll!CWnd::DefWindowProcW(unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 1043 + 0x20 bytes C++ 
mfc90ud.dll!CWnd::WindowProc(unsigned int message=15, unsigned int wParam=0, long lParam=0) Line 1756 + 0x1c bytes C++ 
mfc90ud.dll!AfxCallWndProc(CWnd * pWnd=0x0012fdbc, HWND__ * hWnd=0x000308fe, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 240 + 0x1c bytes C++ 
mfc90ud.dll!AfxWndProc(HWND__ * hWnd=0x000308fe, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 403 C++ 
mfc90ud.dll!AfxWndProcBase(HWND__ * hWnd=0x000308fe, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 441 + 0x15 bytes C++ 
[email protected]() + 0x28 bytes 
[email protected]() + 0xb7 bytes 
[email protected]() + 0x4d bytes  
[email protected]() + 0x24 bytes 
[email protected]() + 0x13 bytes 
[email protected]() + 0xc bytes 
[email protected]() + 0xf bytes 
mfc90ud.dll!AfxInternalPumpMessage() Line 183 C++ 
mfc90ud.dll!CWinThread::PumpMessage() Line 900 C++ 
mfc90ud.dll!AfxPumpMessage() Line 190 + 0xd bytes C++ 
mfc90ud.dll!CWnd::RunModalLoop(unsigned long dwFlags=4) Line 4386 + 0x5 bytes C++ 
mfc90ud.dll!CDialog::DoModal() Line 584 + 0xc bytes C++ 
SetSelection.exe!CSetSelectionApp::InitInstance() Line 64 + 0xb bytes C++ 
mfc90ud.dll!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, wchar_t * lpCmdLine=0x00020a84, int nCmdShow=1) Line 37 + 0xd bytes C++ 
SetSelection.exe!wWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, wchar_t * lpCmdLine=0x00020a84, int nCmdShow=1) Line 34 C++ 
SetSelection.exe!__tmainCRTStartup() Line 578 + 0x35 bytes C 
SetSelection.exe!wWinMainCRTStartup() Line 403 C 
[email protected]() + 0x23 bytes 

那麼,有沒有人有任何洞察到這件事?如果您需要更多信息,請告訴我。


更新:我已經找到了解決辦法,現在,而不是使用SetWindowLong函數我只是把結果賦值給pResult,然後返回。我強制通過調用SetRangeMin(GetRangeMin(),TRUE)重繪子項,不完全優雅,但它的作品。

+2

提示:爲了獲得更好的堆棧跟蹤,請配置一個[symbol server](http://support.microsoft.com/kb/311503) – MSalters 2010-04-13 07:35:54

+0

謝謝,我現在就來玩一玩。 – Andrew 2010-04-13 07:50:17

+0

添加了更好的堆棧跟蹤,感謝提示。 – Andrew 2010-04-13 08:08:43

回答

0

你正在錯誤的窗口呼叫SetWindowLongSetWindowLong的第一個參數是處理消息的對話框,而不是發送消息的窗口。 SetWindowLong(m_hWnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);

您的代碼正在更改窗口長的窗口,最終導致該窗口的私人數據被破壞。