Extracting icon using WinAPI in Qt app - qt

I'm trying to extract icon from exe file using WinAPI, but it doesn't work.
Here's the code:
QIcon OSTools::AppsInterface::extractAppIcon(const QString &fileName) const {
wchar_t *convertedName = new wchar_t[fileName.length() + 1];
fileName.toWCharArray(convertedName);
convertedName[fileName.length()] = '\0';
HICON Icon = ExtractIcon(NULL, convertedName, 0);
QPixmap pixmap = QPixmap::fromWinHICON(Icon);
return QIcon(pixmap);
}
Code outputs:
QPixmap::fromWinHICON(), failed to GetIconInfo()
(ExtractIcon function on MSDN).
I think problem is that I send NULL instead of "A handle to the instance of the application calling the function". But, generally, I use Qt, and it's only one WinAPI function in my app.
What's wrong? What's correct way to extract icon using WinAPI? If you have another function proposal, please, give me an example. This is the first time I'm using WinAPI.
UPDATE: Yes, there is a better way. You may use QFileIconProvider class for doing such things.

Works for me, even with NULL. But obtaining the HINSTANCE is actually very simple. You have a problem elsewhere i guess. Does your target exe really have an embedded icon?
#ifdef Q_WS_WIN
#include <qt_windows.h>
#endif
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
#ifdef Q_WS_WIN
QString fileName("D:\\_dev\\eclipse\\eclipse.exe");
wchar_t *convertedName = new wchar_t[fileName.length() + 1];
fileName.toWCharArray(convertedName);
convertedName[fileName.length()] = '\0';
HINSTANCE hInstance = ::GetModuleHandle(NULL);
HICON Icon = ::ExtractIcon(hInstance, convertedName, 0);
ui->label->setPixmap(QPixmap::fromWinHICON(Icon));
#endif
}

I used QFileIconProvider, and it worked perfectly. Try this :
QPushButton b;
b.show();
QIcon icon;
QFileIconProvider fileiconpr;
icon = fileIconProvider.icon(QFileInfo("/*file name*/"));
b.setIcon(icon);
// And you can also save it where you want :
QPixmap pixmap = icon.pixmap( QSize(/*desired size*/) );
pixmap.save("/Desktop/notepad-icon.png");
Source. Have a nice day.

And solution was very simple. I just sent path to '.lnk' file instead of path to file. That's my inattention.

Related

How to solve undefined references, is the library not imported, or other problems

I'm trying to use Win32 GUI project on a project, but when I compile it, I get a lot of undefined reference errors.
||=== Build: Debug in 05.9.finally (compiler: GNU GCC Compiler) ===|
obj\Debug\main.o||In function Z4OpenP6HWND__':|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|61|undefined
reference towglCreateContext#4'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|63|undefined
reference to wglMakeCurrent#8'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|65|undefined
reference toglClearColor#16'| obj\Debug\main.o||In function
Z4Initv':|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|76|undefined
reference toglBlendFunc#8'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|77|undefined
reference to glClearColor#16'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|78|undefined
reference toglClearDepth#8'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|79|undefined
reference to glDepthFunc#4'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|80|undefined
reference toglEnable#4'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|81|undefined
reference to glShadeModel#4'|
C:\Users\Administrator\Desktop\计算机图形\05.9.finally\main.cpp|82|undefined
reference toglHint#8'| obj\Debug\main.o||In function `Z6Draw3Dv':|
#include <GL/gl.h>
#include <GL/glut.h>
#include <windows.h>
GLfloat step = 0.0f;
HINSTANCE hInstance; // 系统实例句柄
HWND hWndMain; // 主窗体句柄
HWND hWnd; // 窗体句柄变量定义
HDC hDC; // 设备描述表变量定义
PIXELFORMATDESCRIPTOR pfd; // 像素格式结构变量定义
HGLRC hGLRC; // OpenGL渲染描述表变量定义
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 窗体过程函数声明
GLboolean keys[256];
GLfloat rotStep = 30.0f;
void keyPress();
GLuint Open(HWND phWnd)
{
hWnd = phWnd;
hDC = GetDC(hWnd);
pfd.dwDamageMask = 0; // 忽略层遮罩
int pixelformat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelformat, &pfd);
hGLRC = wglCreateContext(hDC);
wglMakeCurrent(hDC,hGLRC);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 初始化背景为灰色
return 0;
}
You includes have a forward slash in the naming. Maybe you wanted #include "path/name".
I believe you would have solved it by now; in case not then you can try providing correct library path. Use command line options -L for path to library folder and -l for library name while compiling/linking.
An online lookup for OpenGL suggests the library file names may be any or all from these: opengl32.a or opengl32.lib, glu32.a or glu32.lib, freeglut.a or freeglut.lib (choose .a if you are building on Linux or .lib on Windows).

