Я не эксперт по MFC, но за последние 15 с лишним лет я создал около десятка пользовательских элементов управления.Я только что сделал CButton
с пользовательской графикой.
Вот проблема: Конечно, мне нужно установить BS_OWNERDRAW
.У меня есть метод OnNcCreate()
, который я вырезал и вставил более 15 лет, который всегда работал в моих пользовательских элементах управления, но по какой-то причине он сейчас не вызывается.
У меня нет никакого интереса или даже понимания OnNcCreate()
за исключением того факта, что это было то место, где я в итоге установил BS_OWNERDRAW
при первой попытке написать пользовательский элемент управления.
Вопрос: Что помешает вызову OnNcCreate()
?Или есть другое место, которое я мог бы или должен установить BS_OWNERDRAW
?
Рабочий класс определяется с помощью:
class CGood : public CStatic {
Неработающий определяется с помощью:
class CBad : public CButton {
Они оба прототипируют метод таким образом:
afx_msg int OnNcCreate( LPCREATESTRUCT lpCreateStruct );
Метод написан идентично (кроме имени класса):
int CGood::OnNcCreate( LPCREATESTRUCT pcrs ) {
wStyleBits = LOWORD( pcrs->style );
DWORD dwStyleSuperclass = MAKELONG( ES_LEFT, HIWORD( pcrs->style ) );
dwStyleSuperclass |= BS_OWNERDRAW;
::SetWindowLong( m_hWnd, GWL_STYLE, dwStyleSuperclass );
pcrs->style = dwStyleSuperclass;
return CStatic::OnNcCreate( pcrs );
}
Диалог используеткак хорошие, так и плохие классы, использующие редактор диалогов Visual Studio 2017, как CustomControl.И хорошие, и плохие классы имеют расширенный стиль 0x0 и стиль 0x50010000.Оба er Disabled = False, ID справки = False, Visible = True, Class = Good или Bad по мере необходимости.
При запуске приложение вызывает метод RegisterControlClass()
каждого класса:
static WNDPROC pfnWndProc = NULL;
BOOL CBad::RegisterControlClass() {
WNDCLASS wcls;
static const TCHAR szClass[] = _T( "CBad" );
if ( ::GetClassInfo( AfxGetInstanceHandle(), szClass, &wcls ) )
return wcls.lpfnWndProc == ( WNDPROC ) CBad::WndProcHook;
VERIFY( ::GetClassInfo( NULL, _T( "button" ), &wcls ) );
pfnWndProc = wcls.lpfnWndProc;
wcls.lpfnWndProc = CBad::WndProcHook;
wcls.hInstance = AfxGetInstanceHandle();
wcls.lpszClassName = szClass;
return RegisterClass( &wcls ) != 0;
}
LRESULT CALLBACK EXPORT CBad::WndProcHook( HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam ) {
CBad* pthis = new CBad();
pthis->Attach( hWnd );
pthis->m_pfnSuper = pfnWndProc;
::SetWindowLong( hWnd, GWL_WNDPROC, ( DWORD )AfxWndProc );
#ifdef STRICT
return ::CallWindowProc( AfxWndProc, hWnd, msg, wParam, lParam );
#else
return ::CallWindowProc( ( FARPROC )AfxWndProc, hWnd, msg, wParam, lParam );
#endif
}
(Забавно: я отмечаю, что в CGood
, производном от CStatic
, там по ошибке есть «кнопка» и она работает нормально; она перестает работать, если я перехожу на «статический». Я рассмотрю это позже. Плохой класс имеет »кнопка "и действительно является CButton
подклассом.)
Вещи, которые я сделал для подтверждения проблемы: Когда я удаляю BS_OWNERDRAW
из CGood::OnNcCreate()
, он перестает вызыватьDrawItem()
.Так что я уверен, что это место, где устанавливается этот флаг.
Установка точки останова в CGood::OnNcCreate()
и CBad::OnNcCreate(),
CBad просто не называется.
Я нашелпримеры в интернете настроек BS_OWNERDRAW
в PreSubclassWindow()
, OnCreate()
и CreateEx()
, ни один из которых не работает, в некоторых случаях по причинам, я думаю, я понимаю.(Например, вы не можете просто установить флаги в OnCreate () и вызвать метод суперкласса, потому что он в конечном итоге получает флаги не из передаваемого вами параметра, а из другого источника.)
Я пробовализменение суперкласса CBad на CStatic, но OnNcCreate () по-прежнему не вызывается.
Я попытался установить BS_OWNERDRAW
в диалоговом окне OnInitDialog()
и что делает кнопку CBadЖивопись подкласса правильно.Так что я знаю, что не случайно создаю их с другим подклассом и т. Д.
CBad* pcbut = (CBad*) GetDlgItem( IDC_MARKCHECK );
pcbut->ModifyStyle(0, BS_OWNERDRAW);