2

J'essaie d'afficher une image GIF comme splash comme démarrage de mon petit programme en studio visuel. Je deviens vraiment fou. J'ai regardé c'est possible dans Qt IDE mais j'en ai vraiment besoin en studio visuel car mon autre code ne fonctionne qu'avec le studio visuel. Et oui j'ai essayé de convertir mon code pour Qt en me donnant trop d'erreurs.Comment afficher GIF comme splash dans Visual Studio C++

J'ai vu this post.

J'utilise GDI + mais dunno comment afficher simplement au lieu de lecture et d'arrêt. C'est correct même au lieu de splash pour afficher une petite forme qui joue le fichier GIF, pouvez-vous me donner un petit extrait de code dans la façon de le faire en C++?

Merci.

Répondre

1

Voici une classe de fenêtre MFC qui implémente un écran de démarrage à l'aide de GDI Plus pour l'affichage d'un GIF (animé).

J'ai tout encapsulé dans un fichier d'en-tête pour simplifier l'utilisation de votre projet. Enregistrez-le en tant que fichier .h (peut-être "SplashWnd.h"), puis incluez-le partout où vous voulez configurer le splash. Vous l'application de InitInstance pourrait être un bon endroit pour l'ajouter - quelque chose comme cette ligne (avant tout DoModal appels):

SplashWnd splash(_T("Filname.gif"));

Le constructeur peut également prendre des paramètres pour contrôler le retard avant la fermeture automatique, et également spécifier une fonction à appeler lorsque le splash est fermé.

La fenêtre de démarrage n'a pas de bordure ou de légende - elle apparaît uniquement comme l'image chargée, flottant au-dessus de toutes les autres fenêtres. Son icône n'apparaît pas dans la barre des tâches et se ferme lorsque son délai expire, ou lorsque l'utilisateur clique sur la fenêtre ou appuie sur une touche.

#pragma once 
#include <functional> 
#include <afxwin.h> 
#include <gdiplus.h> 
#pragma comment(lib,"gdiplus.lib") 

inline void ManageGdiPlusInit(bool release=false) { 
    static int refcount = 0; 
    static ULONG_PTR token; 
    if(release) { 
     if(--refcount == 0) { 
      Gdiplus::GdiplusShutdown(token); 
     } 
    } else if(++refcount == 1) { 
     Gdiplus::GdiplusStartupInput startup_input; 
     Gdiplus::GdiplusStartup(&token, &startup_input, 0); 
} } 

inline void GdiPlusInit() { ManageGdiPlusInit(false); } 
inline void GdiPlusRelease() { ManageGdiPlusInit(true); } 

namespace { 
class SplashWnd : public CWnd { 
protected: 
    static CString WindowClass() { 
     static CString name; 
     if(name.IsEmpty()) { 
      name = AfxRegisterWndClass(CS_DROPSHADOW, 0, (HBRUSH)GetStockObject(GRAY_BRUSH), 0); 
     } 
     return name; 
    } 

    Gdiplus::Image  *m_pImage; 
    UINT     m_FrameCount; 
    unsigned char   *m_FrameDelayData; 
    const UINT   *m_FrameDelays; 
    UINT     m_CurFrameIndex; 
    UINT     m_AnimationTimerId; 
    UINT     m_ExpireTimerId; 
    CRect     m_WindowRect; 
    std::function<void()> m_DismissCallback; 

    DECLARE_MESSAGE_MAP() 

    afx_msg void OnLButtonDown(UINT nFlags, CPoint point) { 
     DestroyWindow(); 
    } 

    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { 
     DestroyWindow(); 
    } 

    afx_msg void OnDestroy() { 
     if(m_AnimationTimerId != UINT(-1)) { 
      KillTimer(m_AnimationTimerId); 
     } 
     if(m_ExpireTimerId != UINT(-1)) { 
      KillTimer(m_ExpireTimerId); 
     } 
     if(m_DismissCallback) { 
      m_DismissCallback(); 
     } 
     CWnd::OnDestroy(); 
    } 

    afx_msg void OnTimer(UINT nIDEvent) { 
     if(nIDEvent == m_AnimationTimerId) { 
      if(++m_CurFrameIndex >= m_FrameCount) { 
       m_CurFrameIndex = 0; 
      } 
      DrawCurFrame(); 
      KillTimer(m_AnimationTimerId); 
      m_AnimationTimerId = SetTimer(1, m_FrameDelays[m_CurFrameIndex], 0); 
      return; 
     } 
     if(nIDEvent == m_ExpireTimerId) { 
      DestroyWindow(); 
      return; 
    } } 

    void PostNcDestroy() { 
     if(m_DeleteSelf) { 
      delete this; 
     } 
    } 

