精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>WINDOWS界面设计>>如何在任务栏状态区显示应用程序图标

主题:如何在任务栏状态区显示应用程序图标
发信人: 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]

[关闭][返回]