Click here to Skip to main content
Click here to Skip to main content

Desktop Calendar

, 4 Mar 2004
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Arun krishnan
Software Developer (Senior) Tata Elxsi Ltd
India India
No Biography provided

Comments and Discussions

 
QuestionHow to display Window 7? Pinmemberdinh_vu_vt200523-Feb-11 21:54 
AnswerRe: How to display Window 7? Pinmembergoriofab20098-Jan-14 2:50 
RantHelp PinmemberSteve Noll18-Aug-10 1:49 
GeneralRe: Help PinmemberArun krishnan20-Aug-10 8:10 
QuestionHow can i put the month and a year? Pinmemberallan paglinawan14-Mar-09 4:32 
QuestionThe code does not support unicode ? PinmemberTo Quang Hiep5-Oct-08 7:16 
GeneralSaveBitmap Function NOTWorking PinmemberGaurang Shah 03331-Aug-07 20:31 
GeneralRe: SaveBitmap Function NOTWorking PinmemberArun krishnan1-Sep-07 17:24 
QuestionSaveBitmap PinmemberMember #7468617-Mar-07 11:33 
AnswerRe: SaveBitmap PinmemberArun krishnan17-Aug-07 7:11 
GeneralmEMORYYY Pinmembermircea13131324-Aug-06 8:08 
Generalnice one Pinmemberseishin6663-Jun-06 1:32 
GeneralPlease give me some directions about advanced functions Pinmemberu852100127-Jan-05 17:23 
GeneralHighlighting Current Date... PinmemberVali_Ali22-Aug-04 21:04 
GeneralVery cool code PinmemberDanYELL17-May-04 17:19 
Generaldifferent language PinsussCuriousInCrossLanguageDeveloper19-Mar-04 21:43 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141220.1 | Last Updated 5 Mar 2004
Article Copyright 2004 by Arun krishnan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid