Класс wxHtmlPrint - производный от wxHtmlEasyPrinting

В этой статье я опишу еще один переопределенный класс для своих нужд. Думаю, что не только для моих нужд. Началось все с того, что мне пришлось выводить нокоторые свои данные на печать в табличном представлении. Но перед этим, как сами понимаете, не лишним будет и предварительный просмотр.

Для реализации этой простой задачи мне приглянулся класс wxHtmlEasyPrinting, которому дастаточно передать строку, содержащую html-код. Вот небольшой пример его использования.

 

Example1.cpp

				
#include <wx/html/htmprint.h>
/*... */
wxHtmlEasyPrinting* prn = new wxHtmlEasyPrinting(wxT("Довідник користувачів"));
prn->GetPrintData()->SetOrientation(wxLANDSCAPE);
prn->GetPageSetupData()->SetMarginTopLeft(wxPoint(10,10));
prn->GetPageSetupData()->SetMarginBottomRight(wxPoint(5,5));
prn->SetFooter(sFooter);
prn->PreviewText(sText);
/*... */

Для пояснения: sFooter - это строка, содержащая html-код нижнего колонтитула; sText - строка, содержащая html-код содержания документа, выводимого на печать.

Выглядит все это довольно неплохо:


Но мне, как всегда нашлось что-то, что не понравилось. Первое, что мне захотелось улучшить, - это кнопки навигации. Второе, - мне (вернее пользователю) нужно было все написать "рідною мовою". Чтобы долго не рассказывать, посмотрите на рисунок ниже, и ощутите разницу.

Теперь, как это мне удалось. Для начала, посмотрите на заголовочный файл.

 

wxHtmlPrint.h

				
#pragma once
#include <wx/html/htmprint.h>
#include <wx/choice.h>
#include <wx/numdlg.h>
#include <wx/bmpbuttn.h>
#include <wx/sizer.h>

class wxPreviewCtrlBar : public wxPreviewControlBar {
wxBitmapButton* m_bPrint;
wxBitmapButton* m_bRewind;
wxBitmapButton* m_bPreview;
wxBitmapButton* m_bNext;
wxBitmapButton* m_bLast;
public:
wxPreviewCtrlBar(wxPrintPreviewBase* preview,
long buttons,
wxWindow* parent,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString& name = wxT("panel"));
void CreateButtons();
void OnGoto();
};

