Hello, friends! Please help solve the problem. I am writing a program where the kitten will run around the desktop. There are pictures of cats, format png / gif. I can not display a picture on the desktop where the background / window (form) will not be visible, but only the kitty will be visible, in the picture of which there is a transparent background. Developing code with c ++ winapi. Maybe someone knows how to display a png / gif image with c ++ winapi, because With the LoadImage function, I can only display bmp and others. I found an example where the GdiPlus library is used, but I am not familiar with it, so I simply inserted the image output function into the program and when I force the program to output the pictures one by one through the GdiPlus library function, they overlap each other and my knowledge to clean up the images lacks. InvalidateRect does not help. An example of the image output function by the GdiPlus library is shown below.

void draw() {//отрисовка изобраТСния gif // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ контСкст рисования ΠΈ устанавливаСм // ΠΏΠΈΠΊΡΠ΅Π»ΡŒΠ½ΡƒΡŽ систСму ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ Graphics g(hdc); g.SetPageUnit(UnitPixel); RectF bounds(0, 0, float(w), float(h)); // Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Ρ„ΠΎΠ½ΠΎΠ²ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ растягиваСм Π΅Π³ΠΎ Π½Π° всС ΠΎΠΊΠ½ΠΎ std::wstring wstr = strToWstring(animations[STATE][(int)currAnim]); LPWSTR lpstr = (LPWSTR)wstr.c_str(); Image bg(lpstr);//L"b.gif" g.DrawImage(&bg, bounds); g.ResetTransform(); } 

enter image description here

3 answers 3

Thanks friends! Everything worked out! Special thanks to the programmer mega, your example helped me a lot! I will lay out a code sample, in case who faces a similar task. This code displays an animation with a transparent background on the screen, sequentially going through the images:


 //объявим ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹ для ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΎΠΊ Ρ„Π°ΠΉΠ»: *.rc IDC_KISS01 RCDATA "cat\kiss_01.bmpx" IDC_KISS02 RCDATA "cat\kiss_02.bmpx" ... IDC_KISS22 RCDATA "cat\kiss_22.bmpx" Ρ„Π°ΠΉΠ»: Resource.h #define IDC_KISS01 111 #define IDC_KISS02 112 ... #define IDC_KISS22 132 //класс, ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽΡ‰ΠΈΠΉ Π·Π° Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΡŽ class CAT{ public: CAT(){ STATE = "kiss"; ptSrc.x = 0; ptSrc.y = 0; } void loadAnimations(HWND hwnd, HINSTANCE hInstance, std::string nameAmim, int nCount, float sp) {//Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠΌ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ-ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² структуру Π΄Π°Π½Π½Ρ‹Ρ… для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с изобраТСниями hwndAnim = hwnd; speed = sp; HGDIOBJ hBitmap; HRSRC hRSrc; HGLOBAL hRes; BITMAPFILEHEADER *pRes; BITMAPINFOHEADER *bi; void *bits, *premultiply; std::vector<alpha> v; int id; if (nameAmim == "kiss") id = 111; for (int i = 0; i < nCount; i++){ // load resource hRSrc = FindResource(hInstance, MAKEINTRESOURCE(id++), RT_RCDATA); hRes = LoadResource(hInstance, hRSrc); pRes = (BITMAPFILEHEADER*)LockResource(hRes); bi = (BITMAPINFOHEADER*)(pRes + 1); bits = ((char*)pRes) + pRes->bfOffBits; // premultiply premultiply = malloc(bi->biHeight * bi->biWidth * sizeof(RGBQUAD)); for (int c = bi->biHeight * bi->biWidth; c--;) { RGBQUAD &src = ((LPRGBQUAD)bits)[c]; RGBQUAD &dst = ((LPRGBQUAD)premultiply)[c]; dst.rgbRed = (BYTE)MulDiv(src.rgbRed, src.rgbReserved, 255); dst.rgbGreen = (BYTE)MulDiv(src.rgbGreen, src.rgbReserved, 255); dst.rgbBlue = (BYTE)MulDiv(src.rgbBlue, src.rgbReserved, 255); dst.rgbReserved = src.rgbReserved; } a.hdcScreen = GetDC(HWND_DESKTOP); // prepare bitmap hBitmap = CreateCompatibleBitmap(a.hdcScreen, bi->biWidth, bi->biHeight); a.hdcMem = CreateCompatibleDC(a.hdcScreen); hBitmap = SelectObject(a.hdcMem, hBitmap); SetDIBitsToDevice( a.hdcMem, 0, 0, bi->biWidth, bi->biHeight, 0, 0, 0, bi->biHeight, premultiply, (BITMAPINFO*)bi, DIB_RGB_COLORS ); a.sizeWnd.cx = bi->biWidth; a.sizeWnd.cy = bi->biHeight; free(premultiply); // prepare window memset(&a.blend, 0, sizeof(a.blend)); a.blend.BlendOp = AC_SRC_OVER; a.blend.SourceConstantAlpha = 255; a.blend.AlphaFormat = AC_SRC_ALPHA; v.push_back(a); }//for //cleanup ReleaseDC(HWND_DESKTOP, a.hdcScreen); //hBitmap = SelectObject(a.hdcMem, hBitmap); DeleteDC(a.hdcMem); //DeleteObject(hBitmap); //Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаях ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π½Π΅ Ρ‚ΠΎΡ‡Π½Ρ‹Π΅ расчСты, Ρ‚.ΠΊ. ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρ‹ послСднСй ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΈ width = a.sizeWnd.cx; heigth = a.sizeWnd.cy; animations.insert(std::pair<std::string, std::vector<alpha>>(nameAmim, v)); } void playAnim() {//ΠΏΡ€ΠΎΠΈΠ³Ρ€Ρ‹Π²Π°Π΅ΠΌ Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΡŽ ΠΈΠ· Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° currAnim += 1 * speed; //!!! Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ пСрСнСсти Π² участок, Π³Π΄Π΅ происходит смСна состояния int cout = animations[STATE].size(); a = animations[STATE][(int)currAnim]; UpdateLayeredWindow(hwndAnim, a.hdcScreen, &ptPos, &a.sizeWnd, a.hdcMem, &ptSrc, 0, &a.blend, ULW_ALPHA); if ((int)currAnim >= cout - 1) currAnim = 0; } void setPos(int &x, int &y) { ptPos.x = x; ptPos.y = y; } private: struct alpha {//структура Π΄Π°Π½Π½Ρ‹Ρ… Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΡ‹Ρ… ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ BLENDFUNCTION blend; HDC hdcScreen, hdcMem; SIZE sizeWnd; }a; float speed, currAnim; std::map<std::string, std::vector<alpha>> animations; std::string STATE;//stand, kiss HWND hwndAnim; POINT ptPos, ptSrc; int width, heigth;//w\h img }; 

PS This example uses the loadAnimations () function which is taken from the example: How to load an image with an alpha channel into the background of the window

  • Please mark your answer as correct in order to make it easier for others to navigate. - Amadey

Did so

  #include "mainwindow.h" #include <QLayout> #include <QLabel> #include <QTimer> #include <QtDebug> #include <QDesktopWidget> #include <QApplication> MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { #------------------------------------ setWindowFlags(Qt::FramelessWindowHint); setAttribute(Qt::WA_TranslucentBackground); #------------------------------------- QPixmap pix; QLabel* lbl = new QLabel("Test"); QLayout* lay = new QVBoxLayout(); pix.load("../mouse.png"); lbl->resize(pix.size()); lbl->setPixmap(pix); lay->addWidget(lbl); setLayout(lay); resize(lbl->size()); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(5); QRect rec = QApplication::desktop()->screenGeometry(); p.setY((rec.height()-height())/2); p.setX((rec.width()-width())); move(p); qDebug() << p; } void MainWindow::paintEvent(QPaintEvent *event) { if(x() <= 0) delta = 1; if(x() >= px()) delta = -1; move(x()+delta,y()); QWidget::paintEvent(event); } void MainWindow::show() { QWidget::show(); p = pos(); qDebug() << p; } MainWindow::~MainWindow() { } 

It turned out that the mouse image moves through the screen on a timer. mouse

    An image in .gif format can be imagined as a set of different frames (or many many pictures coming one after another). These frames should be replaced in a certain order and with a certain delay. Therefore, they usually bind to WM_TIMER or write their own timer to change frames.

    From the given part of the code it is difficult to judge exactly how you work with frames and a timer.

    I suggest you look at the following two links: https://www.codeproject.com/Articles/1776/Adding-GIF-animation-using-GDI https://www.codeproject.com/Articles/27387/Play-GIF-using- GDI