Visual C++编程技巧之八.docx
《Visual C++编程技巧之八.docx》由会员分享,可在线阅读,更多相关《Visual C++编程技巧之八.docx(7页珍藏版)》请在冰豆网上搜索。
![Visual C++编程技巧之八.docx](https://file1.bdocx.com/fileroot1/2022-11/28/11c6f30c-bf33-45fd-9298-2385932162e3/11c6f30c-bf33-45fd-9298-2385932162e31.gif)
VisualC++编程技巧之八
VisualC++编程技巧之八
57、为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
需要将CFrameWnd:
:
m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。
//DisableMFCfromautomaticallydisablingmenuitems.
m_bAuoMenuEnable=FALSE;
//Nowenablethemenuitem.
CMenu*pMenu=GetMenu();
ASSERT_VALID(pMenu);
pMenu->EnableMenuItem(ID_MENU_ITEM,MF_BYCOMMAND|MF_ENABLED);
58、如何给系统菜单添加一个菜单项
给系统菜单添加一个菜单项需要进行下述三个步骤:
首先,使用ResourceSymbols对话(在View菜单中选择ResourceSymbols...
可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000;
其次,调用CWnd:
:
GetSystemMenu获取系统菜单的指针并调用CWnd:
:
Appendmenu将菜单项添加到菜单中。
下例给系统菜单添加两个新的菜单项:
intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
…
//Makesuresystemmenuitemisintherightrange.
ASSERT(IDM_MYSYSITEM&0xFFF0)==IDM_MYSYSITEM);
ASSERT(IDM-MYSYSITEM<0xF000);
//Getpointertosystemmenu.
CMenu*pSysmenu=GetSystemmenu(FALSE);
ASSERT_VALID(pSysMenu);
//Addaseparatorandourmenuitemtosystemmenu.
CStringStrMenuItem(_T("Newmenuitem"));
pSysMenu->Appendmenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_MYSYSITEM,strMenuitem);
…
}
现在,选择系统菜单项时用户应进行检测。
使用ClassWizard处理
WM_SYSCOMMAND消息并检测用户菜单的nID参数:
voidCMainFrame:
:
OnSysCommand(UINTnID,LPARAMlParam)
{
//Determineifoursystemmenuitemwasselected.
if((nID&0xFFF0)==IDM_MYSYSITEM)
{
//TODO-processsystemmenuitem
}
else
CMDIFrameWnd:
:
OnSysCommand(nID,lParam);
}
最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。
59、如何确定顶层菜单所占据的菜单行数
这可以通过简单的减法和除法来实现。
首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。
下例成员函数是一个计算主框菜单所占据的行数的代码实现。
intCMainFrame:
:
GetMenuRows()
{
CRectrcFrame,rcClient;
GetWindowRect(rcFrame);
GetClientRect(rcClient);
return(rcFrame.Height()-rcClient.Height()-
:
:
GetSystemMetrics(SM_CYCAPTION)-
(:
:
getSystemMetrics(SM_CYFRAME)*2))/
:
:
GetSystemMetrics(SM_CYMENU);
}
60、在用户环境中如何确定系统显示元素的颜色
调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。
下例说明了如何在MFC函数CMainFrameWnd:
:
OnNcPaint中调用该函数设置窗口标题颜色。
voidCMiniFrameWnd:
:
OnNcPaint()
{
…
dc.SetTextColor(:
:
GetSysColor(m_bActive?
COLOR_CAPTIONTEXT:
COLOR_INACTIVECAPTIONTEXT));
…
}
61、如何查询和设置系统参数
在Windows3.1SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。
//Createafontthatisusedforicontitles.
LOGFONTstFont;
:
:
SystemParametersInfo(SPIF_GETICONTITLELOGFONT,
sizeof(LOGFONT),&stFont,SPIF_SENDWININICHANGE);
m_font.CreateFontIndirect(&stFont);
//Changethewallpapertoleaves.bmp.
:
:
SystemParametersInfo(SPI_SETDESKWALLPAPER,0,
_T("forest.bmp"),SPIF_UPDATEINIFILE);
62、如何使用一个预定义的Windows光标
调用CWinApp:
:
LoadStandardCursor并传送光标标识符。
BOOLCSampleDialog:
:
OnSetCursor(CWnd*pWnd,UINTnHitTest,UINTmessage)
{
//Displaywaitcursorifbusy.
if(m_bBusy)
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
returnTRUE;
}
returnCDialog:
:
OnSetCursor(pWnd.nHitTest,message);
}
63、如何确定当前屏幕分辨率
调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。
//InitializeCSizeobjectwithscreensize.
CSizesizeScreen(GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN));
64、如何检索原先的TaskManager应用程序使用的任务列表
原先的TaskManager应用程序显示顶层窗口的列表。
为了显示该列表,窗口
必须可见、包含一个标题以及不能被其他窗口拥有。
调用CWnd:
:
GetWindow可以
检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner
可以确定窗口是否应该在列表中。
下例将把TaskManager窗口的标题填充到列表中。
voidGetTadkList(CListBox&list)
{
CStringstrCaption;//Captionofwindow.
list.ResetContent();//Clearlistbox.
//GetfirstWindowinwindowlist.
ASSERT_VALID(AfxGetMainWnd());
CWnd*pWnd=AfxGetMainWnd()->GetWindow(GW_HWNDFIRST);
//Walkwindowlist.
while(pWnd)
{
//Iwindowvisible,hasacaption,anddoesnothaveanowner?
if(pWnd->IsWindowVisible()&&
pWnd->GetWindowTextLength()&&!
pWnd->GetOwner())
{
//Addcaptionowindowtolistbox.
pWnd->GetWindowText(strCaption);
list.AddString(strCaption);
}
//Getnextwindowinwindowlist.
pWnd=pWnd->GetWindow(GW_HWNDNEXT);
}
}
65、如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。
GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数:
TCHARszDir[MAX_PATH];
//Getthefullpathofthewindowsdirectory.
:
:
GetWindowsDirectory(szDir,MAX_PATH);
TRACE("Windowsdirectory%s\n",szDir);
//Getthefullpathofthewindowssystemdirectory.
:
:
GetSystemDirectory(szDir,MAX_PATH);
TRACE("Windowssystemdirectory%s\n",szDir);
66、在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:
如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。
下例说明了如何创建一个临时文件。
…
//getuniquetemporaryfile.
CStringstrFile;
GetUniqueTempName(strFile);
TRY
{
//Createfileandwritedata.Notethatfileisclosed
//inthedestructoroftheCFileobject.
CFilefile(strFile,CFile:
:
modeCreate|CFile:
:
modeWrite);
//writedata
}
CATCH(CFileException,e)
{
//erroropeningfile
}
END_CATCH
…
VoidGetuniqueTempName(CString&strTempName)
{
//Getthetemporaryfilesdirectory.
TCHARszTempPath[MAX_PATH];
DWORDdwResult=:
:
GetTempPath(MAX_PATH,szTempPath);
ASSERT(dwResult);
//Createauniquetemporaryfile.
TCHARszTempFile[MAX_PATH];
UINTnResult=GetTempFileName(szTempPath,_T("~ex"),0,szTempfile);
ASSERT(nResult);
strTempName=szTempFile;
}
67、如何访问桌面窗口
静态函数CWnd:
:
GetDesktopWindow返回桌面窗口的指针。
下例说明了MFC函数CFrameWnd:
:
BeginModalStae是如何使用该函数进入内部窗口列表的。
voidCFrameWnd:
:
BeginModalState()
{
…
//firstcountallwindowsthatneedtobedisabled
UINTnCount=0;
HWNDhWnd=:
:
GetWindow(:
:
GetDesktopWindow(),GW_CHILD);
while(hWnd!
=NULL)
{
if(:
:
IsWindowEnabled(hwnd)&&
CWnd:
:
FromHandlePermanent(hWnd)!
=NULL&&
AfxIsDescendant(pParent->m_hWnd,hWnd)&&
:
:
SendMessage(hWnd,WM_DISABLEMODAL,0,0)==0)
{
++nCount;
}
hWnd=:
:
GetWindow(hWnd,GW_HWNDNEXT);
}
}