class wxPreviewCtrl : public wxPreviewFrame {
wxPreviewCtrlBar* m_ctrlBar;
public:
wxPreviewCtrl(wxPrintPreviewBase* preview,
wxWindow* parent,
const wxString& title = wxT("Print Preview"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE,
const wxString& name = wxT("frame"));
inline wxPreviewControlBar* GetControlBar() const {return (wxPreviewControlBar*)m_ctrlBar;}
void Initialize();
void CreateControlBar();
};

class wxHtmlPrint : public wxHtmlEasyPrinting {
wxString m_sTitle;
wxWindow* m_wParent;
protected:
bool DoPreview(wxHtmlPrintout* printout1, wxHtmlPrintout* printout2);
public:
wxHtmlPrint::wxHtmlPrint(const wxString& name, wxWindow* parentWindow = NULL);
};

Как видите, переопределить пришлось не один класс. а целых три. Теперь, по-порядку. Класс wxPreviewCtrlBar, наследуемый от wxPreviewControlBar нужен больше всего, так как именно в этом классе переопределены кнопки и их названия. Подробнее, вместо wxButton для навигации используются wxBitmapButton, а для кнопки "Close" написано "Закрити". (Интерфейс программы был написан на украинском языке. Кому необходимо, - перепишите по-русски сами) Для реализации этой задачи и нужно было переписать функцию CreateButtons(). Функция OnGoto() переписана для того, чтобы в функцию wxGetNumberFromUser передать строки на украинском языке, а не на английском.

Класс wxPreviewCtrl, наследуемый от wxPreviewFrame, имеет член экземпляра wxPreviewCtrlBar* m_ctrlBar. Его предок использовал предка этого члена. Потому пришлось переписать функции, в которых использовался wxPreviewControlBar, почти полностью, изменив лишь использование wxPreviewControlBar* на wxPreviewCtrlBar*.

В классе wxHtmlPrint, наследнике wxHtmlEasyPrinting, надо было переопределить только функцию DoPreview. Но, так как члены предка wxWindow* m_ParentWindow и wxString m_Name - закрытые, то пришлось ввести их альтернативы: wxWindow* m_wParent и wxString m_sTitle.

 

wxHtmlPrint.cpp

				
#include "wxHtmlPrint.h"

/// XPM
static char * btn_rew_xpm[] = {
"16 16 2 1",
" c None",
". c #000000",
" ",
" .. . ",
" .. .. ",
" .. ... ",
" .. .... ",
" .. ..... ",
" .. ...... ",
" .. ....... ",
" .. ....... ",
" .. ...... ",
" .. ..... ",
" .. .... ",
" .. ... ",
" .. .. ",
" .. . ",
" "};

static char * btn_prev_xpm[] = {
"16 16 2 1",
" c None",
". c #000000",
" ",
" . . ",
" .. .. ",
" ... ... ",
" .... .... ",
" ..... ..... ",
" ...... ...... ",
" .............. ",
" .............. ",
" ...... ...... ",
" ..... ..... ",
" .... .... ",
" ... ... ",
" .. .. ",
" . . ",
" "};

static char * btn_next_xpm[] = {
"16 16 2 1",
" c None",
". c #000000",
" ",
" . . ",
" .. .. ",
" ... ... ",
" .... .... ",
" ..... ..... ",
" ...... ...... ",
" .............. ",
" .............. ",
" ...... ...... ",
" ..... ..... ",
" .... .... ",
" ... ... ",
" .. .. ",
" . . ",
" "};

static char * btn_last_xpm[] = {
"16 16 2 1",
" c None",
". c #000000",
" ",
" . .. ",
" .. .. ",
" ... .. ",
" .... .. ",
" ..... .. ",
" ...... .. ",
" ....... .. ",
" ....... .. ",
" ...... .. ",
" ..... .. ",
" .... .. ",
" ... .. ",
" .. .. ",
" . .. ",
" "};

static char *print_xpm[] = {
/* columns rows colors chars-per-pixel */
"16 15 39 1",
"< c #E3E4E6",
"+ c #C3C3C4",
"i c #FFFFFF",
": c #74879B",
"# c #5A89A6",
"a c #F1F4F7",
"r c #5A809C",
"@ c #BDCCD9",
"e c #7A92A4",
"% c #3F6F93",
"t c #9FA2A6",
"3 c #939495",
"w c #5F666D",
"9 c #65839E",
"5 c #4A7291",
"$ c #4B7F9E",
" c None",
"O c #DFE0E2",
"o c #F3F3F3",
"; c #84A5BB",
"& c #467291",
". c #7897AD",
"* c #407598",
"4 c #CFCFD0",
"7 c #6F90A6",
"y c #6A89A2",
"0 c #AAADB2",
"1 c #D2D3D4",
"u c #4F7592",
", c #BCBDBE",
"p c #57778E",
"q c #979BA0",
"2 c #ABABAC",
"- c #E7E7E7",
"= c #D6DEE6",
"> c #9FA0A0",
"8 c #829EB5",
"X c #8FB0C3",
"6 c #5D7C93",
/* pixels */
" .XXXXXXXX ",
" .oooooooX ",
" .OOOOOOOX ",
" .+++++++X ",
"@##$%&&&&&%*##@ ",
"$=-;:>,<123$-=$ ",
".44.5678.96$44. ",
"7,,,,,,,,,,,,,7 ",
"900qwwwwwwwe009 ",
"rtt9ryyyyyyuttr ",
"6qq6iiiiiii%qq6 ",
"633paiiiiii%336 ",
"XXX*iiiiiii%XXX ",
" 6iiiiiii% ",
" $XXXXXXX# "
};

/// wxPreviewCtrlBar
wxPreviewCtrlBar::wxPreviewCtrlBar(wxPrintPreviewBase* preview,
long buttons,
wxWindow* parent,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name) :
wxPreviewControlBar(preview, buttons, parent, pos, size, style, name)
{
m_bPrint = (wxBitmapButton*)NULL;
m_bRewind = (wxBitmapButton*)NULL;
m_bPreview = (wxBitmapButton*)NULL;
m_bNext = (wxBitmapButton*)NULL;
m_bLast = (wxBitmapButton*)NULL;
}

void wxPreviewCtrlBar::CreateButtons()
{
SetSize(0, 0, 400, 40);

wxBoxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );

m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, wxT("Закрити"),
wxDefaultPosition, wxDefaultSize, 0);
item0->Add(m_closeButton, 0, wxALIGN_CENTRE | wxALL, 5);

