Files
wxWidgets/src/os2/toolbar.cpp
David Webster a885d89ae9 Frame and Window coding
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6160 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2000-02-21 05:12:34 +00:00

1083 lines
31 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: toolbar.cpp
// Purpose: wxToolBar
// Author: David Webster
// Modified by:
// Created: 10/17/99
// RCS-ID: $Id$
// Copyright: (c) David Webster
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE
#include "wx/toolbar.h"
#include "malloc.h"
#include "wx/os2/private.h"
#include "wx/app.h" // for GetComCtl32Version
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// these standard constants are not always defined in compilers headers
// Styles
#ifndef TBSTYLE_FLAT
#define TBSTYLE_LIST 0x1000
#define TBSTYLE_FLAT 0x0800
#define TBSTYLE_TRANSPARENT 0x8000
#endif
// use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT
// Messages
#ifndef TB_GETSTYLE
#define TB_SETSTYLE (WM_USER + 56)
#define TB_GETSTYLE (WM_USER + 57)
#endif
#ifndef TB_HITTEST
#define TB_HITTEST (WM_USER + 69)
#endif
// these values correspond to those used by comctl32.dll
#define DEFAULTBITMAPX 16
#define DEFAULTBITMAPY 15
#define DEFAULTBUTTONX 24
#define DEFAULTBUTTONY 24
#define DEFAULTBARHEIGHT 27
// ----------------------------------------------------------------------------
// private function prototypes
// ----------------------------------------------------------------------------
static void wxMapBitmap( HBITMAP hBitmap
,int nWidth
,int nHeight
);
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class wxToolBarTool : public wxToolBarToolBase
{
public:
inline wxToolBarTool( wxToolBar* pTbar
,int vId
,const wxBitmap& rBitmap1
,const wxBitmap& rBitmap2
,bool bToggle
,wxObject* pClientData
,const wxString& rShortHelpString
,const wxString& rLongHelpString
) : wxToolBarToolBase( pTbar
,vId
,rBitmap1
,rBitmap2
,bToggle
,pClientData
,rShortHelpString
,rLongHelpString
)
{
m_nSepCount = 0;
}
inline wxToolBarTool( wxToolBar* pTbar
,wxControl* pControl
) : wxToolBarToolBase( pTbar
,pControl
)
{
m_nSepCount = 1;
}
// set/get the number of separators which we use to cover the space used by
// a control in the toolbar
inline void SetSeparatorsCount(size_t nCount) { m_nSepCount = nCount; }
inline size_t GetSeparatorsCount(void) const { return m_nSepCount; }
private:
size_t m_nSepCount;
};
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxToolBarTool
// ----------------------------------------------------------------------------
wxToolBarToolBase* wxToolBar::CreateTool(
int nId
, const wxBitmap& rBitmap1
, const wxBitmap& rBitmap2
, bool bToggle
, wxObject* pClientData
, const wxString& rShortHelpString
, const wxString& rLongHelpString
)
{
return(new wxToolBarTool( this
,nId
,rBitmap1
,rBitmap2
,bToggle
,pClientData
,rShortHelpString
,rLongHelpString
));
}
wxToolBarToolBase* wxToolBar::CreateTool(
wxControl* pControl
)
{
return(new wxToolBarTool( this
,pControl
));
}
// ----------------------------------------------------------------------------
// wxToolBar construction
// ----------------------------------------------------------------------------
void wxToolBar::Init()
{
m_hBitmap = 0;
m_nButtons = 0;
m_defaultWidth = DEFAULTBITMAPX;
m_defaultHeight = DEFAULTBITMAPY;
}
bool wxToolBar::Create(
wxWindow* pParent
, wxWindowID vId
, const wxPoint& rPos
, const wxSize& rSize
, long lStyle
, const wxString& rName
)
{
// common initialisation
if (!CreateControl( pParent
,vId
,rPos
,rSize
,lStyle
, wxDefaultValidator
,rName
))
return(FALSE);
// prepare flags
DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included
// TODO
/*
if (lStyle & wxBORDER)
msflags |= WS_BORDER;
msflags |= TBSTYLE_TOOLTIPS;
if (style & wxTB_FLAT)
{
if (wxTheApp->GetComCtl32Version() > 400)
msflags |= TBSTYLE_FLAT;
}
// MSW-specific initialisation
if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) )
return FALSE;
// toolbar-specific post initialisation
::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
// set up the colors and fonts
wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE));
m_foregroundColour = *wxBLACK;
SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
// position it
int x = pos.x;
int y = pos.y;
int width = size.x;
int height = size.y;
if (width <= 0)
width = 100;
if (height <= 0)
height = m_defaultHeight;
if (x < 0)
x = 0;
if (y < 0)
y = 0;
SetSize(x, y, width, height);
*/
return(TRUE);
}
wxToolBar::~wxToolBar()
{
if (m_hBitmap)
{
::GpiDeleteBitmap((HBITMAP) m_hBitmap);
}
}
// ----------------------------------------------------------------------------
// adding/removing tools
// ----------------------------------------------------------------------------
bool wxToolBar::DoInsertTool(
size_t WXUNUSED(nPos)
, wxToolBarToolBase* pTool
)
{
// nothing special to do here - we really create the toolbar buttons in
// Realize() later
pTool->Attach(this);
return(TRUE);
}
bool wxToolBar::DoDeleteTool(
size_t nPos
, wxToolBarToolBase* pTool
)
{
// normally, we only delete one button, but we use several separators to
// cover the space used by one control sometimes (with old comctl32.dll)
size_t nButtonsToDelete = 1;
// get the size of the button we're going to delete
RECTL vRect;
// TODO:
/*
if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) )
{
wxLogLastError(_T("TB_GETITEMRECT"));
}
int width = r.right - r.left;
if ( tool->IsControl() )
{
nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount();
width *= nButtonsToDelete;
}
while ( nButtonsToDelete-- > 0 )
{
if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) )
{
wxLogLastError("TB_DELETEBUTTON");
return FALSE;
}
}
tool->Detach();
m_nButtons -= nButtonsToDelete;
// reposition all the controls after this button
wxToolBarToolsList::Node *node = m_tools.Item(pos);
for ( node = node->GetNext(); node; node = node->GetNext() )
{
wxToolBarToolBase *tool2 = node->GetData();
if ( tool2->IsControl() )
{
int x;
wxControl *control = tool2->GetControl();
control->GetPosition(&x, NULL);
control->Move(x - width, -1);
}
}
*/
return(TRUE);
}
bool wxToolBar::Realize()
{
size_t nTools = GetToolsCount();
if (nTools == 0)
{
// nothing to do
return(TRUE);
}
bool bIsVertical = (GetWindowStyle() & wxTB_VERTICAL) != 0;
// TODO:
/*
// First, add the bitmap: we use one bitmap for all toolbar buttons
// ----------------------------------------------------------------
// if we already have a bitmap, we'll replace the existing one - otherwise
// we'll install a new one
HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap;
int totalBitmapWidth = (int)(m_defaultWidth * nTools);
int totalBitmapHeight = (int)m_defaultHeight;
// Create a bitmap for all the tool bitmaps
HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(),
totalBitmapWidth,
totalBitmapHeight);
if ( !hBitmap )
{
wxLogLastError(_T("CreateCompatibleBitmap"));
return FALSE;
}
m_hBitmap = (WXHBITMAP)hBitmap;
// Now blit all the tools onto this bitmap
HDC memoryDC = ::CreateCompatibleDC(NULL);
HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap);
HDC memoryDC2 = ::CreateCompatibleDC(NULL);
// the button position
wxCoord x = 0;
// the number of buttons (not separators)
int nButtons = 0;
wxToolBarToolsList::Node *node = m_tools.GetFirst();
while ( node )
{
wxToolBarToolBase *tool = node->GetData();
if ( tool->IsButton() )
{
HBITMAP hbmp = GetHbitmapOf(tool->GetBitmap1());
if ( hbmp )
{
HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp);
if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight,
memoryDC2, 0, 0, SRCCOPY) )
{
wxLogLastError("BitBlt");
}
::SelectObject(memoryDC2, oldBitmap2);
}
else
{
wxFAIL_MSG( _T("invalid tool button bitmap") );
}
// still inc width and number of buttons because otherwise the
// subsequent buttons will all be shifted which is rather confusing
// (and like this you'd see immediately which bitmap was bad)
x += m_defaultWidth;
nButtons++;
}
node = node->GetNext();
}
::SelectObject(memoryDC, oldBitmap);
::DeleteDC(memoryDC);
::DeleteDC(memoryDC2);
// Map to system colours
wxMapBitmap(hBitmap, totalBitmapWidth, totalBitmapHeight);
if ( oldToolBarBitmap )
{
TBREPLACEBITMAP replaceBitmap;
replaceBitmap.hInstOld = NULL;
replaceBitmap.hInstNew = NULL;
replaceBitmap.nIDOld = (UINT) oldToolBarBitmap;
replaceBitmap.nIDNew = (UINT) hBitmap;
replaceBitmap.nButtons = nButtons;
if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP,
0, (LPARAM) &replaceBitmap) )
{
wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
}
::DeleteObject(oldToolBarBitmap);
// Now delete all the buttons
for ( size_t pos = 0; pos < m_nButtons; pos++ )
{
if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) )
{
wxLogLastError("TB_DELETEBUTTON");
}
}
}
else // no old bitmap
{
TBADDBITMAP addBitmap;
addBitmap.hInst = 0;
addBitmap.nID = (UINT) hBitmap;
if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP,
(WPARAM) nButtons, (LPARAM)&addBitmap) == -1 )
{
wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
}
}
// Next add the buttons and separators
// -----------------------------------
TBBUTTON *buttons = new TBBUTTON[nTools];
// this array will hold the indices of all controls in the toolbar
wxArrayInt controlIds;
int i = 0;
int bitmapId = 0;
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
wxToolBarToolBase *tool = node->GetData();
// don't add separators to the vertical toolbar - looks ugly
if ( isVertical && tool->IsSeparator() )
continue;
TBBUTTON& button = buttons[i];
wxZeroMemory(button);
switch ( tool->GetStyle() )
{
case wxTOOL_STYLE_CONTROL:
button.idCommand = tool->GetId();
// fall through: create just a separator too
case wxTOOL_STYLE_SEPARATOR:
button.fsState = TBSTATE_ENABLED;
button.fsStyle = TBSTYLE_SEP;
break;
case wxTOOL_STYLE_BUTTON:
button.iBitmap = bitmapId;
button.idCommand = tool->GetId();
if ( tool->IsEnabled() )
button.fsState |= TBSTATE_ENABLED;
if ( tool->IsToggled() )
button.fsState |= TBSTATE_CHECKED;
button.fsStyle = tool->CanBeToggled() ? TBSTYLE_CHECK
: TBSTYLE_BUTTON;
bitmapId++;
break;
}
i++;
}
if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS,
(WPARAM)i, (LPARAM)buttons) )
{
wxLogLastError("TB_ADDBUTTONS");
}
delete [] buttons;
// Deal with the controls finally
// ------------------------------
// adjust the controls size to fit nicely in the toolbar
size_t index = 0;
for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ )
{
wxToolBarToolBase *tool = node->GetData();
if ( !tool->IsControl() )
continue;
wxControl *control = tool->GetControl();
wxSize size = control->GetSize();
// the position of the leftmost controls corner
int left = -1;
// note that we use TB_GETITEMRECT and not TB_GETRECT because the
// latter only appeared in v4.70 of comctl32.dll
RECT r;
if ( !SendMessage(GetHwnd(), TB_GETITEMRECT,
index, (LPARAM)(LPRECT)&r) )
{
wxLogLastError("TB_GETITEMRECT");
}
// TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
#if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 )
// available in headers, now check whether it is available now
// (during run-time)
if ( wxTheApp->GetComCtl32Version() >= 471 )
{
// set the (underlying) separators width to be that of the
// control
TBBUTTONINFO tbbi;
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_SIZE;
tbbi.cx = size.x;
if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO,
tool->GetId(), (LPARAM)&tbbi) )
{
// the id is probably invalid?
wxLogLastError("TB_SETBUTTONINFO");
}
}
else
#endif // comctl32.dll 4.71
// TB_SETBUTTONINFO unavailable
{
// try adding several separators to fit the controls width
int widthSep = r.right - r.left;
left = r.left;
TBBUTTON tbb;
wxZeroMemory(tbb);
tbb.idCommand = 0;
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = TBSTYLE_SEP;
size_t nSeparators = size.x / widthSep;
for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
{
if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON,
index, (LPARAM)&tbb) )
{
wxLogLastError("TB_INSERTBUTTON");
}
index++;
}
// remember the number of separators we used - we'd have to
// delete all of them later
((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators);
// adjust the controls width to exactly cover the separators
control->SetSize((nSeparators + 1)*widthSep, -1);
}
// and position the control itself correctly vertically
int height = r.bottom - r.top;
int diff = height - size.y;
if ( diff < 0 )
{
// the control is too high, resize to fit
control->SetSize(-1, height - 2);
diff = 2;
}
control->Move(left == -1 ? r.left : left, r.top + (diff + 1) / 2);
}
// the max index is the "real" number of buttons - i.e. counting even the
// separators which we added just for aligning the controls
m_nButtons = index;
if ( !isVertical )
{
if ( m_maxRows == 0 )
{
// if not set yet, only one row
SetRows(1);
}
}
else if ( m_nButtons > 0 ) // vertical non empty toolbar
{
if ( m_maxRows == 0 )
{
// if not set yet, have one column
SetRows(m_nButtons);
}
}
*/
return TRUE;
}
// ----------------------------------------------------------------------------
// message handlers
// ----------------------------------------------------------------------------
bool wxToolBar::OS2Command(
WXUINT nCmd
, WXWORD nId
)
{
wxToolBarToolBase* pTool = FindById((int)nId);
if (!pTool)
return(FALSE);
// TODO:
/*
if (pTool->CanBeToggled())
{
LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
tool->SetToggle((state & TBSTATE_CHECKED) != 0);
}
bool toggled = tool->IsToggled();
// OnLeftClick() can veto the button state change - for buttons which may
// be toggled only, of couse
if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() )
{
// revert back
toggled = !toggled;
tool->SetToggle(toggled);
::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0));
}
*/
return(TRUE);
}
bool wxToolBar::OS2OnNotify(
int WXUNUSED(idCtrl)
, WXLPARAM lParam
, WXLPARAM* pResult
)
{
// TODO:
/*
// First check if this applies to us
NMHDR *hdr = (NMHDR *)lParam;
// the tooltips control created by the toolbar is sometimes Unicode, even
// in an ANSI application - this seems to be a bug in comctl32.dll v5
int code = (int)hdr->code;
if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) )
return FALSE;
HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0);
if ( toolTipWnd != hdr->hwndFrom )
return FALSE;
LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
int id = (int)ttText->hdr.idFrom;
wxToolBarToolBase *tool = FindById(id);
if ( !tool )
return FALSE;
const wxString& help = tool->GetShortHelp();
if ( !help.IsEmpty() )
{
if ( code == TTN_NEEDTEXTA )
{
ttText->lpszText = (wxChar *)help.c_str();
}
#if (_WIN32_IE >= 0x0300)
else
{
// FIXME this is a temp hack only until I understand better what
// must be done in both ANSI and Unicode builds
size_t lenAnsi = help.Len();
#ifdef __MWERKS__
// MetroWerks doesn't like calling mbstowcs with NULL argument
size_t lenUnicode = 2*lenAnsi;
#else
size_t lenUnicode = mbstowcs(NULL, help, lenAnsi);
#endif
// using the pointer of right type avoids us doing all sorts of
// pointer arithmetics ourselves
wchar_t *dst = (wchar_t *)ttText->szText,
*pwz = new wchar_t[lenUnicode + 1];
mbstowcs(pwz, help, lenAnsi + 1);
memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
// put the terminating _wide_ NUL
dst[lenUnicode] = 0;
delete [] pwz;
}
#endif // _WIN32_IE >= 0x0300
}
// For backward compatibility...
OnMouseEnter(tool->GetId());
*/
return(TRUE);
}
// ----------------------------------------------------------------------------
// toolbar geometry
// ----------------------------------------------------------------------------
void wxToolBar::SetToolBitmapSize(
const wxSize& rSize
)
{
wxToolBarBase::SetToolBitmapSize(rSize);
// ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y));
}
void wxToolBar::SetRows(
int nRows
)
{
if (nRows == m_maxRows)
{
// avoid resizing the frame uselessly
return;
}
// TODO:
/*
// TRUE in wParam means to create at least as many rows, FALSE -
// at most as many
RECT rect;
::SendMessage(GetHwnd(), TB_SETROWS,
MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)),
(LPARAM) &rect);
m_maxRows = nRows;
UpdateSize();
*/
}
// The button size is bigger than the bitmap size
wxSize wxToolBar::GetToolSize() const
{
// TODO:
/*
// TB_GETBUTTONSIZE is supported from version 4.70
#if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 )
if ( wxTheApp->GetComCtl32Version() >= 470 )
{
DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0);
return wxSize(LOWORD(dw), HIWORD(dw));
}
else
#endif // comctl32.dll 4.70+
{
// defaults
return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
}
*/
return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
}
wxToolBarToolBase *wxToolBar::FindToolForPosition(
wxCoord vX
, wxCoord vY
) const
{
POINTL vPt;
vPt.x = vX;
vPt.y = vY;
int nIndex = 0; //(int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt);
if (nIndex < 0)
{
// it's a separator or there is no tool at all there
return (wxToolBarToolBase *)NULL;
}
return(m_tools.Item((size_t)nIndex)->GetData());
}
void wxToolBar::UpdateSize()
{
// we must refresh the frame after the toolbar size (possibly) changed
wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
if (pFrame)
{
// don't change the size, we just need to generate a WM_SIZE
RECTL vR;
// TODO:
/*
if ( !GetWindowRect(GetHwndOf(frame), &r) )
{
wxLogLastError(_T("GetWindowRect"));
}
(void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED,
MAKELPARAM(r.right - r.left, r.bottom - r.top));
*/
}
}
// ----------------------------------------------------------------------------
// tool state
// ----------------------------------------------------------------------------
void wxToolBar::DoEnableTool(
wxToolBarToolBase* pTool
, bool bEnable
)
{
// TODO:
/*
::SendMessage(GetHwnd(), TB_ENABLEBUTTON,
(WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0));
*/
}
void wxToolBar::DoToggleTool(
wxToolBarToolBase* pTool
, bool bToggle
)
{
// TODO:
/*
::SendMessage(GetHwnd(), TB_CHECKBUTTON,
(WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0));
*/
}
void wxToolBar::DoSetToggle(
wxToolBarToolBase* pTool
, bool bToggle
)
{
// VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or
// without, so we really need to delete the button and recreate it here
wxFAIL_MSG( _T("not implemented") );
}
// ----------------------------------------------------------------------------
// event handlers
// ----------------------------------------------------------------------------
// Responds to colour changes, and passes event on to children.
void wxToolBar::OnSysColourChanged(
wxSysColourChangedEvent& rEvent
)
{
// TODO:
/*
m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
*/
// Remap the buttons
Realize();
Refresh();
// Propagate the event to the non-top-level children
wxWindow::OnSysColourChanged(rEvent);
}
void wxToolBar::OnMouseEvent(
wxMouseEvent& rEvent
)
{
if (rEvent.RightDown())
{
// For now, we don't have an id. Later we could
// try finding the tool.
OnRightClick( (int)-1
,rEvent.GetX()
,rEvent.GetY()
);
}
else
{
rEvent.Skip();
}
}
MRESULT wxToolBar::OS2WindowProc(
WXUINT ulMsg
, MPARAM wParam
, MPARAM lParam
)
{
// TODO:
/*
if (nMsg == WM_SIZE)
{
// calculate our minor dimenstion ourselves - we're confusing the
// standard logic (TB_AUTOSIZE) with our horizontal toolbars and other
// hacks
RECT r;
if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) )
{
int w, h;
if ( GetWindowStyle() & wxTB_VERTICAL )
{
w = r.right - r.left;
if ( m_maxRows )
{
w *= (m_nButtons + m_maxRows - 1)/m_maxRows;
}
h = HIWORD(lParam);
}
else
{
w = LOWORD(lParam);
h = r.bottom - r.top;
if ( m_maxRows )
{
h += 6; // FIXME: this is the separator line height...
h *= m_maxRows;
}
}
if ( MAKELPARAM(w, h) != lParam )
{
// size really changed
SetSize(w, h);
}
// message processed
return 0;
}
}
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
*/
return((MRESULT)0);
}
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
// These are the default colors used to map the bitmap colors to the current
// system colors. Note that they are in BGR format because this is what Windows
// wants (and not RGB)
#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
void wxMapBitmap(
HBITMAP hBitmap
, int nWidth
, int nHeight
)
{
// TODO:
/*
COLORMAP ColorMap[] =
{
{BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
{BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
{BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
{BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
{BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
{BGR_BACKGROUND, COLOR_WINDOW} // magenta
};
int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP));
int n;
for ( n = 0; n < NUM_MAPS; n++)
{
ColorMap[n].to = ::GetSysColor(ColorMap[n].to);
}
HBITMAP hbmOld;
HDC hdcMem = CreateCompatibleDC(NULL);
if (hdcMem)
{
hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap);
int i, j, k;
for ( i = 0; i < width; i++)
{
for ( j = 0; j < height; j++)
{
COLORREF pixel = ::GetPixel(hdcMem, i, j);
//
// BYTE red = GetRValue(pixel);
// BYTE green = GetGValue(pixel);
// BYTE blue = GetBValue(pixel);
//
for ( k = 0; k < NUM_MAPS; k ++)
{
if ( ColorMap[k].from == pixel )
{
// COLORREF actualPixel = ::SetPixel(hdcMem, i, j, ColorMap[k].to);
break;
}
}
}
}
SelectObject(hdcMem, hbmOld);
DeleteObject(hdcMem);
}
*/
}
// Some experiments...
#if 0
// What we want to do is create another bitmap which has a depth of 4,
// and set the bits. So probably we want to convert this HBITMAP into a
// DIB, then call SetDIBits.
// AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of
// the screen), then SetDIBits fails.
HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL);
HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL);
LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB);
dc = ::GetDC(NULL);
// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB;
int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi,
DIB_PAL_COLORS);
DWORD err = GetLastError();
::ReleaseDC(NULL, dc);
// Delete the DIB
GlobalUnlock (newDIB);
GlobalFree (newDIB);
// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap);
// Substitute our new bitmap for the old one
::DeleteObject((HBITMAP) m_hBitmap);
m_hBitmap = (WXHBITMAP) newBitmap;
#endif
#endif