发信人: skyice()
整理人: girlrong(1999-11-10 07:41:57), 站内信件
|
在任务栏状态区显示应用程序图标
数据结构:
有关的数据由NOTIFYICONDATA结构描述:
typedef struct _NOTIFYICONDATA { DWORD cbSize; //结构的大小,必须设置 HWND hWnd; //接受回调消息的窗口的句柄 UINT uID; //应用程序定义的图标标志 UINT uFlags; //标志,可以是NIF_ICON、NIF_MESSAGE、NIF_TIP或其组合
UINT uCallbackMessage;//应用程序定义的回调消息标志 HICON hIcon; //图标句柄 char szTip[64]; //提示字串 } NOTIFYICONDATA, *PNOTIFYICONDATA;
函数说明
由Shell_NotifyIcon()函数向系统发送添加、删除、更改图标的消息。
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDA TA pnid);
DwMessage为所发送消息的标志: NIM_ADD 添加图标到任务栏通知区; NIM_DELETE 删除任务栏通知区的图标; NIM_MODIFY 更改任务栏通知区的图标、回调消息标志、回调窗口句柄或提示 字串; pnid为NOTIFYICONDATA结构的指针。
回调信息的获得及处理
如果一个任务栏图标有应用程序定义的回调消息,那么当这个图标有鼠标操作时 ,系统将给hWnd所标志的窗口发送下列的消息: messageID = uCallbackMessage wParam = uID lParam = mouse event(例如WM_LBUTTONDOWN)
通过这种方式,系统通知应用程序用户对图标的操作。如果一个应用程序生成了 两个以上的图标,那么你可以根据wParam来判断是哪个图标返回的鼠标操作。通 常,标准的Win95任务栏图标有以下鼠标操作响应:
当鼠标停留在图标上时,系统应显示提示信息tooltip; 当使用鼠标右键单击图标时,应用程序应显示快捷菜单; 当使用鼠标左键双击图标时,应用程序应执行快捷菜单的缺省菜单项。
在Microsoft Windows环境中,0x8000到0xBFFF的消息是保留的,应用程序可以定 义自定义消息。
关于消息处理的详细内容,请参考下一部分。
源码及实现
在本文中关于任务栏图标的类叫做CTrayIcon,这个类由CCmdTarget(或CObject) 类派生,它有如下的成员变量和成员函数:
// TrayIcon.h // CTrayIcon command target
class CTrayIcon : public CCmdTarget { public: NOTIFYICONDATA m_nid;//NOTIFYICONDATA结构,你的图标要用的啊 BOOL m_IconExist;//标志,看看图标是不是已经存在了 CWnd* m_NotificationWnd;//接受回调消息的窗口,有它就不必经常AfxGetM ainWnd了 public: CWnd* GetNotificationWnd() const;//得到m_NotificationWnd BOOL SetNotificationWnd(CWnd* pNotifyWnd);//设置(更改)m_Notificati onWnd CTrayIcon();//构造函数 virtual ~CTrayIcon();//析构函数 BOOL CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon, LPSTR lpszTip, UINT CallBackMessage);//在任务栏上生成图标
BOOL DeleteIcon();//删除任务栏上的图标 virtual LRESULT OnNotify(WPARAM WParam, LPARAM LParam);//消息响应函 数 BOOL SetTipText(UINT nID);//设置(更改)提示字串 BOOL SetTipText(LPCTSTR lpszTip);//设置(更改)提示字串 BOOL ChangeIcon(HICON hIcon);//更改图标 BOOL ChangeIcon(UINT nID);//更改图标 BOOL ChangeIcon(LPCTSTR lpszIconName);//更改图标 BOOL ChangeStandardIcon(LPCTSTR lpszIconName);//更改为标准图标 ...... };
下面是成员函数的定义:
// TrayIcon.cpp // CTrayIcon
CTrayIcon::CTrayIcon() {//初始化参数 m_IconExist = FALSE; m_NotificationWnd = NULL; memset(&m_nid, 0, sizeof(m_nid)); m_nid.cbSize = sizeof(m_nid);//这个参数不会改变 }
CTrayIcon::~CTrayIcon() { if (m_IconExist) DeleteIcon();//删除图标 }
BOOL CTrayIcon::CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon, LPSTR lpszTip, UINT CallBackMessage) { //确定接受回调消息的窗口是有效的 ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));
ASSERT(CallBackMessage >= WM_USER);//确定回调消息不发生冲突
ASSERT(_tcslen(lpszTip) <= 64);//提示字串不能超过64个字符
m_NotificationWnd = pNotifyWnd;//获得m_NotificationWnd
//设置NOTIFYICONDATA结构 m_nid.hWnd = pNotifyWnd->GetSafeHwnd(); m_nid.uID = uID; m_nid.hIcon = hIcon; m_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; m_nid.uCallbackMessage = CallBackMessage;
//设置NOTIFYICONDATA结构的提示字串 if (lpszTip) lstrcpyn(m_nid.szTip, lpszTip, sizeof(m_nid.szTip)); else m_nid.szTip[0] = '\0';
//显示图标 m_IconExist = Shell_NotifyIcon(NIM_ADD, &m_nid); return m_IconExist; }
BOOL CTrayIcon::DeleteIcon() {//删除图标 if (!m_IconExist) return FALSE; m_IconExist = FALSE; return Shell_NotifyIcon(NIM_DELETE, &m_nid); }
LRESULT CTrayIcon::OnNotify(WPARAM WParam, LPARAM LParam) {//处理图标返回的消息 if (WParam != m_nid.uID)//如果不是该图标的消息则迅速返回 return 0L;
//准备快捷菜单 CMenu menu; if (!menu.LoadMenu(IDR_POPUP))//你必须确定资源中有ID为IDR_POPUP的菜 单 return 0; CMenu* pSubMenu = menu.GetSubMenu(0);//获得IDR_POPUP的子菜单 if (!pSubMenu) return 0;
if (LParam == WM_RBUTTONUP) {//右键单击弹出快捷菜单
//设置第一个菜单项为缺省 ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE); CPoint pos; GetCursorPos(&pos);
//显示并跟踪菜单 m_NotificationWnd->SetForegroundWindow(); pSubMenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON |TPM_RIGHTBUTTON, pos.x, pos.y, m_NotificationWnd, NULL);
} else if (LParam == WM_LBUTTONDOWN) {//左键单击恢复窗口 m_NotificationWnd->ShowWindow(SW_SHOW);//恢复窗口 m_NotificationWnd->SetForegroundWindow();//放置在前面 } else if (LParam == WM_LBUTTONDBLCLK) {//左键双击执行缺省菜单项 m_NotificationWnd->SendMessage(WM_COMMAND, pSubMenu->GetMenuItemID(0), 0); } return 1L; }
BOOL CTrayIcon::SetTipText(LPCTSTR lpszTip) {//设置提示文字 if (!m_IconExist) return FALSE;
_tcscpy(m_nid.szTip, lpszTip); m_nid.uFlags |= NIF_TIP;
return Shell_NotifyIcon(NIM_MODIFY, &m_nid); }
BOOL CTrayIcon::SetTipText(UINT nID) {//设置提示文字 CString szTip; VERIFY(szTip.LoadString(nID));
return SetTipText(szTip); } BOOL CTrayIcon::ChangeIcon(HICON hIcon) {//更改图标 if (!m_IconExist) return FALSE;
m_nid.hIcon = hIcon; m_nid.uFlags |= NIF_ICON;
return Shell_NotifyIcon(NIM_MODIFY, &m_nid); }
BOOL CTrayIcon::ChangeIcon(UINT nID) {//更改图标 HICON hIcon = AfxGetApp()->LoadIcon(nID); return ChangeIcon(hIcon); }
BOOL CTrayIcon::ChangeIcon(LPCTSTR lpszIconName) {//更改图标 HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName); return ChangeIcon(hIcon); }
BOOL CTrayIcon::ChangeStandardIcon(LPCTSTR lpszIconName) {//更改为标准图标 HICON hIcon = AfxGetApp()->LoadStandardIcon(lpszIconName); return ChangeIcon(hIcon); }
BOOL CTrayIcon::SetNotificationWnd(CWnd * pNotifyWnd) {//设置接受回调消息的窗口 if (!m_IconExist) return FALSE;
//确定窗口是有效的 ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));
m_NotificationWnd = pNotifyWnd; m_nid.hWnd = pNotifyWnd->GetSafeHwnd(); m_nid.uFlags |= NIF_MESSAGE;
return Shell_NotifyIcon(NIM_MODIFY, &m_nid); }
CWnd* CTrayIcon::GetNotificationWnd() const {//返回接受回调消息的窗口 return m_NotificationWnd; }
三点补充: 关于使用回调消息的补充说明:
首先,在MainFrm.cpp中加入自己的消息代码; // MainFrm.cpp : implementation of the CMainFrame class // #define MYWM_ICONNOTIFY WM_USER + 10//定义自己的消息代码
第二步增加消息映射和函数声明,对于自定义消息不能由ClassWizard添加消息映 射,只能手工添加。 // MainFrm.cpp : implementation of the CMainFrame class BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) //其他的消息映射 ...... //}}AFX_MSG_MAP ON_MESSAGE(WM_ICONNOTIFY,OnNotify) END_MESSAGE_MAP() 并且在头文件中添加函数声明 // MainFrm.h afx_msg LRESULT OnNotify(WPARAM WParam, LPARAM LParam);
第三步增加消息处理函数定义 LRESULT CMainFrame::OnNotify(WPARAM WParam, LPARAM LParam) { return trayicon.OnNotify(WParam, LParam);//调用CTrayIcon类的处理函 数 }
如何隐藏任务栏上的按钮:
可以使用下列两种方法: 1.在CreateWindowEx函数中使用WS_EX_TOOLWINDOW窗口式样(相反的如果要确保应 用程序在任务栏上生成按钮,可以使用WS_EX_APPWINDOW窗口式样)。 The probl em with this is that the window decorations are as for a small floatin g toolbar, which isn't normally what's wanted. 2.生成一个空的隐藏的top-level窗口,并使其作为可视窗口的父窗口。 3.在应用程序的InitInstance()函数中使用SW_HIDE式样调用ShowWindow()函数。
//pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->ShowWindow(SW_HIDE); pMainFrame->UpdateWindow();
如何动画任务栏上的图标:
在TrayIcon类中加入下列两个函数:
BOOL CTrayIcon::SetAnimateIcons(HICON* hIcon, UINT Number) {//设置动画图标 ASSERT(Number >= 2);//图标必须为两个以上 ASSERT(hIcon);//图标必须不为空
m_AnimateIcons = new HICON[Number]; CopyMemory(m_AnimateIcons, hIcon, Number * sizeof(HICON)); m_AnimateIconsNumber = Number; return TRUE; }
BOOL CTrayIcon::Animate(UINT Index) {//动画TrayIcon UINT i = Index % m_AnimateIconsNumber; return ChangeIcon(m_AnimateIcons[i]); }
在应用程序中添加相应的菜单和函数(请参考下面的例子):
void CMainFrame::OnMenuAnimate() {//动画TrayIcon,设置图标及定时器 SetTimer(1, 500, NULL); HICON hIcon[3]; hIcon[0] = AfxGetApp()->LoadIcon(IDR_MAINFRAME); hIcon[1] = AfxGetApp()->LoadIcon(IDR_MYTURNTYPE); hIcon[2] = AfxGetApp()->LoadStandardIcon(IDI_HAND); trayicon.SetAnimateIcons(hIcon, 3); }
void CMainFrame::OnTimer(UINT nIDEvent) {//动画TrayIcon UINT static i; i += 1; trayicon.Animate(i);
CMDIFrameWnd::OnTimer(nIDEvent); }
使用拖放的简单方法
如果要为窗口增加接受Drag&Drop的功能,请按照以下步骤:
1、在OnCreate(...)中调用AcceptDrag(TRUE)。
2、增加消息映射
BEGIN_MESSAGE_MAP(……) //{{AFX_MSG_MAP(CDropEdit) ON_WM_CREATE() ON_WM_DROPFILES() // 关于Drag&Drop的消息 //}}AFX_MSG_MAP END_MESSAGE_MAP()
3、处理消息
void CXXXXX::OnDropFiles(HDROP dropInfo) { // 得到Drag&Drop的文件个数 WORD wNumFilesDropped = DragQueryFile(dropInfo, -1, NULL, 0);
CString firstFile="";
// for (WORD x = 0 ; x < wNumFilesDropped; x++) {
// 得到PathName的长度,由于第三个参数为NULL,所以调用会失败并返 回所需长度 WORD wPathnameSize = DragQueryFile(dropInfo, x, NULL, 0);
// 分配memory char * npszFile = (char *) LocalAlloc(LPTR, wPathnameSize += 1 );
// 分配错 if (npszFile == NULL) continue;
// 再次得到文件名 DragQueryFile(dropInfo, x, npszFile, wPathnameSize);
firstFile=npszFile;
// 如果是shortCut则进行转换得到正确的文件名,expandedFile为 最后的文件名 CString expandedFile = ExpandShortcut(firstFile);
// 释放memory LocalFree(npszFile); }
//完成 DragFinish(dropInfo);
}
4、关于ExpandShortcut(...)
CString CXXXXX::ExpandShortcut(CString &inFile) { CString outFile = "";
// Make sure we have a path ASSERT(inFile != _T(""));
IShellLink* psl; HRESULT hres; LPTSTR lpsz = inFile.GetBuffer(MAX_PATH);
// Create instance for shell link hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID*) &psl); if (SUCCEEDED(hres)) { // Get a pointer to the persist file interface IPersistFile* ppf; hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf); if (SUCCEEDED(hres)) { // Make sure it's ANSI WORD wsz[MAX_PATH]; ::MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, MAX_PATH);
// Load shortcut hres = ppf->Load(wsz, STGM_READ); if (SUCCEEDED(hres)) { WIN32_FIND_DATA wfd; // find the path from that HRESULT hres = psl->GetPath(outFile.GetBuffer(MAX_PATH ), MAX_PATH, &wfd, SLGP_UNCPRIORITY);
outFile.ReleaseBuffer(); } ppf->Release(); } psl->Release(); }
inFile.ReleaseBuffer();
// if this fails, outFile == "" return outFile; }
用MFC编制屏幕保护程序
显示器的很多优点,如长寿命的显示屏,液晶和能源之星能源保护模式, 已经 让屏幕保护程序的作用大大地降低. 但是,依然有大量的屏幕保护程序出现,尤其 是共享软件.
这也许是因为写屏幕保护程序是一件非常有趣的事. 因为有CRect和CGdiObject类 ,这些类的绘图功能比单纯的C API函数容易得多, 所以,用MFC写屏幕保护程序会 是一件更有趣的事.
简单地和"Hello, world."应用程序比较,它不需要WinMain()函数,例如: 如果你发掘一下有哪些API函数支持产生一个屏幕保护程序,你会发现可利用的函 数非常少. 例如:用C写屏幕保护程序,大多数情况下都不需要调用DefWindowProc 函数,取而代之的是DefScreenSaverProc函数. 如果调用你自已的函数(一般也就 是三个),你可以编出一个和标准的屏幕保护程序功能一样的屏保程序.
对所有的屏幕保护程序:
屏幕保护程序的名字和描述在字符串1中定义. 屏幕保护程序的图标为ID_APP, 在中定义为100. WINAPI函数ScreenSaverProc必须定义和调用. (CScreenSaverWnd模块为你填充这个API调用.) 程序必需以.SCR为扩展名.
对于可设置的屏幕保护程序:
设置屏幕保护程序的对话框为DLG_SCRNSAVECONFIGURE,在定义为2003. WINAPI函数ScreenSaverConfigureDialog必须被定义和调用. WINAPI函数RegisterDialogClasses必须被定义和调用. (CScreenSaverDlg模块为你填充这个API调用.)
---------------------------------------------------------------------- ----------
某些MFC外部特性
所有这些简单的特性来源于MFC,以及它便利的应用程序框架. 一个屏幕保护程序 并不真的是一个应用程序,它只不过是操作系统在你离开键盘后才调用的一段代码 . 它甚至不需要WINMAIN函数,MFC程序似乎不可能完成这一点,因为它已经调用了 WINMAIN函数. 如果你没有用过WINAPI来编写C程序,你可能不知道MFC已经在幕后 调用了DefWindowProc过程.
你当然能用MFC来生成一个屏幕保护程序,对于上述的限制,你只要在MFC的基础上 做一点点工作即可. 以下提供两个抽象类 CScreenSaverWnd和CScreenSaverDlg, 它会考虑这种限制,并且让你很容易创建一个功能完全的屏幕保护程序.
建一个基于对话框的MFC应用程序. 使用VC4.2或5.0为屏幕保护程序产生一个新工程,你可以使用开发环境提供的App Wizard, 建立一个新"Win32 MFC Application"程序.如果你选择链接时MFC为共享 (linked with MFC in a shared DLL), 屏幕保护程序会小很多.当然,基于对话框 的应用程序将会避免产生不需要用DOC/VIEW构架.
删除所以关于CWinApp的引用和它本身. 删除所有CWinApp派生类的申明和定义,包括一个全局的instance.
产生一个CWnd的派生类. 我们已经创建了一个基于对话框的应用程序,但是屏幕保护程序只是需要一个简单 的CWnd派生类. 你可以使用ClassWizard来产生一个继承于 generic CWnd class 的派生类.
选择父类. 从下载的文件中拷贝CScreenSaverWnd和CScreenSaverDlg的相关文件,*.CPP和*. H (作者要求你能保留源代码中的版权信息). 在你的窗口类中查找CWnd,将其换成 CScreenSaverWnd,将CDialog换为CScreenSaveDlg. 然后重新编译.
一个特定的对话框. 用ClassWizard产生的CDialog的派生类,没有处理命令行参数的构造函数. 因为屏 幕保护程序的设置部分是一个窗口,需要命令行设置, 因此,在此提供了一个可以 使用命令行的构造和析构函数.
全局考虑. 当删掉CWinApp的派生类对象时,也同时删掉了全局的instance, 因此,程序中CSc reenSaverWnd的派生类需要有一个全局的instance. 同样,在CScreenSaverDlg的 派生类中也要保留一个副本.
资源. 如前所述,屏幕保护程序包含以下资源: 字符串1中的描述,不要超过20个字符,当 用户选择屏幕保护程序时,在下拉框中就会出现这个字符串.将图标资源的ID改为 100.将对话框资源的ID改为2003.
泡沫,清洗,重复. 你已经做好一个框架,现在可以编译,调试和开发了. 你可以改变工程输出的文件 扩展名为.SCR,从而能出现屏幕保护程序的设置对话框. 如果你想调试屏幕保护程 序,在运行时你可以用命令行参数:"/save"
分析自带的示例. 示例使用VC5.0,但应该兼容于VC4.2,展示了 CScreenSaverWnd和CScreenSaverDl g的用法, 并且使用了CImageList来调用一个图标库,在屏幕上产生动画,请查看源 程序的注解.
---------------------------------------------------------------------- ----------
代码
虽然CScreenSaverWnd不是CView的派生类,我觉得应该重载OnInitialUpdate和On Draw.我也加入了三个特性,你可以使用,也可以不使用.
CScreenSaverWnd的默认状态是黑屏,这由函数OnEraseBkgnd()来完成,你可以在构 造函数,OnCreate,OnInitalUpadte这三个地方的任一处调用SetAutoBlack(FALSE )来关掉该项. 成员变量m_pPalette指向CPalette,将被用于OnDraw调用之前的调色板设置, 重载 OnQueryNewPalette()和OnPaletteChanged()来正确地处理调色板, 将m_pPalett e设置为NULL,意味着所有的调色板操作代码都由你自已来完成. (注意:使用16色 时(如示例),你不需要做任何调色板的工作). 虽然屏幕保护程序的设置对话框和屏幕保护程序不可能同时出现,但它们确实需要 通讯. 重载SaveOptions和RestoreOptions将用来保存和恢复各项参数. 在什么地 方保存这种参数取决于你,但保留在系统注册表中是个不错的选择.
以下是上述两个类的框架,源程序已经很好地做了注解.
// Implemented class CScreenSaverWnd class CScreenSaverWnd : public CWnd { public: CScreenSaverWnd(); // Attributes public: BOOL IsAutoBlack() const; void SetAutoBlack(BOOL bAutoBlack = TRUE); CPalette* GetPalette() const; void SetPalette(CPalette* pPalette); // Overridables public: virtual void OnDraw(CDC* pDC); virtual void OnInitialUpdate(); virtual void SaveOptions(); virtual void RestoreOptions(); //Implementation public: virtual ~ScreenSaverWnd(); protected: virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam ); virtual LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lPa ram); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaint(); afx_msg BOOL OnQueryNewPalette(); afx_msg void OnPaletteChanged(CWnd* pFocusWnd); }; // Implemented class CScreenSaverDlg class CScreenSaverDlg : public CDialog { public: CScreenSaverDlg(); // Overrides public: virtual BOOL OnInitDialog(); //Implementation public: virtual ~ScreenSaverDlg(); protected: virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam ); virtual LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lPa ram); }; // Implemented APIs LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL WINAPI RegisterDialogClasses(HANDLE hInstance); };
如何编程结束应用程序?如何编程控制windows的重新引导?
这是个很简单又是编程中经常要遇到的问题.
第一问,向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提 示
是否保存修改过的数据.
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE);
还可以创建一个自定义的函数 Terminate Window
void Terminate Window(LPCSTR pCaption)
{
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption);
if (pWnd)
pWnd ->SendMessage(WM_CLOSE);
}
说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如 我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时 FindWin dow就无能为力了,可以通过枚举 windows任务列表的办法来实现。 在 机械出版 社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。
第二问,Use ExitWindowsEx Function函数控制系统是重新引导,还是重启 wind ows.前面已经有人讲过乐,就不再提了。
确定应用程序的 路径
前些天好象有人问过这个问题.
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
Example:
TCHAR exeFullPath[MAX_PATH]; // MAX_PATH在API中定义了吧,好象是128
GetModuleFileName(NULL,exeFullPath,MAX_PATH)
获得各种目录信息
Windows目录: Use "GetWindowsDirectory“
Windows下的system目录: Use "GetSystemDirectory"
temp目录: Use "GetTempPath "
当前目录: Use "GetCurrentDirectory"
请注意前两个函数的第一个参数为 目录变量名,后一个为缓冲区; 后两个相反.
在用户环境中如何确定系统显示元素的颜色
调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在 MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。
void CMiniFrameWnd:: OnNcPaint ()
{
…
dc.SetTextColor (:: GetSysColor (m_bActive ?
COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
…
}
如何查询和设置系统参数
在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);
如何使用一个预定义的Windows光标
调用CWinApp:: LoadStandardCursor并传送光标标识符。
BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT mess age)
{
//Display wait cursor if busy.
if (m_bBusy)
{
SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));
return TRUE;
}
return CDialog:: OnSetCursor (pWnd. nHitTest,message);
}
如何确定当前屏幕分辨率
调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标 题大小、边界大小以及滚动条大小等等。
//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN));
如何检索原先的Task Manager应用程序使用的任务列表
原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口
必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以
检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwn er
可以确定窗口是否应该在列表中。下例将把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);
}
}
如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory, 下例说明了如何使用这两个函数:
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);
在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测T MP环境变量:如果没有指定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;
}
如何访问桌面窗口
静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数C FrameWnd::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);
}
…
}
-- 欢迎您光临程序员之家! http://www.skyice.com http://skyline.t500.net http://skyice.126.com http://skyline.pcchina.net 请您多多关照!
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.99.79.223]
|
|