    void DrawCurFrame() { 
     Gdiplus::Graphics g(m_hWnd); 
     GUID dim_select_id = Gdiplus::FrameDimensionTime; 
     m_pImage->SelectActiveFrame(&dim_select_id, m_CurFrameIndex); 
     g.DrawImage(m_pImage, 0, 0, m_WindowRect.Width(), m_WindowRect.Height()); 
    } 

public: 
    // set m_DeleteSelf to true if a SplashWnd is created with new, and you want it to 
    // auto-delete itself when the window expires or is dismissed. 
    bool m_DeleteSelf; 

    // file_path the gif file path 
    // ExpireMs  the time, in milliseconds until the window automatically closes itself 
    // WidthFactor the fraction of the width of the primary display to use as the splash screen's width 
    // HeightFactor the fraction of the height of the primary display to use as the height 
    // If WidthFactor or HeightFactor are 0, the original image aspect ratio is preserved 
    // If both are 0, the original image size, in pixels is used 
    SplashWnd(CString file_path, DWORD ExpireMs=2000, double WidthFactor=0.4, double HeightFactor=0) { 
     GdiPlusInit(); 

     m_pImage = new Gdiplus::Image(file_path); 

     // Set up an array of frame times for animated images 
     UINT dimension_count = m_pImage->GetFrameDimensionsCount(); 

     GUID dimension_id; 
     m_pImage->GetFrameDimensionsList(&dimension_id, 1); 
     m_FrameCount = m_pImage->GetFrameCount(&dimension_id); 
     UINT frame_delay_size = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay); 

     m_FrameDelayData = new unsigned char[frame_delay_size]; 
     Gdiplus::PropertyItem* frame_delay_item = reinterpret_cast<Gdiplus::PropertyItem*>(m_FrameDelayData); 
     m_pImage->GetPropertyItem(PropertyTagFrameDelay, frame_delay_size, frame_delay_item); 
     m_FrameDelays = reinterpret_cast<const UINT*>(frame_delay_item->value); 

     // Figure out the size and location of the splash window 
     int primary_width = GetSystemMetrics(SM_CXFULLSCREEN); 
     int primary_height = GetSystemMetrics(SM_CYFULLSCREEN); 

     int splash_width = int(primary_width * WidthFactor); 
     int splash_height = int(primary_height * HeightFactor); 

     if(splash_width == 0) { 
      if(splash_height == 0) { 
       splash_width = m_pImage->GetWidth(); 
       splash_height = m_pImage->GetHeight(); 
      } else { 
       splash_width = primary_width * splash_height/primary_height; 
      } 
     } else if(splash_height == 0) { 
      splash_height = primary_height * splash_width/primary_width; 
     } 

     int l = (primary_width - splash_width)/2; 
     int t = (primary_height - splash_height)/2; 
     int r = l + splash_width; 
     int b = t + splash_height; 

     m_WindowRect.SetRect(
      (primary_width - splash_width)/2, 
      (primary_height - splash_height)/2, 
      (primary_width + splash_width)/2, 
      (primary_height + splash_height)/2); 

     // WS_EX_TOPMOST makes the window cover up other, regular windows 
     // WS_EX_TOOLWINDOW prevents an icon for this window in the taskbar 
     // WS_POPUP prevents caption and border from being drawn 
     CreateEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, WindowClass(), _T("Splash"), WS_VISIBLE | WS_POPUP, m_WindowRect, 0, 0); 

     // Show the first frame 
     m_CurFrameIndex = 0; 
     DrawCurFrame(); 

     // Set up the frame-flipping animation timer 
     m_ExpireTimerId = m_AnimationTimerId = UINT(-1); 
     if(m_FrameCount > 1) { 
      m_AnimationTimerId = SetTimer(1, m_FrameDelays[m_CurFrameIndex], 0); 
     } 
     // Set up the expiration timer 
     if(ExpireMs != INFINITE) { 
      m_ExpireTimerId = SetTimer(2, ExpireMs, 0); 
     } 

     m_DeleteSelf = false; 
    } 

    // Constructor which takes a callback function which will be called when the splash window closes 
    template <typename F> 
    SplashWnd(CString file_path, DWORD ExpireMs, double WidthFactor, double HeightFactor, F DismissCallback) 
     : SplashWnd(file_path, ExpireMs, WidthFactor, HeightFactor) 
    { 
     m_DismissCallback = DismissCallback; 
    } 

    ~SplashWnd() { 
     delete [] m_FrameDelayData; 
     delete m_pImage; 
     GdiPlusRelease(); 
    } 
}; 

// Message map, usually in an implementation file, but here encapsulated inside the header 
// using an anonymous namespace to prevent possible ODR problems. 
BEGIN_MESSAGE_MAP(SplashWnd, CWnd) 
    ON_WM_KEYDOWN() 
    ON_WM_LBUTTONDOWN() 
    ON_WM_TIMER() 
    ON_WM_DESTROY() 
END_MESSAGE_MAP() 

}