前言:
这个笔记是去年看这本书的时候记下的,一直仍在电脑里,后来也没看过,今天春节后上班无意间发现了,遂整理出来,方便以后查阅.
第8章:
非模式对话框创建 显示 销毁:
1.m_pDlg=new CMyDlg;
pDlg->Create(IDD_MYDLG);
pDlg->ShowWindow(SW_SHOW);
2.销毁时在PostNcDestroy中调用delete this;
属性表的使用:
1.创建对话框模版,添加类,继承自CPropertyPage
2.由CPropertySheet派生一个属性表类,利用CPropertySheet::AddPage添加属性页
3.由DoModal显示属性表
class CFirstPage::Public CPropertyPage
{
public:
CFirstPage():CPropertyPage(IDD_FIRST_PAGE){};
};
class CMyPropertySheet:public CPropertySheet
{
public:
CFirstPage m_wndFirstPage;
CPropertySheet(LPCTSTR pszCaption,CWnd *pParant=NULL):
CPropertySheet(pszCaption,pParentWnd,0)
{
AddPage(&m_wndFirstPage);
}
};
响应OnApply:
1.在CMyPropertySheet中添加消息 afx_msg void OnApply
2.映射 ON_BN_CLICK(ID_APPLY_NOW,OnApply)
3.消息定义
void OnApply()
{
GetActivePage()->OnOK();
GetActivePage()->SetModified(FALSE);
}
第12章:
在做鼠标命中测试时,要先通过CDC::DPtoLP
OnDraw函数的自动识别:
当滚动事件发生,CScrollView用OnVScroll和OnHScroll来处理消息,调用::ScrollWindow来水平或垂直滚动试图。视图的OnPaint函数被调用,绘制失效部分。在调用OnDraw之前,CView::OnPaint调用虚OnPrepareDC函数,CScrollView覆盖OnPrepareDC并在其中调用CDC::SetMapMode来设置应设模式,调用SetViewportOrg将原点转换为等于水平和垂直滚动位置的值
在OnDraw以外执行CSCrollView窗口中绘制操作时要先将设备描述表传递给OnPrepareDC
CClientDC dc(this);
OnPrepareDC(&dc);
测试单击位置处于逻辑视图的上部还是下部:
void CMyView::OnLButtonDown(UINT nFlags,CPoint point)
{
CPoint pos=point;
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&pos);
//
//CSize GetTotalSize( ) const;
//Call GetTotalSize to retrieve the current horizontal and vertical sizes of the scroll view.
//
CSize size=GetTotalSize();
{
if( ::abs(pos.y)<(size.cy/2) )
{}//Upper
else
{}//Lower
}
}
SetScaleToFitSize实现Zoom To Fit,将整个逻辑视图所放在物理视图中
优化OnDraw,CDC::GetClipBox(CRect)传递给OnDraw的设备描述表对象中被调用,GetClipBox用无效区域矩形的逻辑坐标下的尺寸和位置来初始化CRect
//------------------------------------------------------------------------------------------------------
创建CListView:
1.创建一对图形列表保存视图项目的图形--大图形和小图形的图标
2.把图形列表和视图列表联系起来.传递LVSIT_NORMAL表示图形列表包含大图形,传递LVSIL_SMALL表示含有小图标
3.InsertColumn给视图添加列,最左边的列显示空间中加入的项目.右边的列显示子项目,但只有报表模式下才可见
4.InsertItem添加项目
5.SetItemText给项目的子项目分配文本字符串
使用LVS_TYPEMASK可以屏蔽所有4个表现模式:LVS_ICON LVS_SMALLICON LVS_LIST LVS_REPORT.
#define LVS_ICON 0x0000
#define LVS_REPORT 0x0001
#define LVS_SMALLICON 0x0002
#define LVS_LIST 0x0003
#define LVS_TYPEMASK 0x0003
判断当前表现模式:
DWORD dwStyle=GetStyle() & LVS_TYPEMASK;
if( dwStyle==LVS_ICON )
...
...
第10章:
创建工具栏方法:
1.
CToolBar::Create创建工具栏
m_wndToolbar.Create(this,WS_CHILD | WS_VISIBLE | CBRS_BOTTOM,AFX_IDW_TOOLBAR);
也可以:
m_wndToolBar.Create(this);
m_wndToolBar.SetBarStyle((m_wndToolBar.GetBarStyle() & ~CBRS_TOP) | CBRS_BOTTOM);
调用CToolBar::LoadBitmap加载包含按钮的命令ID
static UINT nButtonIDs[]=
{
ID_FILE_NEW,
ID_FILE_OPEN,
...
};
m_wndToolBar.Create(this);
m_wndToolBar.LoadBitmap(IDB_BITMAP);
m_wndToolbar.SetButtons(nButtonIDs,10);
CToolBar::SetSizes改变图象和按钮尺寸
2.
从资源文件中加载--CToolbar::LoadToolBar
CToolBar::SetButtonText改变按钮表面的字符串
m_wndToolBar.Create(this);
m_wndToolBar.LoadToolBar(IDR_TOOLBAR);
m_wndToolBar.SetButtonText(0,_T("New"));
m_wndToolBar.SetButtonText(1,_T("Open"));
m_wndToolBar.SetSizes(CSize(48,42),CSize(40,19));
TBBS_CHECKBOX创建一个复选按钮
TBBS_CHECKGROUP相当于TBBS_CHECKBOX | TBBS_GROUP这些属性实用CToolBar::SetButtonStyle
把工具栏添加单选按钮,选中其中一个作为默认按钮
int nState=m_wndToolBar.GetToolBarCtrl().GetState(ID_PART_LEFT);
m_wndToolBar.GetToolBarCtrl().SetState(ID_PART_LEFT,nState | TBSTATE_CHECKED);
只有调用工具栏的CControlBar::EnableDocking和框架窗口的CFrameWnd::EnableDocking函数,并有各自的位标志制定
框架窗口一侧作为工具栏的安装位置,工具栏的可浮动和可摆放才有效
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
可使停放在父窗口的任一一侧
用CFrameWnd的成员函数DockControlBar和FloatControlBar使工具栏浮动
DockControlBar(&m_wndToolBar);
FloatControlBar(&m_wndToolBar,CPoint(x,y));父窗口的坐标系
TBBS_WRAPPED相当于回车,后面的按钮放在下一行
m_wndToolBar.SetButtonStyle(1,m_wndToolBar.GetButtonStyle(0)|TBBS_WRAPPED);
工具栏的可见性:
1.
CFrameWnd::OnBarCheck来隐藏或者显示
CFrameWnd::OnUpdateControlBarMenu来选中或取消其ID和工具栏ID匹配的菜单项
On_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR,OnUpdateControlBarMenu)
On_COMMAND_EX(ID_VIEW_STATUS_BAR,OnBarCheck)
编写自己的命令和更新程序并用CFrameWnd::ShowControlBar隐藏或显示,通过查看WS_VISIBLE确定是否显示
ON_COMMAND(ID_VIEW_TOOLBAR,OnVieToolBar)
ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR,OnUpdateViewToolBar)
void CMainFrame::OnViewToolBar()
{
SHowControlBar(&m_wndToolBar,(m_wndToolBar.GetStyle() & WS_VISIBLE)==0,FALSE);
}
void CMainFrame::OnUpdateViewToolBar(CCmdUI *pCmdUI)
{
pCmdUI->SetCheck((m_wndToolBar.GetStyle() & WS_VISIBLE)?1:0);
}
仅仅修改WS_VISIBLE无法实现显示隐藏,因为工具栏的显示隐藏时MFC会调整视图的大小,适应框架窗口客户区域内的变化
CControlBar::OnUpdateCmdUI是个虚函数,主结构在CPU空闲时调用,重载更新那些没有UI更新处理程序的控件
设置工具栏永久化的两个函数:CFrameWnd::SaveBarState和CFrameWnd::LoadBarState
SaveBarState把每个工具栏的停放或浮动状态,位置,方向和可见性写到注册表
在主框架窗口的OnCreate中调用LoadBarState,在OnClose中调用SaveBarState
在工具栏中添加其他按钮控件
1.在TOOLBAR资源中添加一个按钮分隔符或者白按钮,任一ID和图像
2.调用CToolBar::SetButtonInfo来增加预留位置的宽度,使之能容纳控件,在该空白处创建控件
SetButtonInfo(8,IDC_COMBOBOX,TBBS_SPEARATOR,nWidth);
CRect rect;
GetItemRect(8,&rect);
rect.botton=rect.top=nHeight;
m_wndComboBox.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST,rect,this,IDC_COMBOBOX);
HRESULT CALLBACK DllGetVersion(DLLVERSIONINFO *pdvi);
该函数不是API函数,需要用LoadLibrary 和 GetProcAddress来获取函数指针
//检测Common Ctrl的版本
void GetCommonCtrlVersion(DWORD &dwMajor,DWORD &dwMinor)
{
dwMajor=dwMinor=0;
HINSTANCE hLib=::LoadLibrary(_T("Contrl32.dll"));
if( hLib!=NULL )
{
DLLGETVERSIONPROC pDllGetVersion=
(DLLGETVERSIONPROC )::GetProcAddress(hLib,_T("DllGetVersion"));
if( pDllGetVersion )
{
DLLVERSIONINFO dvi;
ZeroMemory(&dvi,sizeof(dvi));
dvi.cbSize=sizeof(dvi);
HRESULT hr=(*pDllGetVersion)(&dvi);
if( SUCCEEDED(hr) )
{
dwmajor=dvi.dwMajorVersion;
dwMinor=dvi.dwMinorVersion;
}
}
else
{
dwMajor=4;
dwMor=0;
}
::Freelibrary(hLib);
}
}
DWORD dwMajor,dwMinor;
GetComctlVersion(dwMajor,dwMinor);
if( (dwMajor==4 && dwMinor>=70) ||
dwMajor>4 )
{
//the feature is supported
}
else
{
//not supported
}
在SDK的Windows程序中,通常使用WM_MENUSELECT消息来更新状态栏的描述性文本
状态栏通过
创建状态栏
static UINT nIndicator[]=
{
ID_SEPARATOR,
ID_INDICATOR_INS
};
m_wndStatusBar.Create(this);
m_wndStatusBar.Setindicators(nIndicators,2);
通过SetPaneInfo来调整窗格信息
m_wndStatusBar.SetPaneInfo(0,ID_SEPARATOR,SBPS_NOBORDERS,64);
可以通过消息映射来更新状态栏的窗格
ON_UPDATE_COMMAND_UI(ID_INDICATORS,OnUpdateTime)
void CMainFrame::OnUpdateTime(CCmdUI *pCmdUI)
{
....
pCmdUI->SetText(...);
}
在状态栏德文本前加一个“/t”,窗格文本居中对齐,两个"/t/t",窗格右对齐
创建ReBar
首先创建ToolBar
m_wndToolBar.CreateEx(this);
m_wndToolBar.LoadToolBar(IDR_TOOLBAR);
m_wndReBar.Create(this);
m_wndReBar.AddBar(&m_wndToolBar);
可以使用AddBar的第2、3个参数指定标签和背景
m_bitmap.LoadBitmap(IDB_BKGND);
m_wndReBar.AddBar(&m_wndToolBar,_T("Main"),&m_bitmap);
第14章
计时器可以实现最短时间间隔为55毫秒,间隔时间的有效值为1毫秒到32位整数所能表示的最大值2的32次方减1
计时器消息永远不会积压在消息队列中.在Windows程序中,计时器的消息处理和回调函数处理在调用::DispatchMessage之前过程都是一样的.在计时器开始运行以后,Windows会在消息队列中设置一个标志,用来表示技术其消息或回调汉书是否在等待处理(开/关标志的特性说明了为什么计时器消息不会在消息队列中对堆积,计时器间隔时间过去以后标志不会累加,只能设置为开状态),如果::GetMessage发现消息队列时空的并且没有窗口需要重绘,它就检查计时器标志.如果设置了,::GetMessage就声称一个WM_TIMER消息,接下来由::DispatchMessage调度.如果产生消息的计时器是WM_TIMER类型的,消息就调度到窗口去处理,如果注册了回调函数,::DispathMessage就要调用回调函数.
擦除恢复窗口标题栏:
首先,ModifyStyle(WS_CAPTION,0);或ModifyStyle(0,WS_CAPTION);
然后,重绘窗口非客户区SWP_DRAWFRAME,SetWindowPos(NULL,0,0,0,0,SWP_NOMOVE,SWP_NOSIZE
| SWP_NOZORDER | SWP_DRAWFRAME);
鼠标点击客户区移动窗口:
UINT CMainWindow::OnNchitText(CPoint point)
{
UINT nHitTest=CFrameWnd::OnNcHitText(point);
if( nHitText==HTCLIENT )
{
nHitTest=HTCAPTION;
}
return nHitTest;
}
在窗口缩放时,窗口会接受到WM_GETMINMAXINFO消息,其中lParam指向MINMAXINFO结构
第15章
Windows通过在适配器硬件调色板编制标准的供选颜色来处理调色板化的设备.这就是所谓的"静态颜色".
在256色适配器中,剩下的236颜色在GDI对象中,通常称为逻辑调色板
创建逻辑调色板:
CPalette palette;
palette.CreateHalftonePalette(pDC);
如果传递给CreateHalftonePalette的设备句柄为NULL,就可以创建与输出设备无关的256色半色调色板.但是不能用CPalette::
CreateHaletonePalette,因为该类函数具有有效性检测.所以使用
CPalette palette;
palette.Attach(::CreateHalftonePalatte(NULL));
在调色板创建以后,可以使用CPalette::GetPaletteEntries检索单个调色板输入项或使用CPalette::SetPaletteEntries修改它们
还可以使用CPalette::ResizePalette调整调色板的大小
CDC::RealizePalette通过申请调色板管理器将逻辑调色板中的颜色映射到系统调色板上
创建COLORREF值有3个宏,分别是RGB,PALETTEINDEX和PALETTERGB
如果希望GDI使用所有调色板颜色,则使用PALETTERGB,如果忽略调色板给系统调色板添加的颜色而只使用静态颜色则使用RGB.
PALETTEINDEX生成的COLORREF指定了逻辑调色板而不是RGB颜色值的索引号
WM_QUERYNEWPALETTE和WM_PALETTECHANGED消息
当顶层窗口的子窗口接收到输入焦点时,就会给顶层窗口发送一个WM_QUERYNEWPALETTE消息.当调色板的实现导致系统调色板改动时,就给系统中顶层窗口发送WM_PALETTECHANGED消息
在运行过程中可以确定逻辑调色板是否可以改善颜色输出,即系统颜色是否符合要求的方法
CClienDC dc(this);
BOOL bUsePalette=FALSE;
if( dc.GetDeviceCaps(RASTERCAPS)&RC_PALETTE )
{
bUsePalette=TRUE;
}
第16章:
公用控件需要Internet Explorer的支持,其实是Comctl32.dll的支持.检测其版本信息的方法如下:
void GetComctlVersion(DWORD &dwMajor,DWORD &dwMinor)
{
dwMajor=dwMinor=0;
HINSTANCE hLib=::LoadLibrary(_T("Comctl32.dll"));
if( hLib!=NULL)
{
DLLGETVERSIONPROC pDllVersion=(DLLGETVERSIONPROC)::GetProcAddress(hLib,_T("DllGetVersion"));
if( pDllGetversion ) //IE 3.0 or higher
{
DLLVERSIONINFO dvi;
::ZeroMemory(&dvi,sizeof(dvi));
HRESULT hr=(*pDllVersion)(&dvi);
if( SUCCESSED(hr) )
{
dwMajor=dvi.dwMajorVersion;
dwMinor=dvi.dwMinorVersion;
}
}
else //Pre IE 3.0
{
dwMajor=4;
dwMinor=0;
}
::FreeLibrary(hLib);
}
}
MFC提供三种创建图像列表:
1.创建空图像列表,然后用CImageList::Add添加图像
2.假定IDB_BITMAP是位图资源ID,包含五个图像,每个图像18个像素宽,16像素高.位图自身为90个像素宽,16个像素高
CImageList li;
li.Create(IDB_BITMAP,18,1,CLR_NONE);
CImageList::Draw在屏幕上显示图像
li.Draw(pDC,2,point,ILD_NORMAL);标识位可以为ILD_TRANSPARENT
获取目录中子项的CString相关函数
void GetSubString(int &nStart,CString &strPath,CString &strResult)
{
strResult=_T("");
int nLen=strPath.GetLength();
if( nStart>=nLen )
return;
int nEnd=strPath.Find(_T('//'),nStart);
if( nEnd!=-1 )
{
strResult=strPath.Right(nLen-nStart);
nStart=nLen;
}
else
{
strResult=strPath.Mid(nStart,nEnd-nStart);
nStart=nEnd+1;
}
}