我不是 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_OWNERDRAW
,CGood::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);