ownerdrw.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 494 行 · 第 1/2 页

CPP
494
字号
///////////////////////////////////////////////////////////////////////////////
// Name:        msw/ownerdrw.cpp
// Purpose:     implementation of wxOwnerDrawn class
// Author:      Vadim Zeitlin
// Modified by:
// Created:     13.11.97
// RCS-ID:      $Id: ownerdrw.cpp,v 1.62.2.2 2006/01/18 16:32:49 JS Exp $
// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence:     wxWindows licence
///////////////////////////////////////////////////////////////////////////////

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#include "wx/msw/private.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
  #include "wx/window.h"
  #include "wx/msw/private.h"
  #include "wx/font.h"
  #include "wx/bitmap.h"
  #include "wx/dcmemory.h"
  #include "wx/menu.h"
  #include "wx/utils.h"
#endif

#include "wx/settings.h"
#include "wx/ownerdrw.h"
#include "wx/menuitem.h"
#include "wx/fontutil.h"
#include "wx/module.h"

#if wxUSE_OWNER_DRAWN

#ifndef SPI_GETKEYBOARDCUES
#define SPI_GETKEYBOARDCUES 0x100A
#endif

class wxMSWSystemMenuFontModule : public wxModule
{
public:

    virtual bool OnInit()
    {
        ms_systemMenuFont = new wxFont;

#if defined(__WXMSW__) && defined(__WIN32__) && defined(SM_CXMENUCHECK)
        NONCLIENTMETRICS nm;
        nm.cbSize = sizeof(NONCLIENTMETRICS);
        SystemParametersInfo(SPI_GETNONCLIENTMETRICS,0,&nm,0);

        ms_systemMenuButtonWidth = nm.iMenuHeight;
        ms_systemMenuHeight = nm.iMenuHeight;

        // create menu font
        wxNativeFontInfo info;
        memcpy(&info.lf, &nm.lfMenuFont, sizeof(LOGFONT));
        ms_systemMenuFont->Create(info);

        if (SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &ms_showCues, 0) == 0)
            ms_showCues = true;
#endif

        return true;
    }

    virtual void OnExit()
    {
        delete ms_systemMenuFont;
        ms_systemMenuFont = NULL;
    }

    static wxFont* ms_systemMenuFont;
    static int ms_systemMenuButtonWidth;   // windows clean install default
    static int ms_systemMenuHeight;        // windows clean install default
    static bool ms_showCues;
private:
    DECLARE_DYNAMIC_CLASS(wxMSWSystemMenuFontModule)
};

// these static variables are from the wxMSWSystemMenuFontModule object
// and reflect the system settings returned by the Win32 API's
// SystemParametersInfo() call.

wxFont* wxMSWSystemMenuFontModule::ms_systemMenuFont = NULL;
int wxMSWSystemMenuFontModule::ms_systemMenuButtonWidth = 18;   // windows clean install default
int wxMSWSystemMenuFontModule::ms_systemMenuHeight = 18;        // windows clean install default
bool wxMSWSystemMenuFontModule::ms_showCues = true;

IMPLEMENT_DYNAMIC_CLASS(wxMSWSystemMenuFontModule, wxModule)


// temporary hack to implement wxOwnerDrawn::IsMenuItem() without breaking
// backwards compatibility
#if wxCHECK_VERSION(2, 7, 0)
    #pragma warning "TODO: remove gs_menuItems hack"
#endif

// VC++ 6 gives a warning here:
//
//      return type for 'OwnerDrawnSet_wxImplementation_HashTable::iterator::
//      operator ->' is 'class wxOwnerDrawn ** ' (ie; not a UDT or reference to
//      a UDT.  Will produce errors if applied using infix notation.
//
// shut it down
#ifdef __VISUALC__
    #if __VISUALC__ <= 1300
        #pragma warning(push)
        #pragma warning(disable: 4284)
        #define POP_WARNINGS
    #endif
#endif

