Results 1 to 4 of 4
  1. #1
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty

    Adding and using Resources with Visual Studios Express

    CREDITS:
    Bradley Grainger (Splash Screen Source)
    Guy Lecky-Thompson (For the Resource Hack)

    Intro:(skip)
    Let me start off by thanking Microsoft for the great tool which is Visual Studios 2008 (though Im sure some are using different versions). One Problem with the Express is however that its resource editor is disabled. This is pretty much a shot in the leg for anyone not used to command line compiling or adding resources manually. Now one option is ofcourse to buy Microsoft Visual Studios Professional, which I might do myself one day if I can ever cough up $200.00, but as of now Im just a hobbyist and haven't made a single redcent programming, so I feel no need in investing in something that so far hasn't made me any money, but enough of my justifying being cheap.
    Another way to add resources to your files is with an external resource editor.


    The Hack:

    1. To start off you will need to take a look at this tutorial.
    VC++ Express External Res Editor: Attach External Tool to Visual C++ Express for Editing Resources


    2. Now you should know how to edit in your resources and compile, but there is a missing part of this tutorial. How do you use these resources? I will fill you in. Usually when you add resources to a files a resource header is added to your project defining certain resources, but all a these defines really do is assign a value to a token. These values reference certain resources.

    Now if you have used XN Resource Editor you may have noticed that when adding resources a number is assigned on the folder of that resource. That number is its reference. And by using the MAKEINTRESOURCE() you can for most cases reference that resource as if it were a file location. All that fancy macro really does is just change your int to a string.


    3. Now that that's all settled give it a shot. Here is an excellent tutorial for a splash screen in C++. Check it out: Splash Screen

    Check out this code too see how I edited it to work with resources:
    Code:
    // whatchmacallit.cpp : Defines the entry point for the application.
    //
    
    #include "stdafx.h"
    //#include "whatchmacallit.h"
    //#include "Objidl.h"
    #include <atlbase.h>
    #include <wincodec.h>
    #include <wincodecsdk.h>
    
    
    
    // Creates a stream object initialized with the data from an executable resource.
    
    IStream* CreateStreamOnResource(LPCTSTR lpName, LPCTSTR lpType)
    {
    
        // initialize return value
        IStream * ipStream = NULL;
    
     
    
        // find the resource
        HRSRC hrsrc = FindResource(NULL, lpName, lpType);
    	if (hrsrc == NULL)
            goto Return;
    
     
    
        // load the resource
        DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
    
        HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
        if (hglbImage == NULL)
            goto Return;
    
     
    
        // lock the resource, getting a pointer to its data
        LPVOID pvSourceResourceData = LockResource(hglbImage);
        if (pvSourceResourceData == NULL)
            goto Return;
    
     
    
        // allocate memory to hold the resource data
        HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
        if (hgblResourceData == NULL)
            goto Return;
    
     
    
        // get a pointer to the allocated memory
        LPVOID pvResourceData = GlobalLock(hgblResourceData);
        if (pvResourceData == NULL)
            goto FreeData;
    
     
    
        // copy the data from the resource to the new memory block
        CopyMemory(pvResourceData, pvSourceResourceData, dwResourceSize);
        GlobalUnlock(hgblResourceData);
    
     
    
        // create a stream on the HGLOBAL containing the data
        if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream)))
            goto Return;
    
     
    
    FreeData:
        // couldn't create stream; free the memory
        GlobalFree(hgblResourceData);
    
     
    
    Return:
        // no need to unlock or free the resource
        return ipStream;
    
    }
    
    
    
    // Loads a PNG image from the specified stream (using Windows Imaging Component).
    
    IWICBitmapSource* LoadBitmapFromStream(IStream * ipImageStream)
    {
    	CComPtr<IStream> stream = ipImageStream;
    
        // initialize return value
        IWICBitmapSource * ipBitmap = NULL;
    
    	char buf[10] = "\0";
    
        // load WIC's PNG decoder
        CComPtr<IWICBitmapDecoder> decoder;
    	
    	HRESULT hr = decoder.CoCreateInstance(CLSID_WICJpegDecoder); 
    	if (FAILED(hr)){MessageBoxA(NULL, "failed", "here", MB_OK); goto Return;}//NULL, CLSCTX_INPROC_SERVER, __uuidof(ipDecoder), reinterpret_cast<void**>(&ipDecoder))))
     
    
        // load the PNG
    	hr = decoder->Initialize(stream,WICDecodeMetadataCacheOnLoad);//WICDecodeMetadataCacheOnLoad WICDecodeMetadataCacheOnDemand
    	if (FAILED(hr)){MessageBoxA(NULL, itoa((int)hr,buf,16), "here", MB_OK); goto ReleaseDecoder;}
    
     
    
        // check for the presence of the first frame in the bitmap
    
        UINT nFrameCount = 0;
    
        if (FAILED(decoder->GetFrameCount(&nFrameCount)) || nFrameCount != 1)
    
            goto ReleaseDecoder;
    
     
    
        // load the first frame (i.e., the image)
    
        IWICBitmapFrameDecode * ipFrame = NULL;
    
        if (FAILED(decoder->GetFrame(0, &ipFrame)))
    
            goto ReleaseDecoder;
    
     
    
        // convert the image to 32bpp BGRA format with pre-multiplied alpha
    
        //   (it may not be stored in that format natively in the PNG resource,
    
        //   but we need this format to create the DIB to use on-screen)
    
        WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, ipFrame, &ipBitmap);
    
        ipFrame->Release();
    
     
    
    ReleaseDecoder:
    
        decoder.Release();
    
    Return:
    
        return ipBitmap;
    
    }
    
    
    
    // Creates a 32-bit DIB from the specified WIC bitmap.
    
    HBITMAP CreateHBITMAP(IWICBitmapSource * ipBitmap)
    
    {
    
        // initialize return value
    
        HBITMAP hbmp = NULL;
    
     
    
        // get image attributes and check for valid image
    
        UINT width = 0;
    
        UINT height = 0;
    
        if (FAILED(ipBitmap->GetSize(&width, &height)) || width == 0 || height == 0)
    
            goto Return;
    
     
    
        // prepare structure giving bitmap information (negative height indicates a top-down DIB)
    
        BITMAPINFO bminfo;
    
        ZeroMemory(&bminfo, sizeof(bminfo));
    
        bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    
        bminfo.bmiHeader.biWidth = width;
    
        bminfo.bmiHeader.biHeight = -((LONG) height);
    
        bminfo.bmiHeader.biPlanes = 1;
    
        bminfo.bmiHeader.biBitCount = 32;
    
        bminfo.bmiHeader.biCompression = BI_RGB;
    
     
    
        // create a DIB section that can hold the image
    
        void * pvImageBits = NULL;
    
        HDC hdcScreen = GetDC(NULL);
    
        hbmp = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
    
        ReleaseDC(NULL, hdcScreen);
    
        if (hbmp == NULL)
    
            goto Return;
    
     
    
        // extract the image into the HBITMAP
    
        const UINT cbStride = width * 4;
    
        const UINT cbImage = cbStride * height;
    
        if (FAILED(ipBitmap->CopyPixels(NULL, cbStride, cbImage, static_cast<BYTE *>(pvImageBits))))
    
        {
    
            // couldn't extract image; delete HBITMAP
    
            DeleteObject(hbmp);
    
            hbmp = NULL;
    
        }
    
     
    
    Return:
    
        return hbmp;
    
    }
    
    // Loads the PNG containing the splash image into a HBITMAP.
    HBITMAP LoadSplashImage()
    {
    
        HBITMAP hbmpSplash = NULL;
    
     
    
        // load the PNG image data into a stream
    
        IStream * ipImageStream = CreateStreamOnResource(MAKEINTRESOURCE(1), _T("JPEG"));
    
    	if (ipImageStream == NULL){MessageBoxA(NULL, "failed", "1", MB_OK); goto Return;}
    
     
    
        // load the bitmap with WIC
    
        IWICBitmapSource * ipBitmap = LoadBitmapFromStream(ipImageStream);
    
    	if (ipBitmap == NULL){MessageBoxA(NULL, "failed", "2", MB_OK); goto ReleaseStream;}
    
     
    
        // create a HBITMAP containing the image
    
        hbmpSplash = CreateHBITMAP(ipBitmap);
    
        ipBitmap->Release();
    	if(!hbmpSplash)MessageBoxA(NULL, "failed", "3", MB_OK);
    
     
    
    ReleaseStream:
    
        ipImageStream->Release();
    
    Return:
    
        return hbmpSplash;
    }
    
    /*void RegisterWindowClass()
    {
        WNDCLASS wc = { 0 };
        wc.lpfnWndProc = DefWindowProc;
        wc.hInstance = g_hInstance;
        wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SPLASHICON));
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.lpszClassName = c_szSplashClass;
        RegisterClass(&wc);
    }*/
    
    void SetSplashImage(HWND hwndSplash, HBITMAP hbmpSplash)
    
    {
    
        // get the size of the bitmap
        BITMAP bm;
        GetObject(hbmpSplash, sizeof(bm), &bm);
        SIZE sizeSplash = { bm.bmWidth, bm.bmHeight };
    
     
    
        // get the primary monitor's info
        POINT ptZero = { 0 };
        HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
        MONITORINFO monitorinfo = { 0 };
        monitorinfo.cbSize = sizeof(monitorinfo);
        GetMonitorInfo(hmonPrimary, &monitorinfo);
    
     
    
        // center the splash screen in the middle of the primary work area
        const RECT & rcWork = monitorinfo.rcWork;
        POINT ptOrigin;
        ptOrigin.x = rcWork.left + (rcWork.right - rcWork.left - sizeSplash.cx) / 2;
        ptOrigin.y = rcWork.top + (rcWork.bottom - rcWork.top - sizeSplash.cy) / 2;
    
     
    
        // create a memory DC holding the splash bitmap
        HDC hdcScreen = GetDC(NULL);
        HDC hdcMem = CreateCompatibleDC(hdcScreen);
        HBITMAP hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpSplash);
    
     
    
        // use the source image's alpha channel for blending
        BLENDFUNCTION blend = { 0 };
        blend.BlendOp = AC_SRC_OVER;
        blend.SourceConstantAlpha = 255;
        blend.AlphaFormat = AC_SRC_ALPHA;
    
     
    
        // paint the window (in the right location) with the alpha-blended bitmap
        UpdateLayeredWindow(hwndSplash, hdcScreen, &ptOrigin, &sizeSplash,
            hdcMem, &ptZero, RGB(0, 0, 0), &blend, ULW_ALPHA);
    
     
    
        // delete temporary objects
        SelectObject(hdcMem, hbmpOld);
        DeleteDC(hdcMem);
        ReleaseDC(NULL, hdcScreen);
    
    }
    
    
    int main()
    {
    	CoInitialize(NULL);	
    	HBITMAP hbit = LoadSplashImage();
    	
    
    // Window Class name
    char* c_szSplashClass = "SplashWindow";
    
    // Registers a window class for the splash and splash owner windows.
    WNDCLASSA wc = { 0 };
        wc.lpfnWndProc = DefWindowProc;
        wc.hInstance = NULL;
        wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(1));
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.lpszClassName = c_szSplashClass;
        RegisterClassA(&wc);
    
    	HWND hwndOwner = CreateWindowA(c_szSplashClass, NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
        HWND hwndSplash = CreateWindowExA(WS_EX_LAYERED, c_szSplashClass, NULL, WS_POPUP | WS_VISIBLE,0, 0, 0, 0, hwndOwner, NULL, NULL, NULL);
    	SetSplashImage(hwndSplash, hbit);
    
    
    	if(hbit)MessageBoxA(NULL, "You really did it!", "WOW", MB_OK);
    	system("pause");
    	return 0;
    }
    Finally let me just say before you head out on this endeavor that you will need the COM SDK which does not come with Visual Studios Express (no wonder). Luckily there is a deprecated SDK (Microsoft Platform SDK for Windows Server 2003 R2) Which Microsoft still distributes which contains all the files you need for working with COM. You can get the Platform SDK here.

    Regards, why06
    Last edited by why06; 04-02-2010 at 01:22 AM.

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  2. #2
    Arhk's Avatar
    Join Date
    Dec 2008
    Gender
    male
    Posts
    3,618
    Reputation
    35
    Thanks
    217
    My Mood
    Amused
    You could just surf your way around and get the "free" version of VS Pro...
    ~
    "If the world hates you, keep in mind that it hated me first." John 15:18

    "True strength isn't determined by when a man has a lot and gives enough, but when he has nothing left but keeps on giving."
    "A man is determined by the strength of his will."
    "Courage has nothing to do with ascertaining any sense of certainty, but the will to go on even
    in the face of uncertainty." - Arhk



  3. #3
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty
    "free" as in cracked. ;P
    That seems like cheating to me. Weird saying that since Im the one cheating at games, but I like to work with what I've got, w/o torrents and such not to mention I could never get into torrents, LimeWire, etc. And I don't trust them. =/

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  4. #4
    Arhk's Avatar
    Join Date
    Dec 2008
    Gender
    male
    Posts
    3,618
    Reputation
    35
    Thanks
    217
    My Mood
    Amused
    Scan before your run.... There's a nice "free" release on tpb pre-activated '08 professional.
    ~
    "If the world hates you, keep in mind that it hated me first." John 15:18

    "True strength isn't determined by when a man has a lot and gives enough, but when he has nothing left but keeps on giving."
    "A man is determined by the strength of his will."
    "Courage has nothing to do with ascertaining any sense of certainty, but the will to go on even
    in the face of uncertainty." - Arhk



Similar Threads

  1. [Help] Differences Between Visual Studio Express And Visual Studio Ultimate
    By kolec94 in forum C++/C Programming
    Replies: 3
    Last Post: 10-19-2011, 01:07 PM
  2. How to code together with Visual Studio 2010
    By A$IAN in forum CrossFire Help
    Replies: 0
    Last Post: 09-14-2010, 08:06 AM
  3. Help With Visual Basic 2008 And The PushToConsole Command
    By CrossFireHacker V1 in forum CrossFire Hack Coding / Programming / Source Code
    Replies: 5
    Last Post: 08-23-2010, 04:21 AM
  4. Visual studio 2008 link so i can use AO teams hack
    By ronon6 in forum Alliance of Valiant Arms (AVA) Hacks & Cheats
    Replies: 15
    Last Post: 06-16-2010, 07:38 AM
  5. OpenGL and Visual Studio
    By gio85 in forum General
    Replies: 0
    Last Post: 03-05-2009, 01:01 AM