Click here to Skip to main content
15,885,767 members
Articles / Desktop Programming / MFC
Article

Desktop Calendar

Rate me:
Please Sign up or sign in to vote.
3.80/5 (21 votes)
4 Mar 2004 84K   2.3K   46   16
A nice desktop calendar that sits on your desktop.

Sample Image - Desktop_Calendar.jpg

Introduction

This article describes a simple calendar that sits on your desktop. I have created this application to just study about alpha blending, desktop wallpapers, and how a device context can be saved as a bitmap. I am planning to make a more refined version including a time scheduler and reminder also.

Using the code

Alpha Blending

HBITMAP Create24BPPDIBSection(HDC hDC, int iWidth, int iHeight)
{
    BITMAPINFO bmi;
    HBITMAP hbm;
    LPBYTE pBits;

    // Initialize header to 0s.
    ZeroMemory(&bmi, sizeof(bmi));

    // Fill out the fields you care about.
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = iWidth;
    bmi.bmiHeader.biHeight = iHeight;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    // Create the surface.
    hbm = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS,(void **)&pBits, NULL, 0);
      
    return(hbm);
}

BOOL BitmapsCompatible(LPBITMAP lpbm1, LPBITMAP lpbm2)
{
    if (lpbm1->bmBitsPixel != lpbm2->bmBitsPixel) 
        return FALSE;
    if (lpbm1->bmPlanes    != lpbm2->bmPlanes)    
        return FALSE;
    if (lpbm1->bmWidth     != lpbm2->bmWidth)     
        return FALSE;
    if (lpbm1->bmHeight    != lpbm2->bmHeight)    
        return FALSE;
    return TRUE;
}

BOOL BlendImages(HBITMAP hbmSrc1, HBITMAP hbmSrc2, HBITMAP hbmDst, DWORD dwWeight1)
{
    BITMAP bmSrc1, bmSrc2, bmDst;
    RGBTRIPLE *lprgbSrc1, *lprgbSrc2, *lprgbDst;
    DWORD dwWidthBytes, dwWeight2;
    int x, y;
    
    // Only values between 0 and 255 are valid.
    if (dwWeight1 > 255) return FALSE;
    
    // Get weighting value for second source image.
    dwWeight2 = 255-dwWeight1;
    
    // Get information about the surfaces you were passed.
    if (!GetObject(hbmSrc1, sizeof(BITMAP), &bmSrc1)) return FALSE;
    if (!GetObject(hbmSrc2, sizeof(BITMAP), &bmSrc2)) return FALSE;
    if (!GetObject(hbmDst,  sizeof(BITMAP), &bmDst))  return FALSE;

    // Make sure you have data that meets your requirements.
    if (!BitmapsCompatible(&bmSrc1, &bmSrc2))
        return FALSE;
    if (!BitmapsCompatible(&bmSrc1, &bmDst))
        return FALSE;
    if (bmSrc1.bmBitsPixel != 24)
        return FALSE;
    if (bmSrc1.bmPlanes != 1)
        return FALSE;
    if (!bmSrc1.bmBits || !bmSrc2.bmBits || !bmDst.bmBits)
        return FALSE;

    dwWidthBytes = bmDst.bmWidthBytes;
    
    // Initialize the surface pointers.
    lprgbSrc1 = (RGBTRIPLE *)bmSrc1.bmBits; 
    lprgbSrc2 = (RGBTRIPLE *)bmSrc2.bmBits;  
    lprgbDst  = (RGBTRIPLE *)bmDst.bmBits;

    for (y=0; y<bmDst.bmHeight; y++) {
        for (x=0; x<bmDst.bmWidth; x++) {
            lprgbDst[x].rgbtRed   = 
              (BYTE)((((DWORD)lprgbSrc1[x].rgbtRed * dwWeight1) + 
              ((DWORD)lprgbSrc2[x].rgbtRed * dwWeight2)) >> 8);
            lprgbDst[x].rgbtGreen = 
              (BYTE)((((DWORD)lprgbSrc1[x].rgbtGreen * dwWeight1) + 
              ((DWORD)lprgbSrc2[x].rgbtGreen * dwWeight2)) >> 8);
            lprgbDst[x].rgbtBlue  = 
              (BYTE)((((DWORD)lprgbSrc1[x].rgbtBlue * dwWeight1) + 
              ((DWORD)lprgbSrc2[x].rgbtBlue * dwWeight2)) >> 8);
        }

        // Move to next scan line.
        lprgbSrc1 = (RGBTRIPLE *)((LPBYTE)lprgbSrc1 + dwWidthBytes);
        lprgbSrc2 = (RGBTRIPLE *)((LPBYTE)lprgbSrc2 + dwWidthBytes);
        lprgbDst  = (RGBTRIPLE *)((LPBYTE)lprgbDst  + dwWidthBytes);
    }

    return TRUE;
}

