2010-04-13 4 views
0

Я вношу некоторые изменения в CSliderCtrl с помощью Custom Draw, элемент управления должен использоваться в диалоговом окне. Вот структура: В моей MessageMap у меня есть: ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, OnNMCustomdraw)SetWindowLong в CustomDraw вызывает необработанное исключение

Метод 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, чтобы установить возвращаемое значение для таможни draw, иначе ваш метод не всегда получит сообщение CDDS_ITEMPREPAINT. Однако при использовании SetWindowLong мое приложение никогда не получит CDDS_ITEMPREPAINT, поэтому мой слайдер просто выглядит как стандартный слайдер. Приложение вылетает, когда на слайдере происходит какое-либо взаимодействие, например, зависание над ним или минимизация и максимизация диалога.

Я отрезал код TBCD_CHANNEL, поскольку он никогда не был достигнут.

При запуске в режиме отладки он выходит из строя в конце метода AfxUnlockGlobals, в afxcrit.cpp. Вот трассировка стека: Обновление: с добавлением символов отладки, авария, похоже, подхвачена на CWnd :: DefWindowProc mwthod.

[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

Совет: чтобы получить лучшие трассировки стека, настройте [сервер символов] (http://support.microsoft.com/kb/311503) – MSalters

+0

Спасибо, у меня будет игра с этим сейчас. – Andrew

+0

Добавлена ​​лучшая трассировка стека, спасибо за подсказку. – Andrew

ответ

0

Вы звоните SetWindowLong не в том окне. Первым параметром SetWindowLong является диалоговое окно, обрабатывающее сообщение, а не окно, которое отправило сообщение. SetWindowLong(m_hWnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);.

Ваш код меняет окно в окне отправителя, что приводит к повреждению личных данных этого окна.