发信人: 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]
  | 
 
 
 |