if (m_buttonFlags & wxPREVIEW_PRINT) {
m_bPrint = new wxBitmapButton(this, wxID_PREVIEW_PRINT, wxBitmap(print_xpm),
wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
item0->Add(m_bPrint, 0, wxALIGN_CENTRE|wxALL, 5);
}

// Exact-fit buttons are too tiny on wxUniversal
int navButtonStyle;
wxSize navButtonSize;
#ifdef __WXUNIVERSAL__
navButtonStyle = 0;
navButtonSize = wxSize(40, m_closeButton->GetSize().y);
#else
navButtonStyle = wxBU_EXACTFIT;
navButtonSize = wxDefaultSize;
#endif

if (m_buttonFlags & wxPREVIEW_FIRST) {
m_bRewind = new wxBitmapButton(this, wxID_PREVIEW_FIRST, wxBitmap(btn_rew_xpm),
wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
item0->Add(m_bRewind, 0, wxALIGN_CENTRE | wxALL, 5);
}
if (m_buttonFlags & wxPREVIEW_PREVIOUS) {
m_bPreview = new wxBitmapButton(this, wxID_PREVIEW_PREVIOUS, wxBitmap(btn_prev_xpm),
wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
item0->Add(m_bPreview, 0, wxALIGN_CENTRE |wxRIGHT | wxTOP | wxBOTTOM, 5);
}
if (m_buttonFlags & wxPREVIEW_NEXT) {
m_bNext = new wxBitmapButton(this, wxID_PREVIEW_NEXT, wxBitmap(btn_next_xpm),
wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
item0->Add(m_bNext, 0, wxALIGN_CENTRE | wxRIGHT | wxTOP | wxBOTTOM, 5);
}
if (m_buttonFlags & wxPREVIEW_LAST) {
m_bLast = new wxBitmapButton(this, wxID_PREVIEW_LAST, wxBitmap(btn_last_xpm),
wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
item0->Add(m_bLast, 0, wxALIGN_CENTRE | wxRIGHT | wxTOP | wxBOTTOM, 5);
}

if (m_buttonFlags & wxPREVIEW_GOTO) {
m_gotoPageButton = new wxButton(this, wxID_PREVIEW_GOTO, wxT("Сторінка..."),
wxDefaultPosition, wxDefaultSize, 0);
item0->Add(m_gotoPageButton, 0, wxALIGN_CENTRE | wxALL, 5);
}

if (m_buttonFlags & wxPREVIEW_ZOOM) {
wxString choices[] = {
wxT("10%"),
wxT("15%"),
wxT("20%"),
wxT("25%"),
wxT("30%"),
wxT("35%"),
wxT("40%"),
wxT("45%"),
wxT("50%"),
wxT("55%"),
wxT("60%"),
wxT("65%"),
wxT("70%"),
wxT("75%"),
wxT("80%"),
wxT("85%"),
wxT("90%"),
wxT("95%"),
wxT("100%"),
wxT("110%"),
wxT("120%"),
wxT("150%"),
wxT("200%")};
int n = WXSIZEOF(choices);
m_zoomControl = new wxChoice(this, wxID_PREVIEW_ZOOM, wxDefaultPosition,
wxSize(70,wxDefaultCoord), n, choices, 0);
item0->Add(m_zoomControl, 0, wxALIGN_CENTRE | wxALL, 5);
SetZoomControl(m_printPreview->GetZoom());
}
SetSizer(item0);
item0->Fit(this);
}


void wxPreviewCtrlBar::OnGoto()
{
wxPrintPreviewBase *preview = GetPrintPreview();
long nPage=0;
if (preview) {
if (preview->GetMinPage() > 0) {
nPage=wxGetNumberFromUser(
wxString::Format("Введіть номер сторінки між %d та %d:",
preview->GetMinPage(),preview->GetMaxPage()),
wxString::Format("%d",preview->GetCurrentPage()),
wxT("Перейти на сторінку"),
preview->GetCurrentPage());
if (preview->GetPrintout()->HasPage(nPage)) {
preview->SetCurrentPage(nPage);
}
}
}
}

/// wxPreviewCtrl
wxPreviewCtrl::wxPreviewCtrl(wxPrintPreviewBase* preview,
wxWindow* parent,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name) :
wxPreviewFrame(preview, parent, title, pos, size, style, name)
{
m_ctrlBar = NULL;
}

void wxPreviewCtrl::Initialize()
{
#if wxUSE_STATUSBAR
CreateStatusBar();
#endif
CreateCanvas();
CreateControlBar();

m_printPreview->SetCanvas(m_previewCanvas);
m_printPreview->SetFrame(this);

wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );

item0->Add(m_ctrlBar, 0, wxGROW | wxALIGN_CENTER_VERTICAL, 5);
item0->Add(m_previewCanvas, 1, wxGROW | wxALIGN_CENTER_VERTICAL, 5);

SetAutoLayout( true );
SetSizer( item0 );

m_windowDisabler = new wxWindowDisabler(this);

Layout();

m_printPreview->AdjustScrollbars(m_previewCanvas);
m_previewCanvas->SetFocus();
m_ctrlBar->SetFocus();
}

void wxPreviewCtrl::CreateControlBar()
{
long buttons = wxPREVIEW_DEFAULT;
if (m_printPreview->GetPrintoutForPrinting())
buttons |= wxPREVIEW_PRINT;

m_ctrlBar = new wxPreviewCtrlBar(m_printPreview, buttons, this, wxPoint(0,0), wxSize(400,40));
m_ctrlBar->CreateButtons();
}

/// wxHtmlPrint
wxHtmlPrint::wxHtmlPrint(const wxString& name, wxWindow* parentWindow) :
wxHtmlEasyPrinting(name, parentWindow),
m_sTitle(name),
m_wParent(parentWindow)
{
}

bool wxHtmlPrint::DoPreview(wxHtmlPrintout* printout1, wxHtmlPrintout* printout2)
{
wxPrintDialogData printDialogData(*GetPrintData());
wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
if (!preview->Ok())
{
delete preview;
return false;
}

wxPreviewCtrl* frame = new wxPreviewCtrl(preview, m_wParent,
m_sTitle + wxT(" (Попередній перегляд)"),
wxPoint(100, 100), wxSize(650, 500));

frame->Centre(wxBOTH);
frame->Initialize();
frame->Show(true);
return true;
}

Теперь, для красивого предварительного просмотра, Вы можете использовать wxHtmlPrint. Использование аналогично его предку - wxHtmlEasyPrinting.

 

Example2.cpp

				
#include <wxHtmlPrint.h>
/* ... */
wxHtmlPrint* prn = new wxHtmlPrint(wxT("Довідник користувачів"));
prn->GetPrintData()->SetOrientation(wxLANDSCAPE);
prn->GetPageSetupData()->SetMarginTopLeft(wxPoint(10,10));
prn->GetPageSetupData()->SetMarginBottomRight(wxPoint(5,5));
prn->SetFooter(sFooter);
/// Предварительный просмотр
prn->PreviewText(sText);
/// Печать без предварительного просмотра
prn->PrintText(sText);
/* ... */


Исходники wxHtmlPrint.zip
Автор: developer@SandyHip.net.ua



Опубликовал admin
15 Авг, Воскресенье 2010г.



Программирование для чайников.