1
///////////////////////////////////////////////////////////////////////////////
2
// Name: src/generic/wizard.cpp
3
// Purpose: generic implementation of wxWizard class
4
// Author: Vadim Zeitlin
5
// Modified by: Robert Cavanaugh
6
// 1) Added capability for wxWizardPage to accept resources
7
// 2) Added "Help" button handler stub
8
// 3) Fixed ShowPage() bug on displaying bitmaps
9
// Robert Vazan (sizers)
11
// RCS-ID: $Id: wizard.cpp 70630 2012-02-20 11:38:52Z JS $
12
// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
13
// Licence: wxWindows licence
14
///////////////////////////////////////////////////////////////////////////////
16
// ============================================================================
18
// ============================================================================
20
// ----------------------------------------------------------------------------
22
// ----------------------------------------------------------------------------
24
// For compilers that support precompilation, includes "wx.h".
25
#include "wx/wxprec.h"
34
#include "wx/dynarray.h"
36
#include "wx/statbmp.h"
37
#include "wx/button.h"
38
#include "wx/settings.h"
42
#include "wx/statline.h"
44
#include "wx/scrolwin.h"
45
#include "wx/wizard.h"
46
#include "wx/dcmemory.h"
48
// ----------------------------------------------------------------------------
50
// ----------------------------------------------------------------------------
52
class wxWizardSizer : public wxSizer
55
wxWizardSizer(wxWizard *owner);
57
virtual wxSizerItem *Insert(size_t index, wxSizerItem *item);
59
virtual void RecalcSizes();
60
virtual wxSize CalcMin();
62
// get the max size of all wizard pages
63
wxSize GetMaxChildSize();
65
// return the border which can be either set using wxWizard::SetBorder() or
67
int GetBorder() const;
69
// hide the pages which we temporarily "show" when they're added to this
70
// sizer (see Insert())
74
wxSize SiblingSize(wxSizerItem *child);
80
// ----------------------------------------------------------------------------
81
// event tables and such
82
// ----------------------------------------------------------------------------
84
wxDEFINE_EVENT( wxEVT_WIZARD_PAGE_CHANGED, wxWizardEvent );
85
wxDEFINE_EVENT( wxEVT_WIZARD_PAGE_CHANGING, wxWizardEvent );
86
wxDEFINE_EVENT( wxEVT_WIZARD_BEFORE_PAGE_CHANGED, wxWizardEvent );
87
wxDEFINE_EVENT( wxEVT_WIZARD_CANCEL, wxWizardEvent );
88
wxDEFINE_EVENT( wxEVT_WIZARD_FINISHED, wxWizardEvent );
89
wxDEFINE_EVENT( wxEVT_WIZARD_HELP, wxWizardEvent );
90
wxDEFINE_EVENT( wxEVT_WIZARD_PAGE_SHOWN, wxWizardEvent );
92
BEGIN_EVENT_TABLE(wxWizard, wxDialog)
93
EVT_BUTTON(wxID_CANCEL, wxWizard::OnCancel)
94
EVT_BUTTON(wxID_BACKWARD, wxWizard::OnBackOrNext)
95
EVT_BUTTON(wxID_FORWARD, wxWizard::OnBackOrNext)
96
EVT_BUTTON(wxID_HELP, wxWizard::OnHelp)
98
EVT_WIZARD_PAGE_CHANGED(wxID_ANY, wxWizard::OnWizEvent)
99
EVT_WIZARD_PAGE_CHANGING(wxID_ANY, wxWizard::OnWizEvent)
100
EVT_WIZARD_CANCEL(wxID_ANY, wxWizard::OnWizEvent)
101
EVT_WIZARD_FINISHED(wxID_ANY, wxWizard::OnWizEvent)
102
EVT_WIZARD_HELP(wxID_ANY, wxWizard::OnWizEvent)
105
IMPLEMENT_DYNAMIC_CLASS(wxWizard, wxDialog)
114
IMPLEMENT_ABSTRACT_CLASS(wxWizardPage, wxPanel)
115
IMPLEMENT_DYNAMIC_CLASS(wxWizardPageSimple, wxWizardPage)
116
IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
118
// ============================================================================
120
// ============================================================================
122
// ----------------------------------------------------------------------------
124
// ----------------------------------------------------------------------------
126
void wxWizardPage::Init()
128
m_bitmap = wxNullBitmap;
131
wxWizardPage::wxWizardPage(wxWizard *parent,
132
const wxBitmap& bitmap)
134
Create(parent, bitmap);
137
bool wxWizardPage::Create(wxWizard *parent,
138
const wxBitmap& bitmap)
140
if ( !wxPanel::Create(parent, wxID_ANY) )
145
// initially the page is hidden, it's shown only when it becomes current
151
// ----------------------------------------------------------------------------
152
// wxWizardPageSimple
153
// ----------------------------------------------------------------------------
155
wxWizardPage *wxWizardPageSimple::GetPrev() const
160
wxWizardPage *wxWizardPageSimple::GetNext() const
165
// ----------------------------------------------------------------------------
167
// ----------------------------------------------------------------------------
169
wxWizardSizer::wxWizardSizer(wxWizard *owner)
171
m_childSize(wxDefaultSize)
175
wxSizerItem *wxWizardSizer::Insert(size_t index, wxSizerItem *item)
177
m_owner->m_usingSizer = true;
179
if ( item->IsWindow() )
181
// we must pretend that the window is shown as otherwise it wouldn't be
182
// taken into account for the layout -- but avoid really showing it, so
183
// just set the internal flag instead of calling wxWindow::Show()
184
item->GetWindow()->wxWindowBase::Show();
187
return wxSizer::Insert(index, item);
190
void wxWizardSizer::HidePages()
192
for ( wxSizerItemList::compatibility_iterator node = GetChildren().GetFirst();
194
node = node->GetNext() )
196
wxSizerItem * const item = node->GetData();
197
if ( item->IsWindow() )
198
item->GetWindow()->wxWindowBase::Show(false);
202
void wxWizardSizer::RecalcSizes()
204
// Effect of this function depends on m_owner->m_page and
205
// it should be called whenever it changes (wxWizard::ShowPage)
206
if ( m_owner->m_page )
208
m_owner->m_page->SetSize(wxRect(m_position, m_size));
212
wxSize wxWizardSizer::CalcMin()
214
return m_owner->GetPageSize();
217
wxSize wxWizardSizer::GetMaxChildSize()
221
for ( wxSizerItemList::compatibility_iterator childNode = m_children.GetFirst();
223
childNode = childNode->GetNext() )
225
wxSizerItem *child = childNode->GetData();
226
maxOfMin.IncTo(child->CalcMin());
227
maxOfMin.IncTo(SiblingSize(child));
230
if ( m_owner->m_started )
232
m_childSize = maxOfMin;
238
int wxWizardSizer::GetBorder() const
240
return m_owner->m_border;
243
wxSize wxWizardSizer::SiblingSize(wxSizerItem *child)
247
if ( child->IsWindow() )
249
wxWizardPage *page = wxDynamicCast(child->GetWindow(), wxWizardPage);
252
for ( wxWizardPage *sibling = page->GetNext();
254
sibling = sibling->GetNext() )
256
if ( sibling->GetSizer() )
258
maxSibling.IncTo(sibling->GetSizer()->CalcMin());
267
// ----------------------------------------------------------------------------
268
// generic wxWizard implementation
269
// ----------------------------------------------------------------------------
271
void wxWizard::Init()
273
m_posWizard = wxDefaultPosition;
275
m_btnPrev = m_btnNext = NULL;
277
m_sizerBmpAndPage = NULL;
282
m_usingSizer = false;
283
m_bitmapBackgroundColour = *wxWHITE;
284
m_bitmapPlacement = 0;
285
m_bitmapMinimumWidth = 115;
288
bool wxWizard::Create(wxWindow *parent,
290
const wxString& title,
291
const wxBitmap& bitmap,
295
bool result = wxDialog::Create(parent,id,title,pos,wxDefaultSize,style);
305
wxWizard::~wxWizard()
307
// normally we don't have to delete this sizer as it's deleted by the
308
// associated window but if we never used it or didn't set it as the window
309
// sizer yet, do delete it manually
310
if ( !m_usingSizer || !m_started )
314
void wxWizard::AddBitmapRow(wxBoxSizer *mainColumn)
316
m_sizerBmpAndPage = new wxBoxSizer(wxHORIZONTAL);
319
1, // Vertically stretchable
320
wxEXPAND // Horizontal stretching, no border
323
0, // No vertical stretching
324
wxEXPAND // No border, (mostly useless) horizontal stretching
328
if ( m_bitmap.IsOk() )
330
wxSize bitmapSize(wxDefaultSize);
331
if (GetBitmapPlacement())
332
bitmapSize.x = GetMinimumBitmapWidth();
334
m_statbmp = new wxStaticBitmap(this, wxID_ANY, m_bitmap, wxDefaultPosition, bitmapSize);
335
m_sizerBmpAndPage->Add(
337
0, // No horizontal stretching
338
wxALL, // Border all around, top alignment
341
m_sizerBmpAndPage->Add(
343
0, // No horizontal stretching
344
wxEXPAND // No border, (mostly useless) vertical stretching
349
// Added to m_sizerBmpAndPage later
350
m_sizerPage = new wxWizardSizer(this);
353
void wxWizard::AddStaticLine(wxBoxSizer *mainColumn)
357
new wxStaticLine(this, wxID_ANY),
358
0, // Vertically unstretchable
359
wxEXPAND | wxALL, // Border all around, horizontally stretchable
363
0, // No vertical stretching
364
wxEXPAND // No border, (mostly useless) horizontal stretching
368
#endif // wxUSE_STATLINE
371
void wxWizard::AddBackNextPair(wxBoxSizer *buttonRow)
373
wxASSERT_MSG( m_btnNext && m_btnPrev,
374
wxT("You must create the buttons before calling ")
375
wxT("wxWizard::AddBackNextPair") );
377
wxBoxSizer *backNextPair = new wxBoxSizer(wxHORIZONTAL);
380
0, // No horizontal stretching
381
wxALL, // Border all around
385
backNextPair->Add(m_btnPrev);
386
backNextPair->Add(10, 0,
387
0, // No horizontal stretching
388
wxEXPAND // No border, (mostly useless) vertical stretching
390
backNextPair->Add(m_btnNext);
393
void wxWizard::AddButtonRow(wxBoxSizer *mainColumn)
395
// the order in which the buttons are created determines the TAB order - at least under MSWindows...
396
// although the 'back' button appears before the 'next' button, a more userfriendly tab order is
397
// to activate the 'next' button first (create the next button before the back button).
398
// The reason is: The user will repeatedly enter information in the wizard pages and then wants to
399
// press 'next'. If a user uses mostly the keyboard, he would have to skip the 'back' button
400
// every time. This is annoying. There is a second reason: RETURN acts as TAB. If the 'next'
401
// button comes first in the TAB order, the user can enter information very fast using the RETURN
402
// key to TAB to the next entry field and page. This would not be possible, if the 'back' button
403
// was created before the 'next' button.
405
bool isPda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
406
int buttonStyle = isPda ? wxBU_EXACTFIT : 0;
408
wxBoxSizer *buttonRow = new wxBoxSizer(wxHORIZONTAL);
410
if (GetExtraStyle() & wxWIZARD_EX_HELPBUTTON)
413
0, // Vertically unstretchable
414
wxGROW|wxALIGN_CENTRE
420
0, // Vertically unstretchable
421
wxALIGN_RIGHT // Right aligned, no border
424
// Desired TAB order is 'next', 'cancel', 'help', 'back'. This makes the 'back' button the last control on the page.
425
// Create the buttons in the right order...
428
if (GetExtraStyle() & wxWIZARD_EX_HELPBUTTON)
429
btnHelp=new wxButton(this, wxID_HELP, wxEmptyString, wxDefaultPosition, wxDefaultSize, buttonStyle);
432
m_btnNext = new wxButton(this, wxID_FORWARD, _("&Next >"));
433
wxButton *btnCancel=new wxButton(this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, buttonStyle);
435
if (GetExtraStyle() & wxWIZARD_EX_HELPBUTTON)
436
btnHelp=new wxButton(this, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, buttonStyle);
438
m_btnPrev = new wxButton(this, wxID_BACKWARD, _("< &Back"), wxDefaultPosition, wxDefaultSize, buttonStyle);
444
0, // Horizontally unstretchable
445
wxALL, // Border all around, top aligned
449
// Put stretchable space between help button and others
450
buttonRow->Add(0, 0, 1, wxALIGN_CENTRE, 0);
454
AddBackNextPair(buttonRow);
458
0, // Horizontally unstretchable
459
wxALL, // Border all around, top aligned
464
void wxWizard::DoCreateControls()
466
// do nothing if the controls were already created
470
bool isPda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
472
// Horizontal stretching, and if not PDA, border all around
473
int mainColumnSizerFlags = isPda ? wxEXPAND : wxALL|wxEXPAND ;
475
// wxWindow::SetSizer will be called at end
476
wxBoxSizer *windowSizer = new wxBoxSizer(wxVERTICAL);
478
wxBoxSizer *mainColumn = new wxBoxSizer(wxVERTICAL);
481
1, // Vertical stretching
482
mainColumnSizerFlags,
486
AddBitmapRow(mainColumn);
489
AddStaticLine(mainColumn);
491
AddButtonRow(mainColumn);
493
SetSizer(windowSizer);
496
void wxWizard::SetPageSize(const wxSize& size)
498
wxCHECK_RET(!m_started, wxT("wxWizard::SetPageSize after RunWizard"));
502
void wxWizard::FitToPage(const wxWizardPage *page)
504
wxCHECK_RET(!m_started, wxT("wxWizard::FitToPage after RunWizard"));
508
wxSize size = page->GetBestSize();
510
m_sizePage.IncTo(size);
512
page = page->GetNext();
516
bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
518
wxASSERT_MSG( page != m_page, wxT("this is useless") );
520
wxSizerFlags flags(1);
521
flags.Border(wxALL, m_border).Expand();
527
m_sizerBmpAndPage->Add(m_sizerPage, flags);
529
// now that our layout is computed correctly, hide the pages
530
// artificially shown in wxWizardSizer::Insert() back again
531
m_sizerPage->HidePages();
536
// remember the old bitmap (if any) to compare with the new one later
539
// check for previous page
542
// send the event to the old page
543
wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGING, GetId(),
544
goingForward, m_page);
545
if ( m_page->GetEventHandler()->ProcessEvent(event) &&
548
// vetoed by the page
554
bmpPrev = m_page->GetBitmap();
557
m_sizerBmpAndPage->Detach(m_page);
563
// terminate successfully
570
SetReturnCode(wxID_OK);
574
// and notify the user code (this is especially useful for modeless
576
wxWizardEvent event(wxEVT_WIZARD_FINISHED, GetId(), false, m_page);
577
(void)GetEventHandler()->ProcessEvent(event);
584
// notice that we change m_page only here so that wxEVT_WIZARD_FINISHED
585
// event above could still use the correct (i.e. old) value of m_page
588
// position and show the new page
589
(void)m_page->TransferDataToWindow();
593
// wxWizardSizer::RecalcSizes wants to be called when m_page changes
594
m_sizerPage->RecalcSizes();
596
else // pages are not managed by the sizer
598
m_sizerBmpAndPage->Add(m_page, flags);
599
m_sizerBmpAndPage->SetItemMinSize(m_page, GetPageSize());
603
// update the bitmap if:it changed
607
bmp = m_page->GetBitmap();
611
if ( !bmpPrev.IsOk() )
614
if (!GetBitmapPlacement())
616
if ( !bmp.IsSameAs(bmpPrev) )
617
m_statbmp->SetBitmap(bmp);
620
#endif // wxUSE_STATBMP
623
// and update the buttons state
624
m_btnPrev->Enable(HasPrevPage(m_page));
626
const bool hasNext = HasNextPage(m_page);
627
const wxString label = hasNext ? _("&Next >") : _("&Finish");
628
if ( label != m_btnNext->GetLabel() )
629
m_btnNext->SetLabel(label);
631
m_btnNext->SetDefault();
634
// send the change event to the new page now
635
wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGED, GetId(), goingForward, m_page);
636
(void)m_page->GetEventHandler()->ProcessEvent(event);
638
// and finally show it
643
m_sizerBmpAndPage->Layout();
652
if (GetBitmapPlacement() && m_statbmp)
656
if ( !bmp.IsSameAs(bmpPrev) )
657
m_statbmp->SetBitmap(bmp);
660
m_sizerPage->RecalcSizes();
663
wxWizardEvent pageShownEvent(wxEVT_WIZARD_PAGE_SHOWN, GetId(),
664
goingForward, m_page);
665
m_page->GetEventHandler()->ProcessEvent(pageShownEvent);
670
/// Do fit, and adjust to screen size if necessary
671
void wxWizard::DoWizardLayout()
673
if ( wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA )
675
if (CanDoLayoutAdaptation())
676
DoLayoutAdaptation();
678
GetSizer()->SetSizeHints(this);
680
if ( m_posWizard == wxDefaultPosition )
684
SetLayoutAdaptationDone(true);
687
bool wxWizard::RunWizard(wxWizardPage *firstPage)
689
wxCHECK_MSG( firstPage, false, wxT("can't run empty wizard") );
691
// can't return false here because there is no old page
692
(void)ShowPage(firstPage, true /* forward */);
696
return ShowModal() == wxID_OK;
699
wxWizardPage *wxWizard::GetCurrentPage() const
704
wxSize wxWizard::GetPageSize() const
706
// default width and height of the page
707
int DEFAULT_PAGE_WIDTH,
709
if ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA )
711
// Make the default page size small enough to fit on screen
712
DEFAULT_PAGE_WIDTH = wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2;
713
DEFAULT_PAGE_HEIGHT = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2;
718
DEFAULT_PAGE_HEIGHT = 270;
721
// start with default minimal size
722
wxSize pageSize(DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT);
724
// make the page at least as big as specified by user
725
pageSize.IncTo(m_sizePage);
729
// make the page at least as tall as the bitmap
730
pageSize.IncTo(wxSize(0, m_bitmap.GetHeight()));
735
// make it big enough to contain all pages added to the sizer
736
pageSize.IncTo(m_sizerPage->GetMaxChildSize());
742
wxSizer *wxWizard::GetPageAreaSizer() const
747
void wxWizard::SetBorder(int border)
749
wxCHECK_RET(!m_started, wxT("wxWizard::SetBorder after RunWizard"));
754
void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(eventUnused))
756
// this function probably can never be called when we don't have an active
757
// page, but a small extra check won't hurt
758
wxWindow *win = m_page ? (wxWindow *)m_page : (wxWindow *)this;
760
wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId(), false, m_page);
761
if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
763
// no objections - close the dialog
766
EndModal(wxID_CANCEL);
770
SetReturnCode(wxID_CANCEL);
774
//else: request to Cancel ignored
777
void wxWizard::OnBackOrNext(wxCommandEvent& event)
779
wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
780
(event.GetEventObject() == m_btnPrev),
781
wxT("unknown button") );
783
wxCHECK_RET( m_page, wxT("should have a valid current page") );
785
// ask the current page first: notice that we do it before calling
786
// GetNext/Prev() because the data transferred from the controls of the page
787
// may change the value returned by these methods
788
if ( !m_page->Validate() || !m_page->TransferDataFromWindow() )
790
// the page data is incorrect, don't do anything
794
bool forward = event.GetEventObject() == m_btnNext;
796
// Give the application a chance to set state which may influence GetNext()/GetPrev()
797
wxWizardEvent eventPreChanged(wxEVT_WIZARD_BEFORE_PAGE_CHANGED, GetId(), forward, m_page);
798
(void)m_page->GetEventHandler()->ProcessEvent(eventPreChanged);
800
if (!eventPreChanged.IsAllowed())
806
page = m_page->GetNext();
810
page = m_page->GetPrev();
812
wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
815
// just pass to the new page (or maybe not - but we don't care here)
816
(void)ShowPage(page, forward);
819
void wxWizard::OnHelp(wxCommandEvent& WXUNUSED(event))
821
// this function probably can never be called when we don't have an active
822
// page, but a small extra check won't hurt
825
// Create and send the help event to the specific page handler
826
// event data contains the active page so that context-sensitive
828
wxWizardEvent eventHelp(wxEVT_WIZARD_HELP, GetId(), true, m_page);
829
(void)m_page->GetEventHandler()->ProcessEvent(eventHelp);
833
void wxWizard::OnWizEvent(wxWizardEvent& event)
835
// the dialogs have wxWS_EX_BLOCK_EVENTS style on by default but we want to
836
// propagate wxEVT_WIZARD_XXX to the parent (if any), so do it manually
837
if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) )
839
// the event will be propagated anyhow
844
wxWindow *parent = GetParent();
846
if ( !parent || !parent->GetEventHandler()->ProcessEvent(event) )
852
if ( ( !m_wasModal ) &&
854
( event.GetEventType() == wxEVT_WIZARD_FINISHED ||
855
event.GetEventType() == wxEVT_WIZARD_CANCEL
863
void wxWizard::SetBitmap(const wxBitmap& bitmap)
867
m_statbmp->SetBitmap(m_bitmap);
870
// ----------------------------------------------------------------------------
872
// ----------------------------------------------------------------------------
874
wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction, wxWizardPage* page)
875
: wxNotifyEvent(type, id)
877
// Modified 10-20-2001 Robert Cavanaugh
878
// add the active page to the event data
879
m_direction = direction;
883
/// Do the adaptation
884
bool wxWizard::DoLayoutAdaptation()
886
wxWindowList windows;
889
// Make all the pages (that use sizers) scrollable
890
for ( wxSizerItemList::compatibility_iterator node = m_sizerPage->GetChildren().GetFirst(); node; node = node->GetNext() )
892
wxSizerItem * const item = node->GetData();
893
if ( item->IsWindow() )
895
wxWizardPage* page = wxDynamicCast(item->GetWindow(), wxWizardPage);
900
if (!pages.Find(page) && page->GetSizer())
902
// Create a scrolled window and reparent
903
wxScrolledWindow* scrolledWindow = new wxScrolledWindow(page, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxVSCROLL|wxHSCROLL|wxBORDER_NONE);
904
wxSizer* oldSizer = page->GetSizer();
906
wxSizer* newSizer = new wxBoxSizer(wxVERTICAL);
907
newSizer->Add(scrolledWindow,1, wxEXPAND, 0);
909
page->SetSizer(newSizer, false /* don't delete the old sizer */);
911
scrolledWindow->SetSizer(oldSizer);
913
wxStandardDialogLayoutAdapter::DoReparentControls(page, scrolledWindow);
916
windows.Append(scrolledWindow);
918
page = page->GetNext();
924
wxStandardDialogLayoutAdapter::DoFitWithScrolling(this, windows);
926
// Size event doesn't get sent soon enough on wxGTK
929
SetLayoutAdaptationDone(true);
934
bool wxWizard::ResizeBitmap(wxBitmap& bmp)
936
if (!GetBitmapPlacement())
941
wxSize pageSize = m_sizerPage->GetSize();
942
if (pageSize == wxSize(0,0))
943
pageSize = GetPageSize();
944
int bitmapWidth = wxMax(bmp.GetWidth(), GetMinimumBitmapWidth());
945
int bitmapHeight = pageSize.y;
947
if (!m_statbmp->GetBitmap().IsOk() || m_statbmp->GetBitmap().GetHeight() != bitmapHeight)
949
wxBitmap bitmap(bitmapWidth, bitmapHeight);
952
dc.SelectObject(bitmap);
953
dc.SetBackground(wxBrush(m_bitmapBackgroundColour));
956
if (GetBitmapPlacement() & wxWIZARD_TILE)
958
TileBitmap(wxRect(0, 0, bitmapWidth, bitmapHeight), dc, bmp);
964
if (GetBitmapPlacement() & wxWIZARD_HALIGN_LEFT)
966
else if (GetBitmapPlacement() & wxWIZARD_HALIGN_RIGHT)
967
x = bitmapWidth - bmp.GetWidth();
969
x = (bitmapWidth - bmp.GetWidth())/2;
971
if (GetBitmapPlacement() & wxWIZARD_VALIGN_TOP)
973
else if (GetBitmapPlacement() & wxWIZARD_VALIGN_BOTTOM)
974
y = bitmapHeight - bmp.GetHeight();
976
y = (bitmapHeight - bmp.GetHeight())/2;
978
dc.DrawBitmap(bmp, x, y, true);
979
dc.SelectObject(wxNullBitmap);
990
bool wxWizard::TileBitmap(const wxRect& rect, wxDC& dc, const wxBitmap& bitmap)
992
int w = bitmap.GetWidth();
993
int h = bitmap.GetHeight();
997
dcMem.SelectObjectAsSource(bitmap);
1000
for (i = rect.x; i < rect.x + rect.width; i += w)
1002
for (j = rect.y; j < rect.y + rect.height; j+= h)
1003
dc.Blit(i, j, bitmap.GetWidth(), bitmap.GetHeight(), & dcMem, 0, 0);
1005
dcMem.SelectObject(wxNullBitmap);
1010
#endif // wxUSE_WIZARDDLG