How can I setup and display a custom QR Code in wxWidgets, to encode and display a string?
(Self answered, feel free to contribute better answers)
1 Answer
Using the wxImagePanel example, and the nayuki/QR-Code-generator C++ library, you can pass a string and scale and the QR Code will generate and show.
The files created are:
wxImagePanel.hpp wxImagePanel.cpp wxQRCode.hpp wxQRCode.cpp First is my cut down wxImagePanel, a widget which lets you set and display images on a rectangular surface:
// wxImagePanel.hpp #include <wx/wx.h> class wxImagePanel : public wxPanel { private: wxBitmap image; void updateSize(); public: wxImagePanel(wxFrame *parent, wxBitmap bitmap); wxImagePanel(wxFrame *parent); void paintNow(); void paintEvent(wxPaintEvent &evt); void render(wxDC &dc); void setBitmap(wxBitmap bitmap); DECLARE_EVENT_TABLE() }; // wxImagePanel.cpp #include "wxImagePanel.hpp" BEGIN_EVENT_TABLE(wxImagePanel, wxPanel) EVT_PAINT(wxImagePanel::paintEvent) END_EVENT_TABLE() wxImagePanel::wxImagePanel(wxFrame *parent, wxBitmap bitmap): wxPanel(parent), image(bitmap) { updateSize(); }; wxImagePanel::wxImagePanel(wxFrame *parent): wxPanel(parent) {}; void wxImagePanel::updateSize() { SetMinSize(wxSize(image.GetWidth(), image.GetHeight())); } void wxImagePanel::paintEvent(wxPaintEvent &evt) { wxPaintDC dc(this); render(dc); } void wxImagePanel::render(wxDC &dc) { int x = (GetSize().GetWidth() - image.GetWidth()) / 2; int y = (GetSize().GetHeight() - image.GetHeight()) / 2; dc.DrawBitmap(image, x, y, false); } void wxImagePanel::paintNow() { wxClientDC dc(this); render(dc); } void wxImagePanel::setBitmap(wxBitmap bitmap) { image = bitmap; updateSize(); paintNow(); } Then a QR Code class which subclasses the wxImagePanel and shows the code:
// wxQRCode.hpp #include "wxImagePanel.hpp" #include <string> class wxQRCode : public wxImagePanel { public: wxQRCode(wxFrame *parent, std::string text, unsigned int scale); void setText(std::string text); void setScale(int scale); int getQRSize(); private: void generateQRBitmap(); std::string qrText; unsigned int bitmapScale; }; // wxQRCode.cpp #include "wxQRCode.hpp" #include "QrCode.hpp" // qr code lib using namespace qrcodegen; wxQRCode::wxQRCode(wxFrame *parent, std::string text, unsigned int scale) : wxImagePanel(parent), qrText(text), bitmapScale(scale) { generateQRBitmap(); }; int wxQRCode::getQRSize() { QrCode qr = QrCode::encodeText(qrText.c_str(), QrCode::Ecc::LOW); return qr.getSize(); } void wxQRCode::generateQRBitmap() { QrCode qr = QrCode::encodeText(qrText.c_str(), QrCode::Ecc::LOW); const int scale = bitmapScale; const int size = qr.getSize() * scale; const int byteWidth = (size + 7) / 8; char bitsChar[size*byteWidth]; for (int y=0; y<size; y++) { for (int xByte=0; xByte<byteWidth; xByte++) { char bitChar = 0x00; if (qrText != "") { for (int xBit=0; xBit<8; xBit++) { int x = xByte*8 + xBit; int xModule = x / scale; int yModule = y / scale; bool black = qr.getModule(xModule, yModule); bitChar += black << (xBit % 8); }} bitsChar[y * byteWidth + xByte] = bitChar; } } wxBitmap *bitmap = new wxBitmap(bitsChar, size, size, 1); setBitmap(*bitmap); }; void wxQRCode::setText(std::string text) { qrText = text; if (text != "") { Show(true); generateQRBitmap(); paintNow(); } else { Show(false); } }; void wxQRCode::setScale(int scale) { bitmapScale = scale; generateQRBitmap(); paintNow(); };