Write text on preview window in directshow? - directshow

I have an application that uses DirectShow to capture video from camera.
It simultaneously save video on disk and show a preview window to user.
I want to add some text to preview window. So i wrote this code:
HWND hwnd = FindWindow(NULL, L"ActiveMovie Window");
HDC DeviceContext = GetDC(hwnd);
SelectObject(DeviceContext, (HFONT)GetStockObject(ANSI_FIXED_FONT));
char DebugTextBuffer[64] = { 0 };
sprintf_s(DebugTextBuffer, sizeof(DebugTextBuffer), "This is just a test.");
TextOutA(DeviceContext, 0, 0, DebugTextBuffer, (int)strlen(DebugTextBuffer));
But it doesn't show any text.
Edit: The above code however render text on a normal windows properly.

Related

Can't get video to fill in QGraphicsView in QT

I am trying to get a video to fill a QGraphicsView. While I do get playback it only fills a portion of the view like so:
Here is the code to play the video in the graphics view:
QMediaPlayer* player;
player = new QMediaPlayer(this);
QGraphicsVideoItem *item = new QGraphicsVideoItem;
player->setVideoOutput(item);
ui->graphicsView->setScene(new QGraphicsScene());
ui->graphicsView->scene()->addItem(item);
ui->graphicsView->show();
player->setMedia(QUrl("http://commondatastorage.googleapis.com/gtv-videos-
bucket/sample/BigBuckBunny.mp4"));
player->play();
What I would like is for the video to fill the whole window. The graphics view itself fills the window. I have tried resizing the video with ui->graphicsView->fitinView(item) as well as changing some scene parameters but I have not seen any difference.

Image scaling is ignored when adding QLabel with image at runtime

I am trying to add a QLabel with an image to my GUI at runtime, but the scaling is ignored and the image expands to its full size (which is larger than the screen), ignoring the size constraints and not scaling the contents correctly.
The image should be fit into the bottom, left side of the window, as my GridLayout describes here:
headerPnl= new HeaderPnl();
buttonPnl = new ButttonPnl;
mainContentPnl = new QStackedWidget;
mainLayout = new QGridLayout;
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
mainLayout->addWidget(headerPnl, 0, 0, 1, 7);
mainLayout->addWidget(mainContentPnl, 1, 0, 10, 6);
mainLayout->addWidget(buttonPnl, 1, 6, 10, 1);
mainLayout->setRowStretch(0,1);
mainLayout->setRowStretch(1,2);
mainLayout->setRowStretch(2,2);
mainLayout->setRowStretch(3,2);
mainLayout->setRowStretch(4,2);
mainLayout->setRowStretch(5,2);
mainLayout->setRowStretch(6,2);
mainLayout->setColumnStretch(0,1);
mainLayout->setColumnStretch(1,1);
mainLayout->setColumnStretch(2,1);
mainLayout->setColumnStretch(3,1);
mainLayout->setColumnStretch(4,1);
mainLayout->setColumnStretch(5,1);
mainLayout->setColumnStretch(6,1);
this->setLayout(mainLayout);
The header goes across the top, the button panel goes along the right side, and the rest of the screen is changing depending on the workflow of the application (ie what buttons are pressed, etc).
When necessary, my GUI replaces the widgets and updates the GUI like this:
void MainWindow::setContentPane(QWidget *content){
mainLayout->replaceWidget(contentPnl, content);
contentPnl = content;
}
void MainWindow::setButtonPanel(QWidget *buttonPanel){
mainLayout->replaceWidget(buttonPnl, buttonPanel);
buttonPnl = buttonPanel;
}
void MainWindow::configureWelcome(){
QLabel *welcomeLbl = new QLabel;
welcomeLbl->setObjectName("welcomeLbl");
welcomeLbl->setPixmap(QPixmap(":/images/welcome.jpg"));
welcomeLbl->setScaledContents(true);
CustomWidget *welcomeWidget = new CustomWidget;
QHBoxLayout *welcomeLayout = new QHBoxLayout;
welcomeLayout->addWidget(welcomeLbl);
welcomeWidget->setLayout(welcomeLayout);
setContentPane(welcomeWidget);
CustomWidget *buttonPnl = createWelcomeButtonPanel();
setButtonPanel(buttonPnl);
}
How can I make this image fit inside the GridLayout properly? It seems like when adding widgets to a layout that has already been set, the GUI doesn't know how to handle the size constraints from the GridLayout. Replacing the buttons works fine, but adding an image does not.
Side question: I have been trying to stay away from a QStackedWidget, as this application is designed for a lower power system, and it doesn't make sense to me to create all the possible screens and add them all to a QStackedWidget when the application starts. Instead I would rather use the resources when necessary, and only create all the GUI elements when I need to (ie, when the right buttons are clicked). Does that make sense?
Did you had a QSizePolicy to the widget containing the QGridLayout? I suggest an horizontal and vertical QSizePolicy::Fixed.
In your first code segment add :
this->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

Setting custom paper size with QPrinter doesn't print correctly

I need to be able to print from qt (the rendered contents of a QGraphicsScene, or a QImage), to scale, on normal printer, pdf, but also on custom printers, including roll fed.
It seems that anything that works for standard printers fails on custom printers, and the reverse.
I have made the printing work as expected on custom printers now (going back and forth between what works in the different printers).
I set the custom size required, and the preferred orientation, based on length/width ratio.
I open a print dialog (and even check the supply- the paper is set to desired size, and the orientation is set as expected)
print:
On custom printer, I get the correct size, and if the supply is smaller, the print clips as needed. margins are set correctly too.
On Pdf, I get a document of custom size as requested, printed correctly - but the orientation is not respected !!! (even though print dialog showed it correctly) - see image
On HP printer, I get a white page - nothing gets printed.
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QPrinter>
#include <QPrintDialog>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// some scene to print - show rectangle for easy measure
QGraphicsScene* s = new QGraphicsScene();
s->setSceneRect(-500, -500, 1500, 1500);
s->setBackgroundBrush(Qt::red);
QGraphicsView* view = new QGraphicsView();
view->setScene(s);
view->show();
qreal in = 72;
QRectF canvasRect(-0.1*in, -0.1*in, 6*in, 4*in);
qreal margins = 0.1*in;
QRectF actualCanvasRect = canvasRect.adjusted(margins,margins,-margins,-margins);
// this is to show actual scene
QGraphicsRectItem* contourItem = new QGraphicsRectItem(actualCanvasRect);
contourItem->setBrush(Qt::blue);
s->addItem(contourItem);
// an item partially on canvas (so I can check margins)
QGraphicsRectItem* item = new QGraphicsRectItem(-.5*in, -in, 2*in, 3*in);
item->setBrush(Qt::yellow);
s->addItem(item);
// actual printing:
// print the scene, to scale, using user margins, on given printer
QPrinter printer;
QPrinter::Orientation orient = (actualCanvasRect.width() >
actualCanvasRect.height() ?
QPrinter::Landscape : QPrinter::Portrait);
printer.setOrientation(orient);
printer.setPaperSize(canvasRect.size(), QPrinter::Point);
printer.setPageMargins(margins, margins, margins, margins, QPrinter::Point);
QPrintDialog printDialog(&printer);
if (printDialog.exec() != QDialog::Accepted)
{
qDebug("dialog canceled");
return 1;
}
QPainter painter;
if (! painter.begin(&printer))
{
qDebug("failed to open printer");
return 1;
}
// render the contents, clipped to printer page size, and scaled from point to device pixel
QRectF source = actualCanvasRect;
// convert target rect to DevicePixel and clip to page
QRectF page = printer.pageRect(QPrinter::DevicePixel);
qreal scale = printer.resolution()/in;
QRectF target = QRectF(page.topLeft(), source.size() * scale);
target &= page; // clip target rect to page
// clip source rect to page - without this, if printer paper is smaller I get unwanted scaling
source &= printer.pageRect(QPrinter::Point);
s->render(&painter, target, source);
painter.end();
return app.exec();
}
I don't understand why pdf creates a portrait page even though I clearly requested landscape (without changing the print dialog: see image). (the width and height are reversed, yet correct - Document Properties shows 4x6, and the page attempts to print correctly and to scale)
More important, I don't understand why a typical laser jet printer prints nothing - blank page - or sometimes for a simple canvas it scales to fit.
BUT if I change any properties in the print dialog from HP, anything irrelevant (like paper source, or paper type.... ), it prints correctly.
What am I doing wrong ?
(using Qt 4.7 and 5.5, must work on 4.7 - Windows, have yet to try Linux)

Use a picture or image in a QToolTip

Is there a way to show a picture/image in a QToolTip?
I want to show small images of keyboard-buttons to explain the user which buttons/shortcuts he can use on that specific widget.
You can easily show images with the following html code:
QToolTip::showText(QCursor::pos(), "<img src=':/icon.png'>Message", this, QRect(), 5000);
This example will show a tooltip with the image from Qt resources and the text for 5 seconds.
For more details, you can see this video: https://youtu.be/X9JD8gKGZ00
Edit1:
If you want to show an image from memory, you can save the QImage/QPixmap to memory (preferably using some lossless compression like PNG) and convert it to base 64 and load it with the html code, like this:
QImage icon = QImage(10, 10, QImage::Format_ARGB32);
icon.fill(QColor(255, 0, 0, 100));
QByteArray data;
QBuffer buffer(&data);
icon.save(&buffer, "PNG", 100);
QString html = QString("<img src='data:image/png;base64, %0'>Message").arg(QString(data.toBase64()));
QToolTip::showText(QCursor::pos(), html, this, QRect(), 5000);
Edit2: Corrected the html string as #Damon Lynch suggests.
With respect to the HTML string, the Python 3 / PyQt equivalent of user2014561's excellent solution to displaying in memory images is like this, assuming a QPixmap (a QImage will work the same):
buffer = QBuffer()
buffer.open(QIODevice.WriteOnly)
pixmap.save(buffer, "PNG", quality=100)
image = bytes(buffer.data().toBase64()).decode()
html = '<img src="data:image/png;base64,{}">'.format(image)

Displaying live camera image in Qt GUI

Im trying to make an application that takes live image recorded by camera and shows it on screen using Qt GUI. The camera driver and api provides me with functionality that refreshes the memory block showed by pointer.
The problem is my image won't refresh inside Qlabel made with Qimage (code below)
QImage myImage(raw_image_data_pointer, 768, 576, QImage::Format_RGB32 );
QLabel myLabel;
myLabel.setPixmap(QPixmap::fromImage(myImage));
myLabel.show();
How can i get my QLabel to be refreshed?
The problem is that you create the label widget with a static image inside. The containing image is not "connected" to your camera anymore, but is just a copy of a frame of your video stream. In order to make QLabel to update itself, you have to constantly replace the containing image with new one. For example, you can set up a timer for that:
MyClass:MyClass()
{
QTimer *timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(10); // Defines how often update the label.
myLabel = new QLabel;
[..]
}
// Slot
MyClass::update()
{
QImage myImage(raw_image_data_pointer, 768, 576, QImage::Format_RGB32 );
myLabel.setPixmap(QPixmap::fromImage(myImage));
}

Resources