#include "wx/hashset.h"
WX_DECLARE_HASH_SET(wxOwnerDrawn*, wxPointerHash, wxPointerEqual, OwnerDrawnSet);

#ifdef POP_WARNINGS
    #pragma warning(pop)
#endif

static OwnerDrawnSet gs_menuItems;

// ============================================================================
// implementation of wxOwnerDrawn class
// ============================================================================

// ctor
// ----
wxOwnerDrawn::wxOwnerDrawn(const wxString& str,
                           bool bCheckable,
                           bool bMenuItem)
            : m_strName(str)
{
    if (ms_nDefaultMarginWidth == 0)
    {
       ms_nDefaultMarginWidth = ::GetSystemMetrics(SM_CXMENUCHECK) +
                                wxSystemSettings::GetMetric(wxSYS_EDGE_X);
       ms_nLastMarginWidth = ms_nDefaultMarginWidth;
    }

    m_bCheckable   = bCheckable;
    m_bOwnerDrawn  = false;
    m_nHeight      = 0;
    m_nMarginWidth = ms_nLastMarginWidth;
    m_nMinHeight   = wxMSWSystemMenuFontModule::ms_systemMenuHeight;

    m_bmpDisabled = wxNullBitmap;

    // TODO: we can't add new m_isMenuItem field in 2.6, so we use this hack
    //       with the map, but do add m_isMenuItem in 2.7
    if ( bMenuItem )
    {
        gs_menuItems.insert(this);
    }
}

wxOwnerDrawn::~wxOwnerDrawn()
{
    // TODO: remove this in 2.7
    gs_menuItems.erase(this);
}

bool wxOwnerDrawn::IsMenuItem() const
{
    // TODO: in 2.7, replace this with simple "return m_isMenuItem"

    // some versions of mingw have problems without const_cast when wxUSE_STL=1
    return gs_menuItems.count(wx_const_cast(wxOwnerDrawn *, this)) == 1;
}


// these items will be set during the first invocation of the c'tor,
// because the values will be determined by checking the system settings,
// which is a chunk of code
size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 0;
size_t wxOwnerDrawn::ms_nLastMarginWidth = 0;


// drawing
// -------

wxFont wxOwnerDrawn::GetFontToUse() const
{
    wxFont font = m_font;
    if ( !font.Ok() )
    {
        if ( IsMenuItem() )
            font = *wxMSWSystemMenuFontModule::ms_systemMenuFont;

        if ( !font.Ok() )
            font = *wxNORMAL_FONT;
    }

    return font;
}

// get size of the item
// The item size includes the menu string, the accel string,
// the bitmap and size for a submenu expansion arrow...
bool wxOwnerDrawn::OnMeasureItem(size_t *pwidth, size_t *pheight)
{
    if ( IsOwnerDrawn() )
    {
        wxMemoryDC dc;

        wxString str = wxStripMenuCodes(m_strName);

        // if we have a valid accel string, then pad out
        // the menu string so that the menu and accel string are not
        // placed on top of each other.
        if ( !m_strAccel.empty() )
        {
            str.Pad(str.Length()%8);
            str += m_strAccel;
        }

        dc.SetFont(GetFontToUse());

        dc.GetTextExtent(str, (long *)pwidth, (long *)pheight);

        // add space at the end of the menu for the submenu expansion arrow
        // this will also allow offsetting the accel string from the right edge
        *pwidth += GetMarginWidth() + 16;
    }
    else // don't draw the text, just the bitmap (if any)
    {
        *pwidth =
        *pheight = 0;
    }

    // increase size to accommodate bigger bitmaps if necessary
    if (m_bmpChecked.Ok())
    {
        // Is BMP height larger then text height?
        size_t adjustedHeight = m_bmpChecked.GetHeight() +
                                  2*wxSystemSettings::GetMetric(wxSYS_EDGE_Y);
        if (*pheight < adjustedHeight)
            *pheight = adjustedHeight;

        const size_t widthBmp = m_bmpChecked.GetWidth();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?