用VC在对话框和窗体中使用系统图标

  • 来源: 天新网 作者: 若水   2008-04-24/17:51

  • 大家知道,很多Windows程序都使用MessageBox()来显示一个对话框给用户以提示,只要在这个API函数的一个参数中使用MB_ICONQUESTION标志,便可以在MessageBox的对话框中显示问号图标。如果用不同的标志,对话框便可以显示不同的图标。与Windows以前的老版本相比,Windows 2000以及Windows XP中的图标越来越好看,种类也越来越多。为了更广泛地使用这些漂亮的图标,本实例将介绍如何获取它们,并把它们运用到自己的对话框或窗体中去。程序编译运行后显示所有获取的系统图标,界面效果如图一所示:


    图一、显示系统的当前图标

    一、实现方法

    上述问题属于Windows编程中最基本的问题,同时也是最容易搞忘的问题。一般情况下,我们通过使用预定义的、形式为IDI_XXX的资源IDs作为参数调用::LoadIcon()函数来获取任何所谓的系统图标。例如:

    HICON hIconQuestion = ::LoadIcon(NULL, IDI_QUESTION);

    为了加载系统图标,程序中定义了SysIcons[]结构数组,其元素定义了图标资源的ID和名称,它的结构定义如下:

    const struct {
    LPCTSTR nResID;
    LPCTSTR name;
    } SysIcons[] = {
    { IDI_APPLICATION, _T("IDI_APPLICATION") },
    { IDI_HAND, _T("IDI_HAND") },
    { IDI_QUESTION, _T("IDI_QUESTION") },
    { IDI_EXCLAMATION, _T("IDI_EXCLAMATION") },
    { IDI_ASTERISK, _T("IDI_ASTERISK") },
    #if(WINVER >= 0x0400)
    { IDI_WINLOGO, _T("IDI_WINLOGO") },
    { IDI_WARNING, _T("IDI_WARNING") },
    { IDI_ERROR, _T("IDI_ERROR") },
    { IDI_INFORMATION, _T("IDI_INFORMATION") },
    #endif
    { NULL, NULL }
    };

    在程序中具体加载图标是在程序的CMainFrame::OnPaint()中进行的:

    for (UINT i=0; SysIcons[i].nResID; i++) {
    HICON hicon = ::LoadIcon(NULL, SysIcons[i].nResID);
    ASSERT(hicon);
    CString name = SysIcons[i].name;
    ......
    }
    ......

    如果想在自己的对话框或其它窗体中使用这些系统图标,方法是这样的:假设m_wndStatic是对话框或窗体中创建的一个CStatic控制。然后用下面的方法加载并显示图标,那末你将在例子程序的"关于"对话框中,看到一个问号图标:

    首先按通常方式创建一个静态控制,:

    HICON hicon = ::LoadIcon(NULL, IDI_HAND);
    m_wndStatic.SetIcon(hicon);

    本实例使用了CStatic类的子CStaticLink类,这样当用户点击鼠标时将进行相关的链接。

    虽然对系统图标的处理没有什么深奥的东西,但Windows把这些简单的东西弄得有点复杂化了,从图一中不难看出,IDI_HAND已不再是手的形状,至少在Windows2000和Window XP中是如此。从称呼上看也变味了,IDI_ASTERISK成了一个含有字母"i"的球形形状。微软对这种词汇上出现的困惑所做的解释是:老版本的Windows显示手形和星号;新版本则是用新的图标。在winuser.h文件中可以窥见这些变化:

    #if(WINVER >= 0x0400)
    #define IDI_WARNING IDI_EXCLAMATION
    #define IDI_ERROR IDI_HAND
    #define IDI_INFORMATION IDI_ASTERISK
    #endif /* WINVER >= 0x0400 */


    如果你想跟上微软的这些变化,那么就使用新符号好了。这样你的代码也会更可读一些,因为现在的警告、错误和信息符号更能传达图标所要表达的本意。

    二、编程步骤

    1、 启动Visual C++6.0,生成一个单文档视图结构的应用程序,将该程序命名为"FindSysIcon";

    2、 使用Class Wizard重载应用程序的CMainFrame类的OnPaint()函数;

    3、 添加代码,编译运行程序。

    三、程序代码

    //////// MainFrm.cpp : implementation of the CMainFrame class
    #include "stdafx.h"
    #include "FindSysIcon.h"
    #include "MainFrm.h"
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    // DO NOT EDIT what you see in these blocks of generated code !
    ON_WM_CREATE()
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    #p#分页标题#e#
    static UINT indicators[] =
    {
    ID_SEPARATOR, // status line indicator
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
    };
    const struct {
    LPCTSTR nResID;
    LPCTSTR name;
    } SysIcons[] = {
    { IDI_APPLICATION, _T("IDI_APPLICATION") },
    { IDI_HAND, _T("IDI_HAND") },
    { IDI_QUESTION, _T("IDI_QUESTION") },
    { IDI_EXCLAMATION, _T("IDI_EXCLAMATION") },
    { IDI_ASTERISK, _T("IDI_ASTERISK") },
    #if(WINVER >= 0x0400)
    { IDI_WINLOGO, _T("IDI_WINLOGO") },
    { IDI_WARNING, _T("IDI_WARNING") },
    { IDI_ERROR, _T("IDI_ERROR") },
    { IDI_INFORMATION, _T("IDI_INFORMATION") },
    #endif
    { NULL, NULL }
    };

    CMainFrame::CMainFrame()
    {
    // TODO: add member initialization code here
    }

    CMainFrame::~CMainFrame()
    {}

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    return CFrameWnd::OnCreate(lpCreateStruct);
    }

    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
    {
    BOOL bRet = CFrameWnd::PreCreateWindow(cs);
    cs.cx=200;
    cs.cy=400;
    return bRet;
    }

    #ifdef _DEBUG
    void CMainFrame::AssertValid() const
    {
    CFrameWnd::AssertValid();
    }

    void CMainFrame::Dump(CDumpContext& dc) const
    {
    CFrameWnd::Dump(dc);
    }

    #endif //_DEBUG

    void CMainFrame::OnPaint()
    {
    CPaintDC dc(this);
    CRect rcClient;
    GetClientRect(&rcClient);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    int cxIcon = GetSystemMetrics(SM_CXICON);
    CRect rcIcon(0,0,cxIcon,cyIcon);
    CRect rcText(cxIcon, 0, rcClient.Width()-cxIcon, cyIcon);
    for (UINT i=0; SysIcons[i].nResID; i++) {
    HICON hicon = ::LoadIcon(NULL, SysIcons[i].nResID);
    ASSERT(hicon);
    CString name = SysIcons[i].name;
    dc.DrawIcon(rcIcon.TopLeft(), hicon);
    dc.DrawText(name, rcText, DT_LEFT);
    rcIcon += CPoint(0, rcIcon.Height());
    rcText += CPoint(0, rcIcon.Height());
    }
    }

    四、小结

    上文介绍了如何获取Windows的系统图标,但是不得不提的一个令人困惑的问题是:虽然winuser.h中新增了一个新的符号IDI_WINLOGO。在基于Windows XP的应用程序里使用这个图标产生的效果并不是我们所熟悉的那个家喻户晓名叫"飞扬"的窗口标志,而是图一里IDI_APPLICATION所表示的一般窗口标志。仔细阅读有关文档后,你会发现微软对此的解释是"设计行为"。为什么这个具有某种代表意义的东西在不同的Windows OS中表现得如此模棱两可呢?此中缘由鲜为人知。


    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多