Files
wxWidgets/src/msw/frame.cpp
Bryan Petty 1580848eeb Work around the limitation of windows API when setting thumbnail toolbar buttons.
- New API: InsertThumbBarButton, AppendThumbBarButton, RemoveThumbBarButton.
- Though MSDN said that "Buttons cannot be added or deleted later, so this must
  be the full defined set. Buttons also cannot be reordered.", we can work
  around it by: when first time adding button, initialize all of the possible
  seven buttons and hide them, except the button adding. In the next time adding
  button, just show it, which can make it looks like it is added on the fly.

Author: Chaobin Zhang

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@77602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2014-09-10 14:51:29 +00:00

1024 lines
29 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/frame.cpp
// Purpose: wxFrame
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/frame.h"
#ifndef WX_PRECOMP
#include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
#include "wx/app.h"
#include "wx/menu.h"
#include "wx/utils.h"
#include "wx/dialog.h"
#include "wx/settings.h"
#include "wx/dcclient.h"
#include "wx/mdi.h"
#include "wx/panel.h"
#include "wx/log.h"
#include "wx/toolbar.h"
#include "wx/statusbr.h"
#include "wx/menuitem.h"
#endif // WX_PRECOMP
#include "wx/msw/private.h"
#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
#include <ole2.h>
#include <aygshell.h>
#include "wx/msw/winundef.h"
#endif
#include "wx/generic/statusbr.h"
#ifdef __WXUNIVERSAL__
#include "wx/univ/theme.h"
#include "wx/univ/colschem.h"
#endif // __WXUNIVERSAL__
#if wxUSE_TASKBARBUTTON
#include "wx/taskbarbutton.h"
#endif
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
#if wxUSE_MENUS || wxUSE_MENUS_NATIVE
extern wxMenu *wxCurrentPopupMenu;
#endif // wxUSE_MENUS || wxUSE_MENUS_NATIVE
#if wxUSE_TASKBARBUTTON
static WXUINT gs_msgTaskbarButtonCreated = 0;
#define wxTHBN_CLICKED 0x1800
#endif // wxUSE_TASKBARBUTTON
// ----------------------------------------------------------------------------
// event tables
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
END_EVENT_TABLE()
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// static class members
// ----------------------------------------------------------------------------
#if wxUSE_STATUSBAR
#if wxUSE_NATIVE_STATUSBAR
bool wxFrame::m_useNativeStatusBar = true;
#else
bool wxFrame::m_useNativeStatusBar = false;
#endif
#endif // wxUSE_NATIVE_STATUSBAR
// ----------------------------------------------------------------------------
// creation/destruction
// ----------------------------------------------------------------------------
void wxFrame::Init()
{
#if wxUSE_MENUS
m_hMenu = NULL;
m_menuDepth = 0;
#endif // wxUSE_MENUS
#if wxUSE_TOOLTIPS
m_hwndToolTip = 0;
#endif
m_wasMinimized = false;
}
bool wxFrame::Create(wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
if ( !wxTopLevelWindow::Create(parent, id, title, pos, size, style, name) )
return false;
SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
#if defined(__SMARTPHONE__)
SetLeftMenu(wxID_EXIT, _("Done"));
#endif
#if wxUSE_ACCEL && defined(__POCKETPC__)
// The guidelines state that Ctrl+Q should quit the app.
// Let's define an accelerator table to send wxID_EXIT.
wxAcceleratorEntry entries[1];
entries[0].Set(wxACCEL_CTRL, 'Q', wxID_EXIT);
wxAcceleratorTable accel(1, entries);
SetAcceleratorTable(accel);
#endif // wxUSE_ACCEL && __POCKETPC__
#if wxUSE_TASKBARBUTTON
m_taskBarButton = NULL;
static bool s_registered = false;
if ( !s_registered )
{
gs_msgTaskbarButtonCreated =
::RegisterWindowMessage(wxT("TaskbarButtonCreated"));
s_registered = true;
}
#endif
return true;
}
wxFrame::~wxFrame()
{
SendDestroyEvent();
DeleteAllBars();
#if wxUSE_TASKBARBUTTON
if ( m_taskBarButton )
delete m_taskBarButton;
#endif
}
// ----------------------------------------------------------------------------
// wxFrame client size calculations
// ----------------------------------------------------------------------------
void wxFrame::DoSetClientSize(int width, int height)
{
// leave enough space for the status bar if we have (and show) it
#if wxUSE_STATUSBAR
wxStatusBar *statbar = GetStatusBar();
if ( statbar && statbar->IsShown() )
{
height += statbar->GetSize().y;
}
#endif // wxUSE_STATUSBAR
// call GetClientAreaOrigin() to take the toolbar into account
wxPoint pt = GetClientAreaOrigin();
width += pt.x;
height += pt.y;
#if wxUSE_TOOLBAR
wxToolBar * const toolbar = GetToolBar();
if ( toolbar )
{
if ( toolbar->HasFlag(wxTB_RIGHT | wxTB_BOTTOM) )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_RIGHT) )
width -= sizeTB.x;
else // wxTB_BOTTOM
height -= sizeTB.y;
}
//else: toolbar already taken into account by GetClientAreaOrigin()
}
#endif // wxUSE_TOOLBAR
wxTopLevelWindow::DoSetClientSize(width, height);
}
// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
void wxFrame::DoGetClientSize(int *x, int *y) const
{
wxTopLevelWindow::DoGetClientSize(x, y);
// account for the possible toolbar
wxPoint pt = GetClientAreaOrigin();
if ( x )
*x -= pt.x;
if ( y )
*y -= pt.y;
#if wxUSE_TOOLBAR
wxToolBar * const toolbar = GetToolBar();
if ( toolbar )
{
if ( toolbar->HasFlag(wxTB_RIGHT | wxTB_BOTTOM) )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_RIGHT) )
{
if ( x )
*x -= sizeTB.x;
}
else // wxTB_BOTTOM
{
if ( y )
*y -= sizeTB.y;
}
}
//else: toolbar already taken into account by GetClientAreaOrigin()
}
#endif // wxUSE_TOOLBAR
#if wxUSE_STATUSBAR
// adjust client area height to take the status bar into account
if ( y )
{
wxStatusBar *statbar = GetStatusBar();
if ( statbar && statbar->IsShown() )
{
*y -= statbar->GetSize().y;
}
}
#endif // wxUSE_STATUSBAR
}
// ----------------------------------------------------------------------------
// wxFrame: various geometry-related functions
// ----------------------------------------------------------------------------
// generate an artificial resize event
void wxFrame::SendSizeEvent(int flags)
{
if ( !m_iconized )
{
RECT r = wxGetWindowRect(GetHwnd());
if ( flags & wxSEND_EVENT_POST )
{
::PostMessage(GetHwnd(), WM_SIZE,
IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED,
MAKELPARAM(r.right - r.left, r.bottom - r.top));
}
else // send it
{
::SendMessage(GetHwnd(), WM_SIZE,
IsMaximized() ? SIZE_MAXIMIZED : SIZE_RESTORED,
MAKELPARAM(r.right - r.left, r.bottom - r.top));
}
}
}
#if wxUSE_STATUSBAR
wxStatusBar *wxFrame::OnCreateStatusBar(int number,
long style,
wxWindowID id,
const wxString& name)
{
wxStatusBar *statusBar wxDUMMY_INITIALIZE(NULL);
#if wxUSE_NATIVE_STATUSBAR
if ( !UsesNativeStatusBar() )
{
statusBar = (wxStatusBar *)new wxStatusBarGeneric(this, id, style);
}
else
#endif
{
statusBar = new wxStatusBar(this, id, style, name);
}
statusBar->SetFieldsCount(number);
return statusBar;
}
void wxFrame::PositionStatusBar()
{
if ( !m_frameStatusBar || !m_frameStatusBar->IsShown() )
return;
int w, h;
GetClientSize(&w, &h);
// Resize the status bar to its default height, as it could have been set
// to a wrong value before by WM_SIZE sent during the frame creation and
// our status bars preserve their programmatically set size to avoid being
// resized by DefWindowProc() to the full window width, so if we didn't do
// this here, the status bar would retain the possibly wrong current height.
m_frameStatusBar->SetSize(wxDefaultSize, wxSIZE_AUTO_HEIGHT);
int sw, sh;
m_frameStatusBar->GetSize(&sw, &sh);
int x = 0;
#if wxUSE_TOOLBAR
wxToolBar * const toolbar = GetToolBar();
if ( toolbar && !toolbar->HasFlag(wxTB_TOP) )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_LEFT | wxTB_RIGHT) )
{
if ( toolbar->HasFlag(wxTB_LEFT) )
x -= sizeTB.x;
w += sizeTB.x;
}
else // wxTB_BOTTOM
{
// we need to position the status bar below the toolbar
h += sizeTB.y;
}
}
//else: no adjustments necessary for the toolbar on top
#endif // wxUSE_TOOLBAR
// Since we wish the status bar to be directly under the client area,
// we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
m_frameStatusBar->SetSize(x, h, w, sh);
}
#endif // wxUSE_STATUSBAR
#if wxUSE_MENUS_NATIVE
void wxFrame::AttachMenuBar(wxMenuBar *menubar)
{
#if defined(__SMARTPHONE__) && defined(__WXWINCE__)
wxMenu *autoMenu = NULL;
if( menubar->GetMenuCount() == 1 )
{
autoMenu = wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(menubar->GetMenu(0));
SetRightMenu(wxID_ANY, menubar->GetMenuLabel(0), autoMenu);
}
else
{
autoMenu = new wxMenu;
for( size_t n = 0; n < menubar->GetMenuCount(); n++ )
{
wxMenu *item = menubar->GetMenu(n);
wxString label = menubar->GetMenuLabel(n);
wxMenu *new_item = wxTopLevelWindowMSW::ButtonMenu::DuplicateMenu(item);
autoMenu->Append(wxID_ANY, label, new_item);
}
SetRightMenu(wxID_ANY, _("Menu"), autoMenu);
}
#elif defined(WINCE_WITHOUT_COMMANDBAR)
if (!GetToolBar())
{
wxToolMenuBar* toolBar = new wxToolMenuBar(this, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxBORDER_NONE | wxTB_HORIZONTAL,
wxToolBarNameStr, menubar);
SetToolBar(toolBar);
menubar->SetToolBar(toolBar);
}
// When the main window is created using CW_USEDEFAULT the height of the
// menubar is not taken into account, so we resize it afterwards if a
// menubar is present
HWND hwndMenuBar = SHFindMenuBar(GetHwnd());
if ( hwndMenuBar )
{
RECT mbRect;
::GetWindowRect(hwndMenuBar, &mbRect);
const int menuHeight = mbRect.bottom - mbRect.top;
RECT rc;
::GetWindowRect(GetHwnd(), &rc);
// adjust for menu / titlebar height
rc.bottom -= (2*menuHeight-1);
::MoveWindow(GetHwnd(), rc.left, rc.top, rc.right, rc.bottom, FALSE);
}
#endif
wxFrameBase::AttachMenuBar(menubar);
if ( !menubar )
{
// actually remove the menu from the frame
m_hMenu = (WXHMENU)0;
InternalSetMenuBar();
}
else // set new non NULL menu bar
{
#if !defined(__WXWINCE__) || defined(WINCE_WITH_COMMANDBAR)
// Can set a menubar several times.
if ( menubar->GetHMenu() )
{
m_hMenu = menubar->GetHMenu();
}
else // no HMENU yet
{
m_hMenu = menubar->Create();
if ( !m_hMenu )
{
wxFAIL_MSG( wxT("failed to create menu bar") );
return;
}
}
#endif
InternalSetMenuBar();
}
}
void wxFrame::InternalSetMenuBar()
{
#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
// Nothing
#else
if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) )
{
wxLogLastError(wxT("SetMenu"));
}
#endif
}
#endif // wxUSE_MENUS_NATIVE
#if wxUSE_MENUS && !defined(__WXUNIVERSAL__)
bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
{
// Unfortunately we need to ignore a message which is sent after
// closing the currently active submenu of the menu bar by pressing Escape:
// in this case we get WM_UNINITMENUPOPUP, from which we generate
// wxEVT_MENU_CLOSE, and _then_ we get WM_MENUSELECT for the top level menu
// from which we overwrite the help string just restored by OnMenuClose()
// handler in wxFrameBase. To prevent this from happening we discard these
// messages but only in the case it's really the top level menu as we still
// need to clear the help string when a submenu is selected in a menu.
if ( flags == (MF_POPUP | MF_HILITE) && !m_menuDepth )
return false;
return wxWindow::HandleMenuSelect(nItem, flags, hMenu);
}
bool wxFrame::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup)
{
// Update the menu depth when dealing with the top level menus.
if ( !popup )
{
if ( evtType == wxEVT_MENU_OPEN )
{
m_menuDepth++;
}
else if ( evtType == wxEVT_MENU_CLOSE )
{
wxASSERT_MSG( m_menuDepth > 0, wxS("No open menus?") );
m_menuDepth--;
}
else
{
wxFAIL_MSG( wxS("Unexpected menu event type") );
}
}
return wxWindow::DoSendMenuOpenCloseEvent(evtType, menu, popup);
}
wxMenu* wxFrame::MSWFindMenuFromHMENU(WXHMENU hMenu)
{
return GetMenuBar() ? GetMenuBar()->MSWGetMenu(hMenu) : NULL;
}
#endif // wxUSE_MENUS && !defined(__WXUNIVERSAL__)
#if wxUSE_TASKBARBUTTON
wxTaskBarButton* wxFrame::MSWGetTaskBarButton()
{
return m_taskBarButton;
}
#endif // wxUSE_TASKBARBUTTON
// Responds to colour changes, and passes event on to children.
void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
// Don't override the colour explicitly set by the user, if any.
if ( !UseBgCol() )
{
SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
Refresh();
}
#if wxUSE_STATUSBAR
if ( m_frameStatusBar )
{
wxSysColourChangedEvent event2;
event2.SetEventObject( m_frameStatusBar );
m_frameStatusBar->HandleWindowEvent(event2);
}
#endif // wxUSE_STATUSBAR
// Propagate the event to the non-top-level children
wxWindow::OnSysColourChanged(event);
}
// Pass true to show full screen, false to restore.
bool wxFrame::ShowFullScreen(bool show, long style)
{
// TODO-CE: add support for CE
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
if ( IsFullScreen() == show )
return false;
if (show)
{
// zap the toolbar, menubar, and statusbar if needed
//
// TODO: hide commandbar for WINCE_WITH_COMMANDBAR
#if wxUSE_TOOLBAR
wxToolBar *theToolBar = GetToolBar();
if ((style & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
{
if ( theToolBar->IsShown() )
{
theToolBar->SetSize(wxDefaultCoord,0);
theToolBar->Show(false);
}
else // prevent it from being restored later
{
style &= ~wxFULLSCREEN_NOTOOLBAR;
}
}
#endif // wxUSE_TOOLBAR
if (style & wxFULLSCREEN_NOMENUBAR)
SetMenu((HWND)GetHWND(), (HMENU) NULL);
#if wxUSE_STATUSBAR
wxStatusBar *theStatusBar = GetStatusBar();
// Save the number of fields in the statusbar
if ((style & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
{
if ( theStatusBar->IsShown() )
theStatusBar->Show(false);
else
style &= ~wxFULLSCREEN_NOSTATUSBAR;
}
#endif // wxUSE_STATUSBAR
}
else // restore to normal
{
// restore the toolbar, menubar, and statusbar if we had hid them
#if wxUSE_TOOLBAR
wxToolBar *theToolBar = GetToolBar();
if ((m_fsStyle & wxFULLSCREEN_NOTOOLBAR) && theToolBar)
{
theToolBar->Show(true);
}
#endif // wxUSE_TOOLBAR
#if wxUSE_MENUS
if (m_fsStyle & wxFULLSCREEN_NOMENUBAR)
{
const WXHMENU hmenu = MSWGetActiveMenu();
if ( hmenu )
::SetMenu(GetHwnd(), (HMENU)hmenu);
}
#endif // wxUSE_MENUS
#if wxUSE_STATUSBAR
wxStatusBar *theStatusBar = GetStatusBar();
if ((m_fsStyle & wxFULLSCREEN_NOSTATUSBAR) && theStatusBar)
{
theStatusBar->Show(true);
PositionStatusBar();
}
#endif // wxUSE_STATUSBAR
}
#endif // !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
return wxFrameBase::ShowFullScreen(show, style);
}
// ----------------------------------------------------------------------------
// tool/status bar stuff
// ----------------------------------------------------------------------------
#if wxUSE_TOOLBAR
wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
{
#if defined(WINCE_WITHOUT_COMMANDBAR)
// We may already have a toolbar from calling SetMenuBar.
if (GetToolBar())
return GetToolBar();
#endif
if ( wxFrameBase::CreateToolBar(style, id, name) )
{
PositionToolBar();
}
return m_frameToolBar;
}
void wxFrame::PositionToolBar()
{
// TODO: we want to do something different in WinCE, because the toolbar
// should be associated with the commandbar, instead of being
// independent window.
#if !defined(WINCE_WITHOUT_COMMANDBAR)
wxToolBar *toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{
// don't call our (or even wxTopLevelWindow) version because we want
// the real (full) client area size, not excluding the tool/status bar
int width, height;
wxWindow::DoGetClientSize(&width, &height);
#if wxUSE_STATUSBAR
wxStatusBar *statbar = GetStatusBar();
if ( statbar && statbar->IsShown() )
{
height -= statbar->GetClientSize().y;
}
#endif // wxUSE_STATUSBAR
int tx, ty, tw, th;
toolbar->GetPosition( &tx, &ty );
toolbar->GetSize( &tw, &th );
int x, y;
if ( toolbar->HasFlag(wxTB_BOTTOM) )
{
x = 0;
y = height - th;
}
else if ( toolbar->HasFlag(wxTB_RIGHT) )
{
x = width - tw;
y = 0;
}
else // left or top
{
x = 0;
y = 0;
}
#if defined(WINCE_WITH_COMMANDBAR)
// We're using a commandbar - so we have to allow for it.
if (GetMenuBar() && GetMenuBar()->GetCommandBar())
{
RECT rect;
::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
y = rect.bottom - rect.top;
}
#endif // WINCE_WITH_COMMANDBAR
if ( toolbar->HasFlag(wxTB_BOTTOM) )
{
if ( ty < 0 && ( -ty == th ) )
ty = height - th;
if ( tx < 0 && (-tx == tw ) )
tx = 0;
}
else if ( toolbar->HasFlag(wxTB_RIGHT) )
{
if( ty < 0 && ( -ty == th ) )
ty = 0;
if( tx < 0 && ( -tx == tw ) )
tx = width - tw;
}
else // left or top
{
if (ty < 0 && (-ty == th))
ty = 0;
if (tx < 0 && (-tx == tw))
tx = 0;
}
int desiredW,
desiredH;
if ( toolbar->IsVertical() )
{
desiredW = tw;
desiredH = height;
}
else
{
desiredW = width;
desiredH = th;
}
// use the 'real' MSW position here, don't offset relatively to the
// client area origin
toolbar->SetSize(x, y, desiredW, desiredH, wxSIZE_NO_ADJUSTMENTS);
}
#endif // !WINCE_WITH_COMMANDBAR
}
#endif // wxUSE_TOOLBAR
// ----------------------------------------------------------------------------
// frame state (iconized/maximized/...)
// ----------------------------------------------------------------------------
// propagate our state change to all child frames: this allows us to emulate X
// Windows behaviour where child frames float independently of the parent one
// on the desktop, but are iconized/restored with it
void wxFrame::IconizeChildFrames(bool bIconize)
{
m_iconized = bIconize;
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
wxWindow *win = node->GetData();
// iconizing the frames with this style under Win95 shell puts them at
// the bottom of the screen (as the MDI children) instead of making
// them appear in the taskbar because they are, by virtue of this
// style, not managed by the taskbar - instead leave Windows take care
// of them
if ( win->GetWindowStyle() & wxFRAME_TOOL_WINDOW )
continue;
// the child MDI frames are a special case and should not be touched by
// the parent frame - instead, they are managed by the user
wxFrame *frame = wxDynamicCast(win, wxFrame);
if ( frame
#if wxUSE_MDI_ARCHITECTURE
&& !frame->IsMDIChild()
#endif // wxUSE_MDI_ARCHITECTURE
)
{
// we don't want to restore the child frames which had been
// iconized even before we were iconized, so save the child frame
// status when iconizing the parent frame and check it when
// restoring it
if ( bIconize )
{
frame->m_wasMinimized = frame->IsIconized();
}
// note that we shouldn't touch the hidden frames neither because
// iconizing/restoring them would show them as a side effect
if ( !frame->m_wasMinimized && frame->IsShown() )
frame->Iconize(bIconize);
}
}
}
WXHICON wxFrame::GetDefaultIcon() const
{
// we don't have any standard icons (any more)
return (WXHICON)0;
}
// ===========================================================================
// message processing
// ===========================================================================
// ---------------------------------------------------------------------------
// preprocessing
// ---------------------------------------------------------------------------
bool wxFrame::MSWDoTranslateMessage(wxFrame *frame, WXMSG *pMsg)
{
if ( wxWindow::MSWTranslateMessage(pMsg) )
return true;
#if wxUSE_MENUS && wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
// try the menu bar accelerators
wxMenuBar *menuBar = GetMenuBar();
if ( menuBar && menuBar->GetAcceleratorTable()->Translate(frame, pMsg) )
return true;
#endif // wxUSE_MENUS && wxUSE_ACCEL
return false;
}
// ---------------------------------------------------------------------------
// our private (non virtual) message handlers
// ---------------------------------------------------------------------------
bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
{
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
switch ( id )
{
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
// only do it it if we were iconized before, otherwise resizing the
// parent frame has a curious side effect of bringing it under it's
// children
if ( !m_iconized )
break;
// restore all child frames too
IconizeChildFrames(false);
(void)SendIconizeEvent(false);
break;
case SIZE_MINIMIZED:
// iconize all child frames too
IconizeChildFrames(true);
break;
}
#else
wxUnusedVar(id);
#endif // !__WXWINCE__
if ( !m_iconized )
{
#if wxUSE_STATUSBAR
PositionStatusBar();
#endif // wxUSE_STATUSBAR
#if wxUSE_TOOLBAR
PositionToolBar();
#endif // wxUSE_TOOLBAR
#if defined(WINCE_WITH_COMMANDBAR)
// Position the menu command bar
if (GetMenuBar() && GetMenuBar()->GetCommandBar())
{
RECT rect;
::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
wxSize clientSz = GetClientSize();
if ( !::MoveWindow((HWND) GetMenuBar()->GetCommandBar(), 0, 0, clientSz.x, rect.bottom - rect.top, true ) )
{
wxLogLastError(wxT("MoveWindow"));
}
}
#endif // WINCE_WITH_COMMANDBAR
}
// call the base class version to generate the appropriate events
return false;
}
bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
{
#if wxUSE_MENUS
#if defined(WINCE_WITHOUT_COMMANDBAR)
if (GetToolBar() && GetToolBar()->FindById(id))
return GetToolBar()->MSWCommand(cmd, id);
#endif
// we only need to handle the menu and accelerator commands from the items
// of our menu bar, base wxWindow class already handles the rest
if ( !control && (cmd == 0 /* menu */ || cmd == 1 /* accel */) )
{
#if wxUSE_MENUS_NATIVE
if ( !wxCurrentPopupMenu )
#endif // wxUSE_MENUS_NATIVE
{
wxMenuItem * const mitem = FindItemInMenuBar((signed short)id);
if ( mitem )
return ProcessCommand(mitem);
}
}
#endif // wxUSE_MENUS
#if wxUSE_TASKBARBUTTON
if ( cmd == wxTHBN_CLICKED && m_taskBarButton )
{
wxTaskBarButtonImpl * const
tbButton = reinterpret_cast<wxTaskBarButtonImpl*>(m_taskBarButton);
wxCommandEvent event(wxEVT_BUTTON, tbButton->GetThumbBarButtonID(id));
event.SetEventObject(this);
return ProcessEvent(event);
}
#endif // wxUSE_TASKBARBUTTON
return wxFrameBase::HandleCommand(id, cmd, control);;
}
// ---------------------------------------------------------------------------
// the window proc for wxFrame
// ---------------------------------------------------------------------------
WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
WXLRESULT rc = 0;
bool processed = false;
switch ( message )
{
case WM_CLOSE:
// if we can't close, tell the system that we processed the
// message - otherwise it would close us
processed = !Close();
break;
case WM_SIZE:
processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
break;
case WM_COMMAND:
{
WORD id, cmd;
WXHWND hwnd;
UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam,
&id, &hwnd, &cmd);
HandleCommand(id, cmd, (WXHWND)hwnd);
// don't pass WM_COMMAND to the base class whether we processed
// it or not because we did generate an event for it (our
// HandleCommand() calls the base class version) and we must
// not do it again or the handlers which skip the event would
// be called twice
processed = true;
}
break;
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
case WM_QUERYDRAGICON:
{
const wxIcon& icon = GetIcon();
HICON hIcon = icon.IsOk() ? GetHiconOf(icon)
: (HICON)GetDefaultIcon();
rc = (WXLRESULT)hIcon;
processed = rc != 0;
}
break;
#endif // !__WXMICROWIN__
}
#if wxUSE_TASKBARBUTTON
if ( message == gs_msgTaskbarButtonCreated )
{
m_taskBarButton = new wxTaskBarButtonImpl(GetHandle());
processed = true;
}
#endif
if ( !processed )
rc = wxFrameBase::MSWWindowProc(message, wParam, lParam);
return rc;
}
// ----------------------------------------------------------------------------
// wxFrame size management: we exclude the areas taken by menu/status/toolbars
// from the client area, so the client area is what's really available for the
// frame contents
// ----------------------------------------------------------------------------
// get the origin of the client area in the client coordinates
wxPoint wxFrame::GetClientAreaOrigin() const
{
wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
#if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__) && \
(!defined(__WXWINCE__) || (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__)))
wxToolBar * const toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_TOP) )
{
pt.y += sizeTB.y;
}
else if ( toolbar->HasFlag(wxTB_LEFT) )
{
pt.x += sizeTB.x;
}
}
#endif // wxUSE_TOOLBAR
#if defined(WINCE_WITH_COMMANDBAR)
if (GetMenuBar() && GetMenuBar()->GetCommandBar())
{
RECT rect;
::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
pt.y += (rect.bottom - rect.top);
}
#endif
return pt;
}