MFC: OnNcCreate () не вызывается; необходимо установить флаг BS_OWNERDRAW для подкласса CButton - PullRequest
0 голосов
/ 19 мая 2019

Я не эксперт по 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);

1 Ответ

0 голосов
/ 19 мая 2019

Ааа!Я просто забыл добавить его в карту сообщений!

BEGIN_MESSAGE_MAP( CBad, CButton )
    //{{AFX_MSG_MAP( CBad )
    ON_WM_NCCREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...