我不是MFC方面的专家,但是在过去的15多年中,我制作了大约十二种自定义控件。我刚刚使用自定义图形制作了CButton
。
这是问题所在:当然,我需要设置BS_OWNERDRAW
。我有一种OnNcCreate()
方法已经粘贴并粘贴了15年以上,该方法在我的自定义控件中一直有效,但是由于某种原因,现在不被调用。
除了{@ {1}}是我第一次尝试编写自定义控件的地方,我最终对OnNcCreate()
的设置没有兴趣,甚至没有了解。
问题:什么会阻止BS_OWNERDRAW
被调用?或者,还有其他我可以或应该设置OnNcCreate()
的地方吗?
工作类定义为:
BS_OWNERDRAW
无效的定义为:
class CGood : public CStatic {
他们俩都以此为方法的原型:
class CBad : public CButton {
方法的编写方式相同(类名除外):
afx_msg int OnNcCreate( LPCREATESTRUCT lpCreateStruct );
对话框使用Visual Studio 2017对话框编辑器作为CustomControl同时使用好类和坏类。好的和坏的类都具有扩展样式0x0和样式0x50010000。视需要而定,Disabled = False,Help ID = False,Visible = True,Class = Good或Bad。
运行时,应用程序将调用每个类的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 );
}
方法:
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断点。
我在互联网上找到了在CBad::OnNcCreate(),
,BS_OWNERDRAW
和PreSubclassWindow()
中设置OnCreate()
的示例,但由于某些原因,我认为这些都不起作用我明白。 (例如,您不能只在OnCreate()中设置标志并调用超类方法,因为它最终不是从您提供的参数中而是从其他来源获得标志。)
我尝试将CBad的超类更改为CStatic,但仍未调用OnNcCreate()。
我尝试在对话框的CreateEx()
中设置BS_OWNERDRAW
,并且确实可以正确绘制CBad按钮子类。所以我知道我不是偶然地用其他子类等创建它们的。
OnInitDialog()
答案 0 :(得分:0)
啊!我只是忘了将其添加到消息映射中!
BEGIN_MESSAGE_MAP( CBad, CButton )
//{{AFX_MSG_MAP( CBad )
ON_WM_NCCREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()