none
problem with showing a splash image function

    Question

  • Hi everyone!

    before I start, I'd like to share that I have 0 knowledge in C++ and somehow I've always found it hard to learn ..

    However,
    I'm having a error on some code that shows a splash screen, Its a long code but ..

    // Splash.cpp
    
    #include "splash.h"
    #include "windowsx.h"
    
    typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)
            (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
    
    lpfnSetLayeredWindowAttributes g_pSetLayeredWindowAttributes;
    
    #define WS_EX_LAYERED 0x00080000 
    
    static LRESULT CALLBACK ExtWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        static CSplash * spl = NULL;
        if(uMsg == WM_CREATE)
        {
            spl = (CSplash*)((LPCREATESTRUCT)lParam)->lpCreateParams;
        }
        if(spl)
            return spl->WindowProc(hwnd, uMsg, wParam, lParam);
        else
            return DefWindowProc (hwnd, uMsg, wParam, lParam);
    }
    
    LRESULT CALLBACK CSplash::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
            HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
        }
    
        return DefWindowProc (hwnd, uMsg, wParam, lParam) ;
    }
    
    void CSplash:: OnPaint(HWND hwnd)
    {
        if (!m_hBitmap)
            return;
    
        PAINTSTRUCT ps ;
        HDC hDC = BeginPaint (hwnd, &ps) ;
    
        RECT   rect;
        ::GetClientRect(m_hwnd, &rect);
        
        HDC hMemDC      = ::CreateCompatibleDC(hDC);
        HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, m_hBitmap);
        
        BitBlt(hDC, 0, 0, m_dwWidth, m_dwHeight, hMemDC, 0, 0, SRCCOPY);
    
        ::SelectObject(hMemDC, hOldBmp);
    
        ::DeleteDC(hMemDC);
        
        EndPaint (hwnd, &ps) ;
    }
    
    void CSplash::Init()
    {
        m_hwnd = NULL;
        m_lpszClassName = TEXT("SPLASH");
        m_colTrans = 0;
        HMODULE hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
    
        g_pSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes)
                            GetProcAddress(hUser32, "SetLayeredWindowAttributes");
    }
    
    CSplash::CSplash()
    {
        Init();
    }
    
    CSplash::CSplash(LPCTSTR lpszFileName, COLORREF colTrans)
    {
        Init();
    
        SetBitmap(lpszFileName);
        SetTransparentColor(colTrans);
    }
    
    CSplash::~CSplash()
    {
        FreeResources();
    }
    
    HWND CSplash::RegAndCreateWindow()
    {
       
        WNDCLASSEX wndclass;
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
        wndclass.lpfnWndProc    = ExtWndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = DLGWINDOWEXTRA;
        wndclass.hInstance      = ::GetModuleHandle(NULL);
        wndclass.hIcon          = NULL;
        wndclass.hCursor        = ::LoadCursor( NULL, IDC_WAIT );
        wndclass.hbrBackground  = (HBRUSH)::GetStockObject(LTGRAY_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = m_lpszClassName;
        wndclass.hIconSm        = NULL;
    
        if(!RegisterClassEx (&wndclass))
            return NULL;
    
        DWORD nScrWidth  = ::GetSystemMetrics(SM_CXFULLSCREEN);
        DWORD nScrHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
    
        int x = (nScrWidth  - m_dwWidth) / 2;
        int y = (nScrHeight - m_dwHeight) / 2;
        m_hwnd = ::CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW, m_lpszClassName, 
                                  TEXT("Banner"), WS_POPUP, x, y, 
                                  m_dwWidth, m_dwHeight, NULL, NULL, NULL, this);
    
        if(m_hwnd)
        {
            MakeTransparent();
            ShowWindow   (m_hwnd, SW_SHOW) ;
            UpdateWindow (m_hwnd);
        }
        return m_hwnd;
    }
    
    int CSplash::DoLoop()
    {
      
        if(!m_hwnd)
            ShowSplash();
    
        MSG msg ;
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg) ;
            DispatchMessage  (&msg) ;
        }
    
        return msg.wParam ;
    
    }
    
    void CSplash::ShowSplash()
    {
        CloseSplash();
        RegAndCreateWindow();
    }
    
    
    DWORD CSplash::SetBitmap(LPCTSTR lpszFileName)
    {
        
        HBITMAP    hBitmap       = NULL;
        hBitmap = (HBITMAP)::LoadImage(0, lpszFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        return SetBitmap(hBitmap);
    }
    
    DWORD CSplash::SetBitmap(HBITMAP hBitmap)
    {
        int nRetValue;
        BITMAP  csBitmapSize;
        
       FreeResources();
        
        if (hBitmap)
        {
            m_hBitmap = hBitmap;
            nRetValue = ::GetObject(hBitmap, sizeof(csBitmapSize), &csBitmapSize);
            if (nRetValue == 0)
            {
                FreeResources();
                return 0;
            }
            m_dwWidth = (DWORD)csBitmapSize.bmWidth;
            m_dwHeight = (DWORD)csBitmapSize.bmHeight;
        }
           
        return 1;
    }
    
    void CSplash::FreeResources()
    {
        if (m_hBitmap)
            ::DeleteObject (m_hBitmap);
        m_hBitmap = NULL;
    }
    
    int CSplash::CloseSplash()
    {
        
        if(m_hwnd)
        {
            DestroyWindow(m_hwnd);
            m_hwnd = 0;
            UnregisterClass(m_lpszClassName, ::GetModuleHandle(NULL));
            return 1;
        }
        return 0;
    }
    
    bool CSplash::SetTransparentColor(COLORREF col)
    {
        m_colTrans = col;
    
        return MakeTransparent();
    }
    
    bool CSplash::MakeTransparent()
    {
       if(m_hwnd && g_pSetLayeredWindowAttributes && m_colTrans )
        {     
            SetWindowLong(m_hwnd, GWL_EXSTYLE, GetWindowLong(m_hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
            g_pSetLayeredWindowAttributes(m_hwnd, m_colTrans, 0, LWA_COLORKEY);
        }    
        return TRUE;
    }

    splash2.cpp:

    #include "stdafx.h"
    #include "Splash.h"
    
    
    void SplashShow(){
        CSplash splash1(TEXT(".\\System/Splash.bmp"), RGB(128, 128, 128));
        splash1.ShowSplash();
        Sleep(3000);
        splash1.CloseSplash();
    }

    Now, I apologize for the long code, just wanted to share the full code just in case.
    I'm getting an error on line 30 in Splash.cpp 

    Could this be a problem that the image is not showing up ?

    Please help ...

    Wednesday, February 07, 2018 11:47 PM

All replies


  • before I start, I'd like to share that I have 0 knowledge in C++ and somehow I've always found it hard to learn ..

    I'm having a error on some code that shows a splash screen, Its a long code but ..

    // Splash.cpp #include "splash.h" #include "windowsx.h" typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes) (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags); lpfnSetLayeredWindowAttributes g_pSetLayeredWindowAttributes; #define WS_EX_LAYERED 0x00080000

    ... }

    splash2.cpp:

    #include "stdafx.h"
    #include "Splash.h"
    
    
    void SplashShow(){
        CSplash splash1(TEXT(".\\System/Splash.bmp"), RGB(128, 128, 128));
        splash1.ShowSplash();
        Sleep(3000);
        splash1.CloseSplash();
    }


    I'm getting an error on line 30 in Splash.cpp 

    Could this be a problem that the image is not showing up ?

    >before I start, I'd like to share that I have 0 knowledge in C++
    >I'm having a error on some code that shows a splash screen,

    Then I think we can safely assume that you didn't write the code
    you posted. Correct?

    >I'm getting an error on line 30 in Splash.cpp
    >Could this be a problem that the image is not showing up ?

    Short answer: Yes

    Long answer: When there are compile or link errors in a build, no exe
    file will be created so naturally there is no program to run. If no
    program runs then obviously there can be no output from the program.

    Since you clearly did not write this code yourself, it would help if
    you identified the source where you got it. That way we can get any
    missing pieces - such as splash.h - read any accompanying documentation, etc.

    The code looks very similar - almost identical - to the class available here:

    CSplash - A Splash Window Class
    https://www.codeproject.com/Articles/7658/CSplash-A-Splash-Window-Class

    Is that where you got it from?

    - Wayne

    Thursday, February 08, 2018 5:05 AM
  • WayneAKing

    The code looks pretty much the same, I'm 100% sure its taken from that article.
    when I compile the project, I get no errors!
    only the splash image is not showing up.

    I've downloaded the source from the article, and build it up in VS 2013 Express
    seems it has the same problem !

    could it be the compiler itself ?
    here is the full code I have (which is almost 90% the same in the article)
    https://pastebin.com/jAiSG8D7

    -- Update ! --
    Alright so the project I have is a dll that gets injected to my MainExe. 
    I've figured out that running the MainExe shows up the Image, but the MainExe should only be started by passing arguments so the Image won't show up for some reason, why?
    • Edited by Zuher Laith Thursday, February 08, 2018 11:09 AM
    Thursday, February 08, 2018 10:29 AM
  • I've figured out that running the MainExe shows up the Image, but the MainExe should only be started by passing arguments so the Image won't show up for some reason, why?


    You'll have to be clearer than that, I'm afraid. Both the original code
    in the article and that which you are using will display the screen
    when executed. (*If* the bmp is found.)  You seem to be saying that
    the code won't show the image if the code isn't run - which is perfectly
    logical and to be expected.

    How does whether or not MainExe is started by passing arguments or not
    affect the execution of SplashShow()?

    You've determined - and I've confirmed - that the code will in fact display
    the splash screen image. So if it isn't showing then the obvious conclusion
    is that the code isn't being executed.

    - Wayne


    • Edited by WayneAKing Thursday, February 08, 2018 10:37 PM
    Thursday, February 08, 2018 3:01 PM

  • How does whether or not MainExe is started by passing arguments or not
    affect the execution of SplashShow()?

    - Wayne

    Exactly!
    It's not a matter of arguments, I'm sure now.
    If I started the MainExe externally (Process.Start in C#), it only does not show the splash, but the whole rest code works completely fine !
    I run it externally from another directory, I don't think it should be suspicious .. right?
    Friday, February 09, 2018 3:40 AM

  • If I started the MainExe externally (Process.Start in C#), it only does not show the splash, but the whole rest code works completely fine !
    I run it externally from another directory, I don't think it should be suspicious .. right?

    >CSplash splash1(TEXT(".\\Protect.bmp"), RGB(128, 128, 128));

    This uses a relative path, which means that the bmp must be in the current
    directory when the program is executed.

    If you run the program from the VS IDE that usually means that the bmp
    file must be in the same directory as the .vcxproj and .cpp files are
    located. If you run the program from the command line or using Windows
    Explorer, etc. then the bmp file must be in the same directory as the
    .exe file at run time.

    The code as written does not check for the existence of the bmp file
    at run time, and if it doesn't exist in the current directory then
    nothing will be shown.

    - Wayne

    • Proposed as answer by Guido Franzke Friday, February 09, 2018 7:20 AM
    Friday, February 09, 2018 4:04 AM
  • There are various approaches possible to ensure that the exe can find the
    bmp file. These include storing the path to the bmp in a Registry entry,
    embedding the bmp in the exe as a resource, and using the path of the
    exe itself to find the bmp. An example of the latter - which assumes that
    the bmp is in the same directory as the exe - follows:

    // splash2,cpp
    #include "stdafx.h"
    #include "Splash.h"
    
    #include <string>
    
    //void SplashShow(){
    void SplashShow(TCHAR *ep){
    
    #ifdef UNICODE
        std::wstring str = ep;
    #else
        std::string str = ep;
    #endif
    
        // add error handling to taste
        int loc = str.find_last_of('\\');
        str.erase(loc);
        str.append(TEXT("\\Protect.bmp")); // no period!
    
        //CSplash splash1(TEXT(".\\Protect.bmp"), RGB(128, 128, 128));
        CSplash splash1(str.c_str(), RGB(128, 128, 128));
        splash1.ShowSplash();
        Sleep(3000);
        splash1.CloseSplash();
    }
    

    // mainprog.cpp
    #include "stdafx.h"
    #include "splash.h"
    
    //void SplashShow();
    void SplashShow(TCHAR *);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        //SplashShow();
        SplashShow(argv[0]);
    
        return 0;
    }
    

    - Wayne

    Friday, February 09, 2018 7:16 PM