How do I disable special handling of & on Qt button labels?

I have inherited a virtual keyboard system with an array of buttons, one for each key. The label for each button is a single QChar. When showing the "symbols" keyboard, the code uses an '&' QChar for a key label, but the key shows as blank. I'm sure Qt is processing the '&' as a shortcut key prefix. Similarly, the entered text is shown on another, longer, button label; this label, as well, handles '&' character as an accelerator. Entering "ABC&DEF" is shown as "ABCDEF" with the 'D' underlined.
I have tried building with QT_NO_SHORTCUT #defined, but that made no difference.
Does anyone know of an easy way to disable this special handling of '&'?
The answer is found in Qt doc. QAbstractButton::text:
If the text contains an ampersand character ('&'), a shortcut is automatically created for it. The character that follows the '&' will be used as the shortcut key. Any previous shortcut will be overwritten or cleared if no shortcut is defined by the text. See the QShortcut documentation for details. To display an actual ampersand, use '&&'.
(Emphasize by me.)
QPushButton is derived from QAbstractButton inheriting this behavior.
Sample testQPushButtonAmp.cc:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QPushButton qBtn("Text with &&");
qBtn.show();
return app.exec();
}
testQPushButtonAmp.pro:
SOURCES = testQPushButtonAmp.cc
QT = widgets
Compiled and tested on cygwin64 on Windows 10:
$ qmake-qt5 testQPushButtonAmp.pro
$ make
$ ./testQPushButtonAmp
Qt Version: 5.9.4
Concerning how to disable this default behavior:
I had a look at woboq.org QAbstractButton::setText().
void QAbstractButton::setText(const QString &text)
{
Q_D(QAbstractButton);
if (d->text == text)
return;
d->text = text;
#ifndef QT_NO_SHORTCUT
QKeySequence newMnemonic = QKeySequence::mnemonic(text);
setShortcut(newMnemonic);
#endif
d->sizeHint = QSize();
update();
updateGeometry();
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(this, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
#endif
}
So, QT_NO_SHORTCUT disables to retrieve the shortcut out of text but it has to be defined when Qt library is built from source. Actually, I'm afraid even with disabled shortcuts, the single & will still become invisible in output.
I digged deeper in woboq.org and found some promising candidates e.g.:
qt_set_sequence_auto_menmonic()
Specifies whether mnemonics for menu items, labels, etc., should be honored or not. On Windows and X11, this feature is on by default; on macOS, it is off. When this feature is off (that is, when b is false), QKeySequence::mnemonic() always returns an empty string.
Note: This function is not declared in any of Qt's header files. To use it in your application, declare the function prototype before calling it.
and a sample in QProxyStyle
#include "textedit.h"
#include <QApplication>
#include <QProxyStyle>
class MyProxyStyle : public QProxyStyle
{
public:
int styleHint(StyleHint hint, const QStyleOption *option = 0,
const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const override
{
if (hint == QStyle::SH_UnderlineShortcut)
return 0;
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
};
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(textedit);
QApplication a(argc, argv);
a.setStyle(new MyProxyStyle);
TextEdit mw;
mw.resize(700, 800);
mw.show();
//...
}
which I tried in my sample.
Finally, nothing of them achieved the desired effect, i.e. only "&&" was rendered as & but "&" never.
__

How to print multiple tables into one pdf

I'm trying to print multiple table (qtablewidget) objects in single pdf using qt.
I can print one table, using the code provided in(https://forum.qt.io/topic/80501/qpainter-howto-draw-table/7)
QPixmap pix(widget->size());
QPainter painter(&pix);
widget->render(&painter);
painter.end();
QPrinter printer(QPrinter::HighResolution);
printer.setOrientation(QPrinter::Landscape);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPaperSize(QPrinter::A4);
printer.setOutputFileName("test.pdf"); // will be in build folder
painter.begin(&printer);
painter.drawPixmap(0, 0, pix);
painter.end();
However, if I try to print multiple tables, the code fails. If I create multiple QPainters, qt just outputs multiple pdfs, with one table in each pdf. I'm trying to do it using one QPainter and multiple QPixmaps, but no success so far.
Would anyone please let me know how I can get around it?
Any help would be appreciated
Regards,
How does the code fail? The below should work (I didn't test it). Note the absence of manual object lifetime management: let the compiler do it for you. A QPainter is a proper C++ class and knows how to release its resources without having to manually invoke QPainter::end().
void printWidgets(QWidgetList widgets) {
QVector<QPixmap> pixmaps;
for (auto *w : widgets) {
QPixmap pix(w->size());
QPainter painter(pix);
w->render(&painter);
pixmaps.push_back(pix);
}
QPrinter printer(QPrinter::HighResolution);
printer.setOrientation(QPrinter::Landscape);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPaperSize(QPrinter::A4);
printer.setOutputFileName("test.pdf"); // will be in build folder
QPainter painter(&printer);
QPoint pos;
for (auto &pix : qAsConst(pixmaps)) {
painter.drawPixmap(pos, pix);
pos.ry() += pix.height(); // stack the output vertically
}
}

Qt crashes when calling nested lambda to change widget

I am working on a project using C++ and QT. Part of the project involves a structure which keeps track of methods to update widgets. I have included a sample program below which highlights the issue, which is the problem distilled.
In the program, I have a list of 'relations', which contains lambdas to change widgets, based on data obtained elsewhere. This works fine (and may be dumped), but the problem is when one lambda is calling another.
An example is below. This program only has a combobox with the three strings, which calls 'slot1()' when changed. Slot one then calls the function pushed into the vector with the row, and calls that function with the parameter.
The Vector is
QVector<std::function<void(int)>> func;
When func.pushback takes setProductIndex as a parameter, the program works (I understand this is essentially a no op). The function is called. When it takes setProductIndex2, the program segfaults when the combobox is changed.
I have verified that the functions are indeed being called, but I'm unsure why it would segfault with setProductIndex2. All that is doing, is calling setProductIndex with the passed value which DOES work.
I can work around this, but I would like to know where I'm going wrong for better understanding.
I'm using GCC v4.8.3 and qt 5.3.2 on Fedora Linux.
Thanks.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
qDebug() << "1";
ui->setupUi(this);
QStringList model;
model.append("Test1");
model.append("Test2");
model.append("Test3");
ui->comboBox->addItems(model);
qDebug() << "2";
std::function<void(int)> setProductIndex = [&] (int x) ->void { ui->comboBox->setCurrentIndex(x);
ui->comboBox->setCurrentIndex(x); return;} ;
std::function<void(int)> setProductIndex2 = [&] (int x) ->void {setProductIndex(x);};
func.push_back(setProductIndex2);
qDebug() << "Func size " << func.size();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slot1(int xx)
{
//ui->comboBox->setCurrentIndex(--xx);
func[0](xx);
}

Segmentation fault when accessing the text of QLabel

I got a problem with the QLabel. I got a QtWidget with a QLabel inside. Now I want to change the text of the Label with following code:
QLabel* safetyLabel = this->findChild<QLabel *>("safety_bits");
safetyLabel->setText(QString("test"));
printf("%i", (safetyLabel->text()).length());
but I always get a "Segmentation fault". I think it's something quite simple, but I just can't see it...
Any ideas?
Your safetyLabel can be NULL if you use QtCreators' designer to build your UI and execute your code before you call ui->setupUi(this); in MainWindows constructor.
Here is the code.
QLabel *safetyLabel = NULL;
safetyLabel = (QLabel *) this->findChild("safety_bits");
if(!safetyLabel)
{
qDebug() << "Failed to find safety_bits label!";
return 1;
}
safetyLabel->setText(QString("safety_bits is here"));

Resources