0

我不是 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、Help 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_OWNERDRAWCGood::OnNcCreate()它停止调用DrawItem(). 所以我确定这就是设置这个标志的地方。

放置一个断点CGood::OnNcCreate()并且CBad::OnNcCreate(),CBad 根本不会被调用。

我在互联网上找到了设置 、 和 的示例BS_OWNERDRAW,但PreSubclassWindow()这些都不起作用,在某些情况下,出于我认为我理解的原因。(例如,您不能只在 OnCreate() 中设置标志并调用超类方法,因为它最终不是从您提供的参数而是从其他来源获取标志。)OnCreate()CreateEx()

我已经尝试将 CBad 的超类更改为 CStatic,但仍然没有调用 OnNcCreate()。

我已经尝试BS_OWNERDRAW在对话框中进行设置,OnInitDialog()并且确实可以正确绘制 CBad 按钮子类。所以我知道我不是偶然用其他子类等创建它们的。

CBad* pcbut = (CBad*) GetDlgItem( IDC_MARKCHECK );
pcbut->ModifyStyle(0, BS_OWNERDRAW);
4

1 回答 1

0

啊!我只是忘记将其添加到消息映射中!

BEGIN_MESSAGE_MAP( CBad, CButton )
    //{{AFX_MSG_MAP( CBad )
    ON_WM_NCCREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
于 2019-05-19T13:23:46.177 回答