VC++编程常见问题解答二十二 问:CDC中的竖排文本? 在OnDraw成员函数中我想让文本竖直对齐,但CDC类似乎不支持该处理 答:如果你的竖直对齐是指旋转文本的话,下面的代码会对你有帮助: 该代码检查 一个Check box控制,查看文本是否需要旋转. // m_pcfYTitle is a CFont* to the selected font. // m_bTotateYTitle is a bool (==TRUE if rotated) void CPage1::OnRotateytitle() { LOGFONT lgf; m_pcfYTitle->GetLogFont(&lgf); m_bRotateYTitle= ((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0; // escapement is reckoned clockwise in 1/10ths of a degree: lgf.lfEscapement=-(m_bRotateYTitle*900); m_pcfYTitle->DeleteObject(); m_pcfYTitle->CreateFontIndirect(&lgf); DrawSampleChart(); } 注意如果你从CFontDialog中选择了不同的字体,你应该自己设定LOGFONT的 lfEscapement成员.将初始化后的lfEscapement值传到CFontDialog中. A2:还有一段代码可参考: LOGFONT LocalLogFont; strcpy(LocalLogFont.lfFaceName, TypeFace); LocalLogFont.lfWeight = fWeight; LocalLogFont.lfEscapement = Orient; LocalLogFont.lfOrientation = Orient; if (MyFont.CreateFontIndirect(&LocalLogFont)) { cMyOldFont = cdc->SelectObject(&MyFont); } 问:如何激活变灰的弹出菜单? 在设计菜单时设定为GRAYED的菜单项,如何在运行时激活它? 答:请看下面的示例代码: void CMyView::OnRButtonDown(UINT nFlags, CPoint point) { CScrollView::OnRButtonDown(nFlags, point); CMenu *menu, *popup; menu = new CMenu(); // load menu from resource file menu->LoadMenu( IDR_POPUPMENU ); popup = menu->GetSubMenu(0); // item 0 is DUMMY UINT nEnable; nEnable = MF_BYCOMMAND|MF_GRAYED; if( your test ) { nEnable = MF_BYCOMMAND|MF_ENABLED; } popup->EnableMenuItem( ID_YOUR_ID, nEnable ); //display menu ClientToScreen(&point); popup->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this ); delete menu; } 问:线程消息? 如何正确地在线程之间传送消息? 答:下面的代码将会帮你的忙: void CThread::OnUserOpen( WPARAM wParm, LPARAM lParm ) { UNUSED( wParm ) ; UNUSED( lParm ) ; AfxMessageBox("User Open", MB_OK|MB_ICONEXCLAMATION); } 当然,也别忘了以下声明: class CThread : public CWinThread { DECLARE_DYNCREATE(CThread) protected: CThread(); // protected constructor used by dynamic creation afx_msg void OnUserOpen( WPARAM wParm, LPARAM lParm ); 问:TreeCtrl控制的显示速度太慢? 我从CTreeCtrl继承了一个TREE控制类,重载主要是为了改写每个节点的文本.我在 OnPaint函数中写了一些代码,但这严重地影响了TREE控制的滚动速度. 答:OnPaint函数 1.可见节点,对于GetFirstVisibleItem和GetNextVisibleItem来讲,是: a.根节点;b.父节点已展开的节点; 因此,"可见"意味着"没有被未展开的父节点隐藏".当节点滚动到客户外时,它对上 述两 个函数来讲仍是可见的. 2.当TREE的内容改变时,它默认只将变为可见的节点重绘.另外其它已经是可见的 节点 没有必要重绘,TREE只是滚动DC的位图而已. 上面的意思是不要绘制你不需要看的节点,那会导致速度降低.建议,测试节点矩形 是否 在客户区,使得只有需要绘制的节点才会被绘制. void CIndentTree::OnPaint() { CPaintDC dc(this); // device context for painting HTREEITEM hItem = NULL; DRAWITEMSTRUCT dis; CRect rc; // redraw only visible items with indentation for( hItem = GetFirstVisibleItem(); hItem; hItem = GetNextVisibleItem( hItem ) ) { if( !GetItemRect( hItem, rc, FALSE ) ) continue; if( rc.top <= dc.m_ps.rcPaint.bottom && rc.bottom> dc.m_ps.rcPaint.top &&=20 rc.left <= dc.m_ps.rcPaint.right && rc.right> dc.m_ps.rcPaint.left ) { dis.hwndItem = (HWND)hItem; dis.rcItem = rc; OnDrawItem(0, &dis, &dc); } } } OnDrawItem函数 1.删掉如下代码: IMAGEINFO* pinfo = new IMAGEINFO; ... delete pinfo; 没有必要使用动态的IMAGEINFO变量,你可以将其定义为堆栈变量. 2.GetItemState和GetItemText都是使用的GetItem,因此,你只需调用一次, 就可 以从节点获得你要的所有信息.