BOOL DoAlphaBlend(
  HDC hdcDest,                 // Handle to destination DC.
  int nXOriginDest,            // X-coord of upper-left corner.
  int nYOriginDest,            // Y-coord of upper-left corner.
  int nWidthDest,              // Destination width.
  int nHeightDest,             // Destination height.
  HDC hdcSrc,                  // Handle to source DC.
  int nXOriginSrc,             // X-coord of upper-left corner.
  int nYOriginSrc,             // Y-coord of upper-left corner.
  int nWidthSrc,               // Source width.
  int nHeightSrc,              // Source height.
  DWORD dwSourceWeight)        // Source weighting (between 0 and 255).
{
    HDC      hdcSrc1 = NULL;
    HDC      hdcSrc2 = NULL;
    HDC      hdcDst  = NULL;
    HBITMAP  hbmSrc1 = NULL;
    HBITMAP  hbmSrc2 = NULL;
    HBITMAP  hbmDst  = NULL;
    BOOL     bReturn;

    // Create surfaces for sources and destination images.
    hbmSrc1 = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest);
    if (!hbmSrc1) goto HANDLEERROR;

    hbmSrc2 = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest);
    if (!hbmSrc2) goto HANDLEERROR;

    hbmDst  = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest);
    if (!hbmDst) goto HANDLEERROR;

    
    // Create HDCs to hold our surfaces.
    hdcSrc1 = CreateCompatibleDC(hdcDest);
    if (!hdcSrc1) goto HANDLEERROR;
    
    hdcSrc2 = CreateCompatibleDC(hdcDest);
    if (!hdcSrc2) goto HANDLEERROR;
    
    hdcDst  = CreateCompatibleDC(hdcDest);
    if (!hdcDst) goto HANDLEERROR;

    
    // Prepare the surfaces for drawing.
    SelectObject(hdcSrc1, hbmSrc1);
    SelectObject(hdcSrc2, hbmSrc2);
    SelectObject(hdcDst,  hbmDst);
    SetStretchBltMode(hdcSrc1, COLORONCOLOR);
    SetStretchBltMode(hdcSrc2, COLORONCOLOR);

    
    // Capture a copy of the source area.
    if (!StretchBlt(hdcSrc1, 0,0,nWidthDest,nHeightDest,
                    hdcSrc,  nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, 
                    SRCCOPY))
         goto HANDLEERROR;
    
    // Capture a copy of the destination area.
    if (!StretchBlt(hdcSrc2, 0,0,nWidthDest,nHeightDest,
                    hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, 
                    SRCCOPY))
         goto HANDLEERROR;

                  
    // Blend the two source areas to create the destination image.
    bReturn = BlendImages(hbmSrc1, hbmSrc2, hbmDst, dwSourceWeight);

    
    // Clean up objects you do not need any longer.
    // You cannot delete an object that's selected into an
    // HDC so delete the HDC first. 
    DeleteDC(hdcSrc1);
    DeleteDC(hdcSrc2);
    DeleteObject(hbmSrc1);
    DeleteObject(hbmSrc2);

    
    // Display the blended (destination) image to the target HDC.
    if (bReturn) {
        BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, 
               hdcDst, 0,0, SRCCOPY);
    }

    
    // Clean up the rest of the objects you created.
    DeleteDC(hdcDst);
    DeleteObject(hbmDst);

    return bReturn;

HANDLEERROR:

    if (hdcSrc1) DeleteDC(hdcSrc1);
    if (hdcSrc2) DeleteDC(hdcSrc2);
    if (hdcDst)  DeleteDC(hdcDst);
    if (hbmSrc1) DeleteObject(hbmSrc1);
    if (hbmSrc2) DeleteObject(hbmSrc2);
    if (hbmDst)  DeleteObject(hbmDst);

    return FALSE;
}

Save Device Context into an uncompressed bitmap

