首页 > C/C++开发工具专区 > VC技术 > Visual C++编程技巧之八
2006
03-14

Visual C++编程技巧之八

57、为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态


需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。


//Disable MFC from automatically disabling menu items.


m_bAuoMenuEnable=FALSE;


//Now enable the menu item.


CMenu* pMenu=GetMenu ();


ASSERT_VALID (pMenu);


pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED);


58、如何给系统菜单添加一个菜单项


给系统菜单添加一个菜单项需要进行下述三个步骤:


首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...


可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000


其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的菜单项:


int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)


{



//Make sure system menu item is in the right range.


ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM);


ASSERT (IDM-MYSYSITEM<0xF000);


//Get pointer to system menu.


CMenu* pSysmenu=GetSystemmenu (FALSE);


ASSERT_VALID (pSysMenu);


//Add a separator and our menu item to system menu.


CString StrMenuItem (_T (“New menu item”));


pSysMenu->Appendmenu (MF_SEPARATOR);


pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem);



}


现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理


WM_SYSCOMMAND消息并检测用户菜单的nID参数:


void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)


{


//Determine if our system menu item was selected.


if ( (nID & 0xFFF0)==IDM_MYSYSITEM)


{


//TODO-process system menu item


}


else


CMDIFrameWnd:: OnSysCommand (nID, lParam);


}


最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。


59、如何确定顶层菜单所占据的菜单行数


这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。


int CMainFrame:: GetMenuRows ()


{


CRect rcFrame,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中调用该函数设置窗口标题颜色。


void CMiniFrameWnd:: OnNcPaint ()


{



dc.SetTextColor (:: GetSysColor (m_bActive ?


COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));



}


61、如何查询和设置系统参数


Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。


//Create a font that is used for icon titles.


LOGFONT stFont;


:: SystemParametersInfo (SPIF_GETICONTITLELOGFONT,


sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE);


m_font.CreateFontIndirect (&stFont);


//Change the wallpaper to leaves.bmp.


:: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0,


_T (” forest.bmp”), SPIF_UPDATEINIFILE);


62、如何使用一个预定义的Windows光标


调用CWinApp:: LoadStandardCursor并传送光标标识符。


BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)


{


//Display wait cursor if busy.


if (m_bBusy)


{


SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));


return TRUE;


}


return CDialog:: OnSetCursor (pWnd. nHitTest,message);


}


63、如何确定当前屏幕分辨率


调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。


//Initialize CSize object with screen size.


CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),


GetSystemMetrics (SM_CYSCREEN));


64、如何检索原先的Task Manager应用程序使用的任务列表


原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口


必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以


检索顶层窗口的列表,调用IsWindowVisibleGetWindowTextLength以及GetOwner


可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。


void GetTadkList (CListBox&list)


{


CString strCaption; //Caption of window.


list.ResetContent (); //Clear list box.


//Get first Window in window list.


ASSERT_VALID (AfxGetMainWnd ());


CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST);


//Walk window list.


while (pWnd)


{


// I window visible, has a caption, and does not have an owner?


if (pWnd ->IsWindowVisible () &&


pWnd ->GetWindowTextLength () &&! pWnd ->GetOwner ())


{


//Add caption o window to list box.


pWnd ->GetWindowText (strCaption);


list.AddString (strCaption);


}


//Get next window in window list.


pWnd=pWnd->GetWindow (GW_HWNDNEXT);


}


}


65、如何确定WindowsWindows系统目录


有两个SDK函数可以完成该功能。GetWindowsDirectoryGetSystemDirectory,下例说明了如何使用这两个函数:


TCHAR szDir [MAX_PATH];


//Get the full path of the windows directory.


:: GetWindowsDirectory (szDir, MAX_PATH);


TRACE (“Windows directory %s\n”, szDir);


//Get the full path of the windows system directory.


:: GetSystemDirectory (szDir, MAX_PATH);


TRACE (“Windows system directory %s\n”, szDir);


66、在哪儿创建临文件


调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。



//get unique temporary file.


CString strFile;


GetUniqueTempName (strFile);


TRY


{


//Create file and write data.Note that file is closed


//in the destructor of the CFile object.


CFile file (strFile,CFile:: modeCreate | CFile:: modeWrite);


//write data


}


CATCH (CFileException, e)


{


//error opening file


}


END_CATCH



Void GetuniqueTempName (CString& strTempName)


{


//Get the temporary files directory.


TCHAR szTempPath [MAX_PATH];


DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);


ASSERT (dwResult);


//Create a unique temporary file.


TCHAR szTempFile [MAX_PATH];


UINT nResult=GetTempFileName (szTempPath, _T (“~ex”),0,szTempfile);


ASSERT (nResult);


strTempName=szTempFile;


}


67、如何访问桌面窗口


静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。


void CFrameWnd::BeginModalState ()


{



//first count all windows that need to be disabled


UINT nCount=0;


HWND hWnd=:: 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);


}



}



留下一个回复