《网易掌握C教程》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
教你如何更好的掌握C++的基础2011-03-1616:59:131分类:默认分类I标签:it动态|字号订阅1.如何获取系统日期CTimetm=CTime::GetCurrentTime();CStringstrTime=tm.Format(_TEXT(u%Y-%M-%d%H:%M:%S));MessageBox(strTime);2.动态分配二维数组int**array;array=newint*[col];if(array==0)exit(-1);for(inti=0;i
1intarray[32][32];inta,b,n=0;intresultl;char*str;for(inti=0;i<32;i++)for(intj=0;j<32;j++){str=str[i][j];if(str[O]>='A'&&str[1]>='A'){〃"AF”a=str[O]-A;b=str。]-'A';resultl=(a+10)*16+(b+10)*1;}elseif(str[0]>=P&&str[1]
2n++;
3if(n%32==0)printf(ttMnM);}将这个矩阵数组在屏幕上显示:#include
4unsignedchar*p;p=&mj3lmage[0][0];然后在循环中,可以p+m_count*4096;5.改变最近打开文档的个数在Initlnstance()中的LoadStdProfileSe怕ng(8);〃括号里是要设置的个数6.打开调色板对话框CColorDialogdig;dlg.Domodal();7.如何添加工具栏,如何使用Slider?在。nlnitDialog()中添加:CSIiderCtrl*pSliderCtrl=(CSIiderCtrl*)GetDlgltem(IDC_SLIDER1);pSIiderCtrl->SetRange(0,255,TRUE);//设置滑动条的范围pSIiderCtrl->SetPos(100);//设置滑动条的初始位置在Dig类中响应WM_HSCROLL消息:CSIiderCtrl*pSliderCtrl=(CSIiderCtrl*)GetDlgltem(IDC_SLIDER1);m_nCur=pSIiderCtrl->GetPos();//获得当前的位置值8.更改光标::SetCursor(::LoadCursor(NULL,IDC_SIZEALL));〃如果是自己定义的光标资源,则要用MAKEINTRESOURCE进行转化,例如:::SetCursor(::LoadCursor(NULL,IDC_CURSOR_CUT));9.设置文本显示的一些函数CDCdc(this);CPenpen(PS_SOLID,2,#0000ff);//初始化一支笔
5CBrush*pBush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));dc.SelectObject(pBrush);dc.SetTextColor(RGB(255,0,255));dc.SetBKMode(TRANSPARENT);〃将文本背景设置为透明5.将对话框中的图像拷贝到剪贴板CWnd*pWnd=GetDlgltem(IDC_IMAGE_SELECT);WINDOWPLACEMENT*winPlacement;WinPlacement=newWINDOWPLACEMENT;pWnd->GetWindowPlacement(winPlacement);//获得一个控件的位置CDC*dcTemp;dcTemp=newCCIientDC(FromHandle(m_hWnd));CDCmemDC;memDC.CreateCompatibleDC(dcTemp);〃创建一个兼容的DCCBitmapbm;CSizesz(IWidth,IHeight);bm.CreateCompatilbleBitmap(dcTemp,sz.cx,sz.cy);〃创建•个兼容的位图CBitmap*oldbm=memDC.SelectObject(&bm);memDC.BitBlt(O,0,sz.cx,sz.cy,deTemp,winPlacement->rcNormalPosition.left,winPlacement->rcNormalPosition.top,SRCCOPY);pWnd->OpenClipboard();〃打开剪贴板,不用pWnd->GetParent()->OpenClipard();::EmptyClipard();::SetClipardData(CF_BITMAP,bm.m_hObject);〃粘贴到剪贴板CloseClipard();
6memDC.SelcetObject(oldbm);deletedeTemp;5.VC里获取一个文件夹路径BROWSEINFObi;TCHARszDisplayName[MAX_PATH];LPITEMIDLISTpidl;LPMALLOCpMalloc=NULL;ZeroMemory(&bi,sizeof(bi));bi.hWndOwner=GetSafeHwnd();bih.pszDisplayName=szDisplayName;bi.lpszTitle=TEXT(uPleaseselectafolder:");bi.ulFlags=BIF_RETURNONLYFSDIRS;Pidl=SHBrowseForFolder(&bi);if(pidl){SHGetPathFromlDList(pidl,szDisplayName);sPath=szDisplayName;MessageBox(sPath);}6.如何设置密码输入时显示的是•号#include
7a[i]=getch();if(i>=8||a[i]==13)break;putchf');i++;}cout<
8PROCESSINFOproinfo;〃进程的信息CreateProcess(NULL,^(••notepad.exeJ'.NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&stinfo,&proinfo);1.如何确定顶层菜单所占据的菜单行数:首先,计算主窗口的高度和客户区高度;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度CRectrc,rcClient;GetWindowRect(rc);GetClientRect(rcClient);IntmenuHeight;menuHeight=(rc.Height()一rcClicent.Height()-::GetSystemMetrics(SM_CYCAPTION)-::GetSystemMetrics(SM_CY)*2))-/::GetSystemMetrics(SM_CYMENU);2.响应下拉菜单的消息为ON_CBN_SELECTDOK(ID_TOOL_ZOOM,OnSelectZoomed)3.设置工具栏的标题m_wndTestBar.SetWindowText(uyourtoolbartitleM);4.如何获得应用程序主窗口的指针CWndpMainWnd=AfxGetAppO->m_pMainWnd;CMain*pMain=((CMain*)pMainWnd;CRectrect;CWnd*pParent=AfxGetApp()->GetMainWnd();pParent・>GetWindowRect(&rect);〃得到应用程序窗口矩形〃移到窗口pParent->MoveWindow(rect.left,rect.top,rect.Width()+1,rect.Height()+1.TRUE);5.获得获得子窗口
9CMDIChildWnd*pChild=(CMDIChildWnd*)GetActive();〃或:CMDIChildWnd*pChild=MDIGetActive();1.获得活动子窗口的活动视图CMyView*pView=(CMyView*)pChild->GetActiveView();获取当前窗口的指针CWnd::GetForegoundWindow();2.从句柄转换到指针HWNDhwnd;hwnd=::FindWindow(NULL,"TEST");CWnd*pWnd=FromHandle(hwnd);3.怎样改变进度条控件的颜色,发送消息m_progress.SendMessage(PBM_SETBKCOLOR,0,#ffOOOO);//背景色mj3rogress.SendMessage(PBM_SETBARCOLOR,0,#OOffOO);//前景色4.定义charnum[10];sprintf(num,calnum);//格式化数字charunit。』'矩形";sprintf(nurr),"%s",unit);〃格式化字符串5.改变字符串的显示字体和大小CFontfont;font.CreatePointFont(300,“华文行楷”,NULL);CFont*pOldFont=dc.SelectObject(&font);dc.SelectObject(pOldFont);
101.将路径中的单““变为’CMyDoc*pDoc=GetDocument();CStringreportPath=pDoc->strPathName;intlentemp=reportPath.GetLength();reportPath=reportPath.Left(lentemp-4);intlenpath=reportPath.GetLength();for(inti=0;i
111.改变对话框的背景色:在In汨nstance()中加入SetDialogBKColor(#a0b4dc,#ffOOOO);〃后面是字体颜色2.让指定的矩形框重画lnvalidateRect(&rect,TRUE);3.怎样选择所选的List当前位置intiTem;POSITIONpos=m_findCtrl.GetFirstSelectedltemPosition();if(pos==0){MessageBox("请选择需要删除的记录');return;}else{iTem=m_findCtrl.GetNextSelectedltem(pos);}〃删除List中的某行m_findCtrl.Deleteltem(iTem);m_findCtrl.Update(iTem);4.动态创建控件CEditm_edit;CRectrect(O,0,100,200);M_edit.Create(WS_CHILD|ES_AUTOHCROLL|WS_BORDER,rect,this,ID_EDIT_1);5.列表控件的应用CListCtrl*mjist;CRectrectjist;this->GetCientRect(&rect_list);rectjist.top+=100;m_list->Create(WS_CHILD|LVS_REPORT|WS_BORDER|LVS_SINGLESEL,rectjist,this,ID_TABLIST);this->m_list->ModifyStyle(LVS_EDITABELS,OL);〃禁止标题编辑
12m」ist->ModifyStyle(OL,LVS_REPORT);〃设置为Report类型m_list->ModifyStyle(OL,LVS_SHOWSELALWAYS);〃始终高亮显示被选中的表项m」ist->ModifyStyle(OL,LVS_NOSORTHEADER);〃禁止标题编辑m_list->SetBkColor(#00c8c8);//设置背景颜色m_list->SetTextBkColor(#00c8c8);〃设置文本背景颜色m_list->ModifyStyle(LVS_OWNERDRAWFIXED,OL);m」ist->SetExtendedStyle(LVS_EX_FULLROWSELET〃整行选中|LVS_EX_HEADERDARGDROP〃允许整列拖动|LVS_EX_GRIDLINES〃画出网格线|LVS_EX_FLATSB);//扁平风格的滚动条1.取得当前获得焦点的窗口句柄HWNDhwnd=::GetFocus();intilD=::GetDlgCtrllD(hwnd);//根据句柄取得其资源符号2.修改控件的字体CFontm_font;m_font.CreateFont(-12,0,0,0,400,FALSE,FALSE,0,GB2312_SHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH|FF_,"楷体_GB2312");〃为想改变字体的控件改变m_editPh.SetFont(&m_font,true);2.如何暂停主线程直到第二个线程的终止?voidCMyTestDialog::PeekMessageLoop(){MSGmsg;while(PeekMessage(&msg,NULL,NULL,NULL,NULL,NULL,PM_REMOVE))TranslateMessage(&msg);DispatchMessage(&msg);}}
13VoidCMyTestDialog::WaitForThreadToTerminate(HANDLEhThread){〃将指示哪个线程需要等待并作进一步处理DWORDdwRet;Do{dwRet=::MsgWaitForMultipleObject(1,&hThread,FALSE,INFINITE,QS_ALLINPUT);if(dwRef!=WAIT_OBJET_0){PeekMessageLoop();}Jwhile((dwRet!=WAIT_OBJET_0)&&(dwRet!=WAIT_FAILED));〃示例代码:假设对话框上有一个按钮,当点击按钮时,开始启动第二个线程,等到第〃二个线程完成后,我们再继续主线程:voidCMyTestDialog::OnButton1(){mjDUpdateThread=Ab(BeginThread(UpdateDeviceContent,(LPVOID)this);if(m_pUpdateThread){WaitForThreadToTerminate(m_pUpdateThread->m_hThread);}〃这里可以加入自己的执行代码Dowhateveryouwantaftertheactionisfinished.}2.改变列表框表头的颜色和字体,发送一个HDM_GETITEM消息voidCHeaderCtrlEx::Drawltem(LPDRAWITEMSTRUCTIpDrawltemStruct){ASSERT(IpDrawltemStruct->ctlType==ODT_HEADER);HDITEMhdi;TCHARlpBuffer[256];Hdi.mask=HDI_TEXT;Hdi.pszText=IpBuffer;Hdi.uhTextMax=256;Getltem(lpDrawltemStruct->itemlD,&hdi);〃画按钮框::DrawControl(lpDrawltemStruct->hdc,&lpDrawltemStruct->rcltem,DFC_BUTTOON,
14DFCS_BUTTONPUSH);COLORREFcrOldColor=::SetTextColor(lpDrawltemStruct->hdc,#ffffOO);::DrawText(lpDrawltemStruct->hdc,IpBuffer,strlen(lpBuffer),&lpDrawltemStruct->rcltem,DT_SINGLELINE|DT_VCENTER|DT_CENTER);::SetTextColor(lpDrawltemStruct->hdc,crOldColor);}2.修改标题栏中“无标题①修改'无标题”部分,重载文档中的虚函数SetTitle,加入:CDocument::SetTitle(Hyourtitle**);②修改后半部分:将字符串资源中的IDR_MAIN修改为我的程序"rrnChange”rTrrnChangeTitle.Document”nChangeDocument或者:在程序的任何地方调用如下语句:(AfxGetMainWnd())->SetWindowText(Myourtitle");③除去标题中间的T可以通过重载CFramWnd类的OnUpdateTitle函数,这个函数在VC提供的帮助文件中找不到,必须手工添加:virtualvoidOnllpdateTitle(BOOLNaDa);voidCMain::OnUpdateTitle(BOOLNaDa){CStringcsAppName;csAppName.Format(AFX_IDS_APP_TITLE);SetWindowText(csAppName);}〃此时显示的结果只有字符串资源AFX_IDS_APP_TITLE所定义的字符串★另一种方法是在CMain的PreCreateWindow函数中修改的窗口风格:BOOLCMain::PreCreateWindow(CREATESTRUCT&cs){cs.style&=-(LONG)FWS_ADDTOTITLE;returnCWnd::PreCreateWindow(cs);}〃使用此方法,窗口的标题只显示IDR_MAIN字符串中第一个“n之前的部分。((CMainFram*)AfxGetMainWnd())->SetWindowText("****");放在App类的lnitlnstance()函数里面
152.const的一些用法inta=0;constint*b=&a;[1]intconst*b=&a;[2]constint*constb=&a;[3]constchar*p="const";[1]charconst*p="const";[2]charconstp="const";[4]constchar*constp="const";[4]inta=0;constint&b=a;[1]intconst&b=a;[2]int&constb=a;[3]constint&constb=a;[4]①如果const位于星号左侧,则const用来修改指针所指向的变量,即指针指向的为不可变的;②如果const位于星号右侧,const就是修饰指针本身,即指针本身是不可变的;③[3]中指针本身是不可变的,而指针所指向的内容是可变的,这种情况下不能对指针本身进行更改操作,如b++是错误的:④[4]中指针本身和指向的内容均为常量3.const作为参数用法voidfunO(constA*a)在函数体中,按照const所修饰的部分进行常量化,如形参为constA*a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;voidfun1(constA&a)形参为constA&a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。[注:参数const通常用于参数为指针或引用的情况]const修饰返回值:constAfun2();constA*fun3()一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二H操作符重载函数,并产生新的对象的时候。[总结]:一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。6.类成员函数中const的使用:一般放在函数体后voidfun()const;如果一个成员函数不会修改数据成员,那么最好将其声明为const,因为const成员函数中不允许对数据成员进行修改,如果修改,编译器会报错,大大提高了程序的健壮性。7.使用const的一些suggestioins:①耍大胆地使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
16②在参数中使用const应使用引用或指针,而不是一般的对象实例;③要避免最一般的赋值操作错误,如将const变量赋值;④不要轻易地将函数的返回类型定为cosnt;⑤除了重载操作符外一般不要将返回值类型定为某个对象的const引用8.让应用程序只运行一个实例:在App的Initlnstance添加如下代码:HANDLEhSem=CreateSemaphore(NULL,1,1,m_pszAppName);if(GetLastError()==ERROR_ALREADY_EXISTS){//信号量存在,则有一个在运行CloseHandle(hSem);〃关闭信号量句柄//寻找先前的实例窗口HWNDhWndPrevious=::GetWindow(::GetDesktopWindow(),GW_CHILD);While(::IsWindow(hWndPrevious)){〃检查窗口是否有预设的标记if(::GetProp(hWndPrevious,m_pszAppName)){//W.则寻找主窗口if(::Islconic(hWndPrevious)){〃窗口最小化,则恢复其大小::SetForegroundWindow(hWndPrevious);〃将主窗口激活::SetForgoundWindow(::GetLastActivePopup(hWndPrevious));〃将主窗口激活::ShowWindow(hWndPrevious,SWNORMAL);reurnFALSE;}〃退出本实例hWndPrevious=::GetWindow(hWndPrevious,GW_HWNDNEXT);//继续找}AfxMessageBox(Honlyoneapplicationprogramcanrun!”);returnFALSE;}}1.获取本机的IP地址#include
17Charname[155];Char*ip;PHOSTENThostinfo;If(WSAStartUp(MAKEWORD(2,0),&wsadate)==0){If(gethostname(name,sizeof(name))==0){lf((hostinfo=gethostbyname(name))!=NULL){〃获得IP的函数Ip=inet_ntoa(*(structin_addr*)*hostinfo->h_addr_list);Printf*“%s"n”,ip);}}WSACIeanup();}}2.CWnd::SetDlgltemlnt();被对话框设定一个由字符串表示的整型值。CSemaphore—aCSyncObjectaCObject在一个进程或多个进程中允许访问一种资源的允许线程数,CSemaphore对象维持当前获取种指定资源的线程个数。当计数大于。时,Semaphore对象的状态是有信号状态;典型应用是用Semaphore去限制使用一种资源的线程个数。用WaitforSingleObject等待有信号状态,返回时则减少对Semaphore的计数。3.得到计算机所有驱动函数GetAIIDriverListOCStringtmp=_T('*A:"""),dir;for(inti=1;i<=25;i++){dir=CString(*A'+i)+_T(U:');if(GetDriveType(dir.GetBuffer(O))==DRIVE_NO_ROOT_DIR)continue;tmp+dir;}returntmp;4.打开对话框,选择文件路径函数OnBrowse()BROWSEINFObi;chardispname[MAX_PATH],path[MAX_PATH];ITEMIDLIST*pidl;bi.hwndOwner=m_hWnd;
18bi.pidlRoot=0;bi.pszDisplayName=dispname;bi.ulFlags=BIF_RETUREONLYFSDIRS|BIF_EDITBOX|BIF_DONTGOBELOWDOMAIN;bi.lpfn=0;bi.lParam=0;bi.ilmage=0;if(pidl=SHBrowseForFolder(&bi)){〃显示一个使用用户可以选择的文件打开对话框SHGetPathFromlDList(pidl,path);〃把一个itemidentifierlist转化为一个文件系统路径m_folder=CString(path);if(m_folder.lsEmpty())mjolder=GetAIIDirverList();UpdateData(FALSE);}SHGetFilelnfo();返回文件系统中对象的信息,比如文件、folder、路径、驮动器2.如何使用ClmageListClmageListmJImageList;m_ilmageList.Create(24,24,TRUE,1,0);HICONhlcon=NULL;hlcon=(HICON)::Loadlmage(::AfxGetlnstanceHandle(),MAKEINTRESOURCE(IDI_KEBIAOO,IMAGE_ICON,24,24,0);mJlmageList.Add(hlcon);m_FileTree.SetlmageList(&m_ilmageList,TVSIL_NORMAL);//m_FileTree为TreeList控件〃或者这样来创建:m_imageList.DeletelmageList();m_image.Create(16,16,ILC_COLORDDB,1,100);mJistCtrl.SetlmageList(&mJlmageList,LVSIL_SMALL);3.遍历一个文件夹的文件OnFindFile(WPARAMwParam,LPARAMIParam){
19CStringstrFilePath=*((CString*)wParam);if(strFilePath.Right(1)!=Mm,,,){strFilePath+="""";}strFilePath+="*.*";CFileFindfinder;CStringstrFileName;BOOLisHave=finder.FindFile(strFilePath);while(isHave){isHave=finder.FindNextFile();if(!finder.lsDirectory()&&!finder.lsDots()){strFileName=finder.GetFilePath();::PostMessage((HWND)(GetMainWnd()->GetSafeHWnd()),WM_DISPLAY,(WPARAM)&strFileName,NULL);}}finder.Close();}2.如何来启动这个查找线程新建一个类派生于CWinThread;CFindFileThread*pFindFileThread;pFindFileThread=(CFindFileThread*)AfxBeginThread(RUNTIME_CLASS(CFindFileThread);pFindFileThread->PostThreadMessage(WM_FINDFILE,(WPARAM)&strFilePath,NULL);8,找到一个则发送消息WM_DISPLAY,并把文件中全路径作为参数返回获取一个文件的信息OnDisplay(WPARAMwParam,LPARAMIParam){count++;〃统计文件个数CStringstrFileName=*((CString*)wParam);CFileStatusstatus;C:GetStatus(strFileName,status);CStringunit="Byte”;
20floatflen=(float)status.m_size;if(flen>1024){flen/=1024;if(flen<1024)unit="KB”;else{flen/=1024;unit="MB”;}}CStringsize;size.Format(M%1.2fn,flen);intpos=strFileName.ReverseFind(4,'H,);SHFILEINFOsfi;〃文件信息结构体if(::SHGetFilelnfo(strFileName,FILE_ATTRIBUTE_NORMAL,&sfi,Sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES|SHGFI_DISPLAYNAME|SHGFI_TYPENAME|SHGFIJCON|SHGFI_SMALLICON)){mJmgList.Add(sfi.hlcon);m_filelist.lnsertltem(count-1,sfi.szDisplayName,count-1);m_filelist.SetltemText(count-1,1,strFileName,Mid(0,pos));m_filelist.SetltemText(count-1,2,(size+unit));m_filelist.SetltemText(count-1,3,sfi.szTypeName);}m_filelist.Update(count-1);}9.在图片中隐藏信息的做法:加社会图片文件为c:"s.jpg,文字为d:"w.txt,在命令行方式窗口中输入命令COPY/BC:"s.jpg+d:"w.txtc:"d.jpg10.获得应用程序所在路径charszCurPathLMAX_PATH];HINSTANCEhlnst=NULL;
21GetMoudleFileName(hlnst,szCurPath,_MAX_PATH);//获得应用程序所在路径char*p=szCurPath;while(strchr(p,""")){p=strchr(p,""");P++;}*p=*"0';ShellExecute(NULL,NULL,_T(uYour.exe"),NULL,_T(szCurPath),SW_SHOWNORMAL);总结问题的解决方法,有助于获得更多的实战经验,不断地积累,在编程方面就会有长足的进步〜!学习的过程是一个不断积累的过程,只有学习的时间累积到一定的程度,才能发生质的提高。。。(1)如何通过代码获得应用程序主窗口的指针?主窗口的指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。AfxGetMainWnd()->ShowWindow(SW_SHOWMAXMIZED)〃使程序最大化.(2)确定应用程序的路径UseGetModuleFileName获得应用程序的路径,然后去掉可执行文件名。Example:TCHARexeFullPath[MAX_PATH]//MAX_PATH在API中定义了吧,好象是128GetModuleFileName(NULL,exeFullPath,MAX_PATH)(3)如何在程序中获得其他程序的图标?两种方法:(1)SDK函数SHGetFilelnfo或使用Extracticon获得图标资源的handle,(2)SDK函数SHGetFilelnfo获得有关文件的很多信息,如大小图标,属性,类型等.Example(1):在程序窗口左上角显示NotePad图标.voidCSampleView:OnDraw(CDC*pDC)(if(::SHGetFilelnfo(_T("c:""pwin95""notepad.exe"),0,&stFilelnfo,sizeof(stFilelnfo),SHGFI_ICON))|pDC->Drawlcon(10,10,stFilelnfo.hlcon)})Example(2):同样功能,UseExtracticonFunctionvoidCSampleView::OnDraw(CDC*pDC)(
22HICONhlcon=::Extractlcon(AfxGetlnstanceHandle(),_T("NotePad.exe"),0)if(hlcon&&hlcon!=(HICON)-1)pDC->Drawlcon(10,10,hlcon))说明:获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到,如果是调用win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点.(4)获得各种目录信息Windows目录:Use"GetWindowsDirectory"Windows下的system目录:Use"GetSystemDirectory"temp目录:Use"GetTempPath"当前H录:Use"GetCurrentDirectory"请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反.(5)如何自定义消息1)手工定义消息,可以这么写#defineWM_MY_MESSAGE(WM_USER+100),MS推荐的至少是WM_USER+100(2)写消息处理函数,用WPARAM.LPARAM返回LRESULT.LRESULTCMainFrame::OnMyMessage(WPARAMwparam,LPARAMIParam)(tempIT录:Use"GetTempPath"〃加入你的处理函数irectory")(6)如何改变窗口的图标?向窗口发送WM_SECTION消息。Example:HICONhlcon=AfxGetApp()->Loadlcon(IDI_ICON)ASSERT(hlcon)AfxGetMainWnd()->SendMessage(WM_SECTION,TRUE,(LPARAM)hlcon)(7)如何改变窗口的缺省风格?重载CWnd::PreCreateWindow并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.
23Example:Delete"Max"ButtonandSetOriginalWindow'sPositionandSizeBOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)(cs.style&=-WS_MAXINIZEMOXcs.x=cs.y=0cs.cx=GetSystemMetrics(SM_CXSCREEN/2)cs.cy=GetSystemMetrics(SM_CYSCREEN/2)returnCMDIFramewnd::PreCreateWindow(cs)}(8)如何将窗口居中显示?CallFunctionCWnd::CenterWindowsExample(1):CenterWindow()//Relativetoit'sparent//RelativetoScreenExample(2):CenterWindow(CWnd::GetDesktopWindow())//RelativetoApplication'sMainWindowAfxGetMainWnd()->CenterWindow()(9)如何让窗口和MDI窗口一启动就最大化和最小化?先说窗口。在InitStance函数中设定m_nCmdShow的取值.m_nCmdShow=SW_SHOWMAXMIZED〃最大化m_nCmdShow=SW_SHOWMINMIZED〃最小化m_nCmdShow=SW_SHOWNORMAL〃正常方式MDI窗口:如果是创建新的应用程序,可以用MFCAppWizard的Advanced按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载MDIWindow的PreCreateWindow函数,设置WS.MAXMIZEorWS_MINMIZE
24如果从CMDIChildWnd派生,调用OnlrdtialUpdate函数中的CWnd::ShowWindow来指定MDIChildWindow的风格。(10)如何限制窗口的大小?也就是FixedDialog形式。Windows发送WM_GETMAXMININFO消息来跟踪,响应它,在OnGetMAXMlNINFO中写代码:(11)如何使窗口不可见?很简单,用SW_HIDE隐藏窗口,可以结合FindWindow,ShowWindow控制.(12)如何创建一个字回绕的CEdtView重载CWnd::PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位,由于CEditView::PreCreateWindow显示设置cs.style,调用基类函数后要修改cs.style,BOOLCSampleEDitView::PreCreateWindow(CREATESTRUCT&cs)(//Firstcallbasseclassfunction.BOOLbResutl=CEditView::PreCreateWindow(cs)//Nowspecifythenewwindowstyle.cs.style&=~(ES_AUTOHSCROLLIWS_HSCROLL)returnbResult)(13)如何使程序保持极小状态?这么办:在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用ClassWizard设置成员函数OnQueryOpen(),addfollowingcode:BoolCMainFrame::OnQueryOpen()(Returnfalse)(14)移动窗口调用CWnd::SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd::MoveWindow时必须要指定窗口的大小。//Movewindowtopositoin100,100ofitsparentwindow.SetWindowPos(NULL,100,100,0,0,SWP_NOSIZEISWP_NOAORDER)(15)通用控件的显示窗口MFC提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEdNiew封装了编辑控件,CTreeView保持了树列表控件,CListView
25封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。(16)重置窗口的大小调用CWnd::SetWindowPos并指定SWP_NOMOVE标志,也可调用CWnd::MoveWindow但必须指定窗口的位置。//Getthesizeofthewindow.GreetreWindowGetWindowRect(reWindow)//Makethewindowtwiceaswideandtwiceastall.SetWindowPos(NULL,0,0,reWindow.Width()*2,reWindow.Height()*2,SWP_NOMOVEISWP_NOZORDER)(17)如何单击除了窗口标题栏以外的区域使窗口移动当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数,如果函数返回HTCLIENT则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。UINTCSampleDialog::OnNcHitTest(Cpointpoint)|UINTnHitTest=Cdialog::OnNcHitTest(point)return(nHitTest==HTCLIENT)?HTCAPTION:nHitTest}上述技术有两点不利之处,其一是在窗口的客户区域双击时,窗口将极大;其二,它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION,voidCSampleView::OnLButtonDown(UINTnFlags,Cpointpoint)(CView::OnLButtonDow(nFlags,pont)//Foolframewindowintothinkingsomeneclickedonitscaptionbar.GetParentFrame()—>PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(poitn.x,point.y))
26}该技术也适用于对话框和基于对的应用程序,只是不必调用CWnd::GetParentFrame。voidCSampleDialog::OnLbuttonDown(UINTnFlags,Cpointpoint)(Cdialog::OnLButtonDow(nFlags,goint)//Fooldialogintothinkingsimeoneclickedonitscaptionbar.PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARM(point.x,point,y)))(18)如何改变视窗的背景颜色Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。//Paintareathatneedstobeerased.BOOLCSampleView::OnEraseBkgnd(CDC*pDC)(//Createapruplebrush.CBrushBrush(RGB(128,0,128))//Selectthebrushintothedevicecontext.CBrush*pOldBrush=pDC—>SelcetObject(&brush)//Gettheareathatneedstobeerased.CRectreClippDC—>GetCilpBox(&rcClip)//Paintthearea.pDC—>PatBIt(rcClip.left,rcClip.top,rcClip.Width(),rcClip.Height(),PATCOPY)//Unselectbrushoutofdevicecontext.pDC—>SelectObject(pOldBrush)//Returnnonzerotohalffrutherprocessing.returnTRUE}(19)如何改变窗口标题调用CWnd::SetWindowText可以改变任何窗口(包括控件)的标题。//Settitleforapplication'smainframewindow.
27A仅GetMainWnd()—>SetWindowText(_T(MApplicationtitle*'))//SettitleforView'sMDIchildframewindow.GetParentFrame()—>SetWindowText(M_T("MDIChildFramenewtitle'*))//Settitlefordialog'spushbuttoncontrol.GetDigitem(IDC_BUTTON)—>SetWindowText(_T("Buttonnewtitle”))如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数A仅SetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化,在以后发行的MFC中将文档化。AfxSetWindowText的实现如下:voikAFXAPIAfxSetWindowText(HWNDhWndCtrl,LPCTSTRIpszNew)(itnnNewLen=Istrlen(Ipaznew)TCHARszOld[256]//fastchecktoseeiftextreallychanges(reducesflashinthecontrols)if(nNewLen>_contof(szOld)||::GetWindowText(hWndCrtl,szOld,_countof(szOld)!=nNewLenIIIstrcmp(szOld,IpszNew)!=0(//changeit::SetWindowText(hWndCtrl,IpszNew)})(20)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard市:置CWnd::PreCreateWindow并关闭FWS_ADDTOTITLE风格。BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)(//TurnoffFWS_ADDTOTITLEinmainframe.cs.styel&=~FWS_ADDTOTITLEreturnCMDIFrameWnd::PreCreateWindow(cs))关闭MDI子窗口的FWS_ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd::SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(21)如何获取有关窗口正在处理的当前消息的信息
28调用CWnd::GetCurrentMessage可以获取一个MSG指针。例J如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。viodCMainFrame::OnCommmonMenuHandler()(//Displayselectedmenuitemindebugwindow.TRACE("Menuitem%uwasselected."n",(22)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX」DW_TOOLBAR标识符,下例说明了如何通过•起调用CWnd::GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针://Getpointertostatusbar.CStatusBar*pStatusBar=(CStatusBar*)AfxGetMainWnd()—>GetDescendantWindow(AFX_IDW_STUTUS_BAR)//Getpointertotoolbar.CToolBar*pToolBar=(CToolBar*)AfxGetMainWnd()—>GetDescendantWindow(AFX_IDW_TOOLBAR)(23)如何使能和禁止工具条的工具提示如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar::GetBarStyle和CControlBar::SetBarStyle建立一个完成此功能的成员函数:voidCMainFrame::EnableToolTips(BOOLbDisplayTips)|ASSERT_VALID(m_wndToolBar)DWORDdwStyle=m_wndToolBar.GetBarStyle()if(bDisplayTips)dwStyleI=CBRS_TOOLTIPSelsedwStyle&=~CBRS_TOOLTIPSm_wndToolBar.SetBarStyle(dwStyle)(24)如何创建一个不规则形状的窗口可以使用新的SDK函数SetWindowRgno该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。ClassCRoundDIg:publicCDialog(
29private:Crgnm_rgn://windowregion)修改OnlnitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:BOOLCRoundDIg::OnlnitDialog()(CDialog::OnlnitDialog()//Getsizeofdialog.CRectrcDialogGetClientRect(rcDialog)//Createregionandassigntowindow.m_rgn.CreateEllipticRgn(0,0,rcDialog.Width(),rcDialog.Height())SetWindowRgn(GetSafeHwnd(),(HRGN)m_rgn,TRUE)returnTRUE)通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。voikCRoundDIg::OnPaint()(CPaintDCde(this)//devicecontextforpainting//drawellipsewithoutanyborderde.SelecStockObject(NULL_PEN)//gettheRGBcolourcomponentsofthespherecolorCOLORREFcolor=RGB(0,0,255)BYTEbyRed=GetRValue(color)BYTEbyGreen=GetGValue(color)BYTEbyBlue=GetBValue(color)//getthesizeoftheviewwindowCrectrectGetClientRect(rect)//getminimunnumberofunitsintnUnits=min(rect.right,rect.bottom)//calculatehehoriaontalandverticalstepsizefloatfltStepHorz=(float)rect.right/nUnitsfloatfltStepVert=(float)rect.bottom/nUnitsintnEllipse=nllnits/3//calculatehowmanytodrawintnlndex//currentellipsethatisbeingdrawCBrushbrush
30//burshusedforellipsefillcolorCBrush*pBrushOld//previousbrushthatwasselectedintode//drawellipse,graduallymovingtowardsupper-rightcornerfor(nlndex=0nlndes<+nEllipsenlndes++)(//creatsolidbrushbrush.CreatSolidBrush(RGB(((nlndex*byRed)/nEllipse).((nlndex*byGreen)/nEllipse),((nlndex*byBlue)/nEllipse)))//selectbrushintodepBrushOld=de.SelectObject(&brhsh)//drawellipsede.Ellipse((int)fltStepHorz*2,(int)fltStepVert*nlndex,rect.right-((int)fltStepHorz*nlndex)+1,rect.bottom-((int)fltStepVert*(nlndex*2))+1)//deletethebrushbrush.DelecteObject()}}最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。UINTCRoundDIg::OnNchitTest(Cpointpoint)//Letusermovewindowbyclickignanywhereonthewindow.UINTnHitTest=CDialog::OnNcHitTest(point)rerurn(nHitTest==HTCLIENT)?HTCAPTION:nHitTest}(25)如何获取应用程序的实例句柄?应用程序的实例句柄保存在CWinAppm_hInstance中,可以这么调用A仅GetlnstancdHandle获得句柄.Example:HANDLEhlnstance=AfxGetlnstanceHandle()(26)如何编程结束应用程序?这是个很简单又是编程中经常要遇到的问题.向窗口发送WM_CLOSE消息,调用CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.Example:AfxGetMainWindow()->SendMessage(WM_CLOSE)还可以创建一个自定义的函数TerminateWindowvoidTerminateWindow(LPCSTRpCaption)(CWnd*pWnd=Cwnd::FindWindow(NULL,pCaption)if(pWnd)pWnd->SendMessage(WM_CLOSE))说明:FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举windows任务列表的办法来实现。在机械出版社"Windows95Api开发人
31员指南"一书有比较详细的介绍,这里就不再多说乐。(27)如何创建和使用无模式对话框MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用Classwizard创建个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog::EndDialog来中止,无模式对话则是调用CWnd::DestroyWindow来中止的,函数CDialog::OnOK和CDialog::OnCancel调用EndDialog,所以需要调用DestroyWindow并重置无模式对话的函数。voidCSampleDialog::OnOK()(//Retrieveandvalidatedialogdata.if(!UpdateData(TRUE))//theUpdateDatarountinew川setfocustocorrectitemTRACEO('*UpdateDatafailedduringdialogterminationJn”)return)//CallDestroyWindowinsteadofEndDialog.DestroyWindow())voidCSampleDialog::OnCancel()(//CallDestroyWindowinsteadofEndDialog.DestroyWindow())其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象:无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对,象。撤销窗口时工作框调用CWnd::PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。voidCSampleDialog::PostNcDestroy()(//DecletetheC++objectthatrepresentsthisdialog.deletethis最后,要创建无模式对话。可以调用CDialog::DoModal创建,个模式对■放,要创建•个无模式对话则要调用CDialog::Createo下面的例子说明了应用程序是如何创建无模式对话的:象;无模式对话不是同步的,创建函数调用后立即返回,voidCMainFrame::OnSampleDialog()
32(//Allocateamodelessdialogobject.CSampleDilog*pDialog=newCSampleDialogASSERT_VALID(pDialog)Destroy()//Createthemodelessdialog.representsthisdialog.BOOLbResult=pDialog—>Creste(IDDJDALOG)ASSERT(bResult))(28)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希里在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard重置CWnd::PreCreateWindow并关闭FWS_ADDTOTITLE风格。BOOLCMainFrame::PreCreateWindow(CREATESTRUCT&cs)//TurnoffFWS_ADDTOTITLEinmainframe.cs.styel&=-FWS_ADDTOTITLEreturnCMDIFrameWnd::PreCreateWindow(cs))关闭MDI子窗口的FWS_ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd::SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(29)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有个AFX」DW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd::GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针://Getpointertostatusbar.CStatusBar*pStatusBar=(CStatusBar*)AfxGetMainWnd()—>GetDescendantWindow(AFX_IDW_STUTUS_BAR)//Getpointertotoolbar.CToolBar*pToolBar=(CToolBar*)AfxGetMainWnd()—>GetDescendantWindow(AFX_IDW_TOOLBAR)(30)怎样加载其他的应用程序?三个SDK函数winexec,shellexecute,createprocess可以使用。WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是己经被加到任务列表里了。
33ShellExecute较WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开cRempT.txt,而不用加载与txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示ReadmeorFaq,我猜就是这么作的啦.ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:""temp"),SW_SHOWMAXMIZED)CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:STARTUPINFOstinfo〃启动窗口的信息PROCESSINFOprocinfo〃进程的信息CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&stinfo,&procinfo)(31)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX」DW_STATUS_BAR标识符,工具条有一个AFX」DW_TOOLBAR标识符,下例说明了如何通过•起调用CWnd::GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针://Getpointertostatusbar.CStatusBar*pStatusBar=(CStatusBar*)AbcGetMainWnd()—>GetDescendantWindow(AFX_IDW_STUTUS_BAR)(32)如何使能和禁止工具条的工具提示如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CContro旧ar::GetBarStyle和CControlBar::SetBarStyle建立一个完成此功能的成员函数:voidCMainFrame::EnableToolTips(BOOLbDisplayTips)(ASSERT_VALID(m_wndToolBar)DWORDdwStyle=m_wndToolBar.GetBarStyle()if(bDisplayTips)dwStyleI=CBRS_TOOLTIPSelsedwStyle&=-CBRS_TOOLTIPSm_wndToolBar.SetBarStyle(dwStyle))//Getpointertotoolbar.CToolBar*pToolBar=(CToolBar*)AfxGetMainWnd()—>GetDescendantWindow(AFX_IDW_TOOLBAR)(33)如何设置工具条标题
34工具条是一个窗口,所以可以在调用CWnd::SetWindowText来设置标题,例子如下:intCMainFrame::OnCreate(LPCREATESTRUCTIpCreateStruct)(//Setthecaptionofthetoolbar.m_wndToolBar.SetWindowText(_T"Standdard")(34)如何使窗口始终在最前方?BringWindowToTop(Handle)SetWindowPos函数,指定窗口的最顶风格,用WS_EX_TOPMOST扩展窗口的风格Example:voidToggleTopMost(CWnd*pWnd)(ASSERT_VALID(pWnd)pWnd->SetWindowPos(pWnd->GetStyle()&WS_EX_TOPMOST)?&wndNoTopMOST:&wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)}(35)如何在对话框中显示一个位图这要归功于Win32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是很容易的,只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。(36)如何改变对话或窗体视窗的背景颜色调用CWinApp::SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。BOOLCSampleApp::Initlnstance()(//usebluedialogwithyellowtext.SetDialogBkColor(RGB(0,0,255),RGB(255,255,0)))需耍重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。首先,给对话基类增加一人成员变量CBursh:classCMyFormView:publicCFormView(
35private:CBrushm_brush//backgroundbrush}其次,在类的构造函数中将刷子初始化为所需要的背景颜色。CMyFormView::CMyFormView()//Initializebackgroundbrush.m_brush.CreateSolidBrush(RGB(0,0,255)))最后,使用Classwizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtIColor参量。HBRUSHCMyFormView::OnCtIColor(CDC*pDC,CWnd*pWnd,UINTnCtIColor)(//Determineifdrawingadialogbox.Ifweare,return+handleto//ourownbackgroundbrush.Otherwiseletwindowshandleit.if(nCtIColor==CTLCOLOR_DLG)return(HBRUSH)m_brush.GetSafeHandle()returnCFormView::OnCtIColor(pDC,pWnd,nCtIColor))(37)如何获取一个对话控件的指针有两种方法。其一,调用CWnd::GetDIgltem,获取一个CWnd*指针调用成员函数。下例调用GetDIgltem,将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl::SetPos函数:BOOLCSampleDialog::OnlnitDialog()(CDialog::OnlnitDialog()//Getpointertospinbutton.CSpinButtonCtrl*pSpin-(CSpinButtonCtrl*)GetDlgltem(IDC_SPIN)ASSERT_VALID(pSpin)//Setspinbutton'sdefaultposition.pSpin—>SetPos(10)returnTRUE}其二,可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择MemberVariables标签,然后选择AddVariable…按钮。如果在对话资源编辑器中,按下Ctrl键并双击控件即可转到AddMemberVariable对话。
36(38)如何禁止和使能控件控件也是窗口,所以可以调用CWnd::EnableWindow使能和禁止控件。//Disablebuttoncontrols.m_wndOK.EnableWindow(FALSE)m_wndApply.EnableWindow(FALSE)(39)如何改变控件的字体由于控件是也是窗口,用户可以调用CWnd::SetFont指定新字体。该函数用一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为8点Arial字体://Declarefontobjectinclassdeclaration(.Hfile).private:Cfontm_font//Setfontinclassimplementation(.Cppfile).Notem_wndButtonisa//membervariableaddedbyClassWizard.DDXroutineshookthemember//variabletoadialogbuttoncontrlo.BOOLCSampleDialog::OnlnitDialog()(//Createan8-pointArialfontm_font.CreateFont(MulDiv(8,-pDC—>GetDeviceCaps(LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSLCHARSER,OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITYVARIABLE_PITCHIFF_SWISS,_T("Arial"))//Setfontforpushbutton.m_wndButton.SetFont(&m_font)}(40)如何在OLE控件中使用OLE_COLOR数据类型诸如COIeControl::GetFortColor和COIeControl::GetBackColor等函数返回OLE_COLOR数据类型的颜色,而GDI对象诸如笔和刷子使用的是COLORREF数据类型,调用COIeControl::TranslateColor可以很容易地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子:voidCSampleControl::OnDraw(CDC*pdcconstCrect&rcBounds,constCrect&rclnvalid)
37(//Createabrushofthecuttentbackgroundcolor.CBrushbrushBack(TranslateColor(GetBackColor()))//Paintthebackgroundusingthecurrentbackgroundcolor.pdc—>FilllRect(rcBounds,&brushBack)//otherdrawigncommands(41)在不使用通用文件打开对话的情况下如何显示一个文件列表调用CWnd::DlgDirList或者CWnd::DlgDirListComboBox,Windows将自动地向列表框或组合框填充可用的驱动器名或者指定目录中的文件,下例将Windows目录中的文件填充在组合框中:BOOLCSampleDig::OnlnitDialog()|CDialog::OnlnitDialog()TCHARszPath[MAX_PATH]={"c/'"windows"}intnResIt=DlgDirListComboBox(szPath,IDC_COMBO,IDC_CURIDIR,DDL_READWRITEIDDL_READONLYIDDL_HIDDENIDDL_SYSTEMIDDL_ARCHIVE)returnTRUE}(42)为什么旋转按钮控件看起来倒转需要调用CSpinCtrl::SetRange设置旋转按钮控件的范围,旋转按钮控件的缺省上限为0.缺省下限为100,这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为。到100:BOOLCAboutDIg::OnlnitDialog()|CDialog::OnlnitDialog()//setthelowerandupperlimitofthespinbuttonm_wndSpin.SetRange(0,100)returnTRUE}VisualC++4.0Print对话中的Copise旋转按钮控件也有同样的问题:按下Up按钮时拷贝的数目减少,而按下Down按钮时拷贝的数H增加。(43)为什么旋转按钮控件不能自动地更新它卜面的编辑控件
38如果使用旋转按钮的autubuddy特性,则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择TabOrder菜单项(或者按下Crtl+D)可以设置对话的标签顺序。(44)如何用位图显示下压按钮Windows95按钮有几处新的创建风格,尤其是BS_BITMAP和BS_ICON,要想具有位图按钮,创建按钮和调用CButton::SetBitmap或CButton::Seticon时要指定BS_BITMAP或BS」CON风格。首先,设置按钮的图标属性。然后,当对话初始化时调用CButton::Seticon。注意:下例用图标代替位图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰色。BOOLCSampleDIg::OnlnitDialog()(CDialog::OnlnitDialog()//settheimagesforthepushbuttons.BOOLCSampleDIg::OnlnitDialog()(CDialog::OnlnitDialog()//settheimagesforthepushbuttons.m_wndButton1.Seticon(AfxGetApp()—>Loadicon(IDI_IPTION1))m_wndButton2.Setlcon(AfxGetApp()—>Loadicon(IDI_IPTION2))m_wndButton3.Setlcon(AfxGetApp()—>Loadicon(IDI_IPTION3))returnTRUE)(45)如何一个创建三态下压按钮可以使用新的BS_PUSHBUTTON风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到时话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。(46)如何动态创建控件分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件://Inclassdeclaration(.Hfile).private:CButton*m_pButton//Inclassimplementation(.cppfile).mjiButton=newCButtonASSERT_VALID(m_pButton)m_pButton—>Create(_T("ButtonTitle"),WS_CHILDIWS_VISIBLEIBS_PUSHBUTTON.Crect(0,0,100,24),this,IDC_MYBUTTON)(47)如何限制编辑框中的准许字符如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标
39志£$_(^111\^£区5,它是亚衍€10\^95新增加的标志,该标志限制编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft的屏蔽编辑控件,它是•个很有用的OLE定制控件。如果希望不使用OLE定制控件自己处理字符,可以派生一个CEdit类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用Classwizard建立一个CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnlNtdialog中调用CWnd::SubclassDIgltem.//Inyourdialogclassdeclaration(,Hfile)private:CMyEditmwndEdit//Instanceofyourneweditcontrol.//Inyoudialogclassimplementation(.CPPfile)BOOLCSampleDialog::OnlnitDialog()|//Subclasstheeditlontrod.m_wndEdit.SubclassDIgltem(IDC_EDIT,this))使用Classwizard处理WM_CHAR消息,计算nChar参量并决定所执行的操作,用户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母字符,则调用CWndOnChar,否则不调用OnChar.//Onlydisplayalphabeticdharacters.voidCMyEdit::OnChar(UINTnChar,UINTnRepCnt,UITNnFlags)(//DetermineifnCharisanalphabeticcharacter.if(::IsCharAlpha((TCHAR)nChar))CEdit::OnChar(nChar,nRepCnt,nFlags))如果要修改字符,则不能仅仅简单地用修改过的nChar调用CEdit::OnChar,然后CEdit::OnChar调用CWnd::Default获取原来的wParam和IParam的值,这样是不行的。要修改.一个字符,需要首先修改nChar,然后用修改过的nChar调用CWnd::DefWindowProc。下例说明了如何将字符转变为大写://MakeallcharactersuppercasevoidCMyEdit::OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)|//Makesurecharacterisuppercase.if(::IsCharAlpha(.(TCHAR)nChar)nChar=::Charllpper(nChar)//BypassdefaultOnCharprocessinganddirectlycall//defaultwindowproc.
40DefWindProc(WM_CHAR,nChar,MAKELPARAM(nRepCnt,nFlags))}(48)如何改变控件的颜色有两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。当控件需要重新着色时,工作框调用父窗口(通常是时话框)的CWnd::OnCrtIColor,可以在父窗口类中重置该函数并指定控件的新的绘画属性。例如,下述代码将对话中的所有编辑控件文本颜色改为红色:HBRUSHCAboutDig::OnCtIColor(CDC*pDCM,CWnd*pWnd,UINTnCtIColor)(HBRUSHhbr=CDialog::OnCtIColor(pDC,pWnd,nCtIColor)//Drawredtextforalleditcontrols.if(nCtlColor==CTLCOLOR_EDIT)pDC—>SetTextColor(RGB(255,0,0,))returnhbr}然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。苜先,使用Classwizard创建一个CListBox的派生类并为该类添加下述数据成员。classCMyListBoxpublilcCListBox(privateCOLORREFm_clrFor//foregroundcolorCOLORREFm_clrBack//backgroundcolorCbrushm_brush//backgroundbrush)其次,在类的构造函数中,初始化数据中。CMyListBox::CMyListBox()(//Initializedatamembers.m_clrFore=RGB(255,255,0)//yellowtextm_clrBack=RGB(0,0,255)〃bluebackgroundm_brush.CreateSolidBrush(m_clrBack))
41最后,使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的绘画属性。HBRUSHCMyListBox::CtIColor(CDC*pDC,UINTnCtIColor)(pDC—>SetTextColor(m_clrFore)pDC—>SetBkColor(mclrBack)return(HBRUSH)m_brush.GetSafeHandle())现在,控件可以自己决定如何绘画,与父窗口无关。(49)当向列表框中添加多个项时如何防止闪烁调用CWnd::SetRedraw清除重画标志可以禁止CListBox(或者窗口)重画。当向列表框添加几个项时,用户可以清除重画标志,然后添加项,最后恢复重画标志。为确保重画列表框的新项,调用SetRedraw(TRUE)之后调用CWnd::lnvalidate»//Disableredrawing.pListBox->SetRedraw(FALSE)//Fillinthelistboxgere//Enabledrwingandmakesurelistboxisredrawn.pListBox->SetRedraw(TRUE)pListBox->lnvalidate()(50)如何向编辑控件中添加文本由于没有CEdit::AppendText函数,用户只好自己做此项工作。调用CEdit::SetSel移动到编辑控件末尾,然后调用CEdit::ReplaceSel添加文本。下例是AppendText的一种实现方法:voidCMyEdit::AppendText(LPCSTRpText){intnLen=GetWindowTextLength()SetFocus()SetSel(nLen,nLen)ReplaceSel(pText))(51)如何访问预定义的GDI对象可以通过调用CDC::SlectStockObject使用Windows的几个预定义的对象,诸如刷子、笔以及字体。下例使用了Windows预定义的笔和刷子GDI对象在视窗中画一个椭圆。//Drawellipseusingstockblackpenandgraybrush.voidCSampleView::OnDraw(CDC*pDC)(
42//Determinesizeofview.CRectreViewGetClientRect(reView)//Usestockblackpenandstockgraybrushtodrawellipse.pDC->SelectStockObject(BLACK_PEN)pDC->SelectStockObject(GRAY_BRUSH)//Drawtheellipse.pDC->Ellipse(reView))也可以调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子,下例用背景色在视窗中画一个椭圆:voidCsampleView::OnDraw(CDC*pDC)(//Determinesizeofview.CRectreViewGetClientRect(reView)//Usebackgroundcolorfortooltipsbrush.CBrush*pOrgBrush=pDC->SelectObject(CBrush::FromHandle(::GetSysColorBrush(COLOR」NFOBK)))//Drawtheellipse.pDC->Ellipse(reView)//Restoreoriginalbrush.pDC->SelectObject(pOrgBrush)}(52)如何获取GDI对象的属性信息可以调用GDlObject::GetObjecto这个函数将指定图表设备的消息写入到缓冲区。下例创建了几个有用的辅助函数。//Determineiffontisbold.BOOLIsFontBold(constCFont&font)LOGFONTstFontfont.GetObject(sizeof(LOGFONT),&stFont)return(stFont.lfBold)?TRUE:FALSE}//Returnthesizeofabitmap.CSizeGetBitmapSize(constCBitmap&bitmap)(BITMAPstBitmapbitmap.GetObject(sizeof(BITMAP),&stBitmap)
43returnCSize(stBitmap.bmWidth,stBitmap.bmHeight))//Createapenwiththesamecolorasabrush.BOOLCreatePenFromBrush(Cpen&pen,costCbrush&brush)(LOGBRUSHstBrushbrush.Getobject(sizeof(LOGBRUSH),&stBrush)returnpen.Createpen(PS_SOLID,0,stBrush.ibColor)}(53)如何实现一个橡皮区矩形CRectTracker是一个很有用的类,可以通过调用CRectTracker::TrackRubberBand响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。首先,在文件档中声明一个CRectTracker数据成员:classCSampleView:PublicCView(public:CrectTrackerm_tracker)其次,在文档类的构造函数中初始化CRectTracker对象:CSampleDoc::CSampleDOC()(//Initializetrackerposition,sizeandstyle.m_tracker.m_rect.SetRect(0,0,10,10)m_tracker.m_nStyle=CRectTracker::resizeinside|CRectTracker::dottedLine}然后,在OnDraw函数中画椭圆和踪迹矩形:voidCSampleView::OnDraw(CDC*pDC)CSampleDoc*pDoc=GetDocument()ASSERT_VALID(pDoc)//Selectbluebrushintodevicecontext.CBrushbrush(RGB(0,0,255))CBrush*pOldBrush=pDC->SelectObject(&brush)//drawellipseintrackingrectangle.GreetrcEllipsepDoc->m_tracker.GetTrueRect(rcEllipse)pDC->Ellipse(rcEllipse)//Drawtrackingrectangle.pDoc->m_tracker.Draw(pDC)//Selectbluebrushoutofdevicecontext.
44pDC->Selectobject(pOldBrush)}最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。voidCSampleView::OnLButtonDown(UINTnFlags,CPointpoint)(//Getpointertodocument.CSampleDoc*pDoc=GetDocument()ASSERT_VALID(pDoc)//Ifclickedonellipse,dragorresizeit.Otherwisecreatea//rubber-bandrectanglendcreateanewellipse.BOOLbResult=pDoc->m_tracker.HitTest(point)!=CRectTracker::hitNothing//Trackerrectanglechangedsoupdateviews.if(bResult)(pDoc->m_tracker.Track(this,point,TRue)pDoc->SetModifiedFlag()pDoc->UpdateAIIViews(NULL)}elsepDoc->m-tracker.TrackRubberBand(this,point,TRUE)CView::onLButtonDown(nFlags,point)}(54)如何更新翻转背景颜色的文本调用CDC::SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。voidCSampleView::OnDraw(CDC*pDC)(//Determintsizeofview.CRectreViewGetClientRect(rcVieew)//Createsamplestringtodisplay.CStringstr(_T("AwesomeShadowText..."))//Setthebackgroundmodetotransparent.pDC->SetBKMode(TRANSPARENT)
45//Drawblackshadowtext.rcView.OffsetRect(1,1)pDc->SetTextColor(RGB(0,0,0))pDC->DrawText(str,str.GetLength(),reView,DT_SINGLELINE|DT_CENTER|DT_VCENTER)//Drawredtext.rcView.OffsetRect(-1,-1)pDc->SetTextColor(RGB(255,0,0))pDC->DrawText(str,str.GetLength(),reView,DT_SINGLELINE|DT_CENTER|DT_VCENTER))(55)如何创建一个具有特定点大小的字体可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便•些。可以如下将字体的点转换为字体的高度:intnHeigth=mulDiv(nPointSize,-dc.GetDeviceCaps(LOGPIXELSY),72)下例创建了一个8点的Apial字体:CCIientDCde(AqfxGetMainWnd())m_font.CreateFont(MulDiv(8,-dc.GetDeviceCaps(LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,VARIABLE_PITCH|FF-SWISS,_T("Arial"))(56)如何计算一个串的大小函数CDC::DettextExtent根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,山此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小山按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。LRESULTCMyButton::OnSettext(WPARAMwParam,LPARAMIParam)(//Passmessagetowindowprocedure.LRESULTbResult=CallWindowProc(*GetSuperWndProcAddr(),m_hWnd,GetCurrentMessage()->message,wParam,IParam)//Gettitleofpushbutton.CStringstrTitleGetWindowText(strTitle)//Selectcurrentfontintodevicecontext.
46CDC*pDC=GetDc()CFont*pFont=GetFont()CFont*pOldFont=pDC->SelectObject(pFont)//Calculatesizeoftitle.CSizesize=pDC->GetTextExent(strTitle,strTitle.GetLength())//Adjustthebutton'ssizebasedonitstitle.//Adda5-pixelborderaroundthebutton.SetWindowPos(NULL,0,0,size.cx+10,size.cy+10,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE)//Cleanup.pDC->SelectFont(pOldFont)ReleaseDC(pDC)returnbResult}(57)如何显示旋转文本只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的计Escapement成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,计Escapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial字体每间隔15度画一个串。voidCSampleView::OnDraw(CDC*pDC)(//Determinethesizeofthewindow.CRectrcClientGetClientRect(rcClient)//Createsamplestring.CStringstr(_T("Wheeee...lamrotating!H))//Drawtransparent,redtext.pDC->SetBkMode(TRANSPARENT)pDC->SetTextColor(RGB(255,0,0))CFontfont//fontobjectLOGFONTstFont//fontdefinition//Setfontattributesthatw川notchange.memset(&stFont,0,sizeof(LOGFONT))stFont.ifheight=MulDiv(14,-pDC->GetDeviceCaps(LOGPIXELSY),72)stFont.ifWeight=FW_NORMALstFont.ifClipPrecision=LCIP_LH_ANGLESstrcpy(stFont.lfFaceName,"Ariar*)
47//Drawtextat15degreeintervals.for(intnAngle=0nAngle<3600nAngle+=150)(//Specifynewangle.stFont.lfEscapement=nAngle//Createandselectfontintode.font.CreateFontlndirect(&stfont)CFont*pOldFont=pDC->SelectObject(&font)//Drawthetext.pDC->SelectObject(pOldFont)font.DelectObjext()}}(58)如何正确显示包含标签字符的串调用GDI文本绘画函数时需要展开标签字符,这可以通过调用CDC::TabbedTextOut或者CDC::DrawText并指定DT_EXPANDTABS标志来完成。TabbedTextOut函数允许指定标签位的数组,下例指定每20设备单位展开一个标签:voidCSampleView::OnDraw(CDC*pDC)(CTestDoc*pDoc=GetDocument()ASSERT_VALID(pDoC)CStringstrstr.Format(_T("Cathy"tNormanntOliver"))intnTabStop=20//tabsareevery20pixelspDC->TabbedtextOut(10,10,str,1,XnTabStop,10)}(59)如何快速地格式化一个CString对象调用CString::Format,该函数和printf函数具有相同的参数,下例说明了如何使用Format函数://Getsizeofwindow.CRectreWindowGetWindowRect(reWindow)//Formatmessagestring.CStringstrMessagestrMessage.Format(_T('WindowSize(%d,%d)M),rcWindow.Width(),rcWindow.Height())//Displaythemessage.MessageBox(strmessage)
48(60)串太长时如何在其末尾显示一个省略号调用CDC::DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。voidCSampleView::OnDraw(CDC*pDC)(CTestDoc*pDoc=GetDocument()ASSERT_VALID(pDoc)//AddellpsistoendofstringifitdoesnotfitpDC->Drawtext(CString("Thisisalongstring"),CRect(10,10,80,30),DT_LEFT|DT_END_ELLIPSIS)//AddellpsistomiddleofstringifitdoesnotfitpDC->DrawText(AfxgetApp()->mj)szhelpfilePath,CRect(10,40,200,60),DT_LEFT|DT_PATH_ELLIPSIS)}(61)为什么即使调用EnableMenultem菜单项后,菜单项还处于禁止状态需要将CFrameWnd::m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。//DisableMFCfromautomaticallydisablingmenuitems.m_bAuoMenuEnable=FALSE//Nowenablethemenuitem.CMenu*pMenu=GetMenu()ASSERT_VALID(pMenu)pMenu->EnableMenultem(ID_MENU_ITEM,MF_BYCOMMAND|MF_ENABLED)(62)如何给系统菜单添加一个菜单项给系统菜单添加一个菜单项需要进行下述三个步骤:首先,使用ResourceSymbols对话(在View菜单中选择ResourceSymbols...可以显示该对话)定义菜单项ID,该ID应大于OxOF而小于OxFOOO:其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd::Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的intCMainFrame::OnCreate(LPCREATESTRUCTIpCreateStruct)(//Makesuresystemmenuitemisintherightrange.ASSERT(IDM_MYSYSITEM&OxFFFO)==IDM_MYSYSITEM)ASSERT(IDM-MYSYSITEM<0xF000)//Getpointertosystemmenu.
49CMenu*pSysmenu=GetSystemmenu(FALSE)ASSERT_VALID(pSysMenu)//Addaseparatorandourmenuitemtosystemmenu.CStringStrMenultem(_TC'NewmenuitemH))pSysMenu->Appendmenu(MF_SEPARATOR)pSysMenu->AppendMenu(MF_STRING,IDM_MYSYSITEM,strMenuitem))现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理WM_SYSCOMMAND消息并检测用户菜单的nID参数:voidCMainFrame::OnSysCommand(UINTnlD,LPARAMIParam)//Determineifoursystemmenuitemwasselected.if((nID&OxFFFO)==IDM_MYSYSITEM)(//TODO-processsystemmenuitem)elseCMDIFrameWnd::OnSysCommand(nID,IParam)}最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。(63)如何确定顶层菜单所占据的菜单行数这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度:最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。intCMainFrame::GetMenuRows()(CRectrcFrame.rcClientGetWindowRect(reFrame)GetClientRect(rcClient)return(reFrame.Height()-rcClient.Height()-::GetSystemMetrics(SM_CYCAPTION)-{::getSystemMetrics(SM_CYFRAME)*2))/::GetSystemMetrics(SM_CYMENU)}(64)在用户环境中如何确定系统显示元素的颜色调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在MFC函数
50CMainFrameWnd::OnNcPaint中调用该函数设置窗口标题颜色。voidCMiniFrameWnd::OnNcPaint(){dc.SetTextColor(::GetSysColor(m_bActive?COLOR_CAPTIONTEXT:COLOR_INACTIVECAPTIONTEXT))(65)如何查询和设置系统参数在Windows3.1SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。//Createafontthatisusedforicontitles.LOGFONTstFont::SystemParametersInfo(SPIF_GETICONTITLELOGFONT,sizeof(LOGFONT),&stFont,SPIF_SENDWININICHANGE)m_font.CreateFontlndirect(&stFont)//Changethewallpapertoleaves.bmp.::SystemParametersInfo(SPI_SETDESKWALLPAPER,0,_T("forest.bmp"),SPIF_UPDATEINIFILE)(66)如何确定当前屏幕分辨率调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。//InitializeCSizeobjectwithscreensize.CSizesizeScreen(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN))(67)如何使用一个预定义的Windows光标调用CWinApp::LoadStandardCursor并传送光标标识符。BOOLCSampleDialog::OnSetCursor(CWnd*pWnd,UINTnHitTest,UINTmessage)(//Displaywaitcursorifbusy.if(m_bBusy){SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT))
51returnTRUE)returnCDialog::OnSetCursor(pWnd.nHitTest,message))(68)如何检索原先的TaskManager应用程序使用的任务列表原先的TaskManager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd::GetWindow可以检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。voidGetTadkList(CListBox&list)CStringstrCaption//Captionofwindow.list.ResetContent()//Clearlistbox.//GetfirstWindowinwindowlist.ASSERT_VALID(AbcGetMainWnd())CWnd*pWnd=AfxGetMainWnd()->GetWindow(GW_HWNDFIRST)//Walkwindowlist.while(pWnd)(//1windowvisible,hasacaption,anddoesnothaveanowner?if(pWnd->lsWindowVisible()&&pWnd->GetWindowTextLength()&&!pWnd->GetOwner())(//Addcaptionowindowtolistbox.pWnd->GetWindowText(strCaption)list.AddString(strCaption))//Getnextwindowinwindowlist.pWnd=pWnd->GetWindow(GW_HWNDNEXT)}}(69)如何确定Windows和Windows系统目录
52有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数:TCHARszDir[MAX_PATH]//Getthefullpathofthewindowsdirectory.::GetWindowsDirectory(szDir,MAX_PATH)TRACE("Windowsdirectory%s"nM,szDir)//Getthefullpathofthewindowssystemdirectory.::GetSystemDirectory(szDir,MAX_PATH)TRACE("Windowssystemdirectory%s"n",szDir)(70)在哪儿创建临文件调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。//getuniquetemporaryfile.CStringstrFileGetUniqueTempName(strFile)TRY(//Createfileandwritedata.Notethatfileisclosed//inthedestructoroftheCFileobject.CFilefile(strFile,CFile::modeCreate|Cfile::modeWrite)//writedata}CATCH(CFileException,e)(//erroropeningfile}END_CATCHVoidGetuniqueTempName(CString&strTempName)(//Getthetemporaryfilesdirectory.TCHARszTempPath[MAX_PATH]DWORDdwResult=::GetTempPath(MAX_PATH,szTempPath)ASSERT(dwResult)//Createauniquetemporaryfile.TCHARszTempFile[MAX_PATH]
53UINTnResult=GetTempFileName(szTempPath,_T("~ex"),O,szTempfile)ASSERT(nResult)strTempName=szTempFile)(71)我怎样才能建立一个等待光标?调用BeginWaitCursor函数来启动等待光标,调用EndWaitCursor函数来结束等待光标。要注意,二者都要调用app的成员函数,如下所示:AfxGetApp()->BeginWaitCursor();//要做的事AfxGetApp()->EndWaitCursor();(72)我在MDI框架中有个form视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?调用OnCloseDocument函数。(73)如何访问桌面窗口静态函数CWnd::GetDesktopWindow返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。voidCFrameWnd::BeginModalState()(//firstcountallwindowsthatneedtobedisabledUINTnCount=0HWNDhWnd=::GetWindow(::GetDesktopWindow(),GW_CHILD)while(hWnd=NULL)(if(::IsWindowEnabled(hwnd)&&CWnd::FromHandlePermanent(hWnd)!=NULL&&AfxlsDescendant(pParent->m_hWnd,hWnd)&&::SendMessage(hWnd,WM_DISABLEMODAL,0,0)==0)(++nCount}hWnd=::GetWindow(hWnd,GW_HWNDNEXT)}
54教你如何更好掌握C++(2)2011-03-1617:00:41|分类:默认分类|标签:应用程序对话框诞文档窗旦|字号订阅(74)什么是COLORREF?我该怎样用它?COLORREF是一个32-bit整型数值,它代表了一种颜色。你可以使用RGB函数来初始化COLORREF,例如:COLORREFcolor=#OOffOO;RGB函数接收三个0-255数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为0,所以在该颜色中没有红色和蓝色。绿色为最大值255=所以该颜色为绿色。0,0,0为黑色,255,255,255为白色。另一种初始化COLORREF的方法如下所示:CColorDialogcolorDialog;COLORREFcolor;if(colorDialog.DoModal()==IDOK){color=colorDialog.GetColor();)这段代码使用了MFC中的颜色对话框,它需要文件。(75)AppWizard所产生的STDAFX文件是干什么用的?它主要是协助产生预编译头文件的。通常你是不需要修改它的。(76)我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?CDWordArray是很好用的,只是因为你没有指定数组的最大尺寸。因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。解决该问题的方法是,你可以使用SetSize函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为500,则每次数组空间超出时它才重新分配并添加500个新空间,而不是1个。这样一来,你就可以不用重新分配而添加了另外499个元素空间,这也会大大提高程序的运行速度。(77)我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?在视中的OnlnitialUpdate函数中调用GetParentFrame函数。GetParentFrame会返回一指向一保存有该视的框架窗口的指针。然后调用在框架窗口上调用MoveWindow,(78)在我的程序的某些部分,我可以调用MessageBox函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?MessageBox函数来自CWnd类,所以你只能在从CWnd继承的类(如
55CView)中调用它。但是,MFC也提供了AfxMessageBox函数,你可以在任何地方调用它。(79)我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?把该变量放到该应用程序类的头文件中的attribute处。然后,在程序的任何地方,你都可以用下面的方法来访问该变量:CMyApp*app=(CMyApp*)AfxGetApp();app->MyGlobalVariable=...(80)我听说MFC可以发现内存漏洞,我怎样使用该特性?如果你在Debug菜单中的Go选项(不是Project菜单中的Execute选项)来运行你的应用程序,MFC应该在程序终止时报告内存漏洞。如果没有,那么试试运行MFCTracer工具程序(在VC++程序组中),并启动跟踪。然后返回应用程序。(81)我怎样才能在我的应用程序中循环浏览已经打开的文档?使用CDocTemplate中未公开的GetFirstDocPosition。和GetNextDoc。函数。(82)才能在我的应用程序中循环浏览己经打开的视?使用CDocument中未公开的GetFirstViewPosition()和GetNextView()函数。(83)数PreCreateWindow是干什么用的?PreCreateWindow允许你在调用CreateWindow之前来改变窗口属性。(84)该怎样防止MFC在窗口标题栏上把文档名预置成应用程序名?在PreCreateWindow函数中删除FWS_PREFIXTITLE标志的窗口样式:cs.style&=~FWS_PREFIXTITLE;(85)我应该怎样防止MFC在窗口标题栏上添加文档名?在PreCreateWindow函数中删除FWS_ADDTOTITLE标志的窗口样式:cs.style&=-FWS_ADDTOTITLE;(86)我应该如何改变视窗口的大小?因为视窗口实际上是框架窗口的子窗口,所以你必须改变框架窗口的大小,而不是改变视窗口。使用CView类中的GetParentFrame()函数获得指向框架窗口的指针,然后调用MoveWindow()函数来改变框架的大小。这会使变尺寸的视充满框架窗口。(87)我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?把“deletethis"加到PostNcDestroy中。这主要用在需要自动删除对象的场合。(88)为什么把"deletethis"放在PostNcDestroy中而不是OnNcDestroy?OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow),则没有窗口处来发送WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除,在OnNcDestroy后,甚至在窗口建立失败之后调用的。
56(89)File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?在应用程序类的Initlnstance函数中对LoadStdProfileSettings的调用中。该调用接受一个参数(在缺省情况下如果没有传递值则为4)。MRU文件名是从INI文件中调用的。如果你有带有ID_FILE_MRU_FILE1的ID的菜单选项,它会为调入的MRU列表所替换。如果你改变传递给LoadStdProfileSettings的数值(最大为16),则你就改变了所装如文件名的最大值。(90)我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么?打开资源文件中的菜单模板。打开新菜单选项的属性对话框。在对话框的底部的Prompt编辑框中,你可以如下指定状态栏上的提示信息和工具栏上的提示信息(如果你已经建立的工具栏按钮):Statusbarstring"nFlyingtag(91)我怎样才能在应用程序的缺省系统菜单中加上一些东西?系统菜单与其它菜单类似,你可以添加或删除项目,这需要使用CMenu类的成员函数。下面的代码在你的系统菜单后面添加一个新菜单项:CMenu*sysmenu;sysmenu=mj3MainWnd->GetSystemMenu(FALSE);sysmenu->AppendMenu(MF_STRING,1000,"xxx");参见MFC帮助文件中的CMenu类。(92)我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?打开资源编辑器中的对话框模板。在Layout菜单中选择TabOrder选项。按你的需求单击对话框中的控制来重新排列这些控制的tab顺序。(93)我怎样才能使一个窗口具有“alwaysontop”特性?在调用OnFileNew后,在你的Initlnstance函数中加上下面的代码:m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWPNOMOVE|SWP_NOSIZE);(94)我要为我的formview添加文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来的。我还建立了相应的资源并在In汨nstance中添加了新的文档模板。但是,当我试图运行该程序时,出现了Assertion信息。为什么?form的对话框模板需要些特殊设置以便可用于CFromView,确保这些设置的最简单方法是使用AppWizard来建立CFormView应用程序,并查看AppWizard所建立的对话框模板所选择的
57StylesProperties。你会发现该对话框模板具有下列样式:没有标题栏、不可见和“Child"。把你的formview的对话框属性变成这样就可以了。(95)我在一对话框中有一列表框,我需要tabbed列表框中的项目。但是,当我处理含有tab字符(用AddString添加的)的列表项时,tab被显示成小黑块而没有展开。哪儿出错了?在对话框模版中,打开列表框的属性。确保选择了“UseTabstops”样式。然后,确保在对话框类中OnlnitDialog函数中调用SetTabStops«(96)我建立了一个应用程序,并使用了CRecordset类。但是,当我运行该程序时,它试图要访问数据库,并给出"InternalApplicationError”对话框。我应该怎样做?通常情况下,当你的程序中向数据库发送信息的SQL语句出现问题时才出现该对话框。例如,参见下面的例子:set.m_strFilter="(ZipCode='27111')";如果ZipCode列被定义为字符串时不会出现问题,如果定义为long,则会出现"InternalApplicationError"对话框,这是由于类型不匹配的缘故。如果你删除27111的单引号,则不会出现问题。当你看到“InternalApplicationError”时,最好检查一下试图要发送给数据库的SQL语句。(97)我用ClassWizard建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做?在ClassWizard对话框关闭后,用文件管理器删除新类的H和CPP文件。然后打开ClassWizard,它会提示丢失了两个文件,并询问你该如何做。你可以选择从项目中删除这两个问的按钮。(98)当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?参见CWnd::CalcWindowRecto(99)我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么?archive类只重载某些类型的>>和。操作符。“int”类型没有在其中,也许是因为int变量在Windows3.1与WindowsNT/95有所不同的缘故吧。“long”类型得到了支持,所以你可以把int类型改成long型。参见MFC帮助文件中CArchive类。(100)如何控制菜单的大小?我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help),我想控制这个菜单的大小(长+高).方法一:查找WM_MEASUREITEM和MEASUREITEMSTRUCT.
58方法二:查询系统::GetSystemMetric(SM_CXMENUSIZE)./*你可以通过如下代码来获得文本的大小:(A)获得被使用的字体*/NONCLIENTMETRICSncm;HFONThFontMenu;SIZEsize;size.cy=size.cy=0;memset(&ncm,0,sizeof(NONCLIENTMETRICS));ncm.cbSize=sizeof(NONCLIENTMETRICS);if(SystemParameterslnfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncm,0))(hFontMenu=CreateFontlndirect(&ncm.lfMenuFont);r(B)获得菜单项的文本:*/charszTextLMAX_PATH];pMenu->GetMenuString(0,szText,_MAX_PATH,MF_BYPOSITION);r然后,获得菜单项文本的高度:*/HFONThFontOld;HDChDC;hDC=::GetDC(NULL);hFontOld=(HFONT)::SelectObject(hDC,hFontMenu);GetTextExtentPoint32(hDC,szText,Istrlen(szText),&size);SelectObject(hDC,hFontOld);::ReleaseDC(NULL,hDC);}/*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4比较合适。*/(101)改变LVIS_SELECTED的状态颜色?我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.方法一渣找函数CustomDraw,它是IE4
59提供的公共控制,允许有你自己的代码.方法二:生成一个draw控件,然后在Drawitem中处理文本颜色.(102)如何只存储文档的某一部分?我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.(103)保存工具条菜单有bug吗?使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下•次启动就会出现在该位置,这是什么原因?你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR);你的工具条需要包括id,而不是象默认的工具条那样.(104)Tipoftheday的bug我创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开mdi应用程序同时打开foo.bsf文档.但当我给mdi应用程序加上atipoftheday组件之后,从资源管理器中双击foo.bsf后,就会给我一个警告:ASSERT(::lsWindow(m_hWnd)),然后mdi应用程序就死那了.当从dde启动应用程序(例如:双击相关文档)时,"TipoftheDay"是有bug的.你可以看看函数"ShowTipAtStartup",它在"In巾nstance"中调用,可以看到tipoftheday作为一个模式对话框显示,在处理其它消息时它一直进行消息循环你可心修改ShowTipAtStartup使其从dde启动时不出现tipoftheday.voidCTipOfApp::ShowTipAtStartup(void)(//CG:Thisfunctionaddedby'TipoftheDay'component.CCommandLinelnfocmdlnfo;ParseCommandLine(cmdlnfo);if(cmdlnfo.m_bShowSplash&&cmdlnfo.m_nShellCommand!=CCommandLinelnf:FileDDE)(CTipDIgdig;if(dlg.m_bStartup)dlg.DoModal();))如果还有其它bug,你可以设定cmdlnfo.m_nShellCommand的过滤.(105)如何可以让我的程序可以显示在其它的窗口上面?
60让用户选择"总是在最上面"最好是在系统菜单里加入•个选项.可以通过修改WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个参数传给OnSysCommand。.要定义标识(id),将如下代码加入到CMainFrame.CPP中:#defineWM_ALWAYSONTOPWM_USER+1将"总在最上面”的菜单项加入到系统菜单中,将如下代码加入到函数CMainFrame::OnCreate()中:CMenu*pSysMenu=GetSystemMenu(FALSE);pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING,WM_ALWAYSONTOP,"&AlwaysOnTop");使用ClassWizard,力口入对WM_SYSCOMMAND消息的处理,你应该改变消息过滤器,使用系统可以处理这个消息.voidCMainFrame::OnSysCommand(UINTnID,LPARAMIParam)(switch(nID)(caseWM_ALWAYSONTOP:if(GetExStyle()&WS_EX_TOPMOST){SetWindowPos(&wndNoTopMost,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);GetSystemMenu(FALSE)->CheckMenultem(WM_ALWAYSONTOP,MF_UNCHECKED);)else(SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);GetSystemMenu(FALSE)->CheckMenultem(WM_ALWAYSONTOP,MF_CHECKED);)break;default:CFrameWnd::OnSysCommand(nlD,IParam);})(106)如何控制窗口框架的最大最小尺寸?要控制一个框架的的最大最小尺寸,你需要做两件事情,在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO
61设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.//最大最小尺寸的象素点・示例#defineMINX200#defineMINY300#defineMAXX300#defineMAXY400voidCMyFrameWnd::OnGetMinMaxlnfo(MINMAXINFOFAR*IpMMI)(CRectrectWindow;GetWindowRect(&rectWindow);CRectrectClient;GetClientRect(&rectClient);//getoffsetoftoolbars,scrollbars,etc.intnWidthOffset=rectWindow.Width()-rectClient.Width();intnHeightOffset=rectWindow.Height()-rectClient.Height();lpMMI->ptMinTrackSize.x=MINX+nWidthOffset;lpMMI->ptMinTrackSize.y=MINY+nHeightOffset;lpMMI->ptMaxTrackSize.x=MAXX+nWidthOffset;lpMMI->ptMaxTrackSize.y=MAXY+nHeightOffset;}第二步,在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果.BOOLCMyFrameWnd::PreCreateWindow(CREATESTRUCT&cs)(cs.style&=-WS_MAXIMIZEBOX;returnCFrameWnd::PreCreateWindow(cs);}(107)如何改变窗口框架的颜色?MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDICIient.给它加上一个成员变量,include"MDICIient.h"classCMainFrame:publicCMDIFrameWnd(protected:CMDICIientm_wndMDICIient;)在CMainFrame中重载CMDIFrameWnd::OnCreateClient
62BOOLCMainFrame::OnCreateClient(LPCREATESTRUCTIpcs,CCreateContext*pContext)(if(CMDIFrameWnd::OnCreateClient(lpcs,pContext)){m_wndMDICIient.SubclassWindow(m_hWndMDICIient);returnTRUE;)elsereturnFALSE;)然后就可以加入对消息WM_ERASEBKGND的处理了.(108)如何将应用程序窗口置于屏幕正中?要将你的应用程序窗口放置在屏幕正中央,只须在MainFrame的OnCreate函数中加入:CenterWindow(GetDesktopWindow());
此文档下载收益归作者所有