// Function to save bitmap
BOOL SaveBitmap(HDC hDC,HBITMAP hBitmap,CString szPath)
{
    FILE * fp= NULL;
    fp = fopen(szPath.GetBuffer(1),"wb");
    if(fp == NULL)
        return false;
    
    BITMAP Bm;
    BITMAPINFO BitInfo;
    ZeroMemory(&BitInfo, sizeof(BITMAPINFO));
    BitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    BitInfo.bmiHeader.biBitCount = 0;

    if(!::GetDIBits(hDC, hBitmap, 0, 0, NULL, &BitInfo, DIB_RGB_COLORS))
        return (false);

    Bm.bmHeight = BitInfo.bmiHeader.biHeight;
    Bm.bmWidth  = BitInfo.bmiHeader.biWidth;

    BITMAPFILEHEADER    BmHdr;
    
    BmHdr.bfType        = 0x4d42;   // 'BM' WINDOWS_BITMAP_SIGNATURE
    BmHdr.bfSize        = (((3 * Bm.bmWidth + 3) & ~3) * Bm.bmHeight) 
                          + sizeof(BITMAPFILEHEADER) 
                          + sizeof(BITMAPINFOHEADER);
    BmHdr.bfReserved1    = BmHdr.bfReserved2 = 0;
    BmHdr.bfOffBits      = (DWORD) sizeof(BITMAPFILEHEADER) 
                          + sizeof(BITMAPINFOHEADER);
    
    BitInfo.bmiHeader.biCompression = 0;
    // Writing Bitmap File Header ////
    fwrite(&BmHdr,sizeof(BITMAPFILEHEADER),1,fp);

    fwrite(&BitInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);

    BYTE *pData = new BYTE[BitInfo.bmiHeader.biSizeImage + 5];
    if(!::GetDIBits(hDC, hBitmap, 0, Bm.bmHeight, 
                 pData, &BitInfo, DIB_RGB_COLORS))
        return (false);
    if(pData != NULL)
        fwrite(pData,1,BitInfo.bmiHeader.biSizeImage,fp);

    fclose(fp);
    delete (pData);

    return (true);
}

// here is how to use the above function

//Get the device context
HDC hDC = ::GetDC(hWnd);
// Create a memory device context
HDC hMemDC = ::CreateCompatibleDC(hDC);
// Create a compatible bitmap 
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, 
                 nScreenWidth,nScreenHeight);
// Select the bitmap into the memory context
::SelectObject(hMemDC,hBitmap);    
// Do what ever drawing you want into the Device Context
...
...
SaveBitmap(hMemDC, hBitmap,"Sample.bmp");

Points of Interest

SetStretchBltMode(hDC,HALFTONE)

Try out this function, this improves the quality of StretchBlt(). I think with our using this mode, SretchBlt() function cannot give you the required quality if you are dealing with big bitmaps.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Tata Elxsi Ltd
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to display Window 7? Pin
vudvpro23-Feb-11 20:54
vudvpro23-Feb-11 20:54 
AnswerRe: How to display Window 7? Pin
goriofab20098-Jan-14 1:50
goriofab20098-Jan-14 1:50 
RantHelp Pin
Steve Noll18-Aug-10 0:49
Steve Noll18-Aug-10 0:49 
GeneralRe: Help Pin
Arun krishnan20-Aug-10 7:10
Arun krishnan20-Aug-10 7:10 
QuestionHow can i put the month and a year? Pin
allan paglinawan14-Mar-09 3:32
allan paglinawan14-Mar-09 3:32 
QuestionThe code does not support unicode ? Pin
To Quang Hiep5-Oct-08 6:16
To Quang Hiep5-Oct-08 6:16 
GeneralSaveBitmap Function NOTWorking Pin
GauranG Shah31-Aug-07 19:31
GauranG Shah31-Aug-07 19:31 
GeneralRe: SaveBitmap Function NOTWorking Pin
Arun krishnan1-Sep-07 16:24
Arun krishnan1-Sep-07 16:24 
QuestionSaveBitmap Pin
Member 7468617-Mar-07 10:33
Member 7468617-Mar-07 10:33 
AnswerRe: SaveBitmap Pin
Arun krishnan17-Aug-07 6:11
Arun krishnan17-Aug-07 6:11 
GeneralmEMORYYY Pin
mircea13131324-Aug-06 7:08
mircea13131324-Aug-06 7:08 
Generalnice one Pin
Seishin#3-Jun-06 0:32
Seishin#3-Jun-06 0:32 
GeneralPlease give me some directions about advanced functions Pin
jackhsu.msi27-Jan-05 16:23
jackhsu.msi27-Jan-05 16:23 
GeneralHighlighting Current Date... Pin
Vali_Ali22-Aug-04 20:04
Vali_Ali22-Aug-04 20:04 
GeneralVery cool code Pin
DanYELL17-May-04 16:19
DanYELL17-May-04 16:19 
Generaldifferent language Pin
CuriousInCrossLanguageDeveloper19-Mar-04 20:43
sussCuriousInCrossLanguageDeveloper19-Mar